Merge branch 'develop' into feature/access-rights-admins

This commit is contained in:
Alexey Kostenko 2021-04-29 15:11:50 +03:00
commit 17d4b0a4db
265 changed files with 7909 additions and 2971 deletions

View File

@ -79,7 +79,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Data.Encryption", "comm
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Projects", "products\ASC.Projects\Server\ASC.Projects.csproj", "{D1A33923-5680-4B86-A7DA-41E78350D997}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASC.CRM", "products\ASC.CRM\Server\ASC.CRM.csproj", "{277F4A2C-07CC-4BC5-B4F3-9695BB2DFFB9}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.CRM", "products\ASC.CRM\Server\ASC.CRM.csproj", "{277F4A2C-07CC-4BC5-B4F3-9695BB2DFFB9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Mail", "products\ASC.Mail\Server\ASC.Mail.csproj", "{137CA67B-D0F5-4746-B8BC-1888D2859B90}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Calendar", "products\ASC.Calendar\Server\ASC.Calendar.csproj", "{F39933F8-7598-492F-9DD3-E25780D68288}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -227,6 +231,14 @@ Global
{277F4A2C-07CC-4BC5-B4F3-9695BB2DFFB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{277F4A2C-07CC-4BC5-B4F3-9695BB2DFFB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{277F4A2C-07CC-4BC5-B4F3-9695BB2DFFB9}.Release|Any CPU.Build.0 = Release|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Debug|Any CPU.Build.0 = Debug|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Release|Any CPU.ActiveCfg = Release|Any CPU
{137CA67B-D0F5-4746-B8BC-1888D2859B90}.Release|Any CPU.Build.0 = Release|Any CPU
{F39933F8-7598-492F-9DD3-E25780D68288}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F39933F8-7598-492F-9DD3-E25780D68288}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F39933F8-7598-492F-9DD3-E25780D68288}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F39933F8-7598-492F-9DD3-E25780D68288}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -60,6 +60,8 @@ servers_products_name_backend=(ASC.CRM)
servers_products_name_backend+=(ASC.Files)
servers_products_name_backend+=(ASC.People)
servers_products_name_backend+=(ASC.Projects)
servers_products_name_backend+=(ASC.Calendar)
servers_products_name_backend+=(ASC.Mail)
# Publish server backend products
for i in ${!servers_products_name_backend[@]}; do

View File

@ -47,10 +47,12 @@
# service host #
API_SYSTEM_HOST=${CONTAINER_PREFIX}api-system
BACKUP_HOST=${CONTAINER_PREFIX}backup
CALENDAR_HOST=${CONTAINER_PREFIX}calendar
CRM_HOST=${CONTAINER_PREFIX}crm
STORAGE_ENCRYPTION_HOST=${CONTAINER_PREFIX}storage-encryption
FILES_HOST=${CONTAINER_PREFIX}files
FILES_SERVICES_HOST=${CONTAINER_PREFIX}files-services
MAIL_HOST=${CONTAINER_PREFIX}mail
STORAGE_MIGRATION_HOST=${CONTAINER_PREFIX}storage-migration
NOTIFY_HOST=${CONTAINER_PREFIX}notify
PEOPLE_SERVER_HOST=${CONTAINER_PREFIX}people-server
@ -68,9 +70,11 @@
SERVICE_API_SYSTEM=${API_SYSTEM_HOST}:${SERVICE_PORT}
SERVICE_BACKUP=${BACKUP_HOST}:${SERVICE_PORT}
SERVICE_CRM=${CRM_HOST}:${SERVICE_PORT}
SERVICE_CALENDAR=${CALENDAR_HOST}:${SERVICE_PORT}
SERVICE_STORAGE_ENCRYPTION=${STORAGE_ENCRYPTION_HOST}:${SERVICE_PORT}
SERVICE_FILES=${FILES_HOST}:${SERVICE_PORT}
SERVICE_FILES_SERVICES=${FILES_SERVICES_HOST}:${SERVICE_PORT}
SERVICE_MAIL=${MAIL_HOST}:${SERVICE_PORT}
SERVICE_STORAGE_MIGRATION=${STORAGE_MIGRATION_HOST}:${SERVICE_PORT}
SERVICE_NOTIFY=${NOTIFY_HOST}:${SERVICE_PORT}
SERVICE_PEOPLE_SERVER=${PEOPLE_SERVER_HOST}:${SERVICE_PORT}

View File

@ -45,11 +45,8 @@ RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
bash build-frontend.sh -sp ${SRC_PATH} && \
bash build-backend.sh -sp ${SRC_PATH} -ar "--disable-parallel" && \
bash publish-backend.sh -sp ${SRC_PATH} -bp ${BUILD_PATH} -ar "--disable-parallel"
COPY config/mysql/conf.d/mysql.cnf /etc/mysql/conf.d/mysql.cnf
COPY config/supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
RUN sed -i 's/Server=.*;Port=/Server=127.0.0.1;Port=/' /app/onlyoffice/config/appsettings.test.json
COPY config/mysql/conf.d/mysql.cnf /etc/mysql/conf.d/mysql.cnf
RUN rm -rf /var/lib/apt/lists/*
@ -107,6 +104,8 @@ COPY --from=base ${SRC_PATH}/web/ASC.Web.Login/dist ${BUILD_PATH}/studio/login
COPY --from=base ${SRC_PATH}/products/ASC.People/Client/dist ${BUILD_PATH}/products/ASC.People/client
COPY --from=base ${SRC_PATH}/products/ASC.Projects/Client/dist ${BUILD_PATH}/products/ASC.Projects/client
COPY --from=base ${SRC_PATH}/web/ASC.Web.Client/dist ${BUILD_PATH}/studio/client
COPY --from=base ${SRC_PATH}/products/ASC.Calendar/Client/dist ${BUILD_PATH}/products/ASC.Calendar/client
COPY --from=base ${SRC_PATH}/products/ASC.Mail/Client/dist ${BUILD_PATH}/products/ASC.Mail/client
COPY /config/nginx/templates/upstream.conf.template /etc/nginx/templates/upstream.conf.template
@ -122,6 +121,8 @@ RUN chown nginx:nginx /etc/nginx/* -R && \
sed -i 's/localhost:5020/$service_projects_server/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5000/$service_api/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5003/$service_studio/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5023/$service_calendar/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5022/$service_mail/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:9999/$service_urlshortener/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/172.*/$document_server;/' /etc/nginx/conf.d/onlyoffice.conf && \
# configute the image nginx whith less privileged https://hub.docker.com/_/nginx
@ -146,6 +147,15 @@ COPY --from=base --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Data.B
CMD ["ASC.Data.Backup.dll", "ASC.Data.Backup", "core:products:folder=/var/www/products/", "core:products:subfolder=server"]
## ASC.Calendar ##
FROM builder AS calendar
WORKDIR ${BUILD_PATH}/products/ASC.Calendar/server/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=base --chown=onlyoffice:onlyoffice ${BUILD_PATH}/products/ASC.Calendar/server/ .
CMD ["ASC.Calendar.dll", "ASC.Calendar"]
## ASC.CRM ##
FROM builder AS crm
WORKDIR ${BUILD_PATH}/products/ASC.CRM/server/
@ -182,6 +192,15 @@ COPY --from=base --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Files.
CMD ["ASC.Files.Service.dll", "ASC.Files.Service", "core:products:folder=/var/www/products/", "core:products:subfolder=server"]
## ASC.Mail ##
FROM builder AS mail
WORKDIR ${BUILD_PATH}/products/ASC.Mail/server/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=base --chown=onlyoffice:onlyoffice ${BUILD_PATH}/products/ASC.Mail/server/ .
CMD ["ASC.Mail.dll", "ASC.Mail"]
## ASC.Data.Storage.Migration ##
FROM builder AS data_storage_migration
WORKDIR ${BUILD_PATH}/services/storage.migration/service/

View File

@ -29,6 +29,9 @@ x-service:
- people_data:/var/www/products/ASC.People/server/
- crm_data:/var/www/products/ASC.CRM/server/
- project_data:/var/www/products/ASC.Projects/server/
- calendar_data:/var/www/products/ASC.Calendar/server/
- mail_data:/var/www/products/ASC.Mail/server/
services:
onlyoffice-elasticsearch:
@ -95,6 +98,11 @@ services:
image: "${REPO}/${STATUS}appserver-backup:${SRV_VERSION}"
container_name: ${BACKUP_HOST}
onlyoffice-calendar:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-calendar:${SRV_VERSION}"
container_name: ${CALENDAR_HOST}
onlyoffice-crm:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-crm:${SRV_VERSION}"
@ -115,6 +123,11 @@ services:
image: "${REPO}/${STATUS}appserver-files-services:${SRV_VERSION}"
container_name: ${FILES_SERVICES_HOST}
onlyoffice-mail:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-mail:${SRV_VERSION}"
container_name: ${MAIL_HOST}
onlyoffice-storage-migration:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-storage-migration:${SRV_VERSION}"
@ -187,10 +200,12 @@ services:
depends_on:
- onlyoffice-api-system
- onlyoffice-backup
- onlyoffice-calendar
- onlyoffice-crm
- onlyoffice-storage-encryption
- onlyoffice-files
- onlyoffice-files-services
- onlyoffice-mail
- onlyoffice-storage-migration
- onlyoffice-people-server
- onlyoffice-projects-server
@ -204,10 +219,12 @@ services:
environment:
- SERVICE_API_SYSTEM=${SERVICE_API_SYSTEM}
- SERVICE_BACKUP=${SERVICE_BACKUP}
- SERVICE_CALENDAR=${SERVICE_CALENDAR}
- SERVICE_CRM=${SERVICE_CRM}
- SERVICE_STORAGE_ENCRYPTION=${SERVICE_STORAGE_ENCRYPTION}
- SERVICE_FILES=${SERVICE_FILES}
- SERVICE_FILES_SERVICES=${SERVICE_FILES_SERVICES}
- SERVICE_MAIL=${SERVICE_MAIL}
- SERVICE_STORAGE_MIGRATION=${SERVICE_STORAGE_MIGRATION}
- SERVICE_NOTIFY=${SERVICE_NOTIFY}
- SERVICE_PEOPLE_SERVER=${SERVICE_PEOPLE_SERVER}
@ -240,3 +257,5 @@ volumes:
people_data:
crm_data:
project_data:
calendar_data:
mail_data:

View File

@ -15,6 +15,13 @@ services:
target: backup
image: "${REPO}/${STATUS}appserver-backup:${SRV_VERSION}"
onlyoffice-calendar:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: calendar
image: "${REPO}/${STATUS}appserver-calendar:${SRV_VERSION}"
onlyoffice-crm:
build:
context: ./
@ -43,6 +50,13 @@ services:
target: files_services
image: "${REPO}/${STATUS}appserver-files-services:${SRV_VERSION}"
onlyoffice-mail:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: mail
image: "${REPO}/${STATUS}appserver-mail:${SRV_VERSION}"
onlyoffice-storage-migration:
build:
context: ./

View File

@ -10,6 +10,11 @@ map $SERVICE_BACKUP $service_backup {
$SERVICE_BACKUP $SERVICE_BACKUP;
}
map $SERVICE_CALENDAR $service_calendar {
volatile;
$SERVICE_CALENDAR $SERVICE_CALENDAR;
}
map $SERVICE_CRM $service_crm {
volatile;
$SERVICE_CRM $SERVICE_CRM;
@ -30,6 +35,11 @@ map $SERVICE_FILES_SERVICES $service_files_services {
$SERVICE_FILES_SERVICES $SERVICE_FILES_SERVICES;
}
map $SERVICE_MAIL $service_mail {
volatile;
$SERVICE_MAIL $SERVICE_MAIL;
}
map $SERVICE_STORAGE_MIGRATION $service_storage_migration {
volatile;
$SERVICE_STORAGE_MIGRATION $SERVICE_STORAGE_MIGRATION;

View File

@ -29,6 +29,8 @@ x-service:
- people_data:/var/www/products/ASC.People/server/
- crm_data:/var/www/products/ASC.CRM/server/
- project_data:/var/www/products/ASC.Projects/server/
- calendar_data:/var/www/products/ASC.Calendar/server/
- mail_data:/var/www/products/ASC.Mail/server/
services:
onlyoffice-notify:
@ -47,3 +49,5 @@ volumes:
people_data:
crm_data:
project_data:
calendar_data:
mail_data:

View File

@ -0,0 +1,2 @@
echo "RUN ASC.Web.Calendar"
call set BROWSER=none&&npm start --prefix ../../products/ASC.Calendar/Client

View File

@ -0,0 +1,2 @@
echo "RUN ASC.Calendar"
call dotnet run --project ..\..\products\ASC.Calendar\Server\ASC.Calendar.csproj --no-build --$STORAGE_ROOT=..\..\..\Data --log__dir=..\..\..\Logs --log__name=calendar

2
build/run/MailClient.bat Normal file
View File

@ -0,0 +1,2 @@
echo "RUN ASC.Web.Mail"
call set BROWSER=none&&npm start --prefix ../../products/ASC.Mail/Client

2
build/run/MailServer.bat Normal file
View File

@ -0,0 +1,2 @@
echo "RUN ASC.Mail"
call dotnet run --project ..\..\products\ASC.Mail\Server\ASC.Mail.csproj --no-build --$STORAGE_ROOT=..\..\..\Data --log__dir=..\..\..\Logs --log__name=mail

View File

@ -28,6 +28,7 @@ using System;
using System.Collections.Generic;
using System.Threading;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Utils;
using ASC.Core;
@ -160,5 +161,18 @@ namespace ASC.FederatedLogin.LoginProviders
}
public abstract LoginProfile GetLoginProfile(string accessToken);
}
public class BaseLoginProviderExtension
{
public static void Register(DIHelper services)
{
services.TryAdd<BoxLoginProvider>();
services.TryAdd<DropboxLoginProvider>();
services.TryAdd<OneDriveLoginProvider>();
services.TryAdd<DocuSignLoginProvider>();
services.TryAdd<GoogleLoginProvider>();
services.TryAdd<WordpressLoginProvider>();
}
}
}

View File

@ -14,6 +14,8 @@
<ItemGroup>
<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>

View File

@ -24,8 +24,11 @@
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ASC.Common.Utils;
@ -39,18 +42,40 @@ namespace ASC.ApiSystem
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
public async static Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.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) =>
{
@ -76,6 +101,5 @@ namespace ASC.ApiSystem
});
});
}
}
}

View File

@ -23,6 +23,8 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</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" />
</ItemGroup>
<ItemGroup>

View File

@ -1,5 +1,7 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ASC.Common.Utils;
@ -13,14 +15,41 @@ using Microsoft.Extensions.Hosting;
namespace ASC.Data.Backup
{
public class Program
{
public static async Task Main(string[] args)
{
await Host.CreateDefaultBuilder(args)
{
public async static Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.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) =>
{
@ -46,10 +75,7 @@ namespace ASC.Data.Backup
{"pathToConf", path }
}
);
})
.UseConsoleLifetime()
.Build()
.RunAsync();
}
});
}
}

View File

@ -22,6 +22,8 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</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" />
</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.
*
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ASC.Common.Utils;
@ -38,13 +40,40 @@ namespace ASC.Data.Storage.Encryption
{
public class Program
{
public static async Task Main(string[] args)
{
await Host.CreateDefaultBuilder(args)
public async static Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.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) =>
{
@ -69,10 +98,6 @@ namespace ASC.Data.Storage.Encryption
.AddJsonFile("kafka.json")
.AddJsonFile($"kafka.{env}.json", true)
.AddEnvironmentVariables();
})
.UseConsoleLifetime()
.Build()
.RunAsync();
}
});
}
}

View File

@ -4,6 +4,11 @@
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\ASC.Common\ASC.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 static async Task Main(string[] args)
{
await Host.CreateDefaultBuilder(args)
public async static Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureAppConfiguration((hostContext, config) =>
{
@ -64,10 +72,6 @@ namespace ASC.Data.Storage.Migration
.ConfigureContainer<ContainerBuilder>((context, builder) =>
{
builder.Register(context.Configuration);
})
.UseConsoleLifetime()
.Build()
.RunAsync();
}
});
}
}

View File

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

View File

@ -21,9 +21,17 @@ namespace ASC.Notify
{
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())
.ConfigureAppConfiguration((hostContext, config) =>
{
@ -73,18 +81,6 @@ namespace ASC.Notify
.ConfigureContainer<ContainerBuilder>((context, builder) =>
{
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>
<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" />
</ItemGroup>

View File

@ -46,9 +46,17 @@ namespace ASC.Socket.IO.Svc
{
public class Program
{
public static async Task Main(string[] args)
{
var host = Host.CreateDefaultBuilder(args)
public async static Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureAppConfiguration((hostContext, config) =>
{
@ -90,18 +98,7 @@ namespace ASC.Socket.IO.Svc
.ConfigureContainer<ContainerBuilder>((context, builder) =>
{
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>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\web\ASC.Web.Core\ASC.Web.Core.csproj" />
<ProjectReference Include="..\..\ASC.Data.Encryption\ASC.Data.Encryption.csproj" />

View File

@ -22,9 +22,17 @@ namespace ASC.Studio.Notify
{
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())
.ConfigureAppConfiguration((hostContext, config) =>
{
@ -67,18 +75,6 @@ namespace ASC.Studio.Notify
.ConfigureContainer<ContainerBuilder>((context, builder) =>
{
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,6 +13,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Telegram.Bot" Version="15.7.1" />
</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.
*
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ASC.Common.Utils;
@ -38,13 +40,40 @@ namespace ASC.TelegramService
{
public class Program
{
public static async Task Main(string[] args)
{
await Host.CreateDefaultBuilder(args)
public async static Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.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) =>
{
@ -69,10 +98,6 @@ namespace ASC.TelegramService
.AddJsonFile("kafka.json")
.AddJsonFile($"kafka.{env}.json", true)
.AddEnvironmentVariables();
})
.UseConsoleLifetime()
.Build()
.RunAsync();
}
});
}
}

View File

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

View File

@ -26,6 +26,7 @@
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using ASC.Common;
@ -45,11 +46,19 @@ using Microsoft.Extensions.Hosting;
namespace ASC.Thumbnails.Svc
{
public class Program
{
public static async Task Main(string[] args)
{
var host = Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
{
public async static Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureAppConfiguration((hostContext, config) =>
{
var buided = config.Build();
@ -89,18 +98,6 @@ namespace ASC.Thumbnails.Svc
.ConfigureContainer<ContainerBuilder>((context, builder) =>
{
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,6 +13,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>

View File

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

View File

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

View File

@ -35,6 +35,24 @@
}
],
"instanceScope": "InstancePerLifetimeScope"
},
{
"type": "ASC.Mail.Configuration.ProductEntryPoint, ASC.Mail",
"services": [
{
"type": "ASC.Web.Core.IWebItem, ASC.Web.Core"
}
],
"instanceScope": "InstancePerLifetimeScope"
},
{
"type": "ASC.Calendar.Configuration.ProductEntryPoint, ASC.Calendar",
"services": [
{
"type": "ASC.Web.Core.IWebItem, ASC.Web.Core"
}
],
"instanceScope": "InstancePerLifetimeScope"
}
]
}

View File

@ -0,0 +1,9 @@
server {
listen 5017;
root /var/www/products/ASC.Calendar/client;
index index.html;
location / {
try_files $uri /index.html =404;
}
}

View File

@ -0,0 +1,9 @@
server {
listen 5016;
root /var/www/products/ASC.Mail/client;
index index.html;
location / {
try_files $uri /index.html =404;
}
}

View File

@ -155,6 +155,16 @@ server {
proxy_pass http://localhost:5021;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
location ~* /mail {
proxy_pass http://localhost:5022;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
location ~* /calendar {
proxy_pass http://localhost:5023;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
}
location /storage {
@ -297,6 +307,68 @@ server {
try_files /$basename /index.html =404;
}
location ~* (/httphandlers/filehandler.ashx|ChunkedUploader.ashx) {
proxy_pass http://localhost:5007;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
}
location ~* /mail {
#rewrite products/mail/(.*) /$1 break;
proxy_pass http://localhost:5016;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
location ~* /sockjs-node {
rewrite products/projects(.*)/sockjs-node/(.*) /$2/$3 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://localhost:5016;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location ~* /(manifest.json|service-worker.js|appIcon.png|bg-error.png) {
root $public_root;
try_files /$basename /index.html =404;
}
location ~* (/httphandlers/filehandler.ashx|ChunkedUploader.ashx) {
proxy_pass http://localhost:5007;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
}
location ~* /calendar {
#rewrite products/calendar/(.*) /$1 break;
proxy_pass http://localhost:5017;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
location ~* /sockjs-node {
rewrite products/projects(.*)/sockjs-node/(.*) /$2/$3 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://localhost:5017;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location ~* /(manifest.json|service-worker.js|appIcon.png|bg-error.png) {
root $public_root;
try_files /$basename /index.html =404;
}
location ~* (/httphandlers/filehandler.ashx|ChunkedUploader.ashx) {
proxy_pass http://localhost:5007;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;

View File

@ -28,6 +28,14 @@
"name": "🚀 @appserver/projects",
"path": "products\\ASC.Projects\\Client"
},
{
"name": "🚀 @appserver/mail",
"path": "products\\ASC.Mail\\Client"
},
{
"name": "🚀 @appserver/calendar",
"path": "products\\ASC.Calendar\\Client"
},
{
"name": "🚀 @appserver/studio",
"path": "web\\ASC.Web.Client"

View File

@ -1,13 +1,18 @@
{
"version": "0.1.6",
"version": "0.1.8",
"npmClient": "yarn",
"packages": [
"packages/asc-web-components",
"packages/asc-web-common",
"web/ASC.Web.Login",
"web/ASC.Web.Client",
"web/ASC.Web.Editor",
"products/ASC.People/Client",
"products/ASC.Files/Client"
"products/ASC.Files/Client",
"products/ASC.CRM/Client",
"products/ASC.Projects/Client",
"products/ASC.Mail/Client",
"products/ASC.Calendar/Client"
],
"useWorkspaces": true
}

View File

@ -10,7 +10,9 @@
"products/ASC.People/Client",
"products/ASC.Files/Client",
"products/ASC.CRM/Client",
"products/ASC.Projects/Client"
"products/ASC.Projects/Client",
"products/ASC.Mail/Client",
"products/ASC.Calendar/Client"
],
"scripts": {
"wipe": "rimraf node_modules yarn.lock web/**/node_modules products/**/node_modules",

View File

@ -4,12 +4,22 @@ import FilesFilter from "./filter";
import { FolderType } from "../../constants";
import find from "lodash/find";
export function openEdit(fileId, doc) {
const params = doc ? `?doc=${doc}` : "";
export function openEdit(fileId, version, doc) {
const params = []; // doc ? `?doc=${doc}` : "";
if (version) {
params.push(`version=${version}`);
}
if (doc) {
params.push(`doc=${doc}`);
}
const paramsString = params.length > 0 ? `?${params.join("&")}` : "";
const options = {
method: "get",
url: `/files/file/${fileId}/openedit${params}`,
url: `/files/file/${fileId}/openedit${paramsString}`,
};
return request(options);

View File

@ -236,7 +236,7 @@ export function getConsumersList() {
export function getAuthProviders() {
return request({
method: "get",
url: `/settings/authproviders`,
url: `/people/thirdparty/providers`,
});
}

View File

@ -1,6 +1,6 @@
{
"name": "@appserver/common",
"version": "0.0.2",
"version": "0.0.3",
"private": true,
"scripts": {
"build": "echo 'skip it'",

View File

@ -8,7 +8,7 @@ import UserStore from "./UserStore";
import { logout as logoutDesktop, desktopConstants } from "../desktop";
import { combineUrl, isAdmin } from "../utils";
import isEmpty from "lodash/isEmpty";
import { AppServerConfig } from "../constants";
import { AppServerConfig, LANGUAGE } from "../constants";
const { proxyURL } = AppServerConfig;
class AuthStore {
@ -43,7 +43,14 @@ class AuthStore {
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() {
let success = false;
if (this.isAuthenticated) {
@ -51,6 +58,8 @@ class AuthStore {
this.userStore.isLoaded &&
this.moduleStore.isLoaded &&
this.settingsStore.isLoaded;
success && this.setLanguage();
} else {
success = this.settingsStore.isLoaded;
}

View File

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

View File

@ -11,7 +11,6 @@ const Badge = (props) => {
if (!props.onClick) return;
e.preventDefault();
e.stopPropagation();
props.onClick(e);
};

View File

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

View File

@ -80,8 +80,8 @@ class ContextMenuButton extends React.Component {
}
}
onIconButtonClick = () => {
if (this.props.isDisabled) {
onIconButtonClick = (e) => {
if (this.props.isDisabled || this.props.isNew) {
this.stopAction;
return;
}
@ -95,7 +95,7 @@ class ContextMenuButton extends React.Component {
!this.props.isDisabled &&
this.state.isOpen &&
this.props.onClick &&
this.props.onClick()
this.props.onClick(e)
); // eslint-disable-line react/prop-types
};
@ -124,6 +124,20 @@ class ContextMenuButton extends React.Component {
return true;
}
callNewMenu = (e) => {
if (this.props.isDisabled || !this.props.isNew) {
this.stopAction;
return;
}
this.setState(
{
data: this.props.getData(),
},
() => this.props.onClick(e)
);
};
render() {
//console.log("ContextMenuButton render", this.props);
const {
@ -148,12 +162,19 @@ class ContextMenuButton extends React.Component {
style,
isFill, // eslint-disable-line react/prop-types
asideHeader, // eslint-disable-line react/prop-types
isNew,
} = this.props;
const { isOpen, displayType, offsetX, offsetY } = this.state;
const iconButtonName = isOpen && iconOpenName ? iconOpenName : iconName;
return (
<StyledOuter ref={this.ref} className={className} id={id} style={style}>
<StyledOuter
ref={this.ref}
className={className}
id={id}
style={style}
onClick={this.callNewMenu}
>
<IconButton
color={color}
hoverColor={hoverColor}
@ -284,6 +305,7 @@ ContextMenuButton.propTypes = {
columnCount: PropTypes.number,
/** Set the display type */
displayType: PropTypes.string,
isNew: PropTypes.bool,
};
ContextMenuButton.defaultProps = {
@ -296,6 +318,7 @@ ContextMenuButton.defaultProps = {
directionX: "left",
isFill: false,
displayType: "dropdown",
isNew: false,
};
export default ContextMenuButton;

View File

@ -154,11 +154,15 @@ class ContextMenuSub extends Component {
<ArrowIcon className={submenuIconClassName} />
);
const submenu = this.renderSubmenu(item);
const dataKeys = Object.fromEntries(
Object.entries(item).filter((el) => el[0].indexOf("data-") === 0)
);
let content = (
<a
href={item.url || "#"}
className={linkClassName}
target={item.target}
{...dataKeys}
onClick={(event) => this.onItemClick(event, item, index)}
role="menuitem"
>

View File

@ -1,6 +1,6 @@
{
"name": "@appserver/components",
"version": "0.0.2",
"version": "0.0.3",
"private": true,
"scripts": {
"build": "echo 'skip it'",

View File

@ -100,6 +100,8 @@ class Row extends React.Component {
className="expandButton"
getData={getOptions}
directionX="right"
isNew={true}
onClick={onContextMenu}
/>
) : (
<div className="expandButton"> </div>

View File

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

View File

@ -9,8 +9,6 @@ import { LANGUAGE } from "@appserver/common/constants";
// have a look at the Quick start guide
// for passing in lng and translations on init
const languages = ["en", "ru"];
i18n
/*
load translation using http -> see /public/locales (i.e. https://github.com/i18next/react-i18next/tree/master/example/react/public/locales)
@ -32,8 +30,6 @@ i18n
*/
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
supportedLngs: languages,
whitelist: languages,
fallbackLng: "en",
load: "languageOnly",
//debug: true,

View File

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

View File

@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ASC.Common.DependencyInjection;
using ASC.Common.Utils;
@ -15,18 +18,40 @@ namespace ASC.CRM
{
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)
{
return Host.CreateDefaultBuilder(args)
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.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) =>
{
@ -54,25 +79,6 @@ namespace ASC.CRM
.ConfigureContainer<ContainerBuilder>((context, builder) =>
{
builder.Register(context.Configuration, true, false);
});
//if (!FilesIntegration.IsRegisteredFileSecurityProvider("crm", "crm_common"))
//{
// FilesIntegration.RegisterFileSecurityProvider("crm", "crm_common", new FileSecurityProvider());
//}
////Register prodjects' calendar events
//CalendarManager.Instance.RegistryCalendarProvider(userid =>
//{
// if (WebItemSecurity.IsAvailableForUser(WebItemManager.CRMProductID, userid))
// {
// return new List<BaseCalendar> { new CRMCalendar(userid) };
// }
// return new List<BaseCalendar>();
//});
}
});//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

@ -0,0 +1,7 @@
{
"presets": ["@babel/preset-react", "@babel/preset-env"],
"plugins": [
"@babel/plugin-transform-runtime",
"@babel/plugin-proposal-class-properties"
]
}

View File

@ -0,0 +1,3 @@
PUBLIC_URL=/products/calendar
WDS_SOCKET_PATH=/products/calendar/sockjs-node
PORT=5017

21
products/ASC.Calendar/Client/.gitignore vendored Normal file
View File

@ -0,0 +1,21 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

View File

@ -0,0 +1,15 @@
FROM node:12
WORKDIR /usr/src/app
COPY package.json ./
COPY yarn.lock ./
RUN yarn install
COPY . .
RUN yarn build
EXPOSE 5017
CMD [ "yarn", "build:start" ]

View File

@ -0,0 +1,17 @@
// script to enable webpack-bundle-analyzer
process.env.NODE_ENV = "production";
const webpack = require("webpack");
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
const webpackConfigProd = require("react-scripts/config/webpack.config")(
"production"
);
webpackConfigProd.plugins.push(new BundleAnalyzerPlugin());
// actually running compilation and waiting for plugin to start explorer
webpack(webpackConfigProd, (err, stats) => {
if (err || stats.hasErrors()) {
console.error(err);
}
});

View File

@ -0,0 +1,83 @@
{
"name": "@appserver/calendar",
"version": "0.1.3",
"private": "true",
"homepage": "/products/calendar",
"id": "32d24cb5-7ece-4606-9c94-19216ba42086",
"title": "ONLYOFFICE",
"scripts": {
"start": "webpack-cli serve",
"start-prod": "webpack --mode production && serve dist -p 5017",
"build": "webpack --mode production",
"serve": "serve dist -p 5017",
"clean": "rm -rf dist"
},
"devDependencies": {
"@babel/core": "^7.12.10",
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/plugin-proposal-export-default-from": "^7.12.1",
"@babel/plugin-transform-runtime": "^7.12.1",
"@babel/preset-env": "^7.12.7",
"@babel/preset-react": "^7.12.10",
"@svgr/webpack": "^5.5.0",
"babel-loader": "^8.2.2",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^7.0.0",
"css-loader": "^3.6.0",
"html-webpack-plugin": "4.5.0",
"json-loader": "^0.5.7",
"serve": "11.3.2",
"source-map-loader": "^1.1.2",
"style-loader": "1.2.1",
"webpack": "5.14.0",
"webpack-cli": "4.5.0",
"webpack-dev-server": "3.11.2",
"workbox-webpack-plugin": "^6.1.1"
},
"dependencies": {
"@babel/runtime": "^7.12.5",
"attr-accept": "^2.2.2",
"axios": "^0.21.0",
"email-addresses": "^3.1.0",
"i18next": "^19.8.4",
"i18next-http-backend": "^1.1.0",
"mobx": "^6.1.1",
"mobx-react": "^7.1.0",
"moment": "^2.29.1",
"copy-to-clipboard": "^3.2.0",
"fast-deep-equal": "^3.1.3",
"prop-types": "^15.7.2",
"rc-tree": "^2.1.4",
"re-resizable": "^6.9.0",
"react": "^17.0.1",
"react-autosize-textarea": "^7.1.0",
"react-content-loader": "^5.1.4",
"react-custom-scrollbars": "^4.2.1",
"react-device-detect": "^1.14.0",
"react-dom": "^17.0.1",
"react-dropzone": "^11.2.4",
"react-i18next": "^11.7.3",
"react-hammerjs": "^1.0.1",
"react-onclickoutside": "^6.9.0",
"react-player": "^1.15.3",
"react-resize-detector": "^5.2.0",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"react-string-format": "^0.1.0",
"react-svg": "^12.0.0",
"react-text-mask": "^5.4.3",
"react-toastify": "^6.1.0",
"react-tooltip": "^4.2.11",
"react-viewer": "^3.2.2",
"react-virtualized-auto-sizer": "^1.0.2",
"react-window": "^1.8.6",
"react-window-infinite-loader": "^1.0.5",
"resize-image": "^0.1.0",
"sass": "^1.29.0",
"sass-loader": "^10.1.0",
"sjcl": "^1.0.8",
"screenfull": "^5.1.0",
"styled-components": "^5.2.1",
"workbox-window": "^6.1.1"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.8814 3H18.9943V1.02931C18.9943 0.460813 18.5335 0 17.9649 0H17.0301C16.4616 0 16.001 0.460813 16.001 1.02931V3H7.99588V1.02931C7.99588 0.460813 7.53507 0 6.96674 0H6.02914C5.46064 0 5 0.460813 5 1.02931V3H3.11844C1.95051 3 1 3.95017 1 5.11844V20.8965C1 22.0641 1.95051 23.0149 3.11844 23.0149H20.8816C22.0493 23.0149 23 22.0642 23 20.8965V5.11844C22.9998 3.95017 22.0491 3 20.8814 3ZM21 21.001H3.02614V8.00104H21V21.001ZM9.8844 17.6579C10.3376 18.114 11.0732 18.114 11.5266 17.6579L16.66 12.4939C16.8777 12.2748 17 11.9777 17 11.668C17 11.3583 16.8777 11.0611 16.66 10.8421C16.2066 10.386 15.4709 10.386 15.0178 10.8421L10.913 14.9713C10.7984 15.0862 10.6126 15.0862 10.4982 14.9713L8.98223 13.4466C8.52885 12.9905 7.7932 12.9905 7.34004 13.4466C6.88665 13.9024 6.88665 14.6425 7.34004 15.0984L9.8844 17.6579Z" fill="#7A95B0"/>
</svg>

After

Width:  |  Height:  |  Size: 984 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -0,0 +1,261 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no, viewport-fit=cover"
/>
<meta name="theme-color" content="#000000" />
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="shortcut icon" href="favicon.ico" />
<link rel="manifest" href="manifest.json" />
<!-- Tell the browser it's a PWA -->
<meta name="mobile-web-app-capable" content="yes" />
<!-- Tell iOS it's a PWA -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<link rel="apple-touch-icon" href="appIcon.png" />
<link
href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i"
rel="stylesheet"
type="text/css"
/>
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<style type="text/css">
body {
height: 100%;
margin: 0;
padding: 0;
width: 100%;
font-family: "Open Sans", sans-serif;
font-size: 13px;
-webkit-font-smoothing: antialiased;
}
.temp-header-container {
align-items: center;
background-color: rgb(15, 64, 113);
display: grid;
grid-template-columns: 24px 168px 1fr 36px;
grid-template-rows: 1fr;
grid-column-gap: 16px;
width: calc(100vw - 16px);
height: 56px;
padding-right: 16px;
}
.temp-content-loader {
padding: 16px;
height: calc(100vh - 91px);
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: calc(100vh - 91px);
grid-column-gap: 8px;
}
@media (max-width: 1024px) {
.temp-content-loader {
grid-template-columns: 1fr;
}
.temp-content__article {
display: none;
}
}
.burger-loader-svg {
width: 24px;
height: 24px;
padding-left: 16px;
}
.logo-loader-svg {
width: 168px;
height: 24px;
position: relative;
cursor: pointer;
padding-left: 16px;
}
.avatar-loader-svg {
width: 36px;
height: 36px;
}
</style>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript> You need to enable JavaScript to run this app. </noscript>
<div id="root"></div>
<div id="temp-content">
<header class="temp-header-container">
<div id="burger-loader-svg" class="burger-loader-svg">
<svg
role="img"
width="100%"
height="100%"
aria-labelledby="loading-aria0"
preserveAspectRatio="none"
>
<rect
rx="3"
ry="3"
width="24"
height="24"
style="fill: url('#fill0');"
></rect>
<defs>
<linearGradient id="fill0">
<stop
offset="0.599964"
stop-color="#fff"
stop-opacity="0.25"
></stop>
</linearGradient>
</defs>
</svg>
</div>
<div id="logo-loader-svg" class="logo-loader-svg">
<svg
role="img"
width="100%"
height="100%"
aria-labelledby="loading-aria01"
preserveAspectRatio="none"
>
<rect
rx="3"
ry="3"
width="168"
height="24"
style="fill: url('#fill01');"
></rect>
<defs>
<linearGradient id="fill01">
<stop
offset="0.599964"
stop-color="#fff"
stop-opacity="0.25"
></stop>
</linearGradient>
</defs>
</svg>
</div>
<div></div>
<div id="avatar-loader-svg" class="avatar-loader-svg">
<svg
role="img"
width="100%"
height="100%"
aria-labelledby="loading-aria01"
preserveAspectRatio="none"
>
<circle
cx="18"
cy="18"
r="18"
width="36"
height="36"
style="fill: url('#fill02');"
></circle>
<defs>
<linearGradient id="fill02">
<stop
offset="0.599964"
stop-color="#fff"
stop-opacity="0.25"
></stop>
</linearGradient>
</defs>
</svg>
</div>
</header>
<div class="temp-content-loader">
<div class="temp-content__article">
<svg
role="img"
width="100%"
height="100%"
aria-labelledby="loading-aria1"
preserveAspectRatio="none"
>
<rect
x="0"
y="0"
width="100%"
height="100%"
clip-path="url(#clip-path1)"
style="fill: url('#fill1');"
></rect>
<defs>
<clipPath id="clip-path1">
<rect x="3" y="3" rx="5" ry="5" width="100%" />
</clipPath>
<linearGradient id="fill1">
<stop
offset="0.599964"
stop-color="#000000"
stop-opacity="0.1"
></stop>
</linearGradient>
</defs>
</svg>
</div>
<div>
<svg
role="img"
width="100%"
height="100%"
aria-labelledby="loading-aria2"
preserveAspectRatio="none"
>
<rect
x="0"
y="0"
width="100%"
height="100%"
clip-path="url(#clip-path2)"
style="fill: url('#fill2');"
></rect>
<defs>
<clipPath id="clip-path2">
<rect x="3" y="3" rx="5" ry="5" width="100%" />
</clipPath>
<linearGradient id="fill2">
<stop
offset="0.599964"
stop-color="#000000"
stop-opacity="0.1"
></stop>
</linearGradient>
</defs>
</svg>
</div>
</div>
</div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
<script>
console.log("It's Calendar INIT");
</script>
</body>
</html>

View File

@ -0,0 +1,7 @@
{
"ComingSoon": "Coming soon",
"ViewWeb": "View web version",
"OpenApp": "Open your {{title}} app",
"LearnMore": "Learn more",
"ModuleDescription": "Schedule meetings and events"
}

View File

@ -0,0 +1,7 @@
{
"ComingSoon": "Скоро появится",
"ViewWeb": "Просмотреть веб-версию",
"OpenApp": "Откройте {{title}}",
"LearnMore": "Узнать больше",
"ModuleDescription": "Планируйте встречи и мероприятия"
}

View File

@ -0,0 +1,15 @@
{
"short_name": "ASC.Calendar",
"name": "ASC.Calendar",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": "./index.html",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View File

@ -0,0 +1,7 @@
//import "./wdyr";
import React from "react";
import Shell from "studio/shell";
const App = () => <Shell />;
export default App;

View File

@ -0,0 +1,15 @@
import React from "react";
import ReactDOM from "react-dom";
import { MemoryRouter } from "react-router-dom";
import App from "./App";
it("renders without crashing", async () => {
const div = document.createElement("div");
ReactDOM.render(
<MemoryRouter>
<App />
</MemoryRouter>,
div
);
await new Promise((resolve) => setTimeout(resolve, 1000));
});

View File

@ -0,0 +1,71 @@
import React, { useEffect } from "react";
import { Provider as PeopleProvider, inject, observer } from "mobx-react";
import { Switch } from "react-router-dom";
import CalendarStore from "./store/CalendarStore";
import ErrorBoundary from "@appserver/common/components/ErrorBoundary";
import toastr from "studio/toastr";
import PrivateRoute from "@appserver/common/components/PrivateRoute";
import AppLoader from "@appserver/common/components/AppLoader";
import { combineUrl, updateTempContent } from "@appserver/common/utils";
import config from "../package.json";
import "./custom.scss";
import i18n from "./i18n";
import { I18nextProvider } from "react-i18next";
import Home from "./pages/Home";
import { AppServerConfig } from "@appserver/common/constants";
const { proxyURL } = AppServerConfig;
const homepage = config.homepage;
const PROXY_HOMEPAGE_URL = combineUrl(proxyURL, homepage);
const Error404 = React.lazy(() => import("studio/Error404"));
const Error404Route = (props) => (
<React.Suspense fallback={<AppLoader />}>
<ErrorBoundary>
<Error404 {...props} />
</ErrorBoundary>
</React.Suspense>
);
const CalendarContent = (props) => {
const { isLoaded, loadBaseInfo } = props;
useEffect(() => {
loadBaseInfo()
.catch((err) => toastr.error(err))
.finally(() => {
//this.props.setIsLoaded(true);
updateTempContent();
});
}, []);
useEffect(() => {
if (isLoaded) updateTempContent();
}, [isLoaded]);
return (
<Switch>
<PrivateRoute exact path={PROXY_HOMEPAGE_URL} component={Home} />
<PrivateRoute component={Error404Route} />
</Switch>
);
};
const Calendar = inject(({ auth, calendarStore }) => ({
loadBaseInfo: async () => {
await calendarStore.init();
auth.setProductVersion(config.version);
},
isLoaded: auth.isLoaded && calendarStore.isLoaded,
}))(observer(CalendarContent));
const calendarStore = new CalendarStore();
export default (props) => (
<PeopleProvider calendarStore={calendarStore}>
<I18nextProvider i18n={i18n}>
<Calendar {...props} />
</I18nextProvider>
</PeopleProvider>
);

View File

@ -0,0 +1,9 @@
import App from "./App";
import React from "react";
import ReactDOM from "react-dom";
import config from "../package.json";
import { registerSW } from "@appserver/common/utils/sw-helper";
ReactDOM.render(<App />, document.getElementById("root"));
registerSW(config.homepage);

View File

@ -0,0 +1,27 @@
// Override default variables before the import
$font-family-base: "Open Sans", sans-serif;
html,
body {
height: 100%;
}
#root {
min-height: 100%;
position: relative;
.pageLoader {
position: absolute;
left: calc(50% - 20px);
top: 35%;
}
}
body {
margin: 0;
overflow: hidden;
}
body.loading * {
cursor: wait !important;
}

View File

@ -0,0 +1,26 @@
import authStore from "@appserver/common/store/AuthStore";
//import store from "../store/store";
//const { getCurrentProduct } = commonStore.auth.selectors;
export const setDocumentTitle = (subTitle = null) => {
// const state = store.getState();
// const { auth: commonState } = state;
const { isAuthenticated, settingsStore, product: currentModule } = authStore;
const { organizationName } = settingsStore;
let title;
if (subTitle) {
if (isAuthenticated && currentModule) {
title = subTitle + " - " + currentModule.title;
} else {
title = subTitle + " - " + organizationName;
}
} else if (currentModule && organizationName) {
title = currentModule.title + " - " + organizationName;
} else {
title = organizationName;
}
document.title = title;
};

View File

@ -0,0 +1,58 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from "i18next-http-backend";
import config from "../package.json";
import { LANGUAGE } from "@appserver/common/constants";
//import LanguageDetector from "i18next-browser-languagedetector";
// not like to use this?
// have a look at the Quick start guide
// for passing in lng and translations on init
const languages = ["en", "ru"];
i18n
/*
load translation using http -> see /public/locales (i.e. https://github.com/i18next/react-i18next/tree/master/example/react/public/locales)
learn more: https://github.com/i18next/i18next-http-backend
*/
.use(Backend)
/*
detect user language
learn more: https://github.com/i18next/i18next-browser-languageDetector
*/
//.use(LanguageDetector)
/*
pass the i18n instance to react-i18next.
*/
.use(initReactI18next)
/*
init i18next
for all options read: https://www.i18next.com/overview/configuration-options
*/
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
supportedLngs: languages,
whitelist: languages,
fallbackLng: "en",
load: "languageOnly",
//debug: true,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
format: function (value, format) {
if (format === "lowercase") return value.toLowerCase();
return value;
},
},
backend: {
loadPath: `${config.homepage}/locales/{{lng}}/{{ns}}.json`,
},
react: {
useSuspense: false,
},
});
export default i18n;

View File

@ -0,0 +1 @@
import("./bootstrap");

View File

@ -0,0 +1,257 @@
import React, { useEffect } from "react";
import { ReactSVG } from "react-svg";
import PropTypes from "prop-types";
import { withRouter } from "react-router";
import Text from "@appserver/components/text";
import Link from "@appserver/components/link";
import Badge from "@appserver/components/badge";
import Box from "@appserver/components/box";
import EmptyScreenContainer from "@appserver/components/empty-screen-container";
import ExternalLinkIcon from "../../../../../../public/images/external.link.react.svg";
import Loaders from "@appserver/common/components/Loaders";
import toastr from "studio/toastr";
import PageLayout from "@appserver/common/components/PageLayout";
import { withTranslation } from "react-i18next";
import styled from "styled-components";
import { isMobile, isTablet, isIOS } from "react-device-detect";
import { setDocumentTitle } from "../../helpers/utils";
import { inject } from "mobx-react";
import i18n from "../../i18n";
import { I18nextProvider } from "react-i18next";
import { combineUrl, deleteCookie } from "@appserver/common/utils";
const commonStyles = `
.link-box {
margin: 8px 0;
.view-web-link {
margin: 8px;
:focus {
outline: 0;
}
}
}
`;
const ComingSoonPage = styled.div`
padding: ${isTablet ? "106px 0 0 0" : isMobile ? "62px 0 0 0" : "0"};
width: ${isTablet ? "500px" : "336px"};
margin: 0 auto;
.module-logo-icon {
float: left;
margin-top: 8px;
margin-right: 16px;
svg {
width: ${isTablet ? "192px" : "96px"};
height: ${isTablet ? "192px" : "96px"};
}
}
.module-title {
margin-top: 14px;
margin-bottom: 14px;
}
.module-info {
margin-bottom: 18px;
.learn-more-link {
white-space: nowrap;
}
}
.coming-soon-badge {
margin-bottom: 26px;
}
${commonStyles}
`;
const StyledDesktopContainer = styled(EmptyScreenContainer)`
img {
width: 150px;
height: 150px;
}
span:first-of-type {
font-size: 24px;
}
span {
font-size: 14px;
> p {
font-size: 14px;
.learn-more-link {
white-space: nowrap;
}
}
}
${commonStyles}
.view-web-link {
font-size: 14px;
}
.coming-soon-badge > div > p {
font-size: 13px;
}
`;
const ExternalLink = ({ label, href, onClick }) => (
<Box className="link-box">
<ExternalLinkIcon
color="#333333"
size={isMobile || isTablet ? "small" : "medium"}
/>
<Link
as="a"
href={href}
onClick={onClick}
target="_blank"
className="view-web-link"
color="#555F65"
isBold
isHovered
>
{label}
</Link>
</Box>
);
const Body = ({ modules, match, isLoaded, setCurrentProductId, t, tReady }) => {
const { error } = match.params;
const { pathname, protocol, hostname } = window.location;
const currentModule = modules.find((m) => m.link === pathname);
const { id, title, imageUrl, link, originUrl, helpUrl } = currentModule;
const url = originUrl ? originUrl : link;
const webLink = combineUrl(
protocol + "//" + hostname,
`${url}?desktop_view=true`
);
const appLink = isIOS
? id === "2A923037-8B2D-487b-9A22-5AC0918ACF3F"
? "message:"
: id === "32D24CB5-7ECE-4606-9C94-19216BA42086"
? "calshow:"
: false
: false;
setDocumentTitle();
useEffect(() => {
setCurrentProductId(id);
}, [id, setCurrentProductId]);
useEffect(() => error && toastr.error(error), [error]);
const appButtons = (
<>
<Badge
label={t("ComingSoon")}
maxWidth="150px"
borderRadius="2px"
className="coming-soon-badge"
/>
<ExternalLink
label={t("ViewWeb")}
onClick={() => {
deleteCookie("desktop_view");
window.open(webLink, "_self", "", true);
}}
/>
{appLink && (
<ExternalLink
label={t("OpenApp", {
title: title,
})}
href={appLink}
/>
)}
</>
);
const moduleDescription = (
<Text className="module-info">
{t("ModuleDescription")}{" "}
{helpUrl && false && (
<Link
as="a"
href={helpUrl}
target="_blank"
className="learn-more-link"
color="#555F65"
isBold
isHovered
>
{t("LearnMore")}...
</Link>
)}
</Text>
);
return !isLoaded || !tReady ? (
<></>
) : isMobile || isTablet ? (
<ComingSoonPage>
<ReactSVG
className="module-logo-icon"
loading={() => (
<Loaders.Rectangle
width="100"
height="14"
backgroundColor="#fff"
foregroundColor="#fff"
backgroundOpacity={0.25}
foregroundOpacity={0.2}
/>
)}
src={imageUrl}
/>
<Box displayProp="flex" flexDirection="column" widthProp="220px">
<Text
fontWeight="600"
fontSize={isTablet ? "24px" : "19px"}
className="module-title"
>
{title}
</Text>
{moduleDescription}
{appButtons}
</Box>
</ComingSoonPage>
) : (
<StyledDesktopContainer
imageSrc={imageUrl}
imageAlt={title}
headerText={title}
descriptionText={moduleDescription}
buttons={appButtons}
/>
);
};
const ComingSoon = (props) => {
return (
<PageLayout>
<PageLayout.SectionBody>
<Body {...props} />
</PageLayout.SectionBody>
</PageLayout>
);
};
ComingSoon.propTypes = {
modules: PropTypes.array,
isLoaded: PropTypes.bool,
};
const ComingSoonWrapper = inject(({ auth }) => ({
modules: auth.moduleStore.modules,
isLoaded: auth.isLoaded,
setCurrentProductId: auth.settingsStore.setCurrentProductId,
}))(withRouter(withTranslation("ComingSoon")(ComingSoon)));
export default (props) => (
<I18nextProvider i18n={i18n}>
<ComingSoonWrapper {...props} />
</I18nextProvider>
);

View File

@ -0,0 +1,39 @@
import { action, makeObservable, observable } from "mobx";
import config from "../../package.json";
import store from "studio/store";
const { auth: authStore } = store;
class CalendarStore {
isLoading = false;
isLoaded = false;
isInit = false;
constructor() {
makeObservable(this, {
isLoading: observable,
isLoaded: observable,
setIsLoading: action,
setIsLoaded: action,
init: action,
});
}
init = async () => {
if (this.isInit) return;
this.isInit = true;
authStore.settingsStore.setModuleInfo(config.homepage, config.id);
this.setIsLoaded(true);
};
setIsLoading = (loading) => {
this.isLoading = loading;
};
setIsLoaded = (isLoaded) => {
this.isLoaded = isLoaded;
};
}
export default CalendarStore;

View File

@ -0,0 +1,12 @@
import React from "react";
if (process.env.NODE_ENV === "development") {
const whyDidYouRender = require("@welldone-software/why-did-you-render");
whyDidYouRender(React, {
trackAllPureComponents: true,
collapseGroups: true,
//trackExtraHooks: [
// [ReactRedux, 'useSelector']
//]
});
}

View File

@ -0,0 +1,198 @@
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack").container
.ModuleFederationPlugin;
const TerserPlugin = require("terser-webpack-plugin");
const { InjectManifest } = require("workbox-webpack-plugin");
const combineUrl = require("@appserver/common/utils/combineUrl");
const AppServerConfig = require("@appserver/common/constants/AppServerConfig");
const path = require("path");
const pkg = require("./package.json");
const deps = pkg.dependencies;
const homepage = pkg.homepage; // combineUrl(AppServerConfig.proxyURL, pkg.homepage);
const title = pkg.title;
var config = {
mode: "development",
entry: "./src/index",
devServer: {
publicPath: homepage,
contentBase: [path.join(__dirname, "dist")],
contentBasePublicPath: homepage,
port: 5017,
historyApiFallback: {
// Paths with dots should still use the history fallback.
// See https://github.com/facebook/create-react-app/issues/387.
disableDotRule: true,
index: homepage,
},
// proxy: [
// {
// context: "/api",
// target: "http://localhost:8092",
// },
// ],
hot: false,
hotOnly: false,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
"Access-Control-Allow-Headers":
"X-Requested-With, content-type, Authorization",
},
},
output: {
publicPath: "auto",
chunkFilename: "static/js/[id].[contenthash].js",
//assetModuleFilename: "static/images/[hash][ext][query]",
path: path.resolve(process.cwd(), "dist"),
filename: "static/js/[name].[contenthash].bundle.js",
},
resolve: {
extensions: [".jsx", ".js", ".json"],
fallback: {
crypto: false,
},
},
module: {
rules: [
{
test: /\.(png|jpe?g|gif|ico)$/i,
type: "asset/resource",
generator: {
filename: "static/images/[hash][ext][query]",
},
},
{
test: /\.m?js/,
type: "javascript/auto",
resolve: {
fullySpecified: false,
},
},
{
test: /\.react.svg$/,
use: [
{
loader: "@svgr/webpack",
options: {
svgoConfig: {
plugins: [{ removeViewBox: false }],
},
},
},
],
},
{ test: /\.json$/, loader: "json-loader" },
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.s[ac]ss$/i,
use: [
// Creates `style` nodes from JS strings
"style-loader",
// Translates CSS into CommonJS
"css-loader",
// Compiles Sass to CSS
"sass-loader",
],
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-react", "@babel/preset-env"],
plugins: [
"@babel/plugin-transform-runtime",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-export-default-from",
],
},
},
"source-map-loader",
],
},
],
},
plugins: [
new CleanWebpackPlugin(),
new ModuleFederationPlugin({
name: "calendar",
filename: "remoteEntry.js",
remotes: {
studio: `studio@${combineUrl(
AppServerConfig.proxyURL,
"/remoteEntry.js"
)}`,
},
exposes: {
"./app": "./src/Calendar.jsx",
},
shared: {
...deps,
react: {
singleton: true,
requiredVersion: deps.react,
},
"react-dom": {
singleton: true,
requiredVersion: deps["react-dom"],
},
},
}),
new HtmlWebpackPlugin({
template: "./public/index.html",
publicPath: homepage,
title: title,
base: `${homepage}/`,
}),
new CopyPlugin({
patterns: [
{
from: "public",
globOptions: {
dot: true,
gitignore: true,
ignore: ["**/index.html"],
},
},
],
}),
],
};
module.exports = (env, argv) => {
if (argv.mode === "production") {
config.mode = "production";
config.optimization = {
splitChunks: { chunks: "all" },
minimize: true,
minimizer: [new TerserPlugin()],
};
config.plugins.push(
new InjectManifest({
mode: "production", //"development",
swSrc: "@appserver/common/utils/sw-template.js", // this is your sw template file
swDest: "sw.js", // this will be created in the build step
exclude: [/\.map$/, /manifest$/, /service-worker\.js$/],
})
);
} else {
config.devtool = "cheap-module-source-map";
}
return config;
};

View File

@ -0,0 +1,47 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<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" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\ASC.Api.Core\ASC.Api.Core.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="Resources\CalendarAddonResource.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>CalendarAddonResource.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resources\CalendarAddonResource.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>CalendarAddonResource.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="Resources\CalendarAddonResource.ru.resx">
<DependentUpon>CalendarAddonResource.resx</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Update="Resources\CalendarAddonResource.de.resx">
<DependentUpon>CalendarAddonResource.resx</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Update="Resources\CalendarAddonResource.es.resx">
<DependentUpon>CalendarAddonResource.resx</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Update="Resources\CalendarAddonResource.fr.resx">
<DependentUpon>CalendarAddonResource.resx</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Update="Resources\CalendarAddonResource.it.resx">
<DependentUpon>CalendarAddonResource.resx</DependentUpon>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@ -0,0 +1,53 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using ASC.Common;
using ASC.Core.Common;
namespace ASC.Web.Calendar.Classes
{
[Scope]
public class PathProvider
{
public string BaseVirtualPath { get; private set; }
public string BaseAbsolutePath { get; private set; }
public PathProvider(BaseCommonLinkUtility commonLinkUtility)
{
BaseVirtualPath = "~/Products/Calendar/";
try
{
BaseAbsolutePath = commonLinkUtility.ToAbsolute(BaseVirtualPath);
}
catch (Exception)
{
BaseAbsolutePath = BaseVirtualPath;
}
}
}
}

View File

@ -0,0 +1,112 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using ASC.Calendar.Resources;
using ASC.Common;
using ASC.Core;
using ASC.Web.Calendar.Classes;
using ASC.Web.Core;
namespace ASC.Calendar.Configuration
{
[Scope]
public class ProductEntryPoint : Product
{
private ProductContext context;
public static readonly Guid ID = WebItemManager.CalendarProductID;
private AuthContext AuthContext { get; }
private UserManager UserManager { get; }
private PathProvider PathProvider { get; }
public ProductEntryPoint(
AuthContext authContext,
UserManager userManager,
PathProvider pathProvider)
{
AuthContext = authContext;
UserManager = userManager;
PathProvider = pathProvider;
}
public override Guid ProductID
{
get { return ID; }
}
public override string Name
{
get { return CalendarAddonResource.AddonName; }
}
public override string Description
{
get { return CalendarAddonResource.AddonDescription; }
}
public override string StartURL
{
get { return PathProvider.BaseAbsolutePath; }
}
public override string HelpURL
{
get { return "https://helpcenter.onlyoffice.com/userguides/calendar.aspx"; }
}
public override string ProductClassName
{
get { return "calendar"; }
}
public override bool Visible { get { return true; } }
public override ProductContext Context
{
get { return context; }
}
public override string ApiURL => "api/2.0/calendar/info.json";
public override void Init()
{
context = new ProductContext
{
//MasterPageFile = String.Concat(PathProvider.BaseVirtualPath, "Masters/BasicTemplate.Master"),
DisabledIconFileName = "product_disabled_logo.png",
IconFileName = "images/calendar.menu.svg",
LargeIconFileName = "images/calendar.svg",
//SubscriptionManager = new ProductSubscriptionManager(),
DefaultSortOrder = 20,
//SpaceUsageStatManager = new ProjectsSpaceUsageStatManager(),
HasComplexHierarchyOfAccessRights = true,
};
}
}
}

View File

@ -0,0 +1,54 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using ASC.Api.Core;
using ASC.Common;
using ASC.Calendar.Configuration;
using ASC.Web.Api.Routing;
using Microsoft.AspNetCore.Mvc;
namespace ASC.Calendar.Controllers
{
[Scope]
[DefaultRoute]
[ApiController]
public class CalendarController : ControllerBase
{
private ProductEntryPoint ProductEntryPoint { get; }
public CalendarController(ProductEntryPoint productEntryPoint)
{
ProductEntryPoint = productEntryPoint;
}
[Read("info")]
public Module GetModule()
{
ProductEntryPoint.Init();
return new Module(ProductEntryPoint);
}
}
}

View File

@ -0,0 +1,56 @@
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace ASC.Calendar
{
public class Program
{
public async static Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
var buided = config.Build();
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(Path.Combine(hostingContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);
config
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true)
.AddJsonFile("storage.json")
.AddJsonFile("kafka.json")
.AddJsonFile($"kafka.{hostingContext.HostingEnvironment.EnvironmentName}.json", true)
.AddEnvironmentVariables()
.AddCommandLine(args)
.AddInMemoryCollection(new Dictionary<string, string>
{
{"pathToConf", path}
});
});
}
}

View File

@ -0,0 +1,29 @@
{
"profiles": {
"Kestrel WebServer": {
"commandName": "Project",
"launchBrowser": false,
"launchUrl": "http://localhost:5023/api/2.0/calendar/info",
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__dir": "../../../Logs",
"log__name": "calendar",
"ASPNETCORE_URLS": "http://localhost:5023",
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WSL 2 : Ubuntu 20.04": {
"commandName": "WSL2",
"launchBrowser": false,
"launchUrl": "http://localhost:5023/api/2.0/calendar/info",
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__dir": "../../../Logs",
"log__name": "calendar",
"ASPNETCORE_URLS": "http://localhost:5023",
"ASPNETCORE_ENVIRONMENT": "Development"
},
"distributionName": "Ubuntu-20.04"
}
}
}

View File

@ -0,0 +1,81 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ASC.Calendar.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class CalendarAddonResource {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal CalendarAddonResource() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ASC.Calendar.Resources.CalendarAddonResource", typeof(CalendarAddonResource).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Organize your work schedule. Track tasks and milestones due dates. Get notifications about events..
/// </summary>
internal static string AddonDescription {
get {
return ResourceManager.GetString("AddonDescription", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Calendar.
/// </summary>
internal static string AddonName {
get {
return ResourceManager.GetString("AddonName", resourceCulture);
}
}
}
}

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AddonDescription" xml:space="preserve">
<value>Stellen Sie Ihren Arbeitsplan auf. Behalten Sie die Übersicht über die Fristen der Aufgaben und Meilensteine. Erhalten Sie Benachrichtigungen über Ereignisse.</value>
</data>
<data name="AddonName" xml:space="preserve">
<value>Kalender</value>
</data>
</root>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AddonDescription" xml:space="preserve">
<value>Organice su calendario de trabajo. Siga tareas e hitos por sus fechas limite. Reciba notificaciones sobre los eventos.</value>
</data>
<data name="AddonName" xml:space="preserve">
<value>Calendario</value>
</data>
</root>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AddonDescription" xml:space="preserve">
<value>Organisez votre horaire de travail. Contrôlez les dates limites des tâches et des jalons. Recevez des notifications d'événements.</value>
</data>
<data name="AddonName" xml:space="preserve">
<value>Calendrier</value>
</data>
</root>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AddonDescription" xml:space="preserve">
<value>Organizza il tuo orario di lavoro. Controlla le attività e le milestone. Ricevi promemoria degli eventi.</value>
</data>
<data name="AddonName" xml:space="preserve">
<value>Calendario</value>
</data>
</root>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AddonDescription" xml:space="preserve">
<value>Organize your work schedule. Track tasks and milestones due dates. Get notifications about events.</value>
</data>
<data name="AddonName" xml:space="preserve">
<value>Calendar</value>
</data>
</root>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AddonDescription" xml:space="preserve">
<value>Организуйте своё рабочее расписание. Отслеживайте даты наступления задач и вех. Получайте оповещения о событиях.</value>
</data>
<data name="AddonName" xml:space="preserve">
<value>Календарь</value>
</data>
</root>

View File

@ -0,0 +1,42 @@
using System.Text;
using ASC.Api.Core;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace ASC.Calendar
{
public class Startup : BaseStartup
{
public override string[] LogParams { get => new string[] { "ASC.Calendar" }; }
public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment)
: base(configuration, hostEnvironment)
{
}
public override void ConfigureServices(IServiceCollection services)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
base.ConfigureServices(services);
}
public override void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors(builder =>
builder
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod());
base.Configure(app, env);
}
}
}

View File

@ -0,0 +1,3 @@
{
"pathToConf": "..\\..\\..\\config"
}

View File

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

View File

@ -1,16 +1,19 @@
{
"OKButton": "OK",
"CancelButton": "Cancel",
"ConfirmationTitle": "Confirmation",
"QuestionDeleteFile": "Are you sure you want to delete this file?",
"FilesModule": "Files",
"FoldersModule": "Folders",
"DeleteDialogQuestion": "Are you sure you want to delete these elements?",
"DeleteDialogNote": "Note: This action can not be undone.",
"QuestionDeleteFolder": "Are you sure you want to delete this folder?",
"QuestionDeleteElements": "Are you sure you want to delete these elements?",
"DeleteOperation": "Deleting",
"DeleteSelectedElem": "Selected elements were successfully deleted",
"DeleteFromTrash": "Selected elements were successfully deleted from trash"
"DeleteFromTrash": "Selected elements were successfully deleted from trash",
"MoveToTrashOneFileTitle": "Move file to Trash?",
"MoveToTrashOneFolderTitle": "Move folder to Trash?",
"MoveToTrashItemsTitle": "Move items to Trash?",
"MoveToTrashOneFileNote": "If you delete a shared file, other users wont be able to access it.",
"MoveToTrashOneFolderNote": "If you delete a shared folder, other users wont be able to access it.",
"MoveToTrashItemsNote": "If you delete shared items, other users wont be able to access them.",
"MoveToTrashButton": "Move to Trash",
"CancelButton": "Cancel"
}

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