Merge branch 'develop' of github.com:ONLYOFFICE/DocSpace into develop
This commit is contained in:
commit
bfa927fcf8
@ -41,23 +41,23 @@ namespace Utils
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var redis = new Redis(session["REDIS_HOST_PROP"], Convert.ToInt32(session["REDIS_PORT_PROP"])))
|
||||
using (var redis = new Redis(session["REDIS_HOST"], Convert.ToInt32(session["REDIS_PORT"])))
|
||||
{
|
||||
|
||||
if (!String.IsNullOrEmpty(session["REDIS_PASSWORD_PROP"].Trim()))
|
||||
redis.Password = session["REDIS_PASSWORD_PROP"];
|
||||
if (!String.IsNullOrEmpty(session["REDIS_PWD"].Trim()))
|
||||
redis.Password = session["REDIS_PWD"];
|
||||
|
||||
var pong = redis.Ping("ONLYOFFICE");
|
||||
|
||||
session.Log("Redis Status: IsConnected is {0}", !String.IsNullOrEmpty(pong));
|
||||
session["RedisServerConnectionError"] = !String.IsNullOrEmpty(pong) ? "" : String.Format("Connection Refused HOST:{0},PORT:{1},PASS:{2}", session["REDIS_HOST_PROP"], session["REDIS_PORT_PROP"], session["REDIS_PASSWORD_PROP"]);
|
||||
session["RedisServerConnectionError"] = !String.IsNullOrEmpty(pong) ? "" : String.Format("Connection Refused HOST:{0},PORT:{1},PASS:{2}", session["REDIS_HOST"], session["REDIS_PORT"], session["REDIS_PWD"]);
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
session.Log("RedisConnectionException '{0}'", ex.Message);
|
||||
session["RedisServerConnectionError"] = String.Format("Connection Refused HOST:{0},PORT:{1},PASS:{2}", session["REDIS_HOST_PROP"], session["REDIS_PORT_PROP"], session["REDIS_PASSWORD_PROP"]);
|
||||
session["RedisServerConnectionError"] = String.Format("Connection Refused HOST:{0},PORT:{1},PASS:{2}", session["REDIS_HOST"], session["REDIS_PORT"], session["REDIS_PWD"]);
|
||||
}
|
||||
|
||||
return ActionResult.Success;
|
||||
@ -69,11 +69,11 @@ namespace Utils
|
||||
{
|
||||
ConnectionFactory factory = new ConnectionFactory();
|
||||
|
||||
factory.HostName = session["RABBITMQ_HOSTNAME_PROP"];
|
||||
factory.Port = Convert.ToInt32(session["RABBITMQ_PORT_PROP"]);
|
||||
factory.VirtualHost = session["RABBITMQ_VIRTUALHOST_PROP"];
|
||||
factory.UserName = session["RABBITMQ_USERNAME_PROP"];
|
||||
factory.Password = session["RABBITMQ_PASSWORD_PROP"];
|
||||
factory.HostName = session["AMQP_HOST"];
|
||||
factory.Port = Convert.ToInt32(session["AMQP_PORT"]);
|
||||
factory.VirtualHost = session["AMQP_VHOST"];
|
||||
factory.UserName = session["AMQP_USER"];
|
||||
factory.Password = session["AMQP_PWD"];
|
||||
|
||||
try
|
||||
{
|
||||
@ -82,11 +82,11 @@ namespace Utils
|
||||
session.Log("RabbitMQ Status: IsConnected is {0}", conn.IsOpen);
|
||||
|
||||
session["RabbitMQServerConnectionError"] = conn.IsOpen ? "" : String.Format("Connection Refused HOST:{0}, PORT:{1}, VirtualHost:{2}, UserName:{3}, PASS:{4}",
|
||||
session["RABBITMQ_HOSTNAME_PROP"],
|
||||
session["RABBITMQ_PORT_PROP"],
|
||||
session["RABBITMQ_VIRTUALHOST_PROP"],
|
||||
session["RABBITMQ_USERNAME_PROP"],
|
||||
session["RABBITMQ_PASSWORD_PROP"]
|
||||
session["AMQP_HOST"],
|
||||
session["AMQP_PORT"],
|
||||
session["AMQP_VHOST"],
|
||||
session["AMQP_USER"],
|
||||
session["AMQP_PWD"]
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -95,11 +95,11 @@ namespace Utils
|
||||
|
||||
session.Log("RabbitMQ.Client.Exceptions.BrokerUnreachableException {0}", ex.Message);
|
||||
session["RabbitMQServerConnectionError"] = String.Format("Connection Refused HOST:{0}, PORT:{1}, VirtualHost:{2}, UserName:{3}, PASS:{4}",
|
||||
session["RABBITMQ_HOSTNAME_PROP"],
|
||||
session["RABBITMQ_PORT_PROP"],
|
||||
session["RABBITMQ_VIRTUALHOST_PROP"],
|
||||
session["RABBITMQ_USERNAME_PROP"],
|
||||
session["RABBITMQ_PASSWORD_PROP"]
|
||||
session["AMQP_HOST"],
|
||||
session["AMQP_PORT"],
|
||||
session["AMQP_VHOST"],
|
||||
session["AMQP_USER"],
|
||||
session["AMQP_PWD"]
|
||||
);
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,4 +13,4 @@ OutputBaseFilename="MySQL Installer Runner"
|
||||
OutputDir=/
|
||||
|
||||
[Run]
|
||||
Filename: "{pf}\MySQL\MySQL Installer for Windows\MySQLInstallerConsole.exe"; Parameters: "community install server;{param:MYSQL_VERSION|5.7.25};X64:*:servertype=Server;passwd={param:PASSWORD_PROP} -silent"; Flags: runhidden
|
||||
Filename: "{pf}\MySQL\MySQL Installer for Windows\MySQLInstallerConsole.exe"; Parameters: "community install server;{param:MYSQL_VERSION|5.7.25};X64:*:servertype=Server;passwd={param:DB_PWD} -silent"; Flags: runhidden
|
@ -1,7 +1,8 @@
|
||||
REM echo ######## Set variables ########
|
||||
set "publisher="Ascensio System SIA""
|
||||
set "nginx_version=1.21.1"
|
||||
set "nuget="%cd%\thirdparty\SimpleRestServices\src\.nuget\NuGet.exe""
|
||||
set "nginx_version=1.21.1"
|
||||
set "environment=test"
|
||||
|
||||
REM echo ######## Extracting and preparing files to build ########
|
||||
%sevenzip% x build\install\win\nginx-%nginx_version%.zip -o"build\install\win\Files" -y
|
||||
@ -11,7 +12,7 @@ md build\install\win\Files\nginx\temp
|
||||
md build\install\win\Files\nginx\logs
|
||||
md build\install\win\Files\tools
|
||||
md build\install\win\Files\Logs
|
||||
md build\install\win\Files\service\
|
||||
md build\install\win\Files\Data
|
||||
md build\install\win\Files\products\ASC.Files\server\temp
|
||||
md build\install\win\Files\products\ASC.People\server\temp
|
||||
md build\install\win\Files\services\ASC.Data.Backup\service\temp
|
||||
@ -39,7 +40,13 @@ copy build\install\win\WinSW3.0.0.exe "build\install\win\Files\tools\Login.exe"
|
||||
copy build\install\win\tools\Login.xml "build\install\win\Files\tools\Login.xml" /y
|
||||
copy "build\install\win\nginx.conf" "build\install\win\Files\nginx\conf\nginx.conf" /y
|
||||
rmdir build\install\win\publish /s /q
|
||||
|
||||
::edit environment
|
||||
%sed% -i "s/\(\W\)PRODUCT.ENVIRONMENT.SUB\(\W\)/\1%environment%\2/g" build\install\win\DocSpace.aip
|
||||
|
||||
::delete nginx configs
|
||||
del /f /q build\install\win\Files\nginx\conf\onlyoffice-login.conf
|
||||
del /f /q build\install\win\Files\nginx\conf\onlyoffice-story.conf
|
||||
|
||||
|
||||
REM echo ######## Build Utils ########
|
||||
@ -50,10 +57,6 @@ rmdir build\install\win\CustomActions\C#\Utils\bin /s /q
|
||||
rmdir build\install\win\CustomActions\C#\Utils\obj /s /q
|
||||
|
||||
REM echo ######## Delete temp files ########
|
||||
del /f /q build\install\win\Files\config\sed*
|
||||
del /f /q build\install\win\Files\nginx\conf\sed*
|
||||
del /f /q build\install\win\Files\nginx\conf\includes\sed*
|
||||
del /f /q build\install\win\Files\services\*\service\config\sed*
|
||||
del /f /q build\install\win\*.back.*
|
||||
|
||||
REM echo ######## Build MySQL Server Installer ########
|
||||
@ -61,4 +64,10 @@ iscc /Qp /S"byparam="signtool" sign /a /n "%publisher%" /t http://timestamp.digi
|
||||
|
||||
REM echo ######## Build DocSpace package ########
|
||||
%AdvancedInstaller% /edit build\install\win\DocSpace.aip /SetVersion %BUILD_VERSION%.%BUILD_NUMBER%
|
||||
|
||||
IF "%SignBuild%"=="true" (
|
||||
:%AdvancedInstaller% /edit build\install\win\DocSpace.aip /SetSig
|
||||
:%AdvancedInstaller% /edit build\install\win\DocSpace.aip /SetDigitalCertificateFile -file %onlyoffice_codesign_path% -password "%onlyoffice_codesign_password%"
|
||||
)
|
||||
|
||||
%AdvancedInstaller% /rebuild build\install\win\DocSpace.aip
|
||||
|
@ -12,31 +12,45 @@ $AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12,Tls13'
|
||||
function DownloadComponents {
|
||||
|
||||
param ( $prereq_list, $path )
|
||||
|
||||
[void](New-Item -ItemType Directory -Force -Path $path)
|
||||
|
||||
ForEach ( $item in $prereq_list ) {
|
||||
$url = $item.link
|
||||
$output = $path + $item.name
|
||||
|
||||
if( $item.download_allways ){
|
||||
[system.console]::WriteLine("Downloading $url")
|
||||
Invoke-WebRequest -Uri $url -OutFile $output
|
||||
} else {
|
||||
if(![System.IO.File]::Exists($output)){
|
||||
try
|
||||
{
|
||||
if( $item.download_allways ){
|
||||
[system.console]::WriteLine("Downloading $url")
|
||||
Invoke-WebRequest -Uri $url -OutFile $output
|
||||
} else {
|
||||
if(![System.IO.File]::Exists($output)){
|
||||
[system.console]::WriteLine("Downloading $url")
|
||||
Invoke-WebRequest -Uri $url -OutFile $output
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Write-Host "[ERROR] Can not download" $item.name "by link" $url
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch ( $env:DOCUMENT_SERVER_VERSION )
|
||||
{
|
||||
latest { $DOCUMENT_SERVER_LINK = "https://download.onlyoffice.com/install/documentserver/windows/onlyoffice-documentserver-ee.exe" }
|
||||
custom { $DOCUMENT_SERVER_LINK = $env:DOCUMENT_SERVER_CUSTOM_LINK.Replace(",", "") }
|
||||
}
|
||||
|
||||
$nginx_version = '1.21.1'
|
||||
$psql_version = '9.5.4'
|
||||
|
||||
$path_prereq = "${pwd}\build\install\win\"
|
||||
|
||||
$prerequisites = @(
|
||||
@{
|
||||
download_allways = $false;
|
||||
name = "nginx-${nginx_version}.zip";
|
||||
name = "nginx-${nginx_version}.zip";
|
||||
link = "https://nginx.org/download/nginx-${nginx_version}.zip";
|
||||
}
|
||||
|
||||
@ -45,6 +59,24 @@ $prerequisites = @(
|
||||
name = "WinSW.NET4new.exe";
|
||||
link = "https://github.com/winsw/winsw/releases/download/v2.11.0/WinSW.NET4.exe";
|
||||
}
|
||||
|
||||
@{
|
||||
download_allways = $true;
|
||||
name = "onlyoffice-documentserver.latest.exe";
|
||||
link = $DOCUMENT_SERVER_LINK
|
||||
}
|
||||
|
||||
@{
|
||||
download_allways = $false;
|
||||
name = "psqlodbc_x64.msi";
|
||||
link = "http://download.onlyoffice.com/install/windows/redist/psqlodbc_x64.msi"
|
||||
}
|
||||
|
||||
@{
|
||||
download_allways = $false;
|
||||
name = "postgresql-${psql_version}-1-windows-x64.exe";
|
||||
link = "https://get.enterprisedb.com/postgresql/postgresql-${psql_version}-1-windows-x64.exe"
|
||||
}
|
||||
)
|
||||
|
||||
$path_nuget_packages = "${pwd}\.nuget\packages\"
|
||||
|
@ -21,6 +21,7 @@ dotnet publish "%PathToRepository%\products\ASC.Files\server\ASC.Files.csproj" -
|
||||
dotnet publish "%PathToRepository%\products\ASC.People\server\ASC.People.csproj" -c Release --self-contained false -o "%PathToAppFolder%\products\ASC.People\server"
|
||||
|
||||
rem backend services (dotnet) in directory 'services'
|
||||
dotnet publish "%PathToRepository%\common\services\ASC.ApiSystem\ASC.ApiSystem.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.ApiSystem\service"
|
||||
dotnet publish "%PathToRepository%\common\services\ASC.Data.Backup\ASC.Data.Backup.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Data.Backup\service"
|
||||
dotnet publish "%PathToRepository%\products\ASC.Files\service\ASC.Files.Service.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Files.Service\service"
|
||||
dotnet publish "%PathToRepository%\common\services\ASC.Notify\ASC.Notify.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Notify\service"
|
||||
|
@ -1,3 +1,123 @@
|
||||
Function RedisSetup
|
||||
On Error Resume Next
|
||||
|
||||
Dim Shell
|
||||
|
||||
Set Shell = CreateObject("WScript.Shell")
|
||||
|
||||
Shell.Run "redis-cli config set save """"", 0, True
|
||||
Shell.Run "redis-cli config rewrite", 0, True
|
||||
|
||||
Set Shell = Nothing
|
||||
End Function
|
||||
|
||||
Function TestPostgreSqlConnection
|
||||
On Error Resume Next
|
||||
|
||||
Dim ErrorText
|
||||
Dim Pos, postgreSqlDriver
|
||||
|
||||
postgreSqlDriver = "PostgreSQL Unicode(x64)"
|
||||
|
||||
Session.Property("PostgreSqlConnectionError") = ""
|
||||
|
||||
Set ConnectionObject = CreateObject("ADODB.Connection")
|
||||
ConnectionObject.Open "Driver={" & postgreSqlDriver & "};" & _
|
||||
"Server=" & Session.Property("PS_DB_HOST") & ";" & _
|
||||
"Port=" & Session.Property("PS_DB_PORT") & ";" & _
|
||||
"Database=" & Session.Property("PS_DB_NAME") & ";" & _
|
||||
"Uid=" & Session.Property("PS_DB_USER") & ";" & _
|
||||
"Pwd=" & Session.Property("PS_DB_PWD")
|
||||
|
||||
If Err.Number <> 0 Then
|
||||
ErrorText = Err.Description
|
||||
Pos = InStrRev( ErrorText, "]" )
|
||||
If 0 < Pos Then
|
||||
ErrorText = Right( ErrorText, Len( ErrorText ) - Pos )
|
||||
End If
|
||||
Session.Property("PostgreSqlConnectionError") = ErrorText
|
||||
End If
|
||||
|
||||
ConnectionObject.Close
|
||||
|
||||
Set ConnectionObject = Nothing
|
||||
|
||||
End Function
|
||||
|
||||
Function PostgreSqlConfigure
|
||||
On Error Resume Next
|
||||
|
||||
If (StrComp(Session.Property("POSTGRE_SQL_PATH"),"FALSE") = 0) Then
|
||||
Wscript.Quit
|
||||
End If
|
||||
|
||||
Dim ErrorText
|
||||
Dim Pos, postgreSqlDriver
|
||||
Dim databaseUserName
|
||||
Dim databaseUserPwd
|
||||
Dim databaseName
|
||||
Dim databasePort
|
||||
Dim databaseHost
|
||||
|
||||
databaseUserName = Session.Property("PS_DB_USER")
|
||||
databaseUserPwd = Session.Property("PS_DB_PWD")
|
||||
databaseName = Session.Property("PS_DB_NAME")
|
||||
databasePort = Session.Property("PS_DB_PORT")
|
||||
databaseHost = Session.Property("PS_DB_HOST")
|
||||
|
||||
Call WriteToLog("PostgreSqlConfig: databaseUserName is " & databaseUserName)
|
||||
Call WriteToLog("PostgreSqlConfig: databaseUserPwd is " & databaseUserPwd)
|
||||
Call WriteToLog("PostgreSqlConfig: databaseName is " & databaseName)
|
||||
Call WriteToLog("PostgreSqlConfig: databasePort is " & databasePort)
|
||||
Call WriteToLog("PostgreSqlConfig: databaseHost is " & databaseHost)
|
||||
|
||||
postgreSqlDriver = "PostgreSQL Unicode(x64)"
|
||||
|
||||
Set ConnectionObject = CreateObject("ADODB.Connection")
|
||||
ConnectionObject.Open "Driver={" & postgreSqlDriver & "};Server=" & databaseHost & ";Port=" & databasePort & ";Database=" & "postgres" & ";Uid=" & "postgres" & ";Pwd=" & "postgres"
|
||||
|
||||
ConnectionObject.Execute "CREATE DATABASE " & databaseName
|
||||
ConnectionObject.Execute "create user " & databaseUserName & " with encrypted password '" & databaseUserPwd & "'"
|
||||
ConnectionObject.Execute "grant all privileges on database " & databaseName & " to " & databaseUserName
|
||||
|
||||
If Err.Number <> 0 Then
|
||||
ErrorText = Err.Description
|
||||
Pos = InStrRev( ErrorText, "]" )
|
||||
If 0 < Pos Then
|
||||
Call WriteToLog("PostgreSqlConfig: error is " & ErrorText)
|
||||
ErrorText = Right( ErrorText, Len( ErrorText ) - Pos )
|
||||
Session.Property("PostgreSqlConnectionError") = ErrorText
|
||||
|
||||
End If
|
||||
End If
|
||||
|
||||
ConnectionObject.Close
|
||||
|
||||
Set ConnectionObject = Nothing
|
||||
|
||||
End Function
|
||||
|
||||
Function RandomString( ByVal strLen )
|
||||
Dim str, min, max
|
||||
|
||||
Const LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMNOPQRSTUVWXYZ0123456789"
|
||||
min = 1
|
||||
max = Len(LETTERS)
|
||||
|
||||
Randomize
|
||||
For i = 1 to strLen
|
||||
str = str & Mid( LETTERS, Int((max-min+1)*Rnd+min), 1 )
|
||||
Next
|
||||
RandomString = str
|
||||
End Function
|
||||
|
||||
Function SetDocumentServerJWTSecretProp
|
||||
On Error Resume Next
|
||||
|
||||
Session.Property("JWT_SECRET") = RandomString( 30 )
|
||||
|
||||
End Function
|
||||
|
||||
Function MySQLConfigure
|
||||
On Error Resume Next
|
||||
|
||||
@ -28,8 +148,8 @@ Function MySQLConfigure
|
||||
Session.Property("MYSQLODBCDRIVER") = mysqlDriver
|
||||
|
||||
Set shell = CreateObject("WScript.Shell")
|
||||
dbname = Session.Property("DATABASE_PROP")
|
||||
dbpass = Session.Property("PASSWORD_PROP")
|
||||
dbname = Session.Property("DB_NAME")
|
||||
dbpass = Session.Property("DB_PWD")
|
||||
|
||||
Err.Clear
|
||||
installDir = shell.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\MySQL AB\MySQL Server 8.0\Location")
|
||||
@ -260,7 +380,7 @@ Function TestSqlConnection
|
||||
Session.Property("MYSQLODBCDRIVER") = mysqlDriver
|
||||
|
||||
Set ConnectionObject = CreateObject("ADODB.Connection")
|
||||
ConnectionObject.Open "Driver={" & mysqlDriver & "};Server=" & Session.Property("SERVER_PROP") & ";Port=" & Session.Property("PORT_PROP") & ";Uid=" & Session.Property("USERNAME_PROP") & ";Pwd=" & Session.Property("PASSWORD_PROP")
|
||||
ConnectionObject.Open "Driver={" & mysqlDriver & "};Server=" & Session.Property("DB_HOST") & ";Port=" & Session.Property("DB_PORT") & ";Uid=" & Session.Property("DB_USER") & ";Pwd=" & Session.Property("DB_PWD")
|
||||
|
||||
If Err.Number <> 0 Then
|
||||
ErrorText = Err.Description
|
||||
|
@ -91,7 +91,7 @@ public class AuditEventsRepository
|
||||
var tenant = _tenantManager.GetCurrentTenant().Id;
|
||||
using var auditTrailContext = _dbContextFactory.CreateDbContext();
|
||||
var query =
|
||||
(from q in auditTrailContext.AuditEvents
|
||||
from q in auditTrailContext.AuditEvents
|
||||
from p in auditTrailContext.Users.Where(p => q.UserId == p.Id).DefaultIfEmpty()
|
||||
where q.TenantId == tenant
|
||||
orderby q.Date descending
|
||||
@ -101,16 +101,7 @@ public class AuditEventsRepository
|
||||
FirstName = p.FirstName,
|
||||
LastName = p.LastName,
|
||||
UserName = p.UserName
|
||||
});
|
||||
|
||||
if (startIndex > 0)
|
||||
{
|
||||
query = query.Skip(startIndex);
|
||||
}
|
||||
if (limit > 0)
|
||||
{
|
||||
query = query.Take(limit);
|
||||
}
|
||||
};
|
||||
|
||||
if (userId.HasValue && userId.Value != Guid.Empty)
|
||||
{
|
||||
@ -197,6 +188,14 @@ public class AuditEventsRepository
|
||||
}
|
||||
}
|
||||
|
||||
if (startIndex > 0)
|
||||
{
|
||||
query = query.Skip(startIndex);
|
||||
}
|
||||
if (limit > 0)
|
||||
{
|
||||
query = query.Take(limit);
|
||||
}
|
||||
return _mapper.Map<List<AuditEventQuery>, IEnumerable<AuditEventDto>>(query.ToList());
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,6 @@ const StyledUserNameLink = styled.span`
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
display: inline-block;
|
||||
${(props) => props.isVisitor && "cursor: default"};
|
||||
}
|
||||
|
||||
.link {
|
||||
|
@ -3,7 +3,7 @@ import { useHistory } from "react-router-dom";
|
||||
|
||||
import Link from "@docspace/components/link";
|
||||
import { StyledUserNameLink } from "../../styles/history";
|
||||
|
||||
import Text from "@docspace/components/text";
|
||||
const HistoryBlockUser = ({ user, withComma, openUser, isVisitor }) => {
|
||||
const username = user.displayName;
|
||||
const history = useHistory();
|
||||
@ -12,13 +12,17 @@ const HistoryBlockUser = ({ user, withComma, openUser, isVisitor }) => {
|
||||
openUser(user, history);
|
||||
};
|
||||
|
||||
const onClickProp = isVisitor ? {} : { onClick: onUserClick };
|
||||
|
||||
return (
|
||||
<StyledUserNameLink key={user.id} className="user" isVisitor={isVisitor}>
|
||||
<Link className="username link" {...onClickProp}>
|
||||
{username}
|
||||
</Link>
|
||||
<StyledUserNameLink key={user.id} className="user">
|
||||
{isVisitor ? (
|
||||
<Text as="span" fontWeight={600}>
|
||||
{username}
|
||||
</Text>
|
||||
) : (
|
||||
<Link className="username link" onClick={onUserClick}>
|
||||
{username}
|
||||
</Link>
|
||||
)}
|
||||
{withComma ? "," : ""}
|
||||
{withComma && <div className="space"></div>}
|
||||
</StyledUserNameLink>
|
||||
|
@ -12,7 +12,7 @@ const User = ({
|
||||
membersHelper,
|
||||
currentMember,
|
||||
updateRoomMemberRole,
|
||||
|
||||
currCanEditUsers,
|
||||
selectionParentRoom,
|
||||
setSelectionParentRoom,
|
||||
}) => {
|
||||
@ -22,12 +22,6 @@ const User = ({
|
||||
const [userIsRemoved, setUserIsRemoved] = useState(false);
|
||||
if (userIsRemoved) return null;
|
||||
|
||||
const currCanEditUsers =
|
||||
currentMember.isOwner ||
|
||||
currentMember.isAdmin ||
|
||||
currentMember?.access === ShareAccessRights.FullAccess ||
|
||||
currentMember?.access === ShareAccessRights.RoomManager;
|
||||
|
||||
const fullRoomRoleOptions = membersHelper.getOptionsByRoomType(
|
||||
selectionParentRoom.roomType,
|
||||
currCanEditUsers
|
||||
|
@ -117,26 +117,35 @@ const Members = ({
|
||||
(member) => member.id === selfId
|
||||
);
|
||||
|
||||
const currCanEditUsers =
|
||||
currentMember.isOwner ||
|
||||
currentMember.isAdmin ||
|
||||
currentMember?.access === ShareAccessRights.FullAccess ||
|
||||
currentMember?.access === ShareAccessRights.RoomManager;
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledUserTypeHeader>
|
||||
<Text className="title">
|
||||
{t("UsersInRoom")} : {members.inRoom.length}
|
||||
</Text>
|
||||
<IconButton
|
||||
className={"icon"}
|
||||
title={t("Common:AddUsers")}
|
||||
iconName="/static/images/person+.react.svg"
|
||||
isFill={true}
|
||||
onClick={onClickInviteUsers}
|
||||
size={16}
|
||||
isDisabled={isDisabledInvite}
|
||||
/>
|
||||
{currCanEditUsers && (
|
||||
<IconButton
|
||||
className={"icon"}
|
||||
title={t("Common:AddUsers")}
|
||||
iconName="/static/images/person+.react.svg"
|
||||
isFill={true}
|
||||
onClick={onClickInviteUsers}
|
||||
size={16}
|
||||
isDisabled={isDisabledInvite}
|
||||
/>
|
||||
)}
|
||||
</StyledUserTypeHeader>
|
||||
|
||||
<StyledUserList>
|
||||
{Object.values(members.inRoom).map((user) => (
|
||||
<User
|
||||
currCanEditUsers={currCanEditUsers}
|
||||
key={user.id}
|
||||
t={t}
|
||||
user={user}
|
||||
@ -154,14 +163,16 @@ const Members = ({
|
||||
{!!members.expected.length && (
|
||||
<StyledUserTypeHeader isExpect>
|
||||
<Text className="title">{t("ExpectPeople")}</Text>
|
||||
<IconButton
|
||||
className={"icon"}
|
||||
title={t("Repeat invitation")}
|
||||
iconName="/static/images/e-mail+.react.svg"
|
||||
isFill={true}
|
||||
onClick={onRepeatInvitation}
|
||||
size={16}
|
||||
/>
|
||||
{currCanEditUsers && (
|
||||
<IconButton
|
||||
className={"icon"}
|
||||
title={t("Repeat invitation")}
|
||||
iconName="/static/images/e-mail+.react.svg"
|
||||
isFill={true}
|
||||
onClick={onRepeatInvitation}
|
||||
size={16}
|
||||
/>
|
||||
)}
|
||||
</StyledUserTypeHeader>
|
||||
)}
|
||||
|
||||
|
@ -105,16 +105,6 @@ const FilesRowContent = ({
|
||||
isRoom,
|
||||
} = item;
|
||||
|
||||
let tags = null;
|
||||
|
||||
if (isRoom) {
|
||||
if (item.tags.length > 0) {
|
||||
tags = item?.tags.join(" | ");
|
||||
} else {
|
||||
tags = t(RoomsTypeTranslations[item.roomType]);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<SimpleFilesRowContent
|
||||
@ -139,18 +129,18 @@ const FilesRowContent = ({
|
||||
{badgesComponent}
|
||||
{!isRoom && !isRooms && quickButtons}
|
||||
</div>
|
||||
{!isRoom && (
|
||||
<Text
|
||||
containerMinWidth="200px"
|
||||
containerWidth="15%"
|
||||
fontSize="12px"
|
||||
fontWeight={400}
|
||||
// color={sideColor}
|
||||
className="row_update-text"
|
||||
>
|
||||
{updatedDate && updatedDate}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<Text
|
||||
containerMinWidth="200px"
|
||||
containerWidth="15%"
|
||||
fontSize="12px"
|
||||
fontWeight={400}
|
||||
// color={sideColor}
|
||||
className="row_update-text"
|
||||
>
|
||||
{updatedDate && updatedDate}
|
||||
</Text>
|
||||
|
||||
<Text
|
||||
containerMinWidth="90px"
|
||||
containerWidth="10%"
|
||||
@ -162,7 +152,7 @@ const FilesRowContent = ({
|
||||
truncate={true}
|
||||
>
|
||||
{isRooms
|
||||
? tags
|
||||
? t(RoomsTypeTranslations[item.roomType])
|
||||
: !fileExst && !contentLength && !providerKey && !isMobileOnly
|
||||
? `${foldersCount} ${t("Translations:Folders")} | ${filesCount} ${t(
|
||||
"Translations:Files"
|
||||
|
@ -1 +0,0 @@
|
||||
export { default as TrashIcon } from "./trash.react.svg";
|
@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import styled from "styled-components";
|
||||
import commonIconsStyles from "@docspace/components/utils/common-icons-style";
|
||||
import { TrashIcon } from "./svg";
|
||||
import TrashIcon from "PUBLIC_DIR/images/trash.react.svg";
|
||||
import PlusIcon from "@docspace/client/public/images/plus.react.svg";
|
||||
import Link from "@docspace/components/link";
|
||||
import TextInput from "@docspace/components/text-input";
|
||||
|
@ -1559,6 +1559,22 @@ class FilesActionStore {
|
||||
const deleteOption = this.getOption("delete-room", t);
|
||||
const showOption = this.getOption("show-info", t);
|
||||
|
||||
const { selection } = this.filesStore;
|
||||
const { canArchiveRoom } = this.accessRightsStore;
|
||||
|
||||
const canArchive = selection.map((s) => canArchiveRoom(s)).filter((s) => s);
|
||||
|
||||
if (canArchive.length <= 0) {
|
||||
let pinName = "unpin";
|
||||
|
||||
selection.forEach((item) => {
|
||||
if (!item.pinned) pinName = "pin";
|
||||
});
|
||||
|
||||
const pin = this.getOption(pinName, t);
|
||||
itemsCollection.set(pinName, pin);
|
||||
}
|
||||
|
||||
itemsCollection
|
||||
.set("unarchive", archive)
|
||||
.set("show-info", showOption)
|
||||
|
@ -1414,15 +1414,24 @@ class FilesStore {
|
||||
}
|
||||
|
||||
if (isArchiveFolder) {
|
||||
roomOptions = this.removeOptions(roomOptions, [
|
||||
"edit-room",
|
||||
"invite-users-to-room",
|
||||
"pin-room",
|
||||
"unpin-room",
|
||||
"archive-room",
|
||||
"separator1",
|
||||
"room-info",
|
||||
]);
|
||||
if (!canArchive) {
|
||||
roomOptions = this.removeOptions(roomOptions, [
|
||||
"edit-room",
|
||||
"invite-users-to-room",
|
||||
"archive-room",
|
||||
"separator1",
|
||||
]);
|
||||
} else {
|
||||
roomOptions = this.removeOptions(roomOptions, [
|
||||
"edit-room",
|
||||
"invite-users-to-room",
|
||||
"pin-room",
|
||||
"unpin-room",
|
||||
"archive-room",
|
||||
"separator1",
|
||||
"room-info",
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
roomOptions = this.removeOptions(roomOptions, [
|
||||
"delete",
|
||||
|
@ -137,7 +137,7 @@ class InfoPanelStore {
|
||||
if (!this.getIsRooms) return;
|
||||
|
||||
const currentFolderRoomId = this.selectedFolderStore.pathParts[1];
|
||||
const prevRoomId = selectionParentRoom?.id;
|
||||
const prevRoomId = this.selectionParentRoom?.id;
|
||||
|
||||
if (!currentFolderRoomId || currentFolderRoomId === prevRoomId) return;
|
||||
|
||||
|
@ -39,9 +39,7 @@ const sideInfoTabletStyle = css`
|
||||
margin: ${(props) => props.theme.rowContent.sideInfo.margin};
|
||||
${commonCss};
|
||||
color: ${(props) => props.color && props.color};
|
||||
white-space: nowrap;
|
||||
overflow: ${(props) => props.theme.rowContent.sideInfo.overflow};
|
||||
text-overflow: ${(props) => props.theme.rowContent.sideInfo.textOverflow};
|
||||
${truncateCss};
|
||||
`;
|
||||
|
||||
const StyledRowContent = styled.div`
|
||||
@ -88,6 +86,7 @@ const MainContainerWrapper = styled.div`
|
||||
${mainWrapperTabletStyle}
|
||||
}
|
||||
`;
|
||||
|
||||
MainContainerWrapper.defaultProps = { theme: Base };
|
||||
|
||||
const MainContainer = styled.div`
|
||||
|
@ -1,142 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import ModalDialog from "@appserver/components/modal-dialog";
|
||||
import Button from "@appserver/components/button";
|
||||
|
||||
import TagHandler from "./handlers/tagHandler";
|
||||
|
||||
import SetRoomParams from "./sub-components/SetRoomParams";
|
||||
import RoomTypeList from "./sub-components/RoomTypeList";
|
||||
import { roomTypes } from "./data";
|
||||
import IconButton from "@appserver/components/icon-button";
|
||||
|
||||
const StyledModalDialog = styled(ModalDialog)`
|
||||
.header-with-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
gap: 12px;
|
||||
}
|
||||
`;
|
||||
|
||||
const CreateRoomDialog = ({
|
||||
t,
|
||||
visible,
|
||||
onClose,
|
||||
onCreate,
|
||||
|
||||
fetchedTags,
|
||||
isLoading,
|
||||
folderFormValidation,
|
||||
}) => {
|
||||
const [isScrollLocked, setIsScrollLocked] = useState(false);
|
||||
|
||||
const [roomParams, setRoomParams] = useState({
|
||||
title: "",
|
||||
type: undefined,
|
||||
tags: [],
|
||||
isPrivate: false,
|
||||
storageLocation: undefined,
|
||||
rememberStorageLocation: false,
|
||||
thirdpartyFolderName: "",
|
||||
icon: "",
|
||||
});
|
||||
|
||||
const setRoomTags = (newTags) =>
|
||||
setRoomParams({ ...roomParams, tags: newTags });
|
||||
|
||||
const tagHandler = new TagHandler(roomParams.tags, setRoomTags, fetchedTags);
|
||||
|
||||
const setRoomType = (newRoomType) => {
|
||||
const [roomByType] = roomTypes.filter((room) => room.type === newRoomType);
|
||||
tagHandler.refreshDefaultTag(t(roomByType.title));
|
||||
setRoomParams((prev) => ({
|
||||
...prev,
|
||||
type: newRoomType,
|
||||
}));
|
||||
};
|
||||
|
||||
const onCreateRoom = () => {
|
||||
onCreate(roomParams);
|
||||
};
|
||||
|
||||
const isChooseRoomType = roomParams.type === undefined;
|
||||
const goBack = () => {
|
||||
setRoomParams({
|
||||
title: "",
|
||||
type: undefined,
|
||||
tags: [],
|
||||
isPrivate: false,
|
||||
storageLocation: undefined,
|
||||
rememberStorageLocation: false,
|
||||
thirdpartyFolderName: "",
|
||||
icon: "",
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledModalDialog
|
||||
displayType="aside"
|
||||
withBodyScroll
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
isScrollLocked={isScrollLocked}
|
||||
withFooterBorder
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
{isChooseRoomType ? (
|
||||
t("ChooseRoomType")
|
||||
) : (
|
||||
<div className="header-with-button">
|
||||
<IconButton
|
||||
size="15px"
|
||||
iconName="/static/images/arrow.path.react.svg"
|
||||
className="sharing_panel-arrow"
|
||||
onClick={goBack}
|
||||
/>
|
||||
<div>{t("CreateRoom")}</div>
|
||||
</div>
|
||||
)}
|
||||
</ModalDialog.Header>
|
||||
|
||||
<ModalDialog.Body>
|
||||
{isChooseRoomType ? (
|
||||
<RoomTypeList t={t} setRoomType={setRoomType} />
|
||||
) : (
|
||||
<SetRoomParams
|
||||
t={t}
|
||||
tagHandler={tagHandler}
|
||||
roomParams={roomParams}
|
||||
setRoomParams={setRoomParams}
|
||||
setRoomType={setRoomType}
|
||||
setIsScrollLocked={setIsScrollLocked}
|
||||
/>
|
||||
)}
|
||||
</ModalDialog.Body>
|
||||
|
||||
{!isChooseRoomType && (
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
tabIndex={5}
|
||||
label={t("Common:Create")}
|
||||
size="normal"
|
||||
primary
|
||||
scale
|
||||
onClick={onCreateRoom}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<Button
|
||||
tabIndex={5}
|
||||
label={t("Common:CancelButton")}
|
||||
size="normal"
|
||||
scale
|
||||
onClick={onClose}
|
||||
/>
|
||||
</ModalDialog.Footer>
|
||||
)}
|
||||
</StyledModalDialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateRoomDialog;
|
@ -1,95 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import ModalDialog from "@appserver/components/modal-dialog";
|
||||
import Button from "@appserver/components/button";
|
||||
|
||||
import TagHandler from "./handlers/tagHandler";
|
||||
import { roomTypes } from "./data";
|
||||
|
||||
import SetRoomParams from "./sub-components/SetRoomParams";
|
||||
|
||||
const EditRoomDialog = ({
|
||||
t,
|
||||
visible,
|
||||
onClose,
|
||||
onSave,
|
||||
isLoading,
|
||||
fetchedRoomParams,
|
||||
fetchedTags,
|
||||
folderFormValidation,
|
||||
}) => {
|
||||
const [isScrollLocked, setIsScrollLocked] = useState(false);
|
||||
|
||||
const [roomParams, setRoomParams] = useState({
|
||||
...fetchedRoomParams,
|
||||
// cant fetch
|
||||
isPrivate: false,
|
||||
storageLocation: undefined,
|
||||
rememberStorageLocation: false,
|
||||
thirdpartyFolderName: "",
|
||||
});
|
||||
|
||||
const setRoomTags = (newTags) =>
|
||||
setRoomParams({ ...roomParams, tags: newTags });
|
||||
|
||||
const tagHandler = new TagHandler(roomParams.tags, setRoomTags, fetchedTags);
|
||||
|
||||
const setRoomType = (newRoomType) => {
|
||||
const [roomByType] = roomTypes.filter((room) => room.type === newRoomType);
|
||||
tagHandler.refreshDefaultTag(t(roomByType.title));
|
||||
setRoomParams((prev) => ({
|
||||
...prev,
|
||||
type: newRoomType,
|
||||
}));
|
||||
};
|
||||
|
||||
const onEditRoom = () => {
|
||||
onSave(roomParams);
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalDialog
|
||||
displayType="aside"
|
||||
withBodyScroll
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
isScrollLocked={isScrollLocked}
|
||||
withFooterBorder
|
||||
>
|
||||
<ModalDialog.Header>{t("RoomEditing")}</ModalDialog.Header>
|
||||
|
||||
<ModalDialog.Body>
|
||||
<SetRoomParams
|
||||
t={t}
|
||||
tagHandler={tagHandler}
|
||||
roomParams={roomParams}
|
||||
setRoomParams={setRoomParams}
|
||||
setRoomType={setRoomType}
|
||||
setIsScrollLocked={setIsScrollLocked}
|
||||
isEdit
|
||||
/>
|
||||
</ModalDialog.Body>
|
||||
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
tabIndex={5}
|
||||
label={t("Common:SaveButton")}
|
||||
size="normal"
|
||||
primary
|
||||
scale
|
||||
onClick={onEditRoom}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<Button
|
||||
tabIndex={5}
|
||||
label={t("Common:CancelButton")}
|
||||
size="normal"
|
||||
scale
|
||||
onClick={onClose}
|
||||
/>
|
||||
</ModalDialog.Footer>
|
||||
</ModalDialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditRoomDialog;
|
@ -1,61 +0,0 @@
|
||||
import { RoomsType } from "@appserver/common/constants";
|
||||
|
||||
export const roomTypes = [
|
||||
{
|
||||
type: RoomsType.FillingFormsRoom,
|
||||
title: "FillingFormsRoomTitle",
|
||||
description: "FillingFormsRoomDescription",
|
||||
withSecondaryInfo: true,
|
||||
},
|
||||
{
|
||||
type: RoomsType.EditingRoom,
|
||||
title: "CollaborationRoomTitle",
|
||||
description: "CollaborationRoomDescription",
|
||||
withSecondaryInfo: true,
|
||||
},
|
||||
{
|
||||
type: RoomsType.ReviewRoom,
|
||||
title: "ReviewRoomTitle",
|
||||
description: "ReviewRoomDescription",
|
||||
withSecondaryInfo: true,
|
||||
},
|
||||
{
|
||||
type: RoomsType.ReadOnlyRoom,
|
||||
title: "ViewOnlyRoomTitle",
|
||||
description: "ViewOnlyRoomDescription",
|
||||
withSecondaryInfo: true,
|
||||
},
|
||||
{
|
||||
type: RoomsType.CustomRoom,
|
||||
title: "CustomRoomTitle",
|
||||
description: "CustomRoomDescription",
|
||||
withSecondaryInfo: false,
|
||||
},
|
||||
];
|
||||
|
||||
export const thirparties = [
|
||||
{
|
||||
id: 1,
|
||||
title: "Onlyoffice DocSpace",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "DropBox",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "Google Drive",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: "OneDrive",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: "Nextcloud",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
title: "Yandex Disk",
|
||||
},
|
||||
];
|
@ -1,49 +0,0 @@
|
||||
class TagHandler {
|
||||
constructor(tags, setTags, fetchedTags) {
|
||||
this.tags = tags;
|
||||
this.setTags = setTags;
|
||||
this.fetchedTags = fetchedTags;
|
||||
}
|
||||
|
||||
createRandomTagId() {
|
||||
return "_" + Math.random().toString(36).substr(2, 9);
|
||||
}
|
||||
|
||||
refreshDefaultTag(name) {
|
||||
let newTags = [...this.tags].filter((tag) => !tag.isDefault);
|
||||
newTags.unshift({
|
||||
id: this.createRandomTagId(),
|
||||
name,
|
||||
isDefault: true,
|
||||
});
|
||||
|
||||
this.setTags(newTags);
|
||||
}
|
||||
|
||||
addTag(name) {
|
||||
let newTags = [...this.tags];
|
||||
newTags.push({
|
||||
id: this.createRandomTagId(),
|
||||
name,
|
||||
});
|
||||
this.setTags(newTags);
|
||||
}
|
||||
|
||||
addNewTag(name) {
|
||||
let newTags = [...this.tags];
|
||||
newTags.push({
|
||||
id: this.createRandomTagId(),
|
||||
isNew: true,
|
||||
name,
|
||||
});
|
||||
this.setTags(newTags);
|
||||
}
|
||||
|
||||
deleteTag(id) {
|
||||
let newTags = [...this.tags];
|
||||
newTags = newTags.filter((tag) => tag.id !== id);
|
||||
this.setTags(newTags);
|
||||
}
|
||||
}
|
||||
|
||||
export default TagHandler;
|
@ -1,177 +0,0 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import styled from "styled-components";
|
||||
|
||||
import IconButton from "@appserver/components/icon-button";
|
||||
import Text from "@appserver/components/text";
|
||||
import RoomLogo from "@appserver/components/room-logo";
|
||||
import HelpButton from "@appserver/components/help-button";
|
||||
|
||||
const StyledRoomType = styled.div`
|
||||
cursor: pointer;
|
||||
padding: 16px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
|
||||
.choose_room-logo_wrapper {
|
||||
width: 32px;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
.choose_room-info_wrapper {
|
||||
.choose_room-title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
.choose_room-title-text {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
}
|
||||
.choose_room-title-info_button {
|
||||
border-radius: 50%;
|
||||
background-color: #a3a9ae;
|
||||
circle,
|
||||
rect {
|
||||
fill: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.choose_room-description {
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
color: #a3a9ae;
|
||||
}
|
||||
}
|
||||
|
||||
.choose_room-forward_btn {
|
||||
margin-left: auto;
|
||||
max-width: 17px;
|
||||
max-height: 17px;
|
||||
min-width: 17px;
|
||||
min-height: 17px;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledDisplayItem = styled(StyledRoomType)`
|
||||
background-color: #f8f8f8;
|
||||
border: 1px solid #f8f8f8;
|
||||
border-radius: 6px;
|
||||
|
||||
.choose_room-forward_btn {
|
||||
display: none;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledListItem = styled(StyledRoomType)`
|
||||
background-color: #ffffff;
|
||||
border: 1px solid ${(props) => (props.isOpen ? "#2DA7DB" : "#ECEEF1")};
|
||||
border-radius: 6px;
|
||||
`;
|
||||
|
||||
const StyledDropdownButton = styled(StyledRoomType)`
|
||||
background-color: #ffffff;
|
||||
border-radius: 6px;
|
||||
border: 1px solid ${(props) => (props.isOpen ? "#2DA7DB" : "#ECEEF1")};
|
||||
|
||||
.choose_room-forward_btn {
|
||||
&.dropdown-button {
|
||||
transform: ${(props) =>
|
||||
props.isOpen ? "rotate(-90deg)" : "rotate(90deg)"};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledDropdownItem = styled(StyledRoomType)`
|
||||
&:hover {
|
||||
background-color: #f3f4f4;
|
||||
}
|
||||
.choose_room-forward_btn {
|
||||
display: none;
|
||||
}
|
||||
`;
|
||||
|
||||
const RoomType = ({ t, room, onClick, type = "listItem", isOpen }) => {
|
||||
const arrowClassName =
|
||||
type === "dropdownButton"
|
||||
? "choose_room-forward_btn dropdown-button"
|
||||
: type === "dropdownItem"
|
||||
? "choose_room-forward_btn dropdown-item"
|
||||
: "choose_room-forward_btn";
|
||||
|
||||
const onSecondaryInfoClick = (e) => {
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const content = (
|
||||
<>
|
||||
<div className="choose_room-logo_wrapper">
|
||||
<RoomLogo type={room.type} />
|
||||
</div>
|
||||
|
||||
<div className="choose_room-info_wrapper">
|
||||
<div className="choose_room-title">
|
||||
<Text noSelect className="choose_room-title-text">
|
||||
{t(room.title)}
|
||||
</Text>
|
||||
{room.withSecondaryInfo && (
|
||||
<div onClick={onSecondaryInfoClick}>
|
||||
<HelpButton
|
||||
displayType="auto"
|
||||
className="choose_room-title-info_button"
|
||||
iconName="/static/images/info.react.svg"
|
||||
offsetRight={0}
|
||||
tooltipContent={isOpen ? t(room.description) : null}
|
||||
size={12}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Text noSelect className="choose_room-description">
|
||||
{t(room.description)}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<IconButton
|
||||
className={arrowClassName}
|
||||
iconName="images/arrow.react.svg"
|
||||
size={16}
|
||||
onClick={() => {}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
return type === "listItem" ? (
|
||||
<StyledListItem onClick={onClick}>{content}</StyledListItem>
|
||||
) : type === "dropdownButton" ? (
|
||||
<StyledDropdownButton onClick={onClick} isOpen={isOpen}>
|
||||
{content}
|
||||
</StyledDropdownButton>
|
||||
) : type === "dropdownItem" ? (
|
||||
<StyledDropdownItem onClick={onClick} isOpen={isOpen}>
|
||||
{content}
|
||||
</StyledDropdownItem>
|
||||
) : (
|
||||
<StyledDisplayItem>{content}</StyledDisplayItem>
|
||||
);
|
||||
};
|
||||
|
||||
RoomType.propTypes = {
|
||||
room: PropTypes.object,
|
||||
onClick: PropTypes.func,
|
||||
type: PropTypes.oneOf([
|
||||
"displayItem",
|
||||
"listItem",
|
||||
"dropdownButton",
|
||||
"dropdownItem",
|
||||
]),
|
||||
isOpen: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default RoomType;
|
@ -1,70 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
import styled from "styled-components";
|
||||
import { roomTypes } from "../data";
|
||||
import RoomType from "./RoomType";
|
||||
|
||||
const StyledRoomTypeDropdown = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
|
||||
.dropdown-content-wrapper {
|
||||
max-width: 100%;
|
||||
position: relative;
|
||||
background: #ffffff;
|
||||
${(props) => !props.isOpen && "display: none"};
|
||||
|
||||
.dropdown-content {
|
||||
margin-top: 4px;
|
||||
background: #ffffff;
|
||||
overflow: visible;
|
||||
z-index: 400;
|
||||
top: 0;
|
||||
left: 0;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 6px 0;
|
||||
border: 1px solid #d0d5da;
|
||||
box-shadow: 0px 12px 40px rgba(4, 15, 27, 0.12);
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const RoomTypeDropdown = ({ t, currentRoom, setRoomType }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const toggleIsOpen = () => setIsOpen(!isOpen);
|
||||
|
||||
return (
|
||||
<StyledRoomTypeDropdown isOpen={isOpen}>
|
||||
<RoomType
|
||||
t={t}
|
||||
room={currentRoom}
|
||||
type="dropdownButton"
|
||||
isOpen={isOpen}
|
||||
onClick={toggleIsOpen}
|
||||
/>
|
||||
<div className="dropdown-content-wrapper">
|
||||
<div className="dropdown-content">
|
||||
{roomTypes.map((room) => (
|
||||
<RoomType
|
||||
t={t}
|
||||
key={room.type}
|
||||
room={room}
|
||||
type="dropdownItem"
|
||||
onClick={() => {
|
||||
setRoomType(room.type);
|
||||
toggleIsOpen();
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</StyledRoomTypeDropdown>
|
||||
);
|
||||
};
|
||||
|
||||
export default RoomTypeDropdown;
|
@ -1,31 +0,0 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { roomTypes } from "../data";
|
||||
|
||||
import RoomType from "./RoomType";
|
||||
|
||||
const StyledRoomTypeList = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
`;
|
||||
|
||||
const RoomTypeList = ({ t, setRoomType }) => {
|
||||
return (
|
||||
<StyledRoomTypeList>
|
||||
{roomTypes.map((room) => (
|
||||
<RoomType
|
||||
t={t}
|
||||
key={room.type}
|
||||
room={room}
|
||||
type={"listItem"}
|
||||
onClick={() => setRoomType(room.type)}
|
||||
/>
|
||||
))}
|
||||
</StyledRoomTypeList>
|
||||
);
|
||||
};
|
||||
|
||||
export default RoomTypeList;
|
@ -1,165 +0,0 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import RoomTypeDropdown from "./RoomTypeDropdown";
|
||||
import StorageLocation from "./StorageLocation";
|
||||
|
||||
import TextInput from "@appserver/components/text-input";
|
||||
import Label from "@appserver/components/label";
|
||||
import ToggleButton from "@appserver/components/toggle-button";
|
||||
import HelpButton from "@appserver/components/help-button";
|
||||
import Text from "@appserver/components/text";
|
||||
import AvatarEditor from "@appserver/components/avatar-editor";
|
||||
import TagInput from "./TagInput";
|
||||
import { StyledParam } from "./StyledParam";
|
||||
import RoomType from "./RoomType";
|
||||
import { roomTypes } from "../data";
|
||||
|
||||
const StyledSetRoomParams = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: 20px;
|
||||
|
||||
.set_room_params-input {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledIconEditorWrapper = styled.div`
|
||||
.use_modal-avatar_editor_body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.use_modal-buttons_wrapper {
|
||||
display: none;
|
||||
}
|
||||
`;
|
||||
|
||||
const SetRoomParams = ({
|
||||
t,
|
||||
roomParams,
|
||||
setRoomParams,
|
||||
setRoomType,
|
||||
tagHandler,
|
||||
setIsScrollLocked,
|
||||
isEdit,
|
||||
}) => {
|
||||
const onChangeName = (e) =>
|
||||
setRoomParams({ ...roomParams, title: e.target.value });
|
||||
|
||||
const onChangeIsPrivate = () =>
|
||||
setRoomParams({ ...roomParams, isPrivate: !roomParams.isPrivate });
|
||||
|
||||
const onChangeThidpartyFolderName = (e) =>
|
||||
setRoomParams({ ...roomParams, thirdpartyFolderName: e.target.value });
|
||||
|
||||
const [currentRoomTypeData] = roomTypes.filter(
|
||||
(room) => room.type === roomParams.type
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledSetRoomParams>
|
||||
{isEdit ? (
|
||||
<RoomType t={t} room={currentRoomTypeData} type="displayItem" />
|
||||
) : (
|
||||
<RoomTypeDropdown
|
||||
t={t}
|
||||
currentRoom={currentRoomTypeData}
|
||||
setRoomType={setRoomType}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="set_room_params-input">
|
||||
<Label
|
||||
display="display"
|
||||
htmlFor="room-name"
|
||||
text={`${t("Common:Name")}:`}
|
||||
title="Fill the first name field"
|
||||
/>
|
||||
<TextInput
|
||||
id="room-name"
|
||||
value={roomParams.title}
|
||||
onChange={onChangeName}
|
||||
scale
|
||||
placeholder={t("NamePlaceholder")}
|
||||
tabIndex={1}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<TagInput
|
||||
t={t}
|
||||
tagHandler={tagHandler}
|
||||
setIsScrollLocked={setIsScrollLocked}
|
||||
/>
|
||||
|
||||
<StyledParam isPrivate>
|
||||
<div className="set_room_params-info">
|
||||
<div className="set_room_params-info-title">
|
||||
<Text className="set_room_params-info-title-text">
|
||||
{t("MakeRoomPrivateTitle")}
|
||||
</Text>
|
||||
<HelpButton
|
||||
displayType="auto"
|
||||
className="set_room_params-info-title-help"
|
||||
iconName="/static/images/info.react.svg"
|
||||
offsetRight={0}
|
||||
tooltipContent={t("MakeRoomPrivateDescription")}
|
||||
size={12}
|
||||
/>
|
||||
</div>
|
||||
<div className="set_room_params-info-description">
|
||||
{t("MakeRoomPrivateDescription")}
|
||||
</div>
|
||||
</div>
|
||||
<ToggleButton
|
||||
className="set_room_params-toggle"
|
||||
isChecked={roomParams.isPrivate}
|
||||
onChange={onChangeIsPrivate}
|
||||
/>
|
||||
</StyledParam>
|
||||
|
||||
<StorageLocation
|
||||
t={t}
|
||||
roomParams={roomParams}
|
||||
setRoomParams={setRoomParams}
|
||||
setIsScrollLocked={setIsScrollLocked}
|
||||
/>
|
||||
|
||||
<StyledParam folderName>
|
||||
<div className="set_room_params-info">
|
||||
<div className="set_room_params-info-title">
|
||||
<Text className="set_room_params-info-title-text">
|
||||
{`${t("FolderNameTitle")}:`}
|
||||
</Text>
|
||||
</div>
|
||||
<div className="set_room_params-info-description">
|
||||
{t("FolderNameDescription")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="set_room_params-input">
|
||||
<TextInput
|
||||
id="room-folder-title"
|
||||
scale
|
||||
value={roomParams.thirdpartyFolderName}
|
||||
onChange={onChangeThidpartyFolderName}
|
||||
placeholder={`${
|
||||
roomParams.storageLocation
|
||||
? roomParams.storageLocation.title + " - "
|
||||
: ""
|
||||
}${t("Home:NewRoom")}`}
|
||||
tabIndex={1}
|
||||
/>
|
||||
</div>
|
||||
</StyledParam>
|
||||
|
||||
{/* <StyledIconEditorWrapper>
|
||||
<AvatarEditor useModalDialog={false}></AvatarEditor>
|
||||
</StyledIconEditorWrapper> */}
|
||||
</StyledSetRoomParams>
|
||||
);
|
||||
};
|
||||
|
||||
export default SetRoomParams;
|
@ -1,184 +0,0 @@
|
||||
import React, { useState, useRef } from "react";
|
||||
import styled from "styled-components";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
import { thirparties } from "../../data";
|
||||
import { StyledDropDown, StyledDropDownWrapper } from "../StyledDropdown";
|
||||
|
||||
import { isHugeMobile } from "@appserver/components/utils/device";
|
||||
import DomHelpers from "@appserver/components/utils/domHelpers";
|
||||
|
||||
import Text from "@appserver/components/text";
|
||||
import Button from "@appserver/components/button";
|
||||
import DropDownItem from "@appserver/components/drop-down-item";
|
||||
import Checkbox from "@appserver/components/checkbox";
|
||||
|
||||
const StyledStorageLocation = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.set_room_params-thirdparty {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 8px;
|
||||
&-combobox {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
padding: 5px 7px;
|
||||
background: #ffffff;
|
||||
border-radius: 3px;
|
||||
max-height: 32px;
|
||||
|
||||
border: ${(props) => `1px solid ${props.isOpen ? "#2DA7DB" : "#d0d5da"}`};
|
||||
&:hover {
|
||||
border: ${(props) =>
|
||||
`1px solid ${props.isOpen ? "#2DA7DB" : "#a3a9ae"}`};
|
||||
}
|
||||
|
||||
&-text {
|
||||
font-weight: 400;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
color: ${(props) => (props.isGrayLabel ? "#a3a9ae" : "#333333")};
|
||||
}
|
||||
|
||||
&-expander {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 6.35px;
|
||||
svg {
|
||||
transform: ${(props) =>
|
||||
props.isOpen ? "rotate(180deg)" : "rotate(0)"};
|
||||
width: 6.35px;
|
||||
height: auto;
|
||||
path {
|
||||
fill: #a3a9ae;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-checkbox {
|
||||
margin-top: 8px;
|
||||
.checkbox {
|
||||
margin-right: 8px;
|
||||
}
|
||||
.checkbox-text {
|
||||
font-weight: 400;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const ThirpartyComboBox = ({
|
||||
t,
|
||||
roomParams,
|
||||
setRoomParams,
|
||||
setIsScrollLocked,
|
||||
}) => {
|
||||
const dropdownRef = useRef(null);
|
||||
const [isGrayLabel, setIsGrayLabel] = useState(true);
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const toggleIsOpen = () => {
|
||||
if (isOpen) setIsScrollLocked(false);
|
||||
else {
|
||||
setIsScrollLocked(true);
|
||||
calculateDropdownDirection();
|
||||
}
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
||||
const [dropdownDirection, setDropdownDirection] = useState("bottom");
|
||||
|
||||
const setStorageLocaiton = (thirparty) => {
|
||||
setIsGrayLabel(false);
|
||||
setRoomParams({ ...roomParams, storageLocation: thirparty });
|
||||
setIsOpen(false);
|
||||
setIsScrollLocked(false);
|
||||
};
|
||||
|
||||
const setRememberStorageLocation = () =>
|
||||
setRoomParams({
|
||||
...roomParams,
|
||||
rememberStorageLocation: !roomParams.rememberStorageLocation,
|
||||
});
|
||||
|
||||
const calculateDropdownDirection = () => {
|
||||
const { top: offsetTop } = DomHelpers.getOffset(dropdownRef.current);
|
||||
const offsetBottom = window.innerHeight - offsetTop;
|
||||
|
||||
const neededHeightDesktop = Math.min(thirparties.length * 32 + 16, 404);
|
||||
const neededHeightMobile = Math.min(thirparties.length * 32 + 16, 180);
|
||||
const neededheight = isHugeMobile()
|
||||
? neededHeightMobile
|
||||
: neededHeightDesktop;
|
||||
|
||||
setDropdownDirection(neededheight > offsetBottom ? "top" : "bottom");
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledStorageLocation isGrayLabel={isGrayLabel} isOpen={isOpen}>
|
||||
<div className="set_room_params-thirdparty">
|
||||
<div
|
||||
className="set_room_params-thirdparty-combobox"
|
||||
onClick={toggleIsOpen}
|
||||
>
|
||||
<Text className="set_room_params-thirdparty-combobox-text" noSelect>
|
||||
{roomParams.storageLocation?.title || "Select"}
|
||||
</Text>
|
||||
<ReactSVG
|
||||
className="set_room_params-thirdparty-combobox-expander"
|
||||
src={"/static/images/expander-down.react.svg"}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className="set_room_params-thirdparty-connect"
|
||||
size="small"
|
||||
label={t("Common:Connect")}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<StyledDropDownWrapper
|
||||
className="dropdown-content-wrapper"
|
||||
ref={dropdownRef}
|
||||
>
|
||||
<StyledDropDown
|
||||
className="dropdown-content"
|
||||
open={isOpen}
|
||||
forwardedRef={dropdownRef}
|
||||
clickOutsideAction={toggleIsOpen}
|
||||
maxHeight={isHugeMobile() ? 158 : 382}
|
||||
directionY={dropdownDirection}
|
||||
marginTop={dropdownDirection === "bottom" ? "4px" : "-36px"}
|
||||
>
|
||||
{thirparties.map((thirdparty) => (
|
||||
<DropDownItem
|
||||
className="dropdown-item"
|
||||
label={thirdparty.title}
|
||||
key={thirdparty.id}
|
||||
height={32}
|
||||
heightTablet={32}
|
||||
onClick={() => setStorageLocaiton(thirdparty)}
|
||||
/>
|
||||
))}
|
||||
</StyledDropDown>
|
||||
</StyledDropDownWrapper>
|
||||
|
||||
<Checkbox
|
||||
className="set_room_params-thirdparty-checkbox"
|
||||
label={t("StorageLocationRememberChoice")}
|
||||
isChecked={roomParams.rememberStorageLocation}
|
||||
onChange={setRememberStorageLocation}
|
||||
/>
|
||||
</StyledStorageLocation>
|
||||
);
|
||||
};
|
||||
|
||||
export default ThirpartyComboBox;
|
@ -1,47 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
import Text from "@appserver/components/text";
|
||||
|
||||
import Checkbox from "@appserver/components/checkbox";
|
||||
import { StyledParam } from "../StyledParam";
|
||||
import HelpButton from "@appserver/components/help-button";
|
||||
import ThirpartyComboBox from "./ThirpartyComboBox";
|
||||
|
||||
const StorageLocation = ({
|
||||
t,
|
||||
roomParams,
|
||||
setRoomParams,
|
||||
setIsScrollLocked,
|
||||
}) => {
|
||||
return (
|
||||
<StyledParam storageLocation>
|
||||
<div className="set_room_params-info">
|
||||
<div className="set_room_params-info-title">
|
||||
<Text className="set_room_params-info-title-text">
|
||||
{t("StorageLocationTitle")}
|
||||
</Text>
|
||||
<HelpButton
|
||||
displayType="auto"
|
||||
className="set_room_params-info-title-help"
|
||||
iconName="/static/images/info.react.svg"
|
||||
offsetRight={0}
|
||||
tooltipContent={t("StorageLocationDescription")}
|
||||
size={12}
|
||||
/>
|
||||
</div>
|
||||
<div className="set_room_params-info-description">
|
||||
{t("StorageLocationDescription")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ThirpartyComboBox
|
||||
t={t}
|
||||
roomParams={roomParams}
|
||||
setRoomParams={setRoomParams}
|
||||
setIsScrollLocked={setIsScrollLocked}
|
||||
/>
|
||||
</StyledParam>
|
||||
);
|
||||
};
|
||||
|
||||
export default StorageLocation;
|
@ -1,57 +0,0 @@
|
||||
import styled from "styled-components";
|
||||
|
||||
import { smallTablet } from "@appserver/components/utils/device";
|
||||
|
||||
import DropDown from "@appserver/components/drop-down";
|
||||
|
||||
const StyledDropDownWrapper = styled.div`
|
||||
width: 100%;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const StyledDropDown = styled(DropDown)`
|
||||
margin-top: ${(props) => (props.marginTop ? props.marginTop : "4px")};
|
||||
padding: 6px 0;
|
||||
background: #ffffff;
|
||||
border: 1px solid #d0d5da;
|
||||
box-shadow: 0px 12px 40px rgba(4, 15, 27, 0.12);
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
|
||||
width: 446px;
|
||||
max-width: 446px;
|
||||
div {
|
||||
max-width: 446px;
|
||||
}
|
||||
|
||||
@media ${smallTablet} {
|
||||
width: calc(100vw - 34px);
|
||||
max-width: calc(100vw - 34px);
|
||||
div {
|
||||
max-width: calc(100vw - 34px);
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
height: 32px !important;
|
||||
max-height: 32px !important;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
padding: 6px 8px;
|
||||
font-weight: 400;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
color: #333333;
|
||||
&:hover {
|
||||
background: #f3f4f4;
|
||||
}
|
||||
|
||||
&-separator {
|
||||
height: 7px !important;
|
||||
max-height: 7px !important;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export { StyledDropDownWrapper, StyledDropDown };
|
@ -1,66 +0,0 @@
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
const StyledParam = styled.div`
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
${(props) =>
|
||||
props.isPrivate
|
||||
? css`
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
`
|
||||
: props.storageLocation
|
||||
? css`
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
`
|
||||
: props.folderName
|
||||
? css`
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
`
|
||||
: ""}
|
||||
|
||||
.set_room_params-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
|
||||
.set_room_params-info-title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
|
||||
.set_room_params-info-title-text {
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.set_room_params-info-title-help {
|
||||
border-radius: 50%;
|
||||
background-color: #a3a9ae;
|
||||
circle,
|
||||
rect {
|
||||
fill: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.set_room_params-info-description {
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
color: #a3a9ae;
|
||||
}
|
||||
}
|
||||
|
||||
.set_room_params-toggle {
|
||||
width: 28px;
|
||||
height: 16px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
`;
|
||||
|
||||
export { StyledParam };
|
@ -1,54 +0,0 @@
|
||||
import Tag from "@appserver/components/tag";
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
const StyledTagList = styled.div`
|
||||
margin-top: 2px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 4px;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
|
||||
.set_room_params-tag_input-tag {
|
||||
padding: 6px 8px;
|
||||
border-radius: 3px;
|
||||
margin: 0;
|
||||
|
||||
.tag-icon {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const TagList = ({ t, tagHandler }) => {
|
||||
const { tags } = tagHandler;
|
||||
|
||||
return (
|
||||
<StyledTagList className="set_room_params-tag_input-tag_list">
|
||||
{tags.length ? (
|
||||
tags.map((tag) => (
|
||||
<Tag
|
||||
key={tag.id}
|
||||
className="set_room_params-tag_input-tag"
|
||||
tag="script"
|
||||
label={tag.name}
|
||||
isNewTag
|
||||
onDelete={() => {
|
||||
tagHandler.deleteTag(tag.id);
|
||||
}}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<Tag
|
||||
className="set_room_params-tag_input-tag"
|
||||
tag="script"
|
||||
label={t("Common:NoTags")}
|
||||
isDisabled
|
||||
/>
|
||||
)}
|
||||
</StyledTagList>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagList;
|
@ -1,161 +0,0 @@
|
||||
import React, { useState, useRef } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import Label from "@appserver/components/label";
|
||||
import TextInput from "@appserver/components/text-input";
|
||||
import TagList from "./TagList";
|
||||
import DropDownItem from "@appserver/components/drop-down-item";
|
||||
import { StyledDropDown, StyledDropDownWrapper } from "../StyledDropdown";
|
||||
import { isMobile } from "@appserver/components/utils/device";
|
||||
|
||||
const StyledTagInput = styled.div`
|
||||
.set_room_params-tag_input {
|
||||
&-label_wrapper {
|
||||
&-label {
|
||||
cursor: pointer;
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-content-wrapper {
|
||||
margin-bottom: -4px;
|
||||
max-width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
`;
|
||||
|
||||
const TagInput = ({ t, tagHandler, setIsScrollLocked }) => {
|
||||
const [tagInput, setTagInput] = useState("");
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const chosenTags = tagHandler.tags.map((tag) => tag.name);
|
||||
const fetchedTags = tagHandler.fetchedTags;
|
||||
const filteredFetchedTags = fetchedTags.filter((tag) =>
|
||||
tag.toLowerCase().includes(tagInput.toLowerCase())
|
||||
);
|
||||
const tagsForDropdown = filteredFetchedTags.filter(
|
||||
(tag) => !chosenTags.includes(tag)
|
||||
);
|
||||
|
||||
const onTagInputChange = (e) => setTagInput(e.target.value);
|
||||
const preventDefault = (e) => e.preventDefault();
|
||||
|
||||
const openDropdown = () => {
|
||||
setIsScrollLocked(true);
|
||||
setIsOpen(true);
|
||||
};
|
||||
const closeDropdown = () => {
|
||||
setIsScrollLocked(false);
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
const tagsInputElement = document.getElementById("tags-input");
|
||||
|
||||
const onClickOutside = () => {
|
||||
tagsInputElement.blur();
|
||||
};
|
||||
|
||||
const addNewTag = () => {
|
||||
tagHandler.addNewTag(tagInput);
|
||||
setTagInput("");
|
||||
tagsInputElement.blur();
|
||||
};
|
||||
|
||||
const addFetchedTag = (name) => {
|
||||
tagHandler.addTag(name);
|
||||
setTagInput("");
|
||||
tagsInputElement.blur();
|
||||
};
|
||||
|
||||
const dropdownRef = useRef(null);
|
||||
|
||||
let dropdownItems = tagsForDropdown.map((tag, i) => (
|
||||
<DropDownItem
|
||||
className="dropdown-item"
|
||||
height={32}
|
||||
heightTablet={32}
|
||||
key={i}
|
||||
label={tag}
|
||||
onClick={() => {
|
||||
addFetchedTag(tag);
|
||||
console.log(tag);
|
||||
}}
|
||||
/>
|
||||
));
|
||||
|
||||
if (
|
||||
tagInput &&
|
||||
![...tagsForDropdown, ...chosenTags].find((tag) => tagInput === tag)
|
||||
) {
|
||||
const dropdownItemNewTag = (
|
||||
<DropDownItem
|
||||
key={-2}
|
||||
className="dropdown-item"
|
||||
onMouseDown={preventDefault}
|
||||
onClick={addNewTag}
|
||||
label={`${t("CreateTagOption")} “${tagInput}”`}
|
||||
height={32}
|
||||
heightTablet={32}
|
||||
/>
|
||||
);
|
||||
//dropdownItems = [dropdownItemNewTag, ...dropdownItems];
|
||||
|
||||
if (tagsForDropdown.length > 0) {
|
||||
dropdownItems = [
|
||||
dropdownItemNewTag,
|
||||
<DropDownItem height={7} heightTablet={7} key={-1} isSeparator />,
|
||||
...dropdownItems,
|
||||
];
|
||||
} else {
|
||||
dropdownItems = [dropdownItemNewTag, ...dropdownItems];
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledTagInput className="set_room_params-input set_room_params-tag_input">
|
||||
<div className="set_room_params-tag_input-label_wrapper">
|
||||
<Label
|
||||
className="set_room_params-tag_input-label_wrapper-label"
|
||||
display="display"
|
||||
htmlFor="tags-input"
|
||||
text={`${t("Common:Tags")}:`}
|
||||
title="Fill the first name field"
|
||||
/>
|
||||
</div>
|
||||
<TextInput
|
||||
id="tags-input"
|
||||
value={tagInput}
|
||||
onChange={onTagInputChange}
|
||||
onFocus={openDropdown}
|
||||
onBlur={closeDropdown}
|
||||
scale
|
||||
placeholder={t("TagsPlaceholder")}
|
||||
tabIndex={2}
|
||||
/>
|
||||
|
||||
<StyledDropDownWrapper
|
||||
className="dropdown-content-wrapper"
|
||||
ref={dropdownRef}
|
||||
onMouseDown={preventDefault}
|
||||
>
|
||||
{dropdownItems.length > 0 && (
|
||||
<StyledDropDown
|
||||
className="dropdown-content"
|
||||
open={isOpen}
|
||||
forwardedRef={dropdownRef}
|
||||
clickOutsideAction={onClickOutside}
|
||||
maxHeight={isMobile() ? 158 : 382}
|
||||
showDisabledItems={false}
|
||||
>
|
||||
{dropdownItems}
|
||||
</StyledDropDown>
|
||||
)}
|
||||
</StyledDropDownWrapper>
|
||||
<TagList t={t} tagHandler={tagHandler} />
|
||||
</StyledTagInput>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagInput;
|
@ -1,25 +0,0 @@
|
||||
import EmptyTrashDialog from "./EmptyTrashDialog";
|
||||
import DeleteDialog from "./DeleteDialog";
|
||||
import DownloadDialog from "./DownloadDialog";
|
||||
import ConvertDialog from "./ConvertDialog";
|
||||
import DeleteThirdPartyDialog from "./DeleteThirdPartyDialog";
|
||||
import ConnectDialog from "./ConnectDialog";
|
||||
import ThirdPartyMoveDialog from "./ThirdPartyMoveDialog";
|
||||
import ThirdPartyDialog from "./ThirdPartyDialog";
|
||||
import ConflictResolveDialog from "./ConflictResolveDialog";
|
||||
import CreateRoomDialog from "./CreateEditRoomDialog/CreateRoomDialog";
|
||||
import EditRoomDialog from "./CreateEditRoomDialog/EditRoomDialog";
|
||||
|
||||
export {
|
||||
EmptyTrashDialog,
|
||||
DeleteDialog,
|
||||
DownloadDialog,
|
||||
ConvertDialog,
|
||||
DeleteThirdPartyDialog,
|
||||
ConnectDialog,
|
||||
ThirdPartyMoveDialog,
|
||||
ThirdPartyDialog,
|
||||
ConflictResolveDialog,
|
||||
CreateRoomDialog,
|
||||
EditRoomDialog,
|
||||
};
|
@ -1,140 +0,0 @@
|
||||
import styled, { css } from "styled-components";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
import {
|
||||
mobile,
|
||||
smallTablet,
|
||||
tablet,
|
||||
} from "@appserver/components/utils/device";
|
||||
|
||||
const StyledHistoryList = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const StyledUserNameLink = styled.span`
|
||||
white-space: normal;
|
||||
margin: 1px 0;
|
||||
.username {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
display: inline-block;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledHistoryBlock = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 16px 0;
|
||||
border-bottom: ${(props) => `solid 1px ${props.theme.infoPanel.borderColor}`};
|
||||
|
||||
.avatar {
|
||||
min-width: 32px;
|
||||
}
|
||||
|
||||
.info {
|
||||
width: calc(100% - 40px);
|
||||
max-width: calc(100% - 40px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 4px;
|
||||
.name {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.secondary-info {
|
||||
white-space: nowrap;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #a3a9ae;
|
||||
@media ${mobile} {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.date {
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
margin-left: auto;
|
||||
font-weight: 600;
|
||||
font-size: 12px;
|
||||
color: #a3a9ae;
|
||||
}
|
||||
}
|
||||
|
||||
.block-content {
|
||||
.appointing {
|
||||
.appointing-user {
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.users {
|
||||
.user-list {
|
||||
.space {
|
||||
width: 4px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.files-list {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 8px 0;
|
||||
background: ${(props) => props.theme.infoPanel.history.fileBlockBg};
|
||||
border-radius: 3px;
|
||||
.file {
|
||||
padding: 4px 16px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
|
||||
.icon {
|
||||
min-width: 24px;
|
||||
}
|
||||
|
||||
.file-title {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
gap: 0;
|
||||
|
||||
.name {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.exst {
|
||||
flex-shrink: 0;
|
||||
color: #a3a9ae;
|
||||
}
|
||||
}
|
||||
|
||||
.location-btn {
|
||||
margin-left: auto;
|
||||
min-width: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledHistoryBlock.defaultProps = { theme: Base };
|
||||
|
||||
export { StyledHistoryList, StyledUserNameLink, StyledHistoryBlock };
|
@ -1,92 +0,0 @@
|
||||
import styled, { css } from "styled-components";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
|
||||
const StyledUserTypeHeader = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 24px 0 16px;
|
||||
|
||||
.title {
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
color: #a3a9ae;
|
||||
}
|
||||
|
||||
.icon {
|
||||
path,
|
||||
rect {
|
||||
fill: ${(props) => props.theme.infoPanel.members.iconColor};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledUserList = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const StyledUser = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 0;
|
||||
|
||||
.avatar {
|
||||
opacity: ${(props) => (props.isExpect ? 0.5 : 1)};
|
||||
min-width: 32px;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.name {
|
||||
opacity: ${(props) => (props.isExpect ? 0.5 : 1)};
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.me-label {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
color: #a3a9ae;
|
||||
margin-left: -8px;
|
||||
}
|
||||
|
||||
.role-wrapper {
|
||||
padding-left: 8px;
|
||||
margin-left: auto;
|
||||
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
white-space: nowrap;
|
||||
|
||||
.role {
|
||||
a {
|
||||
padding-right: ${(props) => (props.canEditRole ? "16px" : "0")};
|
||||
margin-right: ${(props) => (props.canEditRole ? "-6px" : "0")};
|
||||
span {
|
||||
color: ${(props) => (props.canEditRole ? "#555f65" : "#A3A9AE")};
|
||||
}
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
svg {
|
||||
${(props) => !props.canEditRole && "display: none"};
|
||||
path {
|
||||
fill: #a3a9ae;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledUserTypeHeader.defaultProps = { theme: Base };
|
||||
|
||||
export { StyledUserTypeHeader, StyledUserList, StyledUser };
|
@ -1,39 +0,0 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
const EmptyScreenContainer = styled.div`
|
||||
margin: 80px auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
gap: 32px;
|
||||
|
||||
.empty-screen-text {
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
`;
|
||||
|
||||
const EmptyScreen = ({ t }) => {
|
||||
return (
|
||||
<EmptyScreenContainer>
|
||||
<div className="no-thumbnail-img-wrapper">
|
||||
<img
|
||||
size="96px"
|
||||
className="no-thumbnail-img"
|
||||
src="images/empty_screen_info_panel.png"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="empty-screen-text">{t("EmptyScreenText")}</div>
|
||||
</EmptyScreenContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default withTranslation(["InfoPanel"])(EmptyScreen);
|
@ -1,32 +0,0 @@
|
||||
import Text from "@docspace/components/text";
|
||||
import React from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
import { StyledTitle } from "../../styles/styles.js";
|
||||
|
||||
const SeveralItems = (props) => {
|
||||
const { t, selectedItems, getIcon, getFolderInfo } = props;
|
||||
const itemsIcon = getIcon(24, ".file");
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledTitle>
|
||||
<ReactSVG className="icon" src={itemsIcon} />
|
||||
<Text className="text" fontWeight={600} fontSize="16px">
|
||||
{`${t("ItemsSelected")}: ${selectedItems.length}`}
|
||||
</Text>
|
||||
</StyledTitle>
|
||||
|
||||
<div className="no-thumbnail-img-wrapper">
|
||||
<img
|
||||
size="96px"
|
||||
className="no-thumbnail-img"
|
||||
src="images/empty_screen.png"
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default withTranslation(["InfoPanel"])(SeveralItems);
|
@ -1,88 +0,0 @@
|
||||
import React from "react";
|
||||
import EmptyScreen from "./EmptyScreen";
|
||||
import SeveralItems from "./SeveralItems";
|
||||
import SingleItem from "./SingleItem";
|
||||
|
||||
const Details = ({
|
||||
t,
|
||||
|
||||
selectedItems,
|
||||
selectedFolder,
|
||||
|
||||
getFolderInfo,
|
||||
getIcon,
|
||||
getFolderIcon,
|
||||
getShareUsers,
|
||||
onSelectItem,
|
||||
setSharingPanelVisible,
|
||||
createThumbnail,
|
||||
|
||||
personal,
|
||||
culture,
|
||||
|
||||
isRootFolder,
|
||||
isRecycleBinFolder,
|
||||
isRecentFolder,
|
||||
isFavoritesFolder,
|
||||
isShareFolder,
|
||||
isCommonFolder,
|
||||
isPrivacyFolder,
|
||||
}) => {
|
||||
const singleItem = (item) => {
|
||||
const dontShowLocation = isRootFolder;
|
||||
const dontShowSize = item.isFolder && (isFavoritesFolder || isRecentFolder);
|
||||
const dontShowAccess =
|
||||
isRecycleBinFolder ||
|
||||
isRootFolder ||
|
||||
item.rootFolderId === 7 ||
|
||||
(item.isFolder && item.pathParts && item.pathParts[0] === 7);
|
||||
const dontShowOwner = isRootFolder && (isFavoritesFolder || isRecentFolder);
|
||||
|
||||
return (
|
||||
<SingleItem
|
||||
t={t}
|
||||
selectedItem={item}
|
||||
onSelectItem={onSelectItem}
|
||||
setSharingPanelVisible={setSharingPanelVisible}
|
||||
getFolderInfo={getFolderInfo}
|
||||
getIcon={getIcon}
|
||||
getFolderIcon={getFolderIcon}
|
||||
getShareUsers={getShareUsers}
|
||||
dontShowLocation={dontShowLocation}
|
||||
dontShowSize={dontShowSize}
|
||||
dontShowAccess={dontShowAccess}
|
||||
dontShowOwner={dontShowOwner}
|
||||
personal={personal}
|
||||
culture={culture}
|
||||
createThumbnail={createThumbnail}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{selectedItems.length === 0 ? (
|
||||
// Can get future changes, currently only "My documents" displays its info
|
||||
isRootFolder &&
|
||||
(isRecycleBinFolder ||
|
||||
isRecentFolder ||
|
||||
isFavoritesFolder ||
|
||||
isShareFolder ||
|
||||
isCommonFolder) ? (
|
||||
<EmptyScreen />
|
||||
) : (
|
||||
singleItem({
|
||||
...selectedFolder,
|
||||
isFolder: true,
|
||||
})
|
||||
)
|
||||
) : selectedItems.length === 1 ? (
|
||||
singleItem(selectedItems[0])
|
||||
) : (
|
||||
<SeveralItems selectedItems={selectedItems} getIcon={getIcon} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Details;
|
@ -1,26 +0,0 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import Text from "@docspace/components/text";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
const StyledGalleryEmptyScreen = styled.div`
|
||||
.info-panel_gallery-empty-screen-img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
padding: 56px 0 48px 0;
|
||||
}
|
||||
`;
|
||||
|
||||
const GalleryEmptyScreen = ({ t }) => {
|
||||
return (
|
||||
<StyledGalleryEmptyScreen className="info-panel_gallery-empty-screen">
|
||||
<img
|
||||
className="info-panel_gallery-empty-screen-img"
|
||||
src="images/form-gallery-search.react.svg"
|
||||
alt="Empty Screen Gallery image"
|
||||
/>
|
||||
<Text textAlign="center">{t("GalleryEmptyScreenDescription")}</Text>
|
||||
</StyledGalleryEmptyScreen>
|
||||
);
|
||||
};
|
||||
export default withTranslation("FormGallery")(GalleryEmptyScreen);
|
@ -1,89 +0,0 @@
|
||||
import React from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import { LANGUAGE } from "@docspace/common/constants";
|
||||
import Text from "@docspace/components/text";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import {
|
||||
StyledProperties,
|
||||
StyledSubtitle,
|
||||
StyledGalleryThumbnail,
|
||||
StyledTitle,
|
||||
} from "../../styles/styles.js";
|
||||
import getCorrectDate from "@appserver/components/utils/getCorrectDate";
|
||||
|
||||
import getCorrectDate from "@docspace/components/utils/getCorrectDate";
|
||||
import { getCookie } from "@docspace/common/utils/index";
|
||||
|
||||
const SingleItem = (props) => {
|
||||
const { t, selectedItem, getIcon, culture, personal } = props;
|
||||
|
||||
const parseAndFormatDate = (date) => {
|
||||
const locale = personal ? localStorage.getItem(LANGUAGE) : culture;
|
||||
|
||||
const correctDate = getCorrectDate(locale, date);
|
||||
|
||||
return correctDate;
|
||||
};
|
||||
|
||||
const src = getIcon(32, ".docxf");
|
||||
const thumbnailBlank = getIcon(96, ".docxf");
|
||||
|
||||
const thumbnailUrl =
|
||||
selectedItem?.attributes?.template_image?.data.attributes?.formats?.small
|
||||
?.url;
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledTitle>
|
||||
<ReactSVG className="icon" src={src} />
|
||||
<Text className="text">{selectedItem.attributes.name_form}</Text>
|
||||
</StyledTitle>
|
||||
|
||||
{thumbnailUrl ? (
|
||||
<StyledGalleryThumbnail>
|
||||
<img className="info-panel_gallery-img" src={thumbnailUrl} alt="" />
|
||||
</StyledGalleryThumbnail>
|
||||
) : (
|
||||
<div className="no-thumbnail-img-wrapper">
|
||||
<ReactSVG className="no-thumbnail-img" src={thumbnailBlank} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<StyledSubtitle>
|
||||
<Text fontWeight="600" fontSize="14px">
|
||||
{t("SystemProperties")}
|
||||
</Text>
|
||||
</StyledSubtitle>
|
||||
|
||||
<StyledProperties>
|
||||
<div className="property">
|
||||
<Text className="property-title">{t("Home:ByLastModifiedDate")}</Text>
|
||||
<Text className="property-content">
|
||||
{parseAndFormatDate(selectedItem.attributes.updatedAt)}
|
||||
</Text>
|
||||
</div>
|
||||
<div className="property">
|
||||
<Text className="property-title">{t("Common:Size")}</Text>
|
||||
<Text className="property-content">
|
||||
{selectedItem.attributes.file_size}
|
||||
</Text>
|
||||
</div>
|
||||
<div className="property">
|
||||
<Text className="property-title">{t("Common:Pages")}</Text>
|
||||
<Text className="property-content">
|
||||
{selectedItem.attributes.file_pages}
|
||||
</Text>
|
||||
</div>
|
||||
</StyledProperties>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ settingsStore }) => {
|
||||
const { getIcon, personal, culture } = settingsStore;
|
||||
|
||||
return {
|
||||
getIcon,
|
||||
};
|
||||
})(withTranslation(["InfoPanel", "Common", "Files"])(observer(SingleItem)));
|
@ -1,87 +0,0 @@
|
||||
import React from "react";
|
||||
import Text from "@appserver/components/text";
|
||||
import Link from "@appserver/components/link";
|
||||
import IconButton from "@appserver/components/icon-button";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import { StyledUserNameLink } from "../../styles/VirtualRoom/history";
|
||||
|
||||
const HistoryBlockContent = ({ t, action, details }) => {
|
||||
return (
|
||||
<div className="block-content">
|
||||
{action === "message" ? (
|
||||
<Text>{details.message}</Text>
|
||||
) : action === "appointing" ? (
|
||||
<div className="appointing">
|
||||
{`${t("appointed")}
|
||||
${details.appointedRole} `}{" "}
|
||||
<UserNameLink user={details.appointedUser} />
|
||||
</div>
|
||||
) : action === "users" ? (
|
||||
<div className="users">
|
||||
<div className="user-list">
|
||||
added users{" "}
|
||||
{details.users.map((user, i) => (
|
||||
<UserNameLink
|
||||
key={user.id}
|
||||
user={user}
|
||||
withComma={i + 1 !== details.users.length}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : action === "files" ? (
|
||||
<div className="files">
|
||||
<Text>add new 2 files into the folder “My project”</Text>
|
||||
<div className="files-list">
|
||||
{details.files.map((file) => (
|
||||
<div className="file" key={file.id}>
|
||||
<ReactSVG className="icon" src={file.icon} />
|
||||
<div className="file-title">
|
||||
<span className="name">{file.title.split(".")[0]}</span>
|
||||
<span className="exst">{file.fileExst}</span>
|
||||
</div>
|
||||
<IconButton
|
||||
className="location-btn"
|
||||
iconName="/static/images/folder-location.react.svg"
|
||||
size="16"
|
||||
isFill={true}
|
||||
onClick={() => {}}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const UserNameLink = ({ user, withComma }) => {
|
||||
const username = user.displayName || user.email;
|
||||
const space = <div className="space"></div>;
|
||||
|
||||
return (
|
||||
<StyledUserNameLink className="user">
|
||||
{user.profileUrl ? (
|
||||
<Link
|
||||
className="username link"
|
||||
isHovered
|
||||
type="action"
|
||||
href={user.profileURl}
|
||||
>
|
||||
{username}
|
||||
{withComma ? "," : ""}
|
||||
{withComma && space}
|
||||
</Link>
|
||||
) : (
|
||||
<div className="username text" key={user.id}>
|
||||
{username}
|
||||
{withComma ? "," : ""}
|
||||
{withComma && space}
|
||||
</div>
|
||||
)}
|
||||
</StyledUserNameLink>
|
||||
);
|
||||
};
|
||||
|
||||
export default HistoryBlockContent;
|
@ -1,72 +0,0 @@
|
||||
import Avatar from "@appserver/components/avatar";
|
||||
import ContextMenuButton from "@appserver/components/context-menu-button";
|
||||
import Text from "@appserver/components/text";
|
||||
import React from "react";
|
||||
import { StyledTitle } from "../../styles/styles";
|
||||
import {
|
||||
StyledHistoryBlock,
|
||||
StyledHistoryList,
|
||||
} from "../../styles/VirtualRoom/history";
|
||||
import { fillingFormsVR } from "../mock_data";
|
||||
import getCorrectDate from "@appserver/components/utils/getCorrectDate";
|
||||
import HistoryBlockContent from "./historyBlockContent";
|
||||
|
||||
const History = ({ t, personal, culture }) => {
|
||||
const data = fillingFormsVR;
|
||||
|
||||
const parseAndFormatDate = (date) => {
|
||||
const locale = personal ? localStorage.getItem(LANGUAGE) : culture;
|
||||
const correctDate = getCorrectDate(locale, date);
|
||||
return correctDate;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledTitle withBottomBorder>
|
||||
<img className="icon" src={data.icon} alt="thumbnail-icon" />
|
||||
<Text className="text">{data.title}</Text>
|
||||
<ContextMenuButton getData={() => {}} className="context-menu-button" />
|
||||
</StyledTitle>
|
||||
|
||||
<StyledHistoryList>
|
||||
{data.history.map((operation) => (
|
||||
<StyledHistoryBlock key={operation.id}>
|
||||
<Avatar
|
||||
role="user"
|
||||
className="avatar"
|
||||
size="min"
|
||||
source={
|
||||
operation.user.avatar ||
|
||||
(operation.user.displayName
|
||||
? ""
|
||||
: operation.user.email && "/static/images/@.react.svg")
|
||||
}
|
||||
userName={operation.user.displayName}
|
||||
/>
|
||||
<div className="info">
|
||||
<div className="title">
|
||||
<Text className="name">{operation.user.displayName}</Text>
|
||||
{operation.user.isOwner && (
|
||||
<Text className="secondary-info">
|
||||
{t("Common:Owner").toLowerCase()}
|
||||
</Text>
|
||||
)}
|
||||
<Text className="date">
|
||||
{parseAndFormatDate(operation.date)}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<HistoryBlockContent
|
||||
t={t}
|
||||
action={operation.action}
|
||||
details={operation.details}
|
||||
/>
|
||||
</div>
|
||||
</StyledHistoryBlock>
|
||||
))}
|
||||
</StyledHistoryList>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default History;
|
@ -1,78 +0,0 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { StyledUser } from "../../styles/VirtualRoom/members";
|
||||
import Avatar from "@appserver/components/avatar";
|
||||
import LinkWithDropdown from "@appserver/components/link-with-dropdown";
|
||||
|
||||
const User = ({ t, user, selfId, isExpect }) => {
|
||||
return (
|
||||
<StyledUser
|
||||
isExpect={isExpect}
|
||||
key={user.id}
|
||||
canEditRole={user.role !== "Owner"}
|
||||
>
|
||||
<Avatar
|
||||
role="user"
|
||||
className="avatar"
|
||||
size="min"
|
||||
source={
|
||||
user.avatar ||
|
||||
(user.displayName ? "" : user.email && "/static/images/@.react.svg")
|
||||
}
|
||||
userName={user.displayName}
|
||||
/>
|
||||
|
||||
<div className="name">{user.displayName || user.email}</div>
|
||||
{selfId === user.id && (
|
||||
<div className="me-label"> {`(${t("Common:MeLabel")})`}</div>
|
||||
)}
|
||||
|
||||
<div className="role-wrapper">
|
||||
<LinkWithDropdown
|
||||
className="role"
|
||||
containerMinWidth="fit-content"
|
||||
directionX="right"
|
||||
directionY="bottom"
|
||||
fontSize="13px"
|
||||
fontWeight={600}
|
||||
hasScroll={true}
|
||||
withBackdrop={false}
|
||||
dropdownType="apparDashedAfterHover"
|
||||
isDisabled={user.role === "Owner"}
|
||||
data={[
|
||||
{
|
||||
key: "key1",
|
||||
label: "Room manager",
|
||||
onClick: () => {},
|
||||
},
|
||||
{
|
||||
key: "key2",
|
||||
label: "Co-worker",
|
||||
onClick: function noRefCheck() {},
|
||||
},
|
||||
{
|
||||
key: "key3",
|
||||
label: "Viewer",
|
||||
onClick: function noRefCheck() {},
|
||||
},
|
||||
{
|
||||
isSeparator: true,
|
||||
key: "key4",
|
||||
},
|
||||
{
|
||||
key: "key5",
|
||||
label: "Remove",
|
||||
onClick: function noRefCheck() {},
|
||||
},
|
||||
]}
|
||||
>
|
||||
{user.role}
|
||||
</LinkWithDropdown>
|
||||
</div>
|
||||
</StyledUser>
|
||||
);
|
||||
};
|
||||
|
||||
User.propTypes = { user: PropTypes.object };
|
||||
|
||||
export default User;
|
@ -1,27 +0,0 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import User from "./User";
|
||||
|
||||
import { StyledUserList } from "../../styles/VirtualRoom/members";
|
||||
|
||||
const UserList = ({ t, users, selfId, isExpect }) => {
|
||||
return (
|
||||
<StyledUserList>
|
||||
{users.map((user) => (
|
||||
<User
|
||||
t={t}
|
||||
key={user.id}
|
||||
selfId={selfId}
|
||||
user={user}
|
||||
isExpect={isExpect}
|
||||
/>
|
||||
))}
|
||||
</StyledUserList>
|
||||
);
|
||||
};
|
||||
|
||||
UserList.propTypes = {
|
||||
users: PropTypes.array,
|
||||
};
|
||||
|
||||
export default UserList;
|
@ -1,56 +0,0 @@
|
||||
import ContextMenuButton from "@appserver/components/context-menu-button";
|
||||
import IconButton from "@appserver/components/icon-button";
|
||||
import Text from "@appserver/components/text";
|
||||
import React from "react";
|
||||
import { StyledTitle } from "../../styles/styles";
|
||||
import { StyledUserTypeHeader } from "../../styles/VirtualRoom/members";
|
||||
import { fillingFormsVR } from "../mock_data";
|
||||
import UserList from "./UserList";
|
||||
|
||||
const Members = ({ t, selfId }) => {
|
||||
const data = fillingFormsVR;
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledTitle withBottomBorder>
|
||||
<img className="icon" src={data.icon} alt="thumbnail-icon" />
|
||||
<Text className="text">{data.title}</Text>
|
||||
<ContextMenuButton getData={() => {}} className="context-menu-button" />
|
||||
</StyledTitle>
|
||||
|
||||
<StyledUserTypeHeader>
|
||||
<Text className="title">
|
||||
{t("Users in room")} : {data.members.inRoom.length}
|
||||
</Text>
|
||||
<IconButton
|
||||
className={"icon"}
|
||||
title={t("Common:AddUsers")}
|
||||
iconName="/static/images/person+.react.svg"
|
||||
isFill={true}
|
||||
onClick={() => {}}
|
||||
size={16}
|
||||
color={"#316DAA"}
|
||||
/>
|
||||
</StyledUserTypeHeader>
|
||||
|
||||
<UserList t={t} users={data.members.inRoom} selfId={selfId} />
|
||||
|
||||
<StyledUserTypeHeader>
|
||||
<Text className="title">{`${t("Expect people")}:`}</Text>
|
||||
<IconButton
|
||||
className={"icon"}
|
||||
title={t("Repeat invitation")}
|
||||
iconName="/static/images/e-mail+.react.svg"
|
||||
isFill={true}
|
||||
onClick={() => {}}
|
||||
size={16}
|
||||
color={"#316DAA"}
|
||||
/>
|
||||
</StyledUserTypeHeader>
|
||||
|
||||
<UserList t={t} users={data.members.expect} isExpect />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Members;
|
@ -1,123 +0,0 @@
|
||||
const files = [
|
||||
{
|
||||
fileExst: ".png",
|
||||
icon: "/static/images/icons/24/image.svg",
|
||||
isFolder: false,
|
||||
id: 34,
|
||||
title: "Windows 12 Wallpaper Purple.png",
|
||||
},
|
||||
{
|
||||
fileExst: ".pptx",
|
||||
icon: "/static/images/icons/24/pptx.svg",
|
||||
isFolder: false,
|
||||
id: 3,
|
||||
title: "ONLYOFFICE Sample Presentation With Long Name.pptx",
|
||||
},
|
||||
{
|
||||
fileExst: ".docx",
|
||||
icon: "/static/images/icons/24/docx.svg",
|
||||
isFolder: false,
|
||||
id: 5,
|
||||
title: "курсач.docx",
|
||||
},
|
||||
];
|
||||
|
||||
const people = [
|
||||
{
|
||||
email: "nikita.mushka@onlyoffice.com",
|
||||
avatar:
|
||||
"http://192.168.0.102:8092/images/default_user_photo_size_82-82.png",
|
||||
isOwner: true,
|
||||
id: "66faa6e4-f133-11ea-b126-00ffeec8b4ef",
|
||||
displayName: "Мушка Никита",
|
||||
profileUrl: "http://192.168.9.102:8092/products/people/view/administrator",
|
||||
role: "Owner",
|
||||
},
|
||||
{
|
||||
email: "yoshiko05@rohan.biz",
|
||||
avatar: "",
|
||||
isOwner: false,
|
||||
id: "1231234",
|
||||
displayName: "Rebecca Holt",
|
||||
profileUrl: "asdasd",
|
||||
role: "Room manager",
|
||||
},
|
||||
{
|
||||
email: "yoshiko05@rohan.biz",
|
||||
avatar:
|
||||
"https://images.unsplash.com/photo-1519699047748-de8e457a634e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=880&q=80",
|
||||
isOwner: false,
|
||||
id: "345970",
|
||||
displayName: "Angela Garcia",
|
||||
profileUrl: "",
|
||||
role: "Viewer",
|
||||
},
|
||||
{
|
||||
email: "kk@mail.ru",
|
||||
avatar: "/images/default_user_photo_size_82-82.png",
|
||||
isOwner: false,
|
||||
id: "5db1213e-7f73-434e-9d6a-af699821d3c9",
|
||||
displayName:
|
||||
"Some random guy with a really long name, like i mean some dumb long one",
|
||||
profileUrl: "http://localhost:8092/products/people/view/kk",
|
||||
role: "Viewer",
|
||||
},
|
||||
{
|
||||
email: "ycummerata@yahoo.com",
|
||||
avatar: "",
|
||||
isOwner: false,
|
||||
id: "389457",
|
||||
displayName: "",
|
||||
profileUrl: "",
|
||||
role: "Viewer",
|
||||
},
|
||||
];
|
||||
|
||||
const fillingFormsVR = {
|
||||
title: "Filling forms room",
|
||||
icon: "images/icons/32/folder.svg",
|
||||
members: {
|
||||
inRoom: [...people.slice(0, 3)],
|
||||
expect: [...people.slice(3)],
|
||||
},
|
||||
|
||||
history: [
|
||||
{
|
||||
id: 3,
|
||||
user: people[0],
|
||||
date: "2022-04-23T19:04:43.511Z",
|
||||
action: "files",
|
||||
details: { type: "delete", files: [...files] },
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
user: people[0],
|
||||
date: "2022-04-23T18:39:43.511Z",
|
||||
action: "appointing",
|
||||
details: {
|
||||
appointedUser: people[1],
|
||||
appointedRole: "room administrator",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 1,
|
||||
user: people[0],
|
||||
date: "2022-04-23T18:35:43.511Z",
|
||||
action: "users",
|
||||
details: {
|
||||
type: "add",
|
||||
users: [...people.slice(1)],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 0,
|
||||
user: people[0],
|
||||
date: "2022-04-23T18:25:43.511Z",
|
||||
action: "message",
|
||||
details: { message: 'Created room "Filling forms room"' },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export { fillingFormsVR };
|
@ -1,91 +0,0 @@
|
||||
import React from "react";
|
||||
import styled, { css } from "styled-components";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import { isMobile } from "react-device-detect";
|
||||
|
||||
import { default as Container } from "../../../../components/EmptyContainer/EmptyContainer";
|
||||
|
||||
import Link from "@appserver/components/link";
|
||||
import IconButton from "@appserver/components/icon-button";
|
||||
|
||||
import { tablet } from "@appserver/components/utils/device";
|
||||
import { Events } from "../../../../helpers/constants";
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
.empty-folder_container {
|
||||
grid-row-gap: 8px;
|
||||
grid-column-gap: 40px;
|
||||
|
||||
height: 100px;
|
||||
|
||||
align-items: center;
|
||||
|
||||
grid-row-gap: 8px;
|
||||
grid-column-gap: 40px;
|
||||
|
||||
height: 100px;
|
||||
|
||||
@media ${tablet} {
|
||||
padding: 14px 0;
|
||||
}
|
||||
|
||||
${isMobile &&
|
||||
css`
|
||||
padding: 14px 0;
|
||||
`}
|
||||
}
|
||||
`;
|
||||
|
||||
const linkStyles = {
|
||||
isHovered: true,
|
||||
type: "action",
|
||||
fontWeight: "600",
|
||||
className: "empty-folder_link",
|
||||
display: "flex",
|
||||
};
|
||||
|
||||
const EmptyContainer = ({ theme, setCreateRoomDialogVisible }) => {
|
||||
linkStyles.color = theme.filesEmptyContainer.linkColor;
|
||||
|
||||
const onCreateRoom = () => {
|
||||
const event = new Event(Events.ROOM_CREATE);
|
||||
window.dispatchEvent(event);
|
||||
};
|
||||
|
||||
const buttons = (
|
||||
<div className="empty-folder_container-links">
|
||||
<IconButton
|
||||
className="empty-folder_container-icon"
|
||||
size="12"
|
||||
iconName="images/plus.svg"
|
||||
isFill
|
||||
onClick={onCreateRoom}
|
||||
/>
|
||||
<Link onClick={onCreateRoom} {...linkStyles}>
|
||||
Create room
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<Container
|
||||
headerText={"Welcome to virtual rooms!"}
|
||||
descriptionText={"Please create the first room."}
|
||||
imageSrc="images/empty_screen_corporate.png"
|
||||
buttons={buttons}
|
||||
/>
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ auth, dialogsStore }) => {
|
||||
const { theme } = auth.settingsStore;
|
||||
const { setCreateRoomDialogVisible } = dialogsStore;
|
||||
return {
|
||||
theme,
|
||||
setCreateRoomDialogVisible,
|
||||
};
|
||||
})(withTranslation(["Home", "Common"])(observer(EmptyContainer)));
|
Before Width: | Height: | Size: 896 B After Width: | Height: | Size: 896 B |
Loading…
Reference in New Issue
Block a user