Merge branch 'feature/ip-security' of github.com:ONLYOFFICE/AppServer into feature/admin-messages
This commit is contained in:
commit
ab0404e1dc
@ -22,6 +22,10 @@
|
||||
<ROW Property="ARPURLUPDATEINFO" Value="http://www.onlyoffice.com/download.aspx"/>
|
||||
<ROW Property="DATABASE_MIGRATION" Value="true"/>
|
||||
<ROW Property="DATABASE_PROP" Value="onlyoffice"/>
|
||||
<ROW Property="ELASTICSEARCH_HOST" Value="localhost" ValueLocId="-"/>
|
||||
<ROW Property="ELASTICSEARCH_MSG" Value="Unable to connect to remote Elasticsearch server at "/>
|
||||
<ROW Property="ELASTICSEARCH_PORT" Value="9200" ValueLocId="-"/>
|
||||
<ROW Property="ELASTICSEARCH_SCHEME" Value="http" ValueLocId="-"/>
|
||||
<ROW Property="ENVIRONMENT" Value="test"/>
|
||||
<ROW Property="INSTALL_ROOT_FOLDER_NAME" Value="[|Manufacturer]"/>
|
||||
<ROW Property="MSIFASTINSTALL" MultiBuildValue="DefaultBuild:3"/>
|
||||
@ -231,6 +235,7 @@
|
||||
<ROW Property="AI_SETUPEXEPATH" Signature_="AI_EXE_PATH_CU" Builds="DefaultBuild"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiBinaryComponent">
|
||||
<ROW Name="PowerShellScriptLauncher.dll" SourcePath="<AI_CUSTACTS>PowerShellScriptLauncher.dll"/>
|
||||
<ROW Name="Prereq.dll" SourcePath="<AI_CUSTACTS>Prereq.dll"/>
|
||||
<ROW Name="SoftwareDetector.dll" SourcePath="<AI_CUSTACTS>SoftwareDetector.dll"/>
|
||||
<ROW Name="TxtUpdater.dll" SourcePath="<AI_CUSTACTS>TxtUpdater.dll"/>
|
||||
@ -243,6 +248,21 @@
|
||||
<ROW Dialog_="AdminInstallPointDlg" Control="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Attributes="3" Text="[ButtonText_Back]" Order="600" TextLocId="-" MsiKey="AdminInstallPointDlg#Back" Options="1"/>
|
||||
<ROW Dialog_="AdminWelcomeDlg" Control="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Attributes="1" Text="[ButtonText_Back]" Order="400" TextLocId="-" MsiKey="AdminWelcomeDlg#Back" Options="1"/>
|
||||
<ROW Dialog_="CustomizeDlg" Control="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Attributes="3" Text="[ButtonText_Back]" Order="700" TextLocId="-" MsiKey="CustomizeDlg#Back" Options="1"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Attributes="3" Text="[ButtonText_Next]" Order="100" Options="1"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Attributes="3" Text="[ButtonText_Cancel]" Order="200" Options="1"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Attributes="3" Text="[ButtonText_Back]" Order="300" Options="1"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" Attributes="1048577" Text="[BannerBitmap]" Order="400"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control="BannerLine" Type="Line" X="0" Y="44" Width="372" Height="0" Attributes="1" Order="500"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control="BottomLine" Type="Line" X="5" Y="234" Width="368" Height="0" Attributes="1" Order="600"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Attributes="196611" Text="Описание нового диалогового окна..." Order="700"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control="Logo" Type="Text" X="4" Y="228" Width="70" Height="12" Attributes="1" Text="Advanced Installer" Order="800"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Attributes="196611" Text="Новое диалоговое окно" TextStyle="[DlgTitleFont]" Order="900"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control="ProtocolLabel" Type="Text" X="25" Y="65" Width="67" Height="11" Attributes="65539" Text="Protocol" Order="1000"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control="ServerLabel" Type="Text" X="25" Y="92" Width="67" Height="11" Attributes="65539" Text="Server:" Order="1100"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control="PortLabel" Type="Text" X="25" Y="119" Width="67" Height="11" Attributes="65539" Text="Port:" Order="1200"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control="ProtocolEdit" Type="Edit" X="98" Y="61" Width="253" Height="18" Attributes="3" Property="ELASTICSEARCH_SCHEME" Text="{5}" Order="1300"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control="ServerEdit" Type="Edit" X="98" Y="89" Width="253" Height="18" Attributes="3" Property="ELASTICSEARCH_HOST" Text="[ComputerName]" Order="1400"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control="PortEdit" Type="Edit" X="98" Y="116" Width="253" Height="18" Attributes="19" Property="ELASTICSEARCH_PORT" Text="{7}" Order="1500"/>
|
||||
<ROW Dialog_="ExitDialog" Control="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Attributes="1" Text="[ButtonText_Back]" Order="400" TextLocId="-" MsiKey="ExitDialog#Back" Options="1"/>
|
||||
<ROW Dialog_="FatalError" Control="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Attributes="1" Text="[ButtonText_Back]" Order="400" TextLocId="-" MsiKey="FatalError#Back" Options="1"/>
|
||||
<ROW Dialog_="FolderDlg" Control="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Attributes="3" Text="[ButtonText_Back]" Order="800" TextLocId="-" MsiKey="FolderDlg#Back" Options="1"/>
|
||||
@ -280,11 +300,11 @@
|
||||
<ATTRIBUTE name="DeletedRows" value="SQLConnectionDlg#OdbcResourceEdit@SQLConnectionDlg#OdbcResourceLabel@SQLConnectionDlg.aip"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiControlEventComponent">
|
||||
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="FolderDlg" Condition="AI_INSTALL AND ( OLDPRODUCTS = "" )" Ordering="4"/>
|
||||
<ROW Dialog_="FolderDlg" Control_="Next" Event="NewDialog" Argument="SQLConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError <> "" )" Ordering="203"/>
|
||||
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="FolderDlg" Condition="AI_INSTALL AND ( OLDPRODUCTS = "" )" Ordering="7"/>
|
||||
<ROW Dialog_="FolderDlg" Control_="Next" Event="NewDialog" Argument="SQLConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError <> "" )" Ordering="205"/>
|
||||
<ROW Dialog_="FolderDlg" Control_="Back" Event="NewDialog" Argument="WelcomeDlg" Condition="AI_INSTALL" Ordering="1"/>
|
||||
<ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_INSTALL" Ordering="197"/>
|
||||
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="SQLConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError <> "" )" Ordering="202"/>
|
||||
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="ELKConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError <> "" AND ELK_CONNECTION = 0 )" Ordering="203"/>
|
||||
<ROW Dialog_="MaintenanceWelcomeDlg" Control_="Next" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT" Ordering="99"/>
|
||||
<ROW Dialog_="CustomizeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_MAINT" Ordering="101"/>
|
||||
<ROW Dialog_="CustomizeDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT" Ordering="1"/>
|
||||
@ -305,23 +325,40 @@
|
||||
<ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_PATCH" Ordering="199"/>
|
||||
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="PatchWelcomeDlg" Condition="AI_PATCH" Ordering="205"/>
|
||||
<ROW Dialog_="PrerequisitesDlg" Control_="Back" Event="NewDialog" Argument="WelcomePrereqDlg" Condition="AI_BOOTSTRAPPER" Ordering="1"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="Next" Event="DoAction" Argument="AI_DATA_SETTER_5" Condition="AI_INSTALL AND ( SqlConnectionError <> "" )" Ordering="5"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="Next" Event="DoAction" Argument="TestSQLConnectionMsgBox" Condition="AI_INSTALL AND ( SqlConnectionError <> "" )" Ordering="6"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="Next" Event="DoAction" Argument="AI_DATA_SETTER_5" Condition="AI_INSTALL AND ( SqlConnectionError <> "" )" Ordering="4"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="Next" Event="DoAction" Argument="TestSQLConnectionMsgBox" Condition="AI_INSTALL AND ( SqlConnectionError <> "" )" Ordering="5"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="SQLConnectionDlgDialogInitializer" Event="[PASSWORD_PROP]" Argument="{}" Condition="AI_INSTALL AND ( OLDPRODUCTS="" AND SQLConnectionDlg_Cond )" Ordering="4"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="SQLConnectionDlgDialogInitializer" Event="[AI_ButtonText_Next_Orig]" Argument="[ButtonText_Next]" Condition="AI_INSTALL AND ( OLDPRODUCTS="" AND SQLConnectionDlg_Cond )" Ordering="3"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="SQLConnectionDlgDialogInitializer" Event="[ButtonText_Next]" Argument="[[AI_CommitButton]]" Condition="AI_INSTALL AND ( OLDPRODUCTS="" AND SQLConnectionDlg_Cond )" Ordering="2"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="SQLConnectionDlgDialogInitializer" Event="[AI_Text_Next_Orig]" Argument="[Text_Next]" Condition="AI_INSTALL AND ( OLDPRODUCTS="" AND SQLConnectionDlg_Cond )" Ordering="1"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="SQLConnectionDlgDialogInitializer" Event="[Text_Next]" Argument="[Text_Install]" Condition="AI_INSTALL AND ( OLDPRODUCTS="" AND SQLConnectionDlg_Cond )" Ordering="0"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_INSTALL AND ( SqlConnectionError = "" )" Ordering="7"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="Back" Event="NewDialog" Argument="FolderDlg" Condition="AI_INSTALL" Ordering="1"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="Next" Event="NewDialog" Argument="ELKConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError = "" AND ELK_CONNECTION = 0 )" Ordering="7"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="Back" Event="NewDialog" Argument="FolderDlg" Condition="AI_INSTALL AND ( OLDPRODUCTS = "" )" Ordering="2"/>
|
||||
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="DoAction" Argument="TestSqlConnection" Condition="AI_INSTALL" Ordering="1"/>
|
||||
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="SQLConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError <> "" )" Ordering="2"/>
|
||||
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_INSTALL AND ( SqlConnectionError="" )" Ordering="3"/>
|
||||
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="SQLConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError <> "" )" Ordering="4"/>
|
||||
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_INSTALL AND ( SqlConnectionError="" AND ELK_CONNECTION = 1 )" Ordering="6"/>
|
||||
<ROW Dialog_="FolderDlg" Control_="Next" Event="DoAction" Argument="TestSqlConnection" Condition="AI_INSTALL" Ordering="201"/>
|
||||
<ROW Dialog_="FolderDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_INSTALL AND ( SqlConnectionError = "" )" Ordering="204"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="Next" Event="DoAction" Argument="TestSqlConnection" Condition="AI_INSTALL" Ordering="4"/>
|
||||
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="FolderDlg" Condition="AI_INSTALL AND ( OLDPRODUCTS = "" AND SqlConnectionError = "" )" Ordering="201"/>
|
||||
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="WelcomeDlg" Condition="AI_INSTALL" Ordering="203"/>
|
||||
<ROW Dialog_="FolderDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_INSTALL AND ( SqlConnectionError = "" AND ELK_CONNECTION = 1 )" Ordering="207"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="Next" Event="DoAction" Argument="TestSqlConnection" Condition="AI_INSTALL" Ordering="3"/>
|
||||
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="FolderDlg" Condition="AI_INSTALL AND ( OLDPRODUCTS = "" AND SqlConnectionError = "" AND ELK_CONNECTION = 1 )" Ordering="201"/>
|
||||
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="WelcomeDlg" Condition="AI_INSTALL" Ordering="202"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control_="Cancel" Event="SpawnDialog" Argument="CancelDlg" Condition="1" Ordering="100"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_INSTALL AND ( ELK_CONNECTION = 1 AND SqlConnectionError = "" )" Ordering="7"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control_="Back" Event="NewDialog" Argument="FolderDlg" Condition="AI_INSTALL AND ( OLDPRODUCTS = "" )" Ordering="3"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control_="Back" Event="NewDialog" Argument="SQLConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError <> "" )" Ordering="5"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control_="Next" Event="DoAction" Argument="TestElasticsearchConnection" Condition="AI_INSTALL" Ordering="3"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control_="Next" Event="DoAction" Argument="AI_DATA_SETTER_1" Condition="AI_INSTALL" Ordering="2"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control_="Next" Event="DoAction" Argument="TestElasticsearchConnectionMsgBox" Condition="AI_INSTALL AND ( ELK_CONNECTION = 0 )" Ordering="6"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control_="Next" Event="DoAction" Argument="AI_DATA_SETTER" Condition="AI_INSTALL AND ( ELK_CONNECTION = 0 )" Ordering="5"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="Back" Event="NewDialog" Argument="WelcomeDlg" Condition="AI_INSTALL AND ( OLDPRODUCTS <> "" )" Ordering="3"/>
|
||||
<ROW Dialog_="ELKConnectionDlg" Control_="Back" Event="NewDialog" Argument="WelcomeDlg" Condition="AI_INSTALL AND ( OLDPRODUCTS <> "" )" Ordering="4"/>
|
||||
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="DoAction" Argument="TestElasticsearchConnection" Condition="AI_INSTALL AND ( SqlConnectionError = "" )" Ordering="3"/>
|
||||
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="DoAction" Argument="AI_DATA_SETTER_1" Condition="AI_INSTALL AND ( SqlConnectionError = "" )" Ordering="2"/>
|
||||
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="NewDialog" Argument="ELKConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError = "" AND ELK_CONNECTION = 0 )" Ordering="5"/>
|
||||
<ROW Dialog_="SQLConnectionDlg" Control_="Next" Event="SpawnDialog" Argument="VerifyReadyDlg" Condition="AI_INSTALL AND ( SqlConnectionError = "" AND ELK_CONNECTION = 1 )" Ordering="8"/>
|
||||
<ROW Dialog_="FolderDlg" Control_="Next" Event="DoAction" Argument="TestElasticsearchConnection" Condition="AI_INSTALL" Ordering="204"/>
|
||||
<ROW Dialog_="FolderDlg" Control_="Next" Event="DoAction" Argument="AI_DATA_SETTER_1" Condition="AI_INSTALL" Ordering="203"/>
|
||||
<ROW Dialog_="FolderDlg" Control_="Next" Event="NewDialog" Argument="ELKConnectionDlg" Condition="AI_INSTALL AND ( SqlConnectionError = "" AND ELK_CONNECTION = 0 )" Ordering="206"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiCreateFolderComponent">
|
||||
<ROW Directory_="APPDIR" Component_="APPDIR" ManualDelete="true"/>
|
||||
@ -331,6 +368,8 @@
|
||||
<ROW Action="AI_AppSearchEx" Type="1" Source="Prereq.dll" Target="DoAppSearchEx"/>
|
||||
<ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Type="51" Source="AI_SETUPEXEPATH_ORIGINAL" Target="[AI_SETUPEXEPATH]"/>
|
||||
<ROW Action="AI_ConfigFailActions" Type="11265" Source="aicustact.dll" Target="ConfigureServFailActions" WithoutSeq="true"/>
|
||||
<ROW Action="AI_DATA_SETTER" Type="51" Source="CustomActionData" Target="[ELASTICSEARCH_MSG] \n[ELASTICSEARCH_SCHEME]://[ELASTICSEARCH_HOST]:[ELASTICSEARCH_PORT] |[ProductName] Setup |MB_OK,MB_ICONWARNING,MB_DEFBUTTON1||[CLIENTPROCESSID]"/>
|
||||
<ROW Action="AI_DATA_SETTER_1" Type="51" Source="CustomActionData" Target="AEQAaQBnAGkAdABhAGwAbAB5AFMAaQBnAG4AUwBjAHIAaQBwAHQAAgABAEYAbABhAGcAcwACADYAAQBQAGEAcgBhAG0AcwACAAEAUwBjAHIAaQBwAHQAAgAjAFIAZQBxAHUAaQByAGUAcwAgAC0AdgBlAHIAcwBpAG8AbgAgADMADQAKAFAAYQByAGEAbQAoACkADQAKAA0ACgBmAHUAbgBjAHQAaQBvAG4AIABDAGgAZQBjAGsAVABDAFAAUABvAHIAdABBAHYAYQBpAGwAYQBiAGkAbABpAHQAeQAgAFsAXAB7AF0ADQAKAA0ACgAgACAAcABhAHIAYQBtACAAKAAgACQAdABjAHAAXwBoAG8AcwB0ACwAIAAkAHAAbwByAHQAIAApAA0ACgANAAoAIAAgACQAdABpAG0AZQBfAHQAbwBfAHcAYQBpAHQAIAA9ACAAMQAwADAAMAANAAoAIAAgACQAdABjAHAAbwBiAGoAZQBjAHQAIAA9ACAATgBlAHcALQBPAGIAagBlAGMAdAAgAHMAeQBzAHQAZQBtAC4ATgBlAHQALgBTAG8AYwBrAGUAdABzAC4AVABjAHAAQwBsAGkAZQBuAHQADQAKACAAIAAkAGMAbwBuAG4AZQBjAHQAIAA9ACAAJAB0AGMAcABvAGIAagBlAGMAdAAuAEIAZQBnAGkAbgBDAG8AbgBuAGUAYwB0ACgAJAB0AGMAcABfAGgAbwBzAHQALAAgACQAcABvAHIAdAAsACAAJABuAHUAbABsACwAIAAkAG4AdQBsAGwAKQANAAoAIAAgACQAdwBhAGkAdAAgAD0AIAAkAGMAbwBuAG4AZQBjAHQALgBBAHMAeQBuAGMAVwBhAGkAdABIAGEAbgBkAGwAZQAuAFcAYQBpAHQATwBuAGUAKAAkAHQAaQBtAGUAXwB0AG8AXwB3AGEAaQB0ACwAIAAkAGYAYQBsAHMAZQApAA0ACgAgACAAaQBmACAAKAAtAE4AbwB0ACAAJAB3AGEAaQB0ACkAIABbAFwAewBdAA0ACgAgACAAIAAgAHIAZQB0AHUAcgBuACAAMAANAAoAIAAgAFsAXAB9AF0AIABlAGwAcwBlACAAWwBcAHsAXQANAAoAIAAgACAAIAAkAEUAcgByAG8AcgAuAGMAbABlAGEAcgAoACkADQAKACAAIAAgACAAJAB0AGMAcABvAGIAagBlAGMAdAAuAEUAbgBkAEMAbwBuAG4AZQBjAHQAKAAkAGMAbwBuAG4AZQBjAHQAKQAgAHwAIABPAHUAdAAtAE4AdQBsAGwADQAKACAAIAAgACAAaQBmACAAKAAkAEUAcgByAG8AcgBbAFwAWwBdADAAWwBcAF0AXQApACAAWwBcAHsAXQANAAoAIAAgACAAIAAgACAAIAAgAFcAcgBpAHQAZQAtAFcAYQByAG4AaQBuAGcAIAAoACIAWwBcAHsAXQAwAFsAXAB9AF0AIgAgAC0AZgAgACQARQByAHIAbwByAFsAXABbAF0AMABbAFwAXQBdAC4ARQB4AGMAZQBwAHQAaQBvAG4ALgBNAGUAcwBzAGEAZwBlACkADQAKACAAIAAgACAAWwBcAH0AXQAgAGUAbABzAGUAIABbAFwAewBdAA0ACgAgACAAIAAgACAAIAAgACAAcgBlAHQAdQByAG4AIAAxAA0ACgAgACAAIAAgAFsAXAB9AF0ADQAKACAAIABbAFwAfQBdAA0ACgBbAFwAfQBdAA0ACgANAAoAJABFAEwASwBfAEgATwBTAFQAIAA9ACAAQQBJAF8ARwBlAHQATQBzAGkAUAByAG8AcABlAHIAdAB5ACAARQBMAEEAUwBUAEkAQwBTAEUAQQBSAEMASABfAEgATwBTAFQADQAKACQARQBMAEsAXwBQAE8AUgBUACAAPQAgAEEASQBfAEcAZQB0AE0AcwBpAFAAcgBvAHAAZQByAHQAeQAgAEUATABBAFMAVABJAEMAUwBFAEEAUgBDAEgAXwBQAE8AUgBUAA0ACgANAAoAJABFAEwASwBfAEMATwBOAE4ARQBDAFQASQBPAE4AIAA9ACAAQwBoAGUAYwBrAFQAQwBQAFAAbwByAHQAQQB2AGEAaQBsAGEAYgBpAGwAaQB0AHkAIAAkAEUATABLAF8ASABPAFMAVAAgACQARQBMAEsAXwBQAE8AUgBUAA0ACgANAAoAQQBJAF8AUwBlAHQATQBzAGkAUAByAG8AcABlAHIAdAB5ACAARQBMAEsAXwBDAE8ATgBOAEUAQwBUAEkATwBOACAAJABFAEwASwBfAEMATwBOAE4ARQBDAFQASQBPAE4="/>
|
||||
<ROW Action="AI_DATA_SETTER_10" Type="51" Source="CustomActionData" Target="MySQL80"/>
|
||||
<ROW Action="AI_DATA_SETTER_11" Type="51" Source="CustomActionData" Target="MySQL80"/>
|
||||
<ROW Action="AI_DATA_SETTER_12" Type="51" Source="CustomActionData" Target="Elasticsearch"/>
|
||||
@ -388,9 +427,14 @@
|
||||
<ROW Action="StartMySQLService" Type="1" Source="aicustact.dll" Target="StartWinService" Options="1" AdditionalSeq="AI_DATA_SETTER_11"/>
|
||||
<ROW Action="StopElasticSearchService" Type="1" Source="aicustact.dll" Target="StopWinService" Options="1" AdditionalSeq="AI_DATA_SETTER_12"/>
|
||||
<ROW Action="StopMySQLService" Type="1" Source="aicustact.dll" Target="StopWinService" Options="1" AdditionalSeq="AI_DATA_SETTER_10"/>
|
||||
<ROW Action="TestElasticsearchConnection" Type="1" Source="PowerShellScriptLauncher.dll" Target="RunPowerShellScript" WithoutSeq="true" Options="1" AdditionalSeq="AI_DATA_SETTER_1"/>
|
||||
<ROW Action="TestElasticsearchConnectionMsgBox" Type="1" Source="aicustact.dll" Target="MsgBox" WithoutSeq="true" Options="1" AdditionalSeq="AI_DATA_SETTER"/>
|
||||
<ROW Action="TestSQLConnectionMsgBox" Type="1" Source="aicustact.dll" Target="MsgBox" WithoutSeq="true" Options="1" AdditionalSeq="AI_DATA_SETTER_5"/>
|
||||
<ROW Action="TestSqlConnection" Type="6" Source="utils.vbs" Target="TestSqlConnection" WithoutSeq="true"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiDialogComponent">
|
||||
<ROW Dialog="ELKConnectionDlg" HCentering="50" VCentering="50" Width="370" Height="270" Attributes="3" Title="[ProductName] [Setup]" Control_Default="Next" Control_Cancel="Cancel"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiEnvComponent">
|
||||
<ROW Environment="JAVA_HOME" Name="=-*JAVA_HOME" Value="[WindowsVolume]Progra~1\Elastic\Elasticsearch\7.13.1\jdk" Component_="AI_ExePath"/>
|
||||
<ROW Environment="Path" Name="=*Path" Value="[~];%JAVA_HOME%\bin" Component_="AI_ExePath"/>
|
||||
|
@ -75,6 +75,7 @@ namespace ASC.IPSecurity
|
||||
});
|
||||
|
||||
TenantDbContext.TenantIpRestrictions.AddRange(ipsList);
|
||||
TenantDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
return ips.ToList();
|
||||
|
@ -159,7 +159,7 @@
|
||||
"enabled": "true"
|
||||
},
|
||||
"thumbnail": {
|
||||
"thumbnaillHeight": 156,
|
||||
"thumbnaillWidth": 216
|
||||
"thumbnaillHeight": 260,
|
||||
"thumbnaillWidth": 360
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"kafka": {
|
||||
"BootstrapServers": ""
|
||||
}
|
||||
}
|
||||
{
|
||||
"kafka": {
|
||||
"BootstrapServers": "localhost:9092"
|
||||
}
|
||||
}
|
||||
|
@ -13,103 +13,105 @@ import SortButton from "./sub-components/SortButton";
|
||||
|
||||
import { StyledFilterInput, StyledSearchInput } from "./StyledFilterInput";
|
||||
|
||||
const FilterInput = ({
|
||||
t,
|
||||
sectionWidth,
|
||||
getFilterData,
|
||||
getSortData,
|
||||
getViewSettingsData,
|
||||
getSelectedFilterData,
|
||||
onFilter,
|
||||
onSearch,
|
||||
onSort,
|
||||
onChangeViewAs,
|
||||
viewAs,
|
||||
placeholder,
|
||||
contextMenuHeader,
|
||||
headerLabel,
|
||||
viewSelectorVisible,
|
||||
isRecentFolder,
|
||||
isFavoritesFolder,
|
||||
...props
|
||||
}) => {
|
||||
const [viewSettings, setViewSettings] = React.useState([]);
|
||||
const [selectedFilterData, setSelectedFilterData] = React.useState([]);
|
||||
const FilterInput = React.memo(
|
||||
({
|
||||
t,
|
||||
sectionWidth,
|
||||
getFilterData,
|
||||
getSortData,
|
||||
getViewSettingsData,
|
||||
getSelectedFilterData,
|
||||
onFilter,
|
||||
onSearch,
|
||||
onSort,
|
||||
onChangeViewAs,
|
||||
viewAs,
|
||||
placeholder,
|
||||
contextMenuHeader,
|
||||
headerLabel,
|
||||
viewSelectorVisible,
|
||||
isRecentFolder,
|
||||
isFavoritesFolder,
|
||||
...props
|
||||
}) => {
|
||||
const [viewSettings, setViewSettings] = React.useState([]);
|
||||
const [selectedFilterData, setSelectedFilterData] = React.useState([]);
|
||||
|
||||
const [inputValue, setInputValue] = React.useState("");
|
||||
const [inputValue, setInputValue] = React.useState("");
|
||||
|
||||
const getSelectedFilterDataAction = React.useCallback(async () => {
|
||||
const data = await getSelectedFilterData();
|
||||
const getSelectedFilterDataAction = React.useCallback(async () => {
|
||||
const data = await getSelectedFilterData();
|
||||
|
||||
setSelectedFilterData(data);
|
||||
setInputValue(!!data.inputValue ? data.inputValue : "");
|
||||
}, [getSelectedFilterData]);
|
||||
setSelectedFilterData(data);
|
||||
setInputValue(!!data.inputValue ? data.inputValue : "");
|
||||
}, [getSelectedFilterData]);
|
||||
|
||||
React.useEffect(() => {
|
||||
getSelectedFilterDataAction();
|
||||
}, [getSelectedFilterData]);
|
||||
React.useEffect(() => {
|
||||
getSelectedFilterDataAction();
|
||||
}, [getSelectedFilterData]);
|
||||
|
||||
React.useEffect(() => {
|
||||
getViewSettingsData && setViewSettings(getViewSettingsData());
|
||||
}, [getViewSettingsData]);
|
||||
React.useEffect(() => {
|
||||
getViewSettingsData && setViewSettings(getViewSettingsData());
|
||||
}, [getViewSettingsData]);
|
||||
|
||||
const onClearSearch = () => {
|
||||
onSearch && onSearch();
|
||||
};
|
||||
const onClearSearch = () => {
|
||||
onSearch && onSearch();
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledFilterInput {...props} sectionWidth={sectionWidth}>
|
||||
<StyledSearchInput
|
||||
placeholder={placeholder}
|
||||
value={inputValue}
|
||||
onChange={onSearch}
|
||||
onClearSearch={onClearSearch}
|
||||
/>
|
||||
|
||||
<FilterButton
|
||||
t={t}
|
||||
selectedFilterData={selectedFilterData}
|
||||
contextMenuHeader={contextMenuHeader}
|
||||
getFilterData={getFilterData}
|
||||
onFilter={onFilter}
|
||||
headerLabel={headerLabel}
|
||||
/>
|
||||
|
||||
{viewSettings &&
|
||||
!isMobile &&
|
||||
viewSelectorVisible &&
|
||||
!isMobileUtils() &&
|
||||
!isTabletUtils() ? (
|
||||
<ViewSelector
|
||||
style={{ marginLeft: "8px" }}
|
||||
onChangeView={onChangeViewAs}
|
||||
viewAs={viewAs === "table" ? "row" : viewAs}
|
||||
viewSettings={viewSettings}
|
||||
return (
|
||||
<StyledFilterInput {...props} sectionWidth={sectionWidth}>
|
||||
<StyledSearchInput
|
||||
placeholder={placeholder}
|
||||
value={inputValue}
|
||||
onChange={onSearch}
|
||||
onClearSearch={onClearSearch}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{(isMobile || isTabletUtils() || isMobileUtils()) && (
|
||||
<SortButton
|
||||
t={t}
|
||||
selectedFilterData={selectedFilterData}
|
||||
getSortData={getSortData}
|
||||
onChangeViewAs={onChangeViewAs}
|
||||
viewAs={viewAs === "table" ? "row" : viewAs}
|
||||
viewSettings={viewSettings}
|
||||
onSort={onSort}
|
||||
viewSelectorVisible={viewSelectorVisible}
|
||||
isRecentFolder={isRecentFolder}
|
||||
isFavoritesFolder={isFavoritesFolder}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</StyledFilterInput>
|
||||
);
|
||||
};
|
||||
|
||||
<FilterButton
|
||||
t={t}
|
||||
selectedFilterData={selectedFilterData}
|
||||
contextMenuHeader={contextMenuHeader}
|
||||
getFilterData={getFilterData}
|
||||
onFilter={onFilter}
|
||||
headerLabel={headerLabel}
|
||||
/>
|
||||
|
||||
{viewSettings &&
|
||||
!isMobile &&
|
||||
viewSelectorVisible &&
|
||||
!isMobileUtils() &&
|
||||
!isTabletUtils() ? (
|
||||
<ViewSelector
|
||||
style={{ marginLeft: "8px" }}
|
||||
onChangeView={onChangeViewAs}
|
||||
viewAs={viewAs === "table" ? "row" : viewAs}
|
||||
viewSettings={viewSettings}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{(isMobile || isTabletUtils() || isMobileUtils()) && (
|
||||
<SortButton
|
||||
t={t}
|
||||
selectedFilterData={selectedFilterData}
|
||||
getSortData={getSortData}
|
||||
onChangeViewAs={onChangeViewAs}
|
||||
viewAs={viewAs === "table" ? "row" : viewAs}
|
||||
viewSettings={viewSettings}
|
||||
onSort={onSort}
|
||||
viewSelectorVisible={viewSelectorVisible}
|
||||
isRecentFolder={isRecentFolder}
|
||||
isFavoritesFolder={isFavoritesFolder}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</StyledFilterInput>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
FilterInput.defaultProps = {
|
||||
viewSelectorVisible: false,
|
||||
};
|
||||
|
||||
export default React.memo(FilterInput);
|
||||
export default FilterInput;
|
||||
|
@ -30,6 +30,10 @@ const Navigation = ({
|
||||
isRecycleBinFolder,
|
||||
isEmptyFilesList,
|
||||
clearTrash,
|
||||
showFolderInfo,
|
||||
isCurrentFolderInfo,
|
||||
toggleInfoPanel,
|
||||
isInfoPanelVisible,
|
||||
...rest
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = React.useState(false);
|
||||
@ -133,6 +137,8 @@ const Navigation = ({
|
||||
isRecycleBinFolder={isRecycleBinFolder}
|
||||
isEmptyFilesList={isEmptyFilesList}
|
||||
clearTrash={clearTrash}
|
||||
toggleInfoPanel={toggleInfoPanel}
|
||||
isInfoPanelVisible={isInfoPanelVisible}
|
||||
/>
|
||||
</StyledContainer>
|
||||
</>
|
||||
|
@ -3,16 +3,11 @@ import { isMobile, isMobileOnly } from "react-device-detect";
|
||||
import { tablet, desktop, mobile } from "@appserver/components/utils/device";
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
padding: ${(props) => (props.isDropBox ? "14px 0 3px" : "14px 0 0px")};
|
||||
|
||||
width: fit-content;
|
||||
|
||||
width: 100% !important;
|
||||
display: grid;
|
||||
|
||||
grid-template-columns: ${(props) =>
|
||||
props.isRootFolder ? "1fr auto" : "29px 1fr auto"};
|
||||
|
||||
align-items: center;
|
||||
grid-template-columns: ${(props) =>
|
||||
props.isRootFolder ? "auto 1fr" : "29px auto 1fr"};
|
||||
|
||||
.arrow-button {
|
||||
width: 17px;
|
||||
@ -31,8 +26,7 @@ const StyledContainer = styled.div`
|
||||
`}
|
||||
|
||||
@media ${mobile} {
|
||||
width: 100%;
|
||||
padding: ${(props) => (props.isDropBox ? "12px 0 5px" : "12px 0 0")};
|
||||
height: 53px;
|
||||
}
|
||||
|
||||
${isMobileOnly &&
|
||||
|
@ -5,6 +5,7 @@ import ContextMenuButton from "@appserver/components/context-menu-button";
|
||||
import IconButton from "@appserver/components/icon-button";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { tablet } from "@appserver/components/utils/device";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
margin-left: 20px;
|
||||
@ -30,7 +31,8 @@ const StyledContainer = styled.div`
|
||||
}
|
||||
|
||||
.option-button {
|
||||
margin-right: 8px;
|
||||
margin-left: auto;
|
||||
margin-right: 15px;
|
||||
min-width: 17px;
|
||||
}
|
||||
|
||||
@ -39,6 +41,35 @@ const StyledContainer = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledInfoPanelToggleWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-self: center;
|
||||
justify-content: center;
|
||||
margin-left: ${({ isRootFolder }) => (isRootFolder ? "auto" : "none")};
|
||||
|
||||
.info-panel-toggle-bg {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background-color: ${(props) =>
|
||||
props.isInfoPanelVisible
|
||||
? props.theme.infoPanel.sectionHeaderToggleBgActive
|
||||
: props.theme.infoPanel.sectionHeaderToggleBg};
|
||||
|
||||
path {
|
||||
fill: ${(props) =>
|
||||
props.isInfoPanelVisible
|
||||
? props.theme.infoPanel.sectionHeaderToggleIconActive
|
||||
: props.theme.infoPanel.sectionHeaderToggleIcon};
|
||||
}
|
||||
}
|
||||
`;
|
||||
StyledInfoPanelToggleWrapper.defaultProps = { theme: Base };
|
||||
|
||||
const ControlButtons = ({
|
||||
personal,
|
||||
isDropBox,
|
||||
@ -49,6 +80,8 @@ const ControlButtons = ({
|
||||
isRecycleBinFolder,
|
||||
isEmptyFilesList,
|
||||
clearTrash,
|
||||
isInfoPanelVisible,
|
||||
toggleInfoPanel,
|
||||
}) => {
|
||||
return (
|
||||
<StyledContainer isDropBox={isDropBox}>
|
||||
@ -96,6 +129,20 @@ const ControlButtons = ({
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<StyledInfoPanelToggleWrapper
|
||||
isRootFolder={isRootFolder}
|
||||
isInfoPanelVisible={isInfoPanelVisible}
|
||||
>
|
||||
<div className="info-panel-toggle-bg">
|
||||
<IconButton
|
||||
className="info-panel-toggle"
|
||||
iconName="images/panel.svg"
|
||||
size="16"
|
||||
isFill={true}
|
||||
onClick={toggleInfoPanel}
|
||||
/>
|
||||
</div>
|
||||
</StyledInfoPanelToggleWrapper>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
@ -19,6 +19,10 @@ import SubSectionBody from "./sub-components/section-body";
|
||||
import SubSectionBodyContent from "./sub-components/section-body-content";
|
||||
import SubSectionBar from "./sub-components/section-bar";
|
||||
import SubSectionPaging from "./sub-components/section-paging";
|
||||
//import SectionToggler from "./sub-components/section-toggler";
|
||||
import InfoPanel from "./sub-components/info-panel";
|
||||
import SubInfoPanelBody from "./sub-components/info-panel-body";
|
||||
import SubInfoPanelHeader from "./sub-components/info-panel-header";
|
||||
|
||||
import ReactResizeDetector from "react-resize-detector";
|
||||
import FloatingButton from "../FloatingButton";
|
||||
@ -36,8 +40,13 @@ const StyledMainBar = styled.div`
|
||||
box-sizing: border-box;
|
||||
|
||||
margin-left: -20px;
|
||||
width: calc(100vw - 256px);
|
||||
max-width: calc(100vw - 256px);
|
||||
/* width: calc(100vw - 256px);
|
||||
max-width: calc(100vw - 256px); */
|
||||
|
||||
width: ${(props) =>
|
||||
props.infoPanelIsVisible ? "calc(100vw - 657px)" : "calc(100vw - 256px)"};
|
||||
max-width: ${(props) =>
|
||||
props.infoPanelIsVisible ? "calc(100vw - 657px)" : "calc(100vw - 256px)"};
|
||||
|
||||
#bar-banner {
|
||||
margin-bottom: -3px;
|
||||
@ -123,12 +132,24 @@ function SectionPaging() {
|
||||
}
|
||||
SectionPaging.displayName = "SectionPaging";
|
||||
|
||||
function InfoPanelBody() {
|
||||
return null;
|
||||
}
|
||||
InfoPanelBody.displayName = "InfoPanelBody";
|
||||
|
||||
function InfoPanelHeader() {
|
||||
return null;
|
||||
}
|
||||
InfoPanelHeader.displayName = "InfoPanelHeader";
|
||||
|
||||
class Section extends React.Component {
|
||||
static SectionHeader = SectionHeader;
|
||||
static SectionFilter = SectionFilter;
|
||||
static SectionBody = SectionBody;
|
||||
static SectionBar = SectionBar;
|
||||
static SectionPaging = SectionPaging;
|
||||
static InfoPanelBody = InfoPanelBody;
|
||||
static InfoPanelHeader = InfoPanelHeader;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -208,6 +229,7 @@ class Section extends React.Component {
|
||||
setMaintenanceExist,
|
||||
snackbarExist,
|
||||
showText,
|
||||
infoPanelIsVisible,
|
||||
} = this.props;
|
||||
|
||||
let sectionHeaderContent = null;
|
||||
@ -215,6 +237,9 @@ class Section extends React.Component {
|
||||
let sectionFilterContent = null;
|
||||
let sectionPagingContent = null;
|
||||
let sectionBodyContent = null;
|
||||
let infoPanelBodyContent = null;
|
||||
let infoPanelHeaderContent = null;
|
||||
|
||||
React.Children.forEach(children, (child) => {
|
||||
const childType =
|
||||
child && child.type && (child.type.displayName || child.type.name);
|
||||
@ -235,6 +260,12 @@ class Section extends React.Component {
|
||||
case SectionBody.displayName:
|
||||
sectionBodyContent = child;
|
||||
break;
|
||||
case InfoPanelBody.displayName:
|
||||
infoPanelBodyContent = child;
|
||||
break;
|
||||
case InfoPanelHeader.displayName:
|
||||
infoPanelHeaderContent = child;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -277,6 +308,7 @@ class Section extends React.Component {
|
||||
maintenanceExist={maintenanceExist}
|
||||
isSectionBarAvailable={isSectionBarAvailable}
|
||||
isSectionHeaderAvailable={isSectionHeaderAvailable}
|
||||
infoPanelIsVisible={infoPanelIsVisible}
|
||||
>
|
||||
{!isMobile && (
|
||||
<StyledMainBar
|
||||
@ -285,6 +317,7 @@ class Section extends React.Component {
|
||||
className={"main-bar"}
|
||||
showText={showText}
|
||||
isSectionHeaderAvailable={isSectionHeaderAvailable}
|
||||
infoPanelIsVisible={infoPanelIsVisible}
|
||||
>
|
||||
<SubSectionBar
|
||||
setMaintenanceExist={setMaintenanceExist}
|
||||
@ -302,6 +335,7 @@ class Section extends React.Component {
|
||||
snackbarExist={snackbarExist}
|
||||
className="section-header_header"
|
||||
isHeaderVisible={isHeaderVisible}
|
||||
infoPanelIsVisible={infoPanelIsVisible}
|
||||
viewAs={viewAs}
|
||||
showText={showText}
|
||||
>
|
||||
@ -322,6 +356,7 @@ class Section extends React.Component {
|
||||
</SubSectionFilter>
|
||||
</>
|
||||
)}
|
||||
|
||||
{isSectionBodyAvailable && (
|
||||
<>
|
||||
<SubSectionBody
|
||||
@ -341,6 +376,7 @@ class Section extends React.Component {
|
||||
isSectionHeaderAvailable={
|
||||
isSectionHeaderAvailable
|
||||
}
|
||||
infoPanelIsVisible={infoPanelIsVisible}
|
||||
>
|
||||
<SubSectionBar
|
||||
setMaintenanceExist={setMaintenanceExist}
|
||||
@ -358,6 +394,7 @@ class Section extends React.Component {
|
||||
isHeaderVisible={isHeaderVisible}
|
||||
viewAs={viewAs}
|
||||
showText={showText}
|
||||
infoPanelIsVisible={infoPanelIsVisible}
|
||||
>
|
||||
{sectionHeaderContent
|
||||
? sectionHeaderContent.props.children
|
||||
@ -372,11 +409,13 @@ class Section extends React.Component {
|
||||
: null}
|
||||
</SubSectionFilter>
|
||||
)}
|
||||
|
||||
<SubSectionBodyContent>
|
||||
{sectionBodyContent
|
||||
? sectionBodyContent.props.children
|
||||
: null}
|
||||
</SubSectionBodyContent>
|
||||
|
||||
{isSectionPagingAvailable && (
|
||||
<SubSectionPaging>
|
||||
{sectionPagingContent
|
||||
@ -387,6 +426,7 @@ class Section extends React.Component {
|
||||
</SubSectionBody>
|
||||
</>
|
||||
)}
|
||||
|
||||
{!(isMobile || isMobileUtils() || isTabletUtils()) ? (
|
||||
showPrimaryProgressBar && showSecondaryProgressBar ? (
|
||||
<>
|
||||
@ -428,6 +468,12 @@ class Section extends React.Component {
|
||||
<></>
|
||||
)}
|
||||
</SectionContainer>
|
||||
<InfoPanel>
|
||||
<SubInfoPanelHeader>
|
||||
{infoPanelHeaderContent}
|
||||
</SubInfoPanelHeader>
|
||||
<SubInfoPanelBody>{infoPanelBodyContent}</SubInfoPanelBody>
|
||||
</InfoPanel>
|
||||
</Provider>
|
||||
)}
|
||||
</ReactResizeDetector>
|
||||
@ -501,12 +547,14 @@ Section.defaultProps = {
|
||||
withBodyAutoFocus: false,
|
||||
};
|
||||
|
||||
Section.InfoPanelHeader = InfoPanelHeader;
|
||||
Section.InfoPanelBody = InfoPanelBody;
|
||||
Section.SectionHeader = SectionHeader;
|
||||
Section.SectionFilter = SectionFilter;
|
||||
Section.SectionBody = SectionBody;
|
||||
Section.SectionPaging = SectionPaging;
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
export default inject(({ auth, infoPanelStore }) => {
|
||||
const { isLoaded, settingsStore } = auth;
|
||||
const {
|
||||
isHeaderVisible,
|
||||
@ -523,6 +571,9 @@ export default inject(({ auth }) => {
|
||||
showText,
|
||||
} = settingsStore;
|
||||
|
||||
let infoPanelIsVisible = false;
|
||||
if (infoPanelStore) infoPanelIsVisible = infoPanelStore.isVisible;
|
||||
|
||||
return {
|
||||
isLoaded,
|
||||
isTabletView,
|
||||
@ -536,5 +587,7 @@ export default inject(({ auth }) => {
|
||||
isDesktop: isDesktopClient,
|
||||
|
||||
showText,
|
||||
|
||||
infoPanelIsVisible: infoPanelIsVisible,
|
||||
};
|
||||
})(observer(Section));
|
||||
|
@ -0,0 +1,16 @@
|
||||
import Scrollbar from "@appserver/components/scrollbar";
|
||||
import React from "react";
|
||||
|
||||
const SubInfoPanelBody = ({ children }) => {
|
||||
const content = children?.props?.children;
|
||||
|
||||
return (
|
||||
<Scrollbar scrollclass="section-scroll" stype="mediumBlack">
|
||||
{content}
|
||||
</Scrollbar>
|
||||
);
|
||||
};
|
||||
|
||||
SubInfoPanelBody.displayName = "SubInfoPanelBody";
|
||||
|
||||
export default SubInfoPanelBody;
|
@ -0,0 +1,58 @@
|
||||
import IconButton from "@appserver/components/icon-button";
|
||||
import Text from "@appserver/components/text";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
import { tablet } from "@appserver/components/utils/device";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import PropTypes from "prop-types";
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
const StyledInfoPanelHeader = styled.div`
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: 54px;
|
||||
min-height: 54px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: ${(props) => `1px solid ${props.theme.infoPanel.borderColor}`};
|
||||
|
||||
.header-text {
|
||||
margin-left: 20px;
|
||||
}
|
||||
`;
|
||||
|
||||
const SubInfoPanelHeader = ({ children, onHeaderCrossClick }) => {
|
||||
const content = children?.props?.children;
|
||||
|
||||
return (
|
||||
<StyledInfoPanelHeader>
|
||||
<Text className="header-text" fontSize="21px" fontWeight="700">
|
||||
{content}
|
||||
</Text>
|
||||
</StyledInfoPanelHeader>
|
||||
);
|
||||
};
|
||||
|
||||
SubInfoPanelHeader.propTypes = {
|
||||
children: PropTypes.oneOfType([
|
||||
PropTypes.arrayOf(PropTypes.node),
|
||||
PropTypes.node,
|
||||
PropTypes.any,
|
||||
]),
|
||||
toggleIsVisible: PropTypes.func,
|
||||
};
|
||||
|
||||
StyledInfoPanelHeader.defaultProps = { theme: Base };
|
||||
SubInfoPanelHeader.defaultProps = { theme: Base };
|
||||
|
||||
SubInfoPanelHeader.displayName = "SubInfoPanelHeader";
|
||||
|
||||
export default inject(({ infoPanelStore }) => {
|
||||
let onHeaderCrossClick = () => {};
|
||||
if (infoPanelStore) {
|
||||
onHeaderCrossClick = infoPanelStore.onHeaderCrossClick;
|
||||
}
|
||||
return { onHeaderCrossClick };
|
||||
})(observer(SubInfoPanelHeader));
|
@ -0,0 +1,140 @@
|
||||
import IconButton from "@appserver/components/icon-button";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
import { isTablet, mobile, tablet } from "@appserver/components/utils/device";
|
||||
import { inject } from "mobx-react";
|
||||
import PropTypes from "prop-types";
|
||||
import React, { useEffect } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
const StyledInfoPanelWrapper = styled.div.attrs(({ id }) => ({
|
||||
id: id,
|
||||
}))`
|
||||
height: auto;
|
||||
width: auto;
|
||||
background: rgba(6, 22, 38, 0.2);
|
||||
backdrop-filter: blur(18px);
|
||||
|
||||
@media ${tablet} {
|
||||
z-index: 309;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledInfoPanel = styled.div`
|
||||
height: 100%;
|
||||
width: 400px;
|
||||
background-color: ${(props) => props.theme.infoPanel.backgroundColor};
|
||||
border-left: ${(props) => `1px solid ${props.theme.infoPanel.borderColor}`};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@media ${tablet} {
|
||||
position: absolute;
|
||||
border: none;
|
||||
right: 0;
|
||||
width: 480px;
|
||||
max-width: calc(100vw - 69px);
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
bottom: 0;
|
||||
height: 80%;
|
||||
width: 100vw;
|
||||
max-width: 100vw;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledCloseButtonWrapper = styled.div`
|
||||
position: absolute;
|
||||
display: none;
|
||||
background-color: ${(props) => props.theme.infoPanel.closeButtonBg};
|
||||
padding: ${(props) => props.theme.infoPanel.closeButtonWrapperPadding};
|
||||
border-radius: 50%;
|
||||
|
||||
.info-panel-button {
|
||||
svg {
|
||||
width: ${(props) => props.theme.infoPanel.closeButtonSize};
|
||||
height: ${(props) => props.theme.infoPanel.closeButtonSize};
|
||||
}
|
||||
path {
|
||||
fill: ${(props) => props.theme.infoPanel.closeButtonIcon};
|
||||
}
|
||||
}
|
||||
|
||||
@media ${tablet} {
|
||||
display: block;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin-top: 18px;
|
||||
margin-left: -34px;
|
||||
}
|
||||
@media ${mobile} {
|
||||
right: 0;
|
||||
left: auto;
|
||||
margin-top: -34px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
`;
|
||||
|
||||
const InfoPanel = ({ children, isVisible, setIsVisible }) => {
|
||||
if (!isVisible) return null;
|
||||
|
||||
const closeInfoPanel = () => setIsVisible(false);
|
||||
|
||||
useEffect(() => {
|
||||
const onMouseDown = (e) => {
|
||||
if (e.target.id === "InfoPanelWrapper") closeInfoPanel();
|
||||
};
|
||||
|
||||
if (isTablet()) document.addEventListener("mousedown", onMouseDown);
|
||||
return () => document.removeEventListener("mousedown", onMouseDown);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<StyledInfoPanelWrapper className="info-panel" id="InfoPanelWrapper">
|
||||
<StyledInfoPanel>
|
||||
<StyledCloseButtonWrapper>
|
||||
<IconButton
|
||||
onClick={closeInfoPanel}
|
||||
iconName="/static/images/cross.react.svg"
|
||||
className="info-panel-button"
|
||||
/>
|
||||
</StyledCloseButtonWrapper>
|
||||
{children}
|
||||
</StyledInfoPanel>
|
||||
</StyledInfoPanelWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
InfoPanel.propTypes = {
|
||||
children: PropTypes.oneOfType([
|
||||
PropTypes.arrayOf(PropTypes.node),
|
||||
PropTypes.node,
|
||||
PropTypes.any,
|
||||
]),
|
||||
isVisible: PropTypes.bool,
|
||||
};
|
||||
|
||||
StyledInfoPanelWrapper.defaultProps = { theme: Base };
|
||||
StyledCloseButtonWrapper.defaultProps = { theme: Base };
|
||||
StyledInfoPanel.defaultProps = { theme: Base };
|
||||
InfoPanel.defaultProps = { theme: Base };
|
||||
|
||||
export default inject(({ infoPanelStore }) => {
|
||||
let isVisible = false;
|
||||
let setIsVisible = () => {};
|
||||
|
||||
if (infoPanelStore) {
|
||||
isVisible = infoPanelStore.isVisible;
|
||||
setIsVisible = infoPanelStore.setIsVisible;
|
||||
}
|
||||
|
||||
return {
|
||||
isVisible,
|
||||
setIsVisible,
|
||||
};
|
||||
})(InfoPanel);
|
@ -38,8 +38,10 @@ const StyledSectionContainer = styled.section`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
width: 100%;
|
||||
max-width: 100vw;
|
||||
width: ${(props) =>
|
||||
props.infoPanelIsVisible ? "calc(100% - 677px)" : "100%"};
|
||||
max-width: ${(props) =>
|
||||
props.infoPanelIsVisible ? "calc(100vw - 677px)" : "100vw"};
|
||||
|
||||
@media ${tablet} {
|
||||
width: 100%;
|
||||
|
@ -16,8 +16,16 @@ const StyledSectionHeader = styled.div`
|
||||
margin-right: 20px;
|
||||
${NoUserSelect}
|
||||
|
||||
width: calc(100vw - 296px);
|
||||
max-width: calc(100vw - 296px);
|
||||
display: grid;
|
||||
align-items: center;
|
||||
|
||||
/* width: calc(100vw - 296px);
|
||||
max-width: calc(100vw - 296px); */
|
||||
|
||||
width: ${(props) =>
|
||||
props.infoPanelIsVisible ? "calc(100vw - 696px)" : "calc(100vw - 296px)"};
|
||||
max-width: ${(props) =>
|
||||
props.infoPanelIsVisible ? "calc(100vw - 696px)" : "calc(100vw - 296px)"};
|
||||
|
||||
@media ${tablet} {
|
||||
width: ${(props) =>
|
||||
|
@ -11,7 +11,6 @@ export const EmployeeActivationStatus = Object.freeze({
|
||||
Pending: 2,
|
||||
AutoGenerated: 4,
|
||||
});
|
||||
|
||||
/**
|
||||
* Enum for employee status.
|
||||
* @readonly
|
||||
@ -20,7 +19,6 @@ export const EmployeeStatus = Object.freeze({
|
||||
Active: 1,
|
||||
Disabled: 2,
|
||||
});
|
||||
|
||||
/**
|
||||
* Enum for employee type.
|
||||
* @readonly
|
||||
@ -29,7 +27,6 @@ export const EmployeeType = Object.freeze({
|
||||
User: 1,
|
||||
Guest: 2,
|
||||
});
|
||||
|
||||
/**
|
||||
* Enum for filter type.
|
||||
* @readonly
|
||||
@ -48,7 +45,6 @@ export const FilterType = Object.freeze({
|
||||
ByExtension: 11,
|
||||
MediaOnly: 12,
|
||||
});
|
||||
|
||||
/**
|
||||
* Enum for file type.
|
||||
* @readonly
|
||||
@ -63,7 +59,6 @@ export const FileType = Object.freeze({
|
||||
Presentation: 6,
|
||||
Document: 7,
|
||||
});
|
||||
|
||||
/**
|
||||
* Enum for file action.
|
||||
* @readonly
|
||||
@ -72,7 +67,6 @@ export const FileAction = Object.freeze({
|
||||
Create: 0,
|
||||
Rename: 1,
|
||||
});
|
||||
|
||||
/**
|
||||
* Enum for root folders type.
|
||||
* @readonly
|
||||
@ -90,7 +84,6 @@ export const FolderType = Object.freeze({
|
||||
Templates: 12,
|
||||
Privacy: 13,
|
||||
});
|
||||
|
||||
export const ShareAccessRights = Object.freeze({
|
||||
None: 0,
|
||||
FullAccess: 1,
|
||||
@ -102,7 +95,6 @@ export const ShareAccessRights = Object.freeze({
|
||||
FormFilling: 7,
|
||||
CustomFilter: 8,
|
||||
});
|
||||
|
||||
export const ConflictResolveType = Object.freeze({
|
||||
Skip: 0,
|
||||
Overwrite: 1,
|
||||
@ -127,7 +119,6 @@ export const providersData = Object.freeze({
|
||||
icon: "/static/images/share.linkedin.react.svg",
|
||||
},
|
||||
});
|
||||
|
||||
export const LoaderStyle = {
|
||||
title: "",
|
||||
width: "100%",
|
||||
@ -183,7 +174,6 @@ export const TenantTrustedDomainsType = Object.freeze({
|
||||
Custom: 1,
|
||||
All: 2,
|
||||
});
|
||||
|
||||
export const PasswordLimitSpecialCharacters = "!@#$%^&*";
|
||||
|
||||
/**
|
||||
|
@ -7,11 +7,9 @@ html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#root {
|
||||
min-height: 100%;
|
||||
position: relative;
|
||||
|
||||
.pageLoader {
|
||||
position: fixed;
|
||||
left: calc(50% - 20px);
|
||||
@ -40,17 +38,14 @@ body {
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body.loading * {
|
||||
cursor: wait !important;
|
||||
}
|
||||
|
||||
body.drag-cursor * {
|
||||
cursor: url('data:image/svg+xml;utf8,<svg width="20" height="23" viewBox="0 0 20 23" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><rect width="20" height="23" fill="url(%23pattern0)"/><defs><pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1"><use xlink:href="%23image0" transform="scale(0.05 0.0434783)"/></pattern><image id="image0" width="20" height="23" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAYAAAALHW+jAAABS2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMzggNzkuMTU5ODI0LCAyMDE2LzA5LzE0LTAxOjA5OjAxICAgICAgICAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIi8+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+IEmuOgAAAzhJREFUOI2VlT1PI1cUhp/58DgZbMAOi2AcQZMFCSHREK3EKsoWNDRYCIkum7+Qf0BP4Y4K8QfSEtEgpUoatLuRiyDxUcSI2JKF8JCZAeyZe08Kj5GxTNgc6ejcO3Puc99zr86M4XkeqRmA05u4rvvGsqxfAEZGRt7Ytl3XWsv09JSampqODMNARNjb26PfjFKpBICIvLJt+1OhUMg+PDzI0tKSu7+/nxMR1tfXI9/3FcDd3d3p2dnZW0AAnUbpAc0+uOV53tfHx8evKpXK5P39fS6Xy5HP54njeOTg4GD06OhoNAzDb7LZ7DiQBay0MoYBtWVZHcdxGB8fJ45jAIIgwDRNSqUSExMTOI4zOjk5+cfY2NjrYVDTskyM7rSptRYA3/cJw/BxpyAIaLV8zs/PmZubsw4PD0srKys/z8/PfwtkUmEGgKm1RmtZAFZFuoqz2SzFYvERWCwWMc3uro7jsLi4yO7u7usgCH4F3CdKZ2dnv9vY2EjW1tZkZeWtxHEsnU5HfN8XERGttbRaLVFKSZIkcnNzIyIiFxcX4nleAswCXwFfACYLCwsiIhJFkbx7973c3t7K51i1WhXP80JgHigBecA2RaQDEIYhImAYTy7tWUvzjPQMM72Sba11W0ScKIqo1WokSYKI/BcLABHp5Rl9ji2iieMY13Upl8vYto3W+kVg9zKf5AmAnSQqD1AoFNjZ2QFAKfUiMJfLoZRyB5+blmX9Vq1WlVKK/+OXl5dxkiR/DQINIDMzM9M5OTl5UVXParUam5ubf56env4oIg9ACPjAnWlZlrRard8/fPj42eoymQyNRiMnIgpQQJJGbSqldBAEq+/f//D31dWVvASL45hms6kdx6mnkBhop1AxK5WKBpJ6vb66tbWVDIFI6iilCMOQcrlcv76+/qkPGKdjsbe3twG01rrRaNQz7XZ72Dl3B4ZBs9nE9303bYgeMCH9NtpRFGGapga+DMPoZnl52emDPGkbwzBQSiEi1ykg6VOnBxf0fgEuMJpG+5mLlhR0B/yTxpiBBdJXwn06t54Bkqp7SPMfW2ZQgQY6Kaw9WPKQ3F7Jj80/uKDX5OaQd89Bpc/5F/DGMQusl3V8AAAAAElFTkSuQmCC"/></defs></svg>')
|
||||
6 6,
|
||||
auto !important;
|
||||
}
|
||||
|
||||
body.desktop {
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
@ -59,7 +54,6 @@ body.desktop {
|
||||
-o-user-select: none;
|
||||
mozuserselect: none;
|
||||
}
|
||||
|
||||
#snackbar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -0,0 +1,3 @@
|
||||
<svg width="17" height="15" viewBox="0 0 17 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.5 2.5H13.5C14.0523 2.5 14.5 2.94772 14.5 3.5V11.5C14.5 12.0523 14.0523 12.5 13.5 12.5H11.5V2.5ZM9 2.5H3.5C2.94772 2.5 2.5 2.94772 2.5 3.5V11.5C2.5 12.0523 2.94772 12.5 3.5 12.5H9V2.5ZM17 1.5C17 0.671573 16.3284 0 15.5 0H14.5H2.5H1.5C0.671573 0 0 0.671573 0 1.5V2.88462V12.1154V13.5C0 14.3284 0.671573 15 1.5 15H2.5H14.5H15.5C16.3284 15 17 14.3284 17 13.5V12.1154V2.88462V1.5Z" fill="#A3A9AE"/>
|
||||
</svg>
|
After Width: | Height: | Size: 550 B |
@ -37,10 +37,6 @@ export const StyledSubmenuItems = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 4px;
|
||||
padding: 0 20px;
|
||||
@media ${tablet} {
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
overflow: hidden;
|
||||
&::-webkit-scrollbar {
|
||||
|
@ -45,11 +45,19 @@ const StyledButton = styled(Button)`
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.button-content {
|
||||
@media ${tablet} {
|
||||
flex-direction: column;
|
||||
gap: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@media ${tablet} {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
height: 60px;
|
||||
padding: 22px 12px 0 12px;
|
||||
padding: 0px 12px;
|
||||
.btnIcon {
|
||||
padding: 0;
|
||||
margin: 0 auto;
|
||||
@ -57,7 +65,7 @@ const StyledButton = styled(Button)`
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
padding: 18px 16px 0 16px;
|
||||
padding: 0 16px;
|
||||
height: 50px;
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
|
@ -7,7 +7,7 @@ import { isMobile } from "react-device-detect";
|
||||
const StyledTableContainer = styled.div`
|
||||
-moz-user-select: none;
|
||||
|
||||
width: calc(100% - 5px);
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin-top: -19px;
|
||||
|
||||
@ -79,7 +79,7 @@ const StyledTableGroupMenu = styled.div`
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
z-index: 199;
|
||||
height: 52px;
|
||||
height: 53px;
|
||||
box-shadow: ${(props) => props.theme.tableContainer.groupMenu.boxShadow};
|
||||
border-radius: 0px 0px 6px 6px;
|
||||
margin: 0;
|
||||
@ -125,6 +125,42 @@ const StyledTableGroupMenu = styled.div`
|
||||
|
||||
StyledTableGroupMenu.defaultProps = { theme: Base };
|
||||
|
||||
const StyledInfoPanelToggleWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-self: center;
|
||||
justify-content: center;
|
||||
margin: 0 20px 0 auto;
|
||||
height: 100%;
|
||||
width: auto;
|
||||
padding-left: 20px;
|
||||
|
||||
@media ${tablet} {
|
||||
margin: 0 16px 0 auto;
|
||||
}
|
||||
|
||||
.info-panel-toggle-bg {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background-color: ${(props) =>
|
||||
props.isInfoPanelVisible
|
||||
? props.theme.infoPanel.sectionHeaderToggleBgActive
|
||||
: props.theme.infoPanel.sectionHeaderToggleBg};
|
||||
|
||||
path {
|
||||
fill: ${(props) =>
|
||||
props.isInfoPanelVisible
|
||||
? props.theme.infoPanel.sectionHeaderToggleIconActive
|
||||
: props.theme.infoPanel.sectionHeaderToggleIcon};
|
||||
}
|
||||
}
|
||||
`;
|
||||
StyledInfoPanelToggleWrapper.defaultProps = { theme: Base };
|
||||
|
||||
const StyledTableHeader = styled.div`
|
||||
position: fixed;
|
||||
background: ${(props) => props.theme.tableContainer.header.background};
|
||||
@ -302,6 +338,9 @@ const StyledScrollbar = styled(Scrollbar)`
|
||||
.scroll-body {
|
||||
display: flex;
|
||||
}
|
||||
.nav-thumb-vertical {
|
||||
display: none !important;
|
||||
}
|
||||
.nav-thumb-horizontal {
|
||||
${isMobile && "display: none !important"};
|
||||
}
|
||||
@ -318,6 +357,7 @@ export {
|
||||
StyledTableCell,
|
||||
StyledTableSettings,
|
||||
StyledTableGroupMenu,
|
||||
StyledInfoPanelToggleWrapper,
|
||||
StyledEmptyTableContainer,
|
||||
StyledScrollbar,
|
||||
};
|
||||
|
@ -1,10 +1,15 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import Checkbox from "../checkbox";
|
||||
import { StyledTableGroupMenu, StyledScrollbar } from "./StyledTableContainer";
|
||||
import {
|
||||
StyledTableGroupMenu,
|
||||
StyledScrollbar,
|
||||
StyledInfoPanelToggleWrapper,
|
||||
} from "./StyledTableContainer";
|
||||
import ComboBox from "../combobox";
|
||||
import GroupMenuItem from "./GroupMenuItem";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import IconButton from "../icon-button";
|
||||
|
||||
const TableGroupMenu = (props) => {
|
||||
const {
|
||||
@ -14,15 +19,14 @@ const TableGroupMenu = (props) => {
|
||||
onChange,
|
||||
checkboxOptions,
|
||||
checkboxMargin,
|
||||
isInfoPanelVisible,
|
||||
toggleInfoPanel,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const onCheckboxChange = (e) => {
|
||||
onChange && onChange(e.target && e.target.checked);
|
||||
};
|
||||
|
||||
const { t } = useTranslation("Common");
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledTableGroupMenu
|
||||
@ -54,11 +58,21 @@ const TableGroupMenu = (props) => {
|
||||
<GroupMenuItem key={index} item={item} />
|
||||
))}
|
||||
</StyledScrollbar>
|
||||
<StyledInfoPanelToggleWrapper isInfoPanelVisible={isInfoPanelVisible}>
|
||||
<div className="info-panel-toggle-bg">
|
||||
<IconButton
|
||||
className="info-panel-toggle"
|
||||
iconName="images/panel.svg"
|
||||
size="16"
|
||||
isFill={true}
|
||||
onClick={toggleInfoPanel}
|
||||
/>
|
||||
</div>
|
||||
</StyledInfoPanelToggleWrapper>
|
||||
</StyledTableGroupMenu>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
TableGroupMenu.propTypes = {
|
||||
isChecked: PropTypes.bool,
|
||||
isIndeterminate: PropTypes.bool,
|
||||
@ -68,5 +82,4 @@ TableGroupMenu.propTypes = {
|
||||
onChange: PropTypes.func,
|
||||
checkboxMargin: PropTypes.string,
|
||||
};
|
||||
|
||||
export default TableGroupMenu;
|
||||
|
@ -117,7 +117,7 @@ class TableHeader extends React.Component {
|
||||
const column2Width = this.getSubstring(widths[colIndex]);
|
||||
|
||||
const defaultColumn = document.getElementById("column_" + colIndex);
|
||||
if (defaultColumn.dataset.defaultSize) return;
|
||||
if (!defaultColumn || defaultColumn.dataset.defaultSize) return;
|
||||
|
||||
if (column2Width + offset >= defaultMinColumnSize) {
|
||||
widths[+columnIndex] = newWidth + "px";
|
||||
@ -236,8 +236,8 @@ class TableHeader extends React.Component {
|
||||
const storageSize =
|
||||
!resetColumnsSize && localStorage.getItem(columnStorageName);
|
||||
|
||||
const defaultSize = this.props.columns.find((col) => col.defaultSize)
|
||||
?.defaultSize;
|
||||
const defaultSize =
|
||||
this.props.columns.find((col) => col.defaultSize)?.defaultSize || 0;
|
||||
|
||||
//TODO: Fixed columns size if something went wrong
|
||||
if (storageSize) {
|
||||
@ -262,9 +262,12 @@ class TableHeader extends React.Component {
|
||||
|
||||
const containerWidth = +container.clientWidth;
|
||||
|
||||
const oldWidth = tableContainer
|
||||
.map((column) => this.getSubstring(column))
|
||||
.reduce((x, y) => x + y);
|
||||
const oldWidth =
|
||||
tableContainer
|
||||
.map((column) => this.getSubstring(column))
|
||||
.reduce((x, y) => x + y) -
|
||||
defaultSize -
|
||||
settingsSize;
|
||||
|
||||
let str = "";
|
||||
|
||||
@ -278,7 +281,7 @@ class TableHeader extends React.Component {
|
||||
const enable =
|
||||
index == tableContainer.length - 1 ||
|
||||
(column ? column.dataset.enable === "true" : item !== "0px");
|
||||
const defaultSize = column && column.dataset.defaultSize;
|
||||
const defaultColumnSize = column && column.dataset.defaultSize;
|
||||
|
||||
const isActiveNow = item === "0px" && enable;
|
||||
if (isActiveNow && column) activeColumnIndex = index;
|
||||
@ -301,18 +304,14 @@ class TableHeader extends React.Component {
|
||||
} else if (item !== `${settingsSize}px`) {
|
||||
const percent = (this.getSubstring(item) / oldWidth) * 100;
|
||||
|
||||
if (index == 1) {
|
||||
const newItemWidth = (containerWidth * percent) / 100 + "px";
|
||||
gridTemplateColumns.push(newItemWidth);
|
||||
} else {
|
||||
const newItemWidth = defaultSize
|
||||
? `${defaultSize}px`
|
||||
: percent === 0
|
||||
? `${minColumnSize}px`
|
||||
: (containerWidth * percent) / 100 + "px";
|
||||
const newItemWidth = defaultColumnSize
|
||||
? `${defaultColumnSize}px`
|
||||
: percent === 0
|
||||
? `${minColumnSize}px`
|
||||
: ((containerWidth - defaultSize - settingsSize) * percent) / 100 +
|
||||
"px";
|
||||
|
||||
gridTemplateColumns.push(newItemWidth);
|
||||
}
|
||||
gridTemplateColumns.push(newItemWidth);
|
||||
} else {
|
||||
gridTemplateColumns.push(item);
|
||||
}
|
||||
@ -351,7 +350,8 @@ class TableHeader extends React.Component {
|
||||
|
||||
const enableColumns = this.props.columns
|
||||
.filter((x) => x.enable)
|
||||
.filter((x) => !x.defaultSize);
|
||||
.filter((x) => !x.defaultSize)
|
||||
.filter((x) => !x.default);
|
||||
|
||||
const container = containerRef.current
|
||||
? containerRef.current
|
||||
|
@ -1952,6 +1952,29 @@ const Base = {
|
||||
},
|
||||
},
|
||||
|
||||
infoPanel: {
|
||||
sectionHeaderToggleIcon: gray,
|
||||
sectionHeaderToggleIconActive: "#3B72A7",
|
||||
sectionHeaderToggleBg: "transparent",
|
||||
sectionHeaderToggleBgActive: grayLight,
|
||||
|
||||
backgroundColor: white,
|
||||
borderColor: grayLightMid,
|
||||
thumbnailBorderColor: grayLightMid,
|
||||
textColor: black,
|
||||
|
||||
closeButtonWrapperPadding: "0px",
|
||||
closeButtonIcon: white,
|
||||
closeButtonSize: "17px",
|
||||
closeButtonBg: "transparent",
|
||||
|
||||
accessGroupBg: grayLightMid,
|
||||
accessGroupText: black,
|
||||
|
||||
showAccessUsersTextColor: gray,
|
||||
showAccessPanelTextColor: "#3b72a7",
|
||||
},
|
||||
|
||||
filesArticleBody: {
|
||||
background: lightGrayishStrongBlue,
|
||||
panelBackground: lightGrayishStrongBlue,
|
||||
|
@ -1954,6 +1954,29 @@ const Dark = {
|
||||
},
|
||||
},
|
||||
|
||||
infoPanel: {
|
||||
sectionHeaderToggleIcon: "#858585",
|
||||
sectionHeaderToggleIconActive: "#c4c4c4",
|
||||
sectionHeaderToggleBg: "transparent",
|
||||
sectionHeaderToggleBgActive: "#292929",
|
||||
|
||||
backgroundColor: black,
|
||||
borderColor: "#292929",
|
||||
thumbnailBorderColor: grayLightMid,
|
||||
textColor: white,
|
||||
|
||||
closeButtonWrapperPadding: "6px",
|
||||
closeButtonIcon: black,
|
||||
closeButtonSize: "12px",
|
||||
closeButtonBg: "#a2a2a2",
|
||||
|
||||
accessGroupBg: "#242424",
|
||||
accessGroupText: white,
|
||||
|
||||
showAccessUsersTextColor: gray,
|
||||
showAccessPanelTextColor: "#E06A1B",
|
||||
},
|
||||
|
||||
filesArticleBody: {
|
||||
background: black,
|
||||
panelBackground: "#474747",
|
||||
|
BIN
products/ASC.Files/Client/public/images/empty_screen.png
Normal file
BIN
products/ASC.Files/Client/public/images/empty_screen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
3
products/ASC.Files/Client/public/images/info.react.svg
Normal file
3
products/ASC.Files/Client/public/images/info.react.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 15C11.866 15 15 11.866 15 8C15 4.13401 11.866 1 8 1C4.13401 1 1 4.13401 1 8C1 11.866 4.13401 15 8 15ZM7 6V4H9V6H7ZM7 12V7H9V12H7Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 301 B |
3
products/ASC.Files/Client/public/images/panel.svg
Normal file
3
products/ASC.Files/Client/public/images/panel.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="17" height="15" viewBox="0 0 17 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.5 2.5H13.5C14.0523 2.5 14.5 2.94772 14.5 3.5V11.5C14.5 12.0523 14.0523 12.5 13.5 12.5H11.5V2.5ZM9 2.5H3.5C2.94772 2.5 2.5 2.94772 2.5 3.5V11.5C2.5 12.0523 2.94772 12.5 3.5 12.5H9V2.5ZM17 1.5C17 0.671573 16.3284 0 15.5 0H14.5H2.5H1.5C0.671573 0 0 0.671573 0 1.5V2.88462V12.1154V13.5C0 14.3284 0.671573 15 1.5 15H2.5H14.5H15.5C16.3284 15 17 14.3284 17 13.5V12.1154V2.88462V1.5Z" fill="#A3A9AE"/>
|
||||
</svg>
|
After Width: | Height: | Size: 550 B |
15
products/ASC.Files/Client/public/locales/en/InfoPanel.json
Normal file
15
products/ASC.Files/Client/public/locales/en/InfoPanel.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"Info": "Info",
|
||||
"ViewDetails": "View Details",
|
||||
"ItemsSelected": "Items selected",
|
||||
"SystemProperties": "System properties",
|
||||
"WhoHasAccess": "Who has access",
|
||||
"Members": "members",
|
||||
"OpenSharingSettings": "Open sharing settings",
|
||||
|
||||
"Location": "Location",
|
||||
"FileExtension": "File extension",
|
||||
"LastModifiedBy": "Last modified by",
|
||||
"Versions": "Versions",
|
||||
"Comments": "Comments"
|
||||
}
|
15
products/ASC.Files/Client/public/locales/ru/InfoPanel.json
Normal file
15
products/ASC.Files/Client/public/locales/ru/InfoPanel.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"Info": "Информация",
|
||||
"ViewDetails": "Просмотреть подробную информацию",
|
||||
"ItemsSelected": "Выбрано элементов",
|
||||
"SystemProperties": "Системные свойства",
|
||||
"WhoHasAccess": "У кого есть доступ",
|
||||
"Members": "участников",
|
||||
"OpenSharingSettings": "Открыть настройки общего доступа",
|
||||
|
||||
"Location": "Местоположение",
|
||||
"FileExtension": "Расширение файла",
|
||||
"LastModifiedBy": "Автор последнего корректива",
|
||||
"Versions": "Версии",
|
||||
"Comments": "Комментарии"
|
||||
}
|
@ -82,6 +82,7 @@ export default function withFileActions(WrappedFileItem) {
|
||||
if (mouseButton || e.currentTarget.tagName !== "DIV" || label) {
|
||||
return e;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
setTooltipPosition(e.pageX, e.pageY);
|
||||
setStartDrag(true);
|
||||
@ -92,13 +93,14 @@ export default function withFileActions(WrappedFileItem) {
|
||||
const { viewAs } = this.props;
|
||||
|
||||
if (
|
||||
e.target.closest(".checkbox") ||
|
||||
e.target.tagName === "INPUT" ||
|
||||
e.target.tagName === "SPAN" ||
|
||||
e.target.tagName === "A" ||
|
||||
e.target.closest(".expandButton") ||
|
||||
e.target.closest(".badges") ||
|
||||
e.target.closest(".checkbox") ||
|
||||
e.button !== 0 ||
|
||||
e.target.closest(".expandButton") ||
|
||||
e.target.querySelector(".expandButton") ||
|
||||
e.target.closest(".badges") ||
|
||||
e.target.closest(".not-selectable")
|
||||
)
|
||||
return;
|
||||
@ -106,12 +108,10 @@ export default function withFileActions(WrappedFileItem) {
|
||||
if (viewAs === "tile") {
|
||||
if (e.target.closest(".edit-button") || e.target.tagName === "IMG")
|
||||
return;
|
||||
|
||||
if (e.detail === 1) this.fileContextClick();
|
||||
} else {
|
||||
this.fileContextClick();
|
||||
}
|
||||
} else this.fileContextClick();
|
||||
};
|
||||
|
||||
onFilesClick = (e) => {
|
||||
const { item, openFileAction } = this.props;
|
||||
if (
|
||||
@ -247,6 +247,7 @@ export default function withFileActions(WrappedFileItem) {
|
||||
activeFiles,
|
||||
activeFolders,
|
||||
} = filesStore;
|
||||
|
||||
const { startUpload } = uploadDataStore;
|
||||
const { type, extension, id } = fileActionStore;
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
import Text from "@appserver/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);
|
@ -0,0 +1,415 @@
|
||||
import { FileType } from "@appserver/common/constants";
|
||||
import { LANGUAGE } from "@appserver/common/constants";
|
||||
import Link from "@appserver/components/link";
|
||||
import Text from "@appserver/components/text";
|
||||
import Tooltip from "@appserver/components/tooltip";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import {
|
||||
StyledAccess,
|
||||
StyledAccessItem,
|
||||
StyledOpenSharingPanel,
|
||||
StyledProperties,
|
||||
StyledSubtitle,
|
||||
StyledThumbnail,
|
||||
StyledTitle,
|
||||
} from "./styles/styles.js";
|
||||
|
||||
const moment = require("moment");
|
||||
|
||||
const SingleItem = (props) => {
|
||||
const {
|
||||
t,
|
||||
selectedItem,
|
||||
onSelectItem,
|
||||
setSharingPanelVisible,
|
||||
getFolderInfo,
|
||||
getIcon,
|
||||
getFolderIcon,
|
||||
getShareUsers,
|
||||
dontShowSize,
|
||||
dontShowLocation,
|
||||
dontShowAccess,
|
||||
} = props;
|
||||
|
||||
let updateSubscription = true;
|
||||
const [item, setItem] = useState({
|
||||
id: "",
|
||||
isFolder: false,
|
||||
title: "",
|
||||
iconUrl: "",
|
||||
thumbnailUrl: "",
|
||||
properties: [],
|
||||
access: {
|
||||
owner: {
|
||||
img: "",
|
||||
link: "",
|
||||
},
|
||||
others: [],
|
||||
},
|
||||
});
|
||||
|
||||
const updateItemsInfo = async (selectedItem) => {
|
||||
const getItemIcon = (item, size) => {
|
||||
return item.isFolder
|
||||
? getFolderIcon(item.providerKey, size)
|
||||
: getIcon(size, item.fileExst || ".file");
|
||||
};
|
||||
|
||||
const getSingleItemProperties = (item) => {
|
||||
const styledLink = (text, href) => (
|
||||
<Link className="property-content" href={href} isHovered={true}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
|
||||
const styledText = (text) => (
|
||||
<Text className="property-content">{text}</Text>
|
||||
);
|
||||
|
||||
const parseAndFormatDate = (date) => {
|
||||
return moment(date)
|
||||
.locale(localStorage.getItem(LANGUAGE))
|
||||
.format("DD.MM.YY hh:mm A");
|
||||
};
|
||||
|
||||
const getItemType = (fileType) => {
|
||||
switch (fileType) {
|
||||
case FileType.Unknown:
|
||||
return t("Common:Unknown");
|
||||
case FileType.Archive:
|
||||
return t("Common:Archive");
|
||||
case FileType.Video:
|
||||
return t("Common:Video");
|
||||
case FileType.Audio:
|
||||
return t("Common:Audio");
|
||||
case FileType.Image:
|
||||
return t("Common:Image");
|
||||
case FileType.Spreadsheet:
|
||||
return t("Home:Spreadsheet");
|
||||
case FileType.Presentation:
|
||||
return t("Home:Presentation");
|
||||
case FileType.Document:
|
||||
return t("Home:Document");
|
||||
default:
|
||||
return t("Home:Folder");
|
||||
}
|
||||
};
|
||||
|
||||
const itemSize = item.isFolder
|
||||
? `${t("Translations:Folders")}: ${item.foldersCount} | ${t(
|
||||
"Translations:Files"
|
||||
)}: ${item.filesCount}`
|
||||
: item.contentLength;
|
||||
|
||||
const itemType = getItemType(item.fileType);
|
||||
|
||||
let result = [
|
||||
{
|
||||
id: "Owner",
|
||||
title: t("Common:Owner"),
|
||||
content: styledLink(
|
||||
item.createdBy?.displayName,
|
||||
item.createdBy?.profileUrl
|
||||
),
|
||||
},
|
||||
// {
|
||||
// id: "Location",
|
||||
// title: t("InfoPanel:Location"),
|
||||
// content: styledText("..."),
|
||||
// },
|
||||
{
|
||||
id: "Type",
|
||||
title: t("Common:Type"),
|
||||
content: styledText(itemType),
|
||||
},
|
||||
{
|
||||
id: "Size",
|
||||
title: t("Common:Size"),
|
||||
content: styledText(itemSize),
|
||||
},
|
||||
{
|
||||
id: "ByLastModifiedDate",
|
||||
title: t("Home:ByLastModifiedDate"),
|
||||
content: styledText(parseAndFormatDate(item.updated)),
|
||||
},
|
||||
{
|
||||
id: "LastModifiedBy",
|
||||
title: t("LastModifiedBy"),
|
||||
content: styledLink(
|
||||
item.updatedBy?.displayName,
|
||||
item.updatedBy?.profileUrl
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "ByCreationDate",
|
||||
title: t("Home:ByCreationDate"),
|
||||
content: styledText(parseAndFormatDate(item.created)),
|
||||
},
|
||||
];
|
||||
|
||||
if (item.isFolder) return result;
|
||||
|
||||
result.splice(3, 0, {
|
||||
id: "FileExtension",
|
||||
title: t("FileExtension"),
|
||||
content: styledText(
|
||||
item.fileExst ? item.fileExst.split(".")[1].toUpperCase() : "-"
|
||||
),
|
||||
});
|
||||
|
||||
result.push(
|
||||
{
|
||||
id: "Versions",
|
||||
title: t("Versions"),
|
||||
content: styledText(item.version),
|
||||
},
|
||||
{
|
||||
id: "Comments",
|
||||
title: t("Comments"),
|
||||
content: styledText(item.comment),
|
||||
}
|
||||
);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const displayedItem = {
|
||||
id: selectedItem.id,
|
||||
isFolder: selectedItem.isFolder,
|
||||
title: selectedItem.title,
|
||||
iconUrl: getItemIcon(selectedItem, 32),
|
||||
thumbnailUrl: selectedItem.thumbnailUrl || getItemIcon(selectedItem, 96),
|
||||
properties: getSingleItemProperties(selectedItem),
|
||||
access: {
|
||||
owner: {
|
||||
img: selectedItem.createdBy?.avatarSmall,
|
||||
link: selectedItem.createdBy?.profileUrl,
|
||||
},
|
||||
others: [],
|
||||
},
|
||||
};
|
||||
|
||||
setItem(displayedItem);
|
||||
await loadAsyncData(displayedItem, selectedItem);
|
||||
};
|
||||
|
||||
const loadAsyncData = async (displayedItem, selectedItem) => {
|
||||
if (!updateSubscription) return;
|
||||
|
||||
const updateLoadedItemProperties = async (displayedItem, selectedItem) => {
|
||||
const parentFolderId = selectedItem.isFolder
|
||||
? selectedItem.parentId
|
||||
: selectedItem.folderId;
|
||||
|
||||
const noLocationProperties = [...displayedItem.properties].filter(
|
||||
(dip) => dip.id !== "Location"
|
||||
);
|
||||
|
||||
let result;
|
||||
await getFolderInfo(parentFolderId)
|
||||
.catch(() => {
|
||||
result = noLocationProperties;
|
||||
})
|
||||
.then((data) => {
|
||||
if (!data) {
|
||||
result = noLocationProperties;
|
||||
return;
|
||||
}
|
||||
result = [...displayedItem.properties].map((dip) =>
|
||||
dip.id === "Location"
|
||||
? {
|
||||
id: "Location",
|
||||
title: t("Location"),
|
||||
content: (
|
||||
<Link
|
||||
className="property-content"
|
||||
href={`/products/files/filter?folder=${parentFolderId}`}
|
||||
isHovered={true}
|
||||
>
|
||||
{data.title}
|
||||
</Link>
|
||||
),
|
||||
}
|
||||
: dip
|
||||
);
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const updateLoadedItemAccess = async (selectedItem) => {
|
||||
const accesses = await getShareUsers(
|
||||
[selectedItem.isFolder ? selectedItem.parentId : selectedItem.folderId],
|
||||
[selectedItem.id]
|
||||
);
|
||||
|
||||
const result = {
|
||||
owner: {},
|
||||
others: [],
|
||||
};
|
||||
|
||||
accesses.forEach((access) => {
|
||||
let key = access.sharedTo.id,
|
||||
img = access.sharedTo.avatarSmall,
|
||||
link = access.sharedTo.profileUrl,
|
||||
name = access.sharedTo.displayName || access.sharedTo.name,
|
||||
{ manager } = access.sharedTo;
|
||||
|
||||
if (access.isOwner) result.owner = { key, img, link, name };
|
||||
else {
|
||||
if (access.sharedTo.email)
|
||||
result.others.push({ key, type: "user", img, link, name });
|
||||
else if (access.sharedTo.manager)
|
||||
result.others.push({ key, type: "group", name, manager });
|
||||
}
|
||||
});
|
||||
|
||||
result.others = result.others.sort((a) => (a.type === "group" ? -1 : 1));
|
||||
return result;
|
||||
};
|
||||
|
||||
// const properties = await updateLoadedItemProperties(
|
||||
// displayedItem,
|
||||
// selectedItem
|
||||
// );
|
||||
|
||||
if (dontShowAccess) {
|
||||
setItem({
|
||||
...displayedItem,
|
||||
//properties: properties,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const access = await updateLoadedItemAccess(selectedItem);
|
||||
setItem({
|
||||
...displayedItem,
|
||||
// properties: properties,
|
||||
access: access,
|
||||
});
|
||||
};
|
||||
|
||||
const openSharingPanel = () => {
|
||||
const { id, isFolder } = item;
|
||||
onSelectItem({ id, isFolder });
|
||||
setSharingPanelVisible(true);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedItem.id !== item.id && updateSubscription)
|
||||
updateItemsInfo(selectedItem);
|
||||
return () => (updateSubscription = false);
|
||||
}, [selectedItem]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledTitle>
|
||||
<ReactSVG className="icon" src={item.iconUrl} />
|
||||
<Text className="text">{item.title}</Text>
|
||||
</StyledTitle>
|
||||
|
||||
{selectedItem.thumbnailUrl ? (
|
||||
<StyledThumbnail>
|
||||
<img src={item.thumbnailUrl} alt="" />
|
||||
</StyledThumbnail>
|
||||
) : (
|
||||
<div className="no-thumbnail-img-wrapper">
|
||||
<ReactSVG className="no-thumbnail-img" src={item.thumbnailUrl} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<StyledSubtitle>
|
||||
<Text fontWeight="600" fontSize="14px">
|
||||
{t("SystemProperties")}
|
||||
</Text>
|
||||
</StyledSubtitle>
|
||||
|
||||
<StyledProperties>
|
||||
{item.properties.map((p) => {
|
||||
if (dontShowSize && p.id === "Size") return;
|
||||
if (dontShowLocation && p.id === "Location") return;
|
||||
return (
|
||||
<div key={p.title} className="property">
|
||||
<Text className="property-title">{p.title}</Text>
|
||||
{p.content}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</StyledProperties>
|
||||
|
||||
{!dontShowAccess && item.access && (
|
||||
<>
|
||||
<StyledSubtitle>
|
||||
<Text fontWeight="600" fontSize="14px">
|
||||
{t("WhoHasAccess")}
|
||||
</Text>
|
||||
</StyledSubtitle>
|
||||
|
||||
<StyledAccess>
|
||||
<Tooltip
|
||||
id="access-item-tooltip"
|
||||
getContent={(dataTip) =>
|
||||
dataTip ? <Text fontSize="13px">{dataTip}</Text> : null
|
||||
}
|
||||
/>
|
||||
|
||||
<StyledAccessItem>
|
||||
<div
|
||||
data-for="access-item-tooltip"
|
||||
className="access-item-tooltip"
|
||||
data-tip={item.access.owner.name}
|
||||
>
|
||||
<div className="item-user">
|
||||
<a href={item.access.owner.link}>
|
||||
<img src={item.access.owner.img} />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</StyledAccessItem>
|
||||
|
||||
{item.access.others.length > 0 && <div className="divider"></div>}
|
||||
|
||||
{item.access.others.map((item, i) => {
|
||||
if (i < 3)
|
||||
return (
|
||||
<div key={item.key}>
|
||||
<StyledAccessItem>
|
||||
<div
|
||||
data-for="access-item-tooltip"
|
||||
data-tip={item.name}
|
||||
className="access-item-tooltip"
|
||||
>
|
||||
{item.type === "user" ? (
|
||||
<div className="item-user">
|
||||
<a href={item.link}>
|
||||
<img src={item.img} />
|
||||
</a>
|
||||
</div>
|
||||
) : (
|
||||
<div className="item-group">
|
||||
<span>{item.name.substr(0, 2).toUpperCase()}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</StyledAccessItem>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
{item.access.others.length > 3 && (
|
||||
<div className="show-more-users" onClick={openSharingPanel}>
|
||||
{`+ ${item.access.others.length - 3} ${t("Members")}`}
|
||||
</div>
|
||||
)}
|
||||
</StyledAccess>
|
||||
<StyledOpenSharingPanel onClick={openSharingPanel}>
|
||||
{t("OpenSharingSettings")}
|
||||
</StyledOpenSharingPanel>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SingleItem;
|
109
products/ASC.Files/Client/src/pages/Home/InfoPanel/Body/index.js
Normal file
109
products/ASC.Files/Client/src/pages/Home/InfoPanel/Body/index.js
Normal file
@ -0,0 +1,109 @@
|
||||
import { inject, observer } from "mobx-react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { withRouter } from "react-router";
|
||||
import SeveralItems from "./SeveralItems";
|
||||
import SingleItem from "./SingleItem";
|
||||
import { StyledInfoRoomBody } from "./styles/styles.js";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
|
||||
const InfoPanelBodyContent = ({
|
||||
t,
|
||||
selectedFolder,
|
||||
selectedItems,
|
||||
getFolderInfo,
|
||||
getIcon,
|
||||
getFolderIcon,
|
||||
getShareUsers,
|
||||
onSelectItem,
|
||||
setSharingPanelVisible,
|
||||
isRecycleBinFolder,
|
||||
isRecentFolder,
|
||||
isFavoritesFolder,
|
||||
}) => {
|
||||
const singleItem = (item) => {
|
||||
const dontShowLocation = item.isFolder && item.parentId === 0;
|
||||
const dontShowSize = item.isFolder && (isFavoritesFolder || isRecentFolder);
|
||||
const dontShowAccess =
|
||||
isRecycleBinFolder ||
|
||||
(item.isFolder && item.parentId === 0) ||
|
||||
item.rootFolderId === 7 ||
|
||||
(item.isFolder && item.pathParts && item.pathParts[0] === 7);
|
||||
|
||||
return (
|
||||
<SingleItem
|
||||
t={t}
|
||||
selectedItem={item}
|
||||
onSelectItem={onSelectItem}
|
||||
setSharingPanelVisible={setSharingPanelVisible}
|
||||
getFolderInfo={getFolderInfo}
|
||||
getIcon={getIcon}
|
||||
getFolderIcon={getFolderIcon}
|
||||
getShareUsers={getShareUsers}
|
||||
dontShowLocation={dontShowLocation}
|
||||
dontShowSize={dontShowSize}
|
||||
dontShowAccess={dontShowAccess}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledInfoRoomBody>
|
||||
<>
|
||||
{selectedItems.length === 0 ? (
|
||||
singleItem({
|
||||
...selectedFolder,
|
||||
isFolder: true,
|
||||
})
|
||||
) : selectedItems.length === 1 ? (
|
||||
singleItem(selectedItems[0])
|
||||
) : (
|
||||
<SeveralItems selectedItems={selectedItems} getIcon={getIcon} />
|
||||
)}
|
||||
</>
|
||||
</StyledInfoRoomBody>
|
||||
);
|
||||
};
|
||||
|
||||
InfoPanelBodyContent.defaultProps = { theme: Base };
|
||||
|
||||
export default inject(
|
||||
({
|
||||
filesStore,
|
||||
settingsStore,
|
||||
filesActionsStore,
|
||||
dialogsStore,
|
||||
treeFoldersStore,
|
||||
selectedFolderStore,
|
||||
}) => {
|
||||
const { selection, getFolderInfo, getShareUsers } = filesStore;
|
||||
const { getIcon, getFolderIcon } = settingsStore;
|
||||
const { onSelectItem } = filesActionsStore;
|
||||
const { setSharingPanelVisible } = dialogsStore;
|
||||
const {
|
||||
isRecycleBinFolder,
|
||||
isRecentFolder,
|
||||
isFavoritesFolder,
|
||||
} = treeFoldersStore;
|
||||
|
||||
return {
|
||||
selectedFolder: { ...selectedFolderStore },
|
||||
selectedItems: [...selection],
|
||||
getFolderInfo,
|
||||
getShareUsers,
|
||||
getIcon,
|
||||
getFolderIcon,
|
||||
onSelectItem,
|
||||
setSharingPanelVisible,
|
||||
isRecycleBinFolder,
|
||||
isRecentFolder,
|
||||
isFavoritesFolder,
|
||||
};
|
||||
}
|
||||
)(
|
||||
withRouter(
|
||||
withTranslation(["InfoPanel", "Home", "Common", "Translations"])(
|
||||
observer(InfoPanelBodyContent)
|
||||
)
|
||||
)
|
||||
);
|
@ -0,0 +1,234 @@
|
||||
import styled from "styled-components";
|
||||
|
||||
import { Base } from "@appserver/components/themes";
|
||||
|
||||
const StyledInfoRoomBody = styled.div`
|
||||
padding: 0px 0px 0 16px;
|
||||
height: auto;
|
||||
background-color: ${(props) => props.theme.infoPanel.backgroundColor};
|
||||
color: ${(props) => props.theme.infoPanel.textColor};
|
||||
|
||||
.no-item {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.no-thumbnail-img-wrapper {
|
||||
height: auto;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.no-thumbnail-img {
|
||||
height: 96px;
|
||||
width: 96px;
|
||||
}
|
||||
}
|
||||
|
||||
.current-folder-loader-wrapper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 96px;
|
||||
margin-top: 116.56px;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledTitle = styled.div`
|
||||
display: flex;
|
||||
flex-wrap: no-wrap;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
padding: 23px 0;
|
||||
|
||||
.icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
svg {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
max-height: 44px;
|
||||
margin: 0 8px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledThumbnail = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
img {
|
||||
border: ${(props) => `solid 1px ${props.theme.infoPanel.borderColor}`};
|
||||
border-radius: 6px;
|
||||
//width: 100%;
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledSubtitle = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 24px 0;
|
||||
`;
|
||||
|
||||
const StyledProperties = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: 8px;
|
||||
|
||||
.property {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 150px 1fr;
|
||||
grid-column-gap: 24px;
|
||||
|
||||
.property-title {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.property-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledAccess = styled.div`
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
.divider {
|
||||
background: ${(props) => props.theme.infoPanel.borderColor};
|
||||
margin: 2px 4px;
|
||||
width: 1px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.show-more-users {
|
||||
position: static;
|
||||
width: 101px;
|
||||
height: 16px;
|
||||
left: 120px;
|
||||
top: 8px;
|
||||
padding-left: 1px;
|
||||
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
text-align: left;
|
||||
|
||||
color: ${(props) => props.theme.infoPanel.showAccessUsersTextColor};
|
||||
|
||||
flex: none;
|
||||
order: 3;
|
||||
flex-grow: 0;
|
||||
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledAccessItem = styled.div`
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
|
||||
.access-item-tooltip {
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.item-group {
|
||||
border-radius: 50%;
|
||||
background-color: ${(props) => props.theme.infoPanel.accessGroupBg};
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
span {
|
||||
font-family: "Open Sans";
|
||||
font-weight: 700;
|
||||
font-size: 12px;
|
||||
color: ${(props) => props.theme.infoPanel.accessGroupText};
|
||||
line-height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.item-user {
|
||||
img {
|
||||
border-radius: 50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledOpenSharingPanel = styled.div`
|
||||
position: static;
|
||||
width: auto;
|
||||
height: 15px;
|
||||
left: 0px;
|
||||
top: 2px;
|
||||
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
line-height: 15px;
|
||||
|
||||
color: ${(props) => props.theme.infoPanel.showAccessPanelTextColor};
|
||||
|
||||
display: flex;
|
||||
margin: 16px 0px;
|
||||
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
text-decoration-style: dashed;
|
||||
`;
|
||||
|
||||
StyledInfoRoomBody.defaultProps = { theme: Base };
|
||||
StyledThumbnail.defaultProps = { theme: Base };
|
||||
StyledAccess.defaultProps = { theme: Base };
|
||||
StyledAccessItem.defaultProps = { theme: Base };
|
||||
StyledOpenSharingPanel.defaultProps = { theme: Base };
|
||||
|
||||
export {
|
||||
StyledInfoRoomBody,
|
||||
StyledTitle,
|
||||
StyledThumbnail,
|
||||
StyledSubtitle,
|
||||
StyledProperties,
|
||||
StyledAccess,
|
||||
StyledAccessItem,
|
||||
StyledOpenSharingPanel,
|
||||
};
|
@ -0,0 +1,8 @@
|
||||
import React from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
const InfoPanelHeaderContent = ({ t }) => {
|
||||
return <>{t("Info")}</>;
|
||||
};
|
||||
|
||||
export default withTranslation(["InfoPanel"])(InfoPanelHeaderContent);
|
@ -0,0 +1,2 @@
|
||||
export { default as InfoPanelHeaderContent } from "./Header";
|
||||
export { default as InfoPanelBodyContent } from "./Body";
|
@ -97,8 +97,8 @@ const StyledSimpleFilesRow = styled(Row)`
|
||||
}
|
||||
|
||||
.row_content {
|
||||
${(props) => props.sectionWidth > 500 && `max-width: fit-content;`}
|
||||
min-width: auto;
|
||||
${(props) =>
|
||||
props.sectionWidth > 500 && `max-width: fit-content;`}//min-width: auto;;
|
||||
}
|
||||
|
||||
.badges {
|
||||
|
@ -146,15 +146,17 @@ const StyledFileTileTop = styled.div`
|
||||
align-items: baseline;
|
||||
height: 156px;
|
||||
position: relative;
|
||||
border-radius: 6px 6px 0 0;
|
||||
|
||||
.thumbnail-image {
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
object-fit: ${(props) => (props.isMedia ? "cover" : "none")};
|
||||
object-fit: cover;
|
||||
object-position: top;
|
||||
z-index: 0;
|
||||
border-radius: 6px 6px 0 0;
|
||||
}
|
||||
|
||||
.temporary-icon > .injected-svg {
|
||||
|
@ -71,6 +71,7 @@ const SectionBodyContent = (props) => {
|
||||
(e.target.closest(".scroll-body") &&
|
||||
!e.target.closest(".files-item") &&
|
||||
!e.target.closest(".not-selectable") &&
|
||||
!e.target.closest(".info-panel") &&
|
||||
!e.target.closest(".table-container_group-menu")) ||
|
||||
e.target.closest(".files-main-button") ||
|
||||
e.target.closest(".add-button") ||
|
||||
|
@ -18,7 +18,7 @@ import TableGroupMenu from "@appserver/components/table-container/TableGroupMenu
|
||||
import Navigation from "@appserver/common/components/Navigation";
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
padding: 0 0 15px;
|
||||
/* padding: 0 0 15px;
|
||||
|
||||
@media ${tablet} {
|
||||
padding: 0 0 17px;
|
||||
@ -36,7 +36,7 @@ const StyledContainer = styled.div`
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
padding: 0 0 13px;
|
||||
`}
|
||||
`} */
|
||||
|
||||
.table-container_group-menu {
|
||||
${(props) =>
|
||||
@ -317,6 +317,7 @@ class SectionHeaderContent extends React.Component {
|
||||
const {
|
||||
t,
|
||||
tReady,
|
||||
isInfoPanelVisible,
|
||||
isRootFolder,
|
||||
title,
|
||||
canCreate,
|
||||
@ -344,6 +345,8 @@ class SectionHeaderContent extends React.Component {
|
||||
width={context.sectionWidth}
|
||||
isRootFolder={isRootFolder}
|
||||
canCreate={canCreate}
|
||||
isRecycleBinFolder={isRecycleBinFolder}
|
||||
title={title}
|
||||
isTitle={title}
|
||||
isDesktop={isDesktop}
|
||||
isTabletView={isTabletView}
|
||||
@ -357,6 +360,8 @@ class SectionHeaderContent extends React.Component {
|
||||
isChecked={isHeaderChecked}
|
||||
isIndeterminate={isHeaderIndeterminate}
|
||||
headerMenu={headerMenu}
|
||||
isInfoPanelVisible={this.props.isInfoPanelVisible}
|
||||
toggleInfoPanel={this.props.toggleInfoPanel}
|
||||
/>
|
||||
) : (
|
||||
<div className="header-container">
|
||||
@ -383,6 +388,8 @@ class SectionHeaderContent extends React.Component {
|
||||
isEmptyFilesList={isEmptyFilesList}
|
||||
clearTrash={this.onEmptyTrashAction}
|
||||
onBackToParentFolder={this.onBackToParentFolder}
|
||||
toggleInfoPanel={this.props.toggleInfoPanel}
|
||||
isInfoPanelVisible={this.props.isInfoPanelVisible}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@ -403,6 +410,7 @@ export default inject(
|
||||
treeFoldersStore,
|
||||
filesActionsStore,
|
||||
settingsStore,
|
||||
infoPanelStore,
|
||||
}) => {
|
||||
const {
|
||||
setSelected,
|
||||
@ -441,9 +449,10 @@ export default inject(
|
||||
backToParentFolder,
|
||||
} = filesActionsStore;
|
||||
|
||||
const { toggleIsVisible, isVisible } = infoPanelStore;
|
||||
|
||||
return {
|
||||
showText: auth.settingsStore.showText,
|
||||
|
||||
isDesktop: auth.settingsStore.isDesktopClient,
|
||||
isRootFolder: selectedFolderStore.parentId === 0,
|
||||
title: selectedFolderStore.title,
|
||||
@ -451,6 +460,8 @@ export default inject(
|
||||
pathParts: selectedFolderStore.pathParts,
|
||||
navigationPath: selectedFolderStore.navigationPath,
|
||||
canCreate,
|
||||
toggleInfoPanel: toggleIsVisible,
|
||||
isInfoPanelVisible: isVisible,
|
||||
isHeaderVisible,
|
||||
isHeaderIndeterminate,
|
||||
isHeaderChecked,
|
||||
|
@ -22,6 +22,7 @@ import {
|
||||
SectionPagingContent,
|
||||
Bar,
|
||||
} from "./Section";
|
||||
import { InfoPanelBodyContent, InfoPanelHeaderContent } from "./InfoPanel";
|
||||
|
||||
import { ArticleMainButtonContent } from "../../components/Article";
|
||||
|
||||
@ -287,6 +288,7 @@ class PureHome extends React.Component {
|
||||
setMaintenanceExist,
|
||||
snackbarExist,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<>
|
||||
<MediaViewer />
|
||||
@ -345,6 +347,14 @@ class PureHome extends React.Component {
|
||||
</Consumer>
|
||||
</Section.SectionBody>
|
||||
|
||||
<Section.InfoPanelHeader>
|
||||
<InfoPanelHeaderContent />
|
||||
</Section.InfoPanelHeader>
|
||||
|
||||
<Section.InfoPanelBody>
|
||||
<InfoPanelBodyContent />
|
||||
</Section.InfoPanelBody>
|
||||
|
||||
<Section.SectionPaging>
|
||||
<SectionPagingContent tReady={tReady} />
|
||||
</Section.SectionPaging>
|
||||
|
@ -22,6 +22,7 @@ class ContextOptionsStore {
|
||||
uploadDataStore;
|
||||
versionHistoryStore;
|
||||
settingsStore;
|
||||
infoPanelStore;
|
||||
|
||||
constructor(
|
||||
authStore,
|
||||
@ -32,7 +33,8 @@ class ContextOptionsStore {
|
||||
treeFoldersStore,
|
||||
uploadDataStore,
|
||||
versionHistoryStore,
|
||||
settingsStore
|
||||
settingsStore,
|
||||
infoPanelStore
|
||||
) {
|
||||
makeAutoObservable(this);
|
||||
this.authStore = authStore;
|
||||
@ -44,6 +46,7 @@ class ContextOptionsStore {
|
||||
this.uploadDataStore = uploadDataStore;
|
||||
this.versionHistoryStore = versionHistoryStore;
|
||||
this.settingsStore = settingsStore;
|
||||
this.infoPanelStore = infoPanelStore;
|
||||
}
|
||||
|
||||
onOpenFolder = (item) => {
|
||||
@ -335,6 +338,11 @@ class ContextOptionsStore {
|
||||
return options;
|
||||
};
|
||||
|
||||
onShowInfoPanel = () => {
|
||||
const { setIsVisible } = this.infoPanelStore;
|
||||
setIsVisible(true);
|
||||
};
|
||||
|
||||
getFilesContextOptions = (item, t) => {
|
||||
const { contextOptions } = item;
|
||||
const isRootThirdPartyFolder =
|
||||
@ -510,6 +518,13 @@ class ContextOptionsStore {
|
||||
disabled: true,
|
||||
},
|
||||
...versionActions,
|
||||
{
|
||||
key: "show-info",
|
||||
label: t("InfoPanel:ViewDetails"),
|
||||
icon: "/static/images/info.outline.react.svg",
|
||||
onClick: this.onShowInfoPanel,
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
key: "block-unblock-version",
|
||||
label: t("UnblockVersion"),
|
||||
|
@ -1,26 +1,26 @@
|
||||
import { makeAutoObservable } from "mobx";
|
||||
|
||||
import {
|
||||
removeFiles,
|
||||
checkFileConflicts,
|
||||
deleteFile,
|
||||
deleteFolder,
|
||||
finalizeVersion,
|
||||
lockFile,
|
||||
downloadFiles,
|
||||
markAsRead,
|
||||
checkFileConflicts,
|
||||
removeShareFiles,
|
||||
getSubfolders,
|
||||
emptyTrash,
|
||||
finalizeVersion,
|
||||
getSubfolders,
|
||||
lockFile,
|
||||
markAsRead,
|
||||
removeFiles,
|
||||
removeShareFiles,
|
||||
} from "@appserver/common/api/files";
|
||||
import {
|
||||
ConflictResolveType,
|
||||
FileAction,
|
||||
FileStatus,
|
||||
} from "@appserver/common/constants";
|
||||
import { makeAutoObservable } from "mobx";
|
||||
import toastr from "studio/toastr";
|
||||
|
||||
import { TIMEOUT } from "../helpers/constants";
|
||||
import { loopTreeFolders, checkProtocol } from "../helpers/files-helpers";
|
||||
import toastr from "studio/toastr";
|
||||
import { combineUrl } from "@appserver/common/utils";
|
||||
import { AppServerConfig } from "@appserver/common/constants";
|
||||
import config from "../../package.json";
|
||||
@ -34,6 +34,7 @@ class FilesActionStore {
|
||||
settingsStore;
|
||||
dialogsStore;
|
||||
mediaViewerDataStore;
|
||||
infoPanelStore;
|
||||
|
||||
constructor(
|
||||
authStore,
|
||||
@ -43,7 +44,8 @@ class FilesActionStore {
|
||||
selectedFolderStore,
|
||||
settingsStore,
|
||||
dialogsStore,
|
||||
mediaViewerDataStore
|
||||
mediaViewerDataStore,
|
||||
infoPanelStore
|
||||
) {
|
||||
makeAutoObservable(this);
|
||||
this.authStore = authStore;
|
||||
@ -53,6 +55,7 @@ class FilesActionStore {
|
||||
this.selectedFolderStore = selectedFolderStore;
|
||||
this.settingsStore = settingsStore;
|
||||
this.dialogsStore = dialogsStore;
|
||||
this.infoPanelStore = infoPanelStore;
|
||||
this.mediaViewerDataStore = mediaViewerDataStore;
|
||||
}
|
||||
|
||||
@ -786,6 +789,7 @@ class FilesActionStore {
|
||||
switch (option) {
|
||||
case "share":
|
||||
return isAccessedSelected && !personal; //isFavoritesFolder ||isRecentFolder
|
||||
case "showInfo":
|
||||
case "copy":
|
||||
case "download":
|
||||
return hasSelection;
|
||||
@ -831,6 +835,8 @@ class FilesActionStore {
|
||||
setDeleteDialogVisible,
|
||||
} = this.dialogsStore;
|
||||
|
||||
const { toggleIsVisible } = this.infoPanelStore;
|
||||
|
||||
switch (option) {
|
||||
case "share":
|
||||
if (!this.isAvailableOption("share")) return null;
|
||||
@ -915,6 +921,7 @@ class FilesActionStore {
|
||||
const moveTo = this.getOption("moveTo", t);
|
||||
const copy = this.getOption("copy", t);
|
||||
const deleteOption = this.getOption("delete", t);
|
||||
const showInfo = this.getOption("showInfo", t);
|
||||
|
||||
itemsCollection
|
||||
.set("share", share)
|
||||
@ -922,7 +929,8 @@ class FilesActionStore {
|
||||
.set("downloadAs", downloadAs)
|
||||
.set("moveTo", moveTo)
|
||||
.set("copy", copy)
|
||||
.set("delete", deleteOption);
|
||||
.set("delete", deleteOption)
|
||||
.set("showInfo", showInfo);
|
||||
|
||||
return this.convertToArray(itemsCollection);
|
||||
};
|
||||
@ -932,12 +940,15 @@ class FilesActionStore {
|
||||
const download = this.getOption("download", t);
|
||||
const downloadAs = this.getOption("downloadAs", t);
|
||||
const copy = this.getOption("copy", t);
|
||||
const showInfo = this.getOption("showInfo", t);
|
||||
|
||||
itemsCollection
|
||||
.set("share", share)
|
||||
.set("download", download)
|
||||
.set("downloadAs", downloadAs)
|
||||
.set("copy", copy);
|
||||
.set("copy", copy)
|
||||
.set("showInfo", showInfo);
|
||||
|
||||
return this.convertToArray(itemsCollection);
|
||||
};
|
||||
|
||||
@ -948,6 +959,7 @@ class FilesActionStore {
|
||||
const download = this.getOption("download", t);
|
||||
const downloadAs = this.getOption("downloadAs", t);
|
||||
const copy = this.getOption("copy", t);
|
||||
const showInfo = this.getOption("showInfo", t);
|
||||
|
||||
itemsCollection
|
||||
.set("share", share)
|
||||
@ -960,7 +972,9 @@ class FilesActionStore {
|
||||
setUnsubscribe(true);
|
||||
setDeleteDialogVisible(true);
|
||||
},
|
||||
});
|
||||
})
|
||||
.set("showInfo", showInfo);
|
||||
|
||||
return this.convertToArray(itemsCollection);
|
||||
};
|
||||
|
||||
@ -968,12 +982,15 @@ class FilesActionStore {
|
||||
const moveTo = this.getOption("moveTo", t);
|
||||
const deleteOption = this.getOption("delete", t);
|
||||
const download = this.getOption("download", t);
|
||||
const showInfo = this.getOption("showInfo", t);
|
||||
|
||||
itemsCollection
|
||||
.set("download", download)
|
||||
.set("moveTo", moveTo)
|
||||
|
||||
.set("delete", deleteOption);
|
||||
.set("delete", deleteOption)
|
||||
.set("showInfo", showInfo);
|
||||
|
||||
return this.convertToArray(itemsCollection);
|
||||
};
|
||||
|
||||
@ -984,6 +1001,7 @@ class FilesActionStore {
|
||||
const download = this.getOption("download", t);
|
||||
const downloadAs = this.getOption("downloadAs", t);
|
||||
const copy = this.getOption("copy", t);
|
||||
const showInfo = this.getOption("showInfo", t);
|
||||
|
||||
itemsCollection
|
||||
.set("share", share)
|
||||
@ -999,7 +1017,9 @@ class FilesActionStore {
|
||||
.then(() => toastr.success(t("RemovedFromFavorites")))
|
||||
.catch((err) => toastr.error(err));
|
||||
},
|
||||
});
|
||||
})
|
||||
.set("showInfo", showInfo);
|
||||
|
||||
return this.convertToArray(itemsCollection);
|
||||
};
|
||||
|
||||
@ -1012,6 +1032,7 @@ class FilesActionStore {
|
||||
const download = this.getOption("download", t);
|
||||
const downloadAs = this.getOption("downloadAs", t);
|
||||
const deleteOption = this.getOption("delete", t);
|
||||
const showInfo = this.getOption("showInfo", t);
|
||||
|
||||
itemsCollection
|
||||
.set("download", download)
|
||||
@ -1021,9 +1042,12 @@ class FilesActionStore {
|
||||
onClick: () => setMoveToPanelVisible(true),
|
||||
iconUrl: "/static/images/move.react.svg",
|
||||
})
|
||||
.set("delete", deleteOption);
|
||||
.set("delete", deleteOption)
|
||||
.set("showInfo", showInfo);
|
||||
|
||||
return this.convertToArray(itemsCollection);
|
||||
};
|
||||
|
||||
getHeaderMenu = (t) => {
|
||||
const {
|
||||
isFavoritesFolder,
|
||||
|
@ -1,23 +1,24 @@
|
||||
import { makeAutoObservable, runInAction } from "mobx";
|
||||
import api from "@appserver/common/api";
|
||||
import {
|
||||
FolderType,
|
||||
FilterType,
|
||||
FileType,
|
||||
FileAction,
|
||||
AppServerConfig,
|
||||
FileAction,
|
||||
FileType,
|
||||
FilterType,
|
||||
FolderType,
|
||||
FileStatus,
|
||||
} from "@appserver/common/constants";
|
||||
import history from "@appserver/common/history";
|
||||
import { loopTreeFolders } from "../helpers/files-helpers";
|
||||
import config from "../../package.json";
|
||||
import { combineUrl } from "@appserver/common/utils";
|
||||
import { updateTempContent } from "@appserver/common/utils";
|
||||
import { thumbnailStatuses } from "../helpers/constants";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { openDocEditor as openEditor } from "../helpers/utils";
|
||||
import toastr from "studio/toastr";
|
||||
|
||||
import config from "../../package.json";
|
||||
import { thumbnailStatuses } from "../helpers/constants";
|
||||
import { loopTreeFolders } from "../helpers/files-helpers";
|
||||
import { openDocEditor as openEditor } from "../helpers/utils";
|
||||
|
||||
const { FilesFilter } = api;
|
||||
const storageViewAs = localStorage.getItem("viewAs");
|
||||
|
||||
@ -717,6 +718,7 @@ class FilesStore {
|
||||
"version", //category
|
||||
"finalize-version",
|
||||
"show-version-history",
|
||||
"show-info",
|
||||
"block-unblock-version", //need split
|
||||
"separator1",
|
||||
"open-location",
|
||||
@ -1004,6 +1006,7 @@ class FilesStore {
|
||||
"separator0",
|
||||
"sharing-settings",
|
||||
"owner-change",
|
||||
"show-info",
|
||||
"link-for-portal-users",
|
||||
"separator1",
|
||||
"open-location",
|
||||
|
27
products/ASC.Files/Client/src/store/InfoPanelStore.js
Normal file
27
products/ASC.Files/Client/src/store/InfoPanelStore.js
Normal file
@ -0,0 +1,27 @@
|
||||
import { makeAutoObservable } from "mobx";
|
||||
|
||||
class InfoPanelStore {
|
||||
isVisible = false;
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
onHeaderCrossClick = () => {
|
||||
this.isVisible = false;
|
||||
};
|
||||
|
||||
toggleIsVisible = () => {
|
||||
this.isVisible = !this.isVisible;
|
||||
};
|
||||
|
||||
setVisible = () => {
|
||||
this.isVisible = true;
|
||||
};
|
||||
|
||||
setIsVisible = (bool) => {
|
||||
this.isVisible = bool;
|
||||
};
|
||||
}
|
||||
|
||||
export default InfoPanelStore;
|
@ -1,11 +1,11 @@
|
||||
import { makeAutoObservable } from "mobx";
|
||||
import api from "@appserver/common/api";
|
||||
import axios from "axios";
|
||||
import {
|
||||
setFavoritesSetting,
|
||||
setRecentSetting,
|
||||
} from "@appserver/common/api/files";
|
||||
import { FolderType } from "@appserver/common/constants";
|
||||
import axios from "axios";
|
||||
import { makeAutoObservable } from "mobx";
|
||||
import { presentInArray } from "../helpers/files-helpers";
|
||||
|
||||
class SettingsStore {
|
||||
@ -62,6 +62,10 @@ class SettingsStore {
|
||||
this.treeFoldersStore = treeFoldersStore;
|
||||
}
|
||||
|
||||
get infoPanelIsVisible() {
|
||||
return this.infoPanelIsVisible;
|
||||
}
|
||||
|
||||
setIsLoaded = (isLoaded) => {
|
||||
this.settingsIsLoaded = isLoaded;
|
||||
};
|
||||
|
@ -16,13 +16,12 @@ import selectedFilesStore from "./SelectedFilesStore";
|
||||
import ContextOptionsStore from "./ContextOptionsStore";
|
||||
import HotkeyStore from "./HotkeyStore";
|
||||
import store from "studio/store";
|
||||
import InfoPanelStore from "./InfoPanelStore";
|
||||
|
||||
const selectedFolderStore = new SelectedFolderStore(store.auth.settingsStore);
|
||||
|
||||
const treeFoldersStore = new TreeFoldersStore(selectedFolderStore);
|
||||
|
||||
const settingsStore = new SettingsStore(thirdPartyStore, treeFoldersStore);
|
||||
|
||||
const filesStore = new FilesStore(
|
||||
store.auth,
|
||||
store.auth.settingsStore,
|
||||
@ -37,10 +36,8 @@ const mediaViewerDataStore = new MediaViewerDataStore(
|
||||
filesStore,
|
||||
settingsStore
|
||||
);
|
||||
|
||||
const secondaryProgressDataStore = new SecondaryProgressDataStore();
|
||||
const primaryProgressDataStore = new PrimaryProgressDataStore();
|
||||
|
||||
const dialogsStore = new DialogsStore(
|
||||
store.auth,
|
||||
treeFoldersStore,
|
||||
@ -57,6 +54,8 @@ const uploadDataStore = new UploadDataStore(
|
||||
settingsStore
|
||||
);
|
||||
|
||||
const infoPanelStore = new InfoPanelStore();
|
||||
|
||||
const filesActionsStore = new FilesActionsStore(
|
||||
store.auth,
|
||||
uploadDataStore,
|
||||
@ -65,11 +64,11 @@ const filesActionsStore = new FilesActionsStore(
|
||||
selectedFolderStore,
|
||||
settingsStore,
|
||||
dialogsStore,
|
||||
mediaViewerDataStore
|
||||
mediaViewerDataStore,
|
||||
infoPanelStore
|
||||
);
|
||||
|
||||
const versionHistoryStore = new VersionHistoryStore(filesStore);
|
||||
|
||||
const contextOptionsStore = new ContextOptionsStore(
|
||||
store.auth,
|
||||
dialogsStore,
|
||||
@ -79,7 +78,8 @@ const contextOptionsStore = new ContextOptionsStore(
|
||||
treeFoldersStore,
|
||||
uploadDataStore,
|
||||
versionHistoryStore,
|
||||
settingsStore
|
||||
settingsStore,
|
||||
infoPanelStore
|
||||
);
|
||||
|
||||
const hotkeyStore = new HotkeyStore(
|
||||
@ -105,6 +105,7 @@ const stores = {
|
||||
selectedFilesStore,
|
||||
contextOptionsStore,
|
||||
hotkeyStore,
|
||||
infoPanelStore,
|
||||
};
|
||||
|
||||
export default stores;
|
||||
|
12
public/images/info.outline.react.svg
Normal file
12
public/images/info.outline.react.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_21120_56765)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.5 2C5.18629 2 2.5 4.68629 2.5 8C2.5 11.3137 5.18629 14 8.5 14C11.8137 14 14.5 11.3137 14.5 8C14.5 4.68629 11.8137 2 8.5 2ZM0.5 8C0.5 3.58172 4.08172 0 8.5 0C12.9183 0 16.5 3.58172 16.5 8C16.5 12.4183 12.9183 16 8.5 16C4.08172 16 0.5 12.4183 0.5 8Z" fill="#333333"/>
|
||||
<circle cx="8.5" cy="5" r="1" fill="#333333"/>
|
||||
<rect x="7.5" y="7" width="2" height="5" rx="1" fill="#333333"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_21120_56765">
|
||||
<rect width="16" height="16" fill="white" transform="translate(0.5)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 710 B |
@ -100,12 +100,20 @@
|
||||
"NotFoundTitle": "Nothing found",
|
||||
"PasswordMinLenght": "Minimal password length",
|
||||
"Path": "Path",
|
||||
"PleaseNote": "Please note",
|
||||
"PleaseNoteDescription": " <0>{{pleaseNote}}</0>: your old portal address will become available to new ©linney users once you click the <2>{{save}}</2> button.",
|
||||
"PeopleAdministratorsCan": "People module admins can create profiles and groups, import people, and invite users.",
|
||||
"PortalAccess": "Portal access",
|
||||
"PortalAccessSubTitle": "This section allows you to provide users with safe and convenient ways to access the portal.",
|
||||
"PortalAdmins": "Portal admins",
|
||||
"PortalAdminsDescription": "Have the same access rights as the portal owner, except the right to: change portal owner; deactivate or delete portal.",
|
||||
"PortalOwner": "Portal Owner",
|
||||
"PortalRenaming": "Portal Renaming",
|
||||
"PortalRenamingDescription": "Here you can change your portal address.",
|
||||
"PortalRenamingDescriptionTooltip": "Enter the part that will appear next to the onlyoffice.com/onlyoffice.eu portal address.",
|
||||
"PortalRenamingLabelText": "New portal name",
|
||||
"PortalRenamingMobile": "Enter the part that will appear next to the onlyoffice.com/onlyoffice.eu portal address. Please note: your old portal address will become available to new ©linney users once you click the Save button.",
|
||||
"PortalRenamingSettingsTooltip": "<0>{{text}}</0> Enter the part that will appear next to the onlyoffice.com/onlyoffice.eu portal address.",
|
||||
"ProductUserOpportunities": "View profiles and groups",
|
||||
"RegistrationDate": "Registration date",
|
||||
"RestoreBackup": "Data Restore",
|
||||
@ -147,7 +155,6 @@
|
||||
"TrustedMail": "Trusted mail domain settings",
|
||||
"TrustedMailDescription": "Trusted Mail Domain Settings is a way to specify the mail servers used for user self-registration.",
|
||||
"TrustedMailHelper": "You can either check the Custom domains option and enter the trusted mail server in the field below so that a person who has an account at it will be able to register him(her)self by clicking the Join link on the Sign In page or disable this option.",
|
||||
"TrustedMailWarningHelper": "Users with trusted email domains will automatically be listed in the Waiting Room section of the Address book.",
|
||||
"TwoFactorAuth": "Two-factor authentication",
|
||||
"TwoFactorAuthDescription": "Two-factor authentication provides a more secure way to log in. After entering the credentials, the user will have to enter a code from an SMS or the authentication app. ",
|
||||
"TwoFactorAuthHelper": "Note: SMS messages can be sent if you have a positive balance only. You can always check your current balance in your SMS provider account. Do not forget to replenish your balance in good time. ",
|
||||
|
@ -147,7 +147,6 @@
|
||||
"TrustedMail": "Настройки доверенных почтовых доменов",
|
||||
"TrustedMailDescription": "Настройки доверенных почтовых доменов позволяют указать почтовые серверы, которые могут использовать пользователи при самостоятельной регистрации в ONLYOFFICE.",
|
||||
"TrustedMailHelper": "Можно отметить опцию Пользовательские домены и ввести доверенный почтовый сервер в поле ниже, чтобы любой сотрудник вашей компании, имеющий учетную запись на указанном почтовом сервере, смог зарегистрироваться самостоятельно, нажав ссылку Присоединиться на странице входа и введя адрес электронной почты с именем доверенного домена, который Вы добавили.",
|
||||
"TrustedMailWarningHelper": "Пользователи с доверенными почтовыми доменами будут автоматически попадать в Waiting Room в разделе Address book.",
|
||||
"TwoFactorAuth": "Двухфакторная аутентификация",
|
||||
"TwoFactorAuthDescription": "Двухфакторная аутентификация обеспечивает более безопасный способ входа на портал. После ввода учетных данных пользователь должен будет ввести код из SMS или приложения для аутентификации.",
|
||||
"TwoFactorAuthHelper": "Обратите внимание: отправка SMS-сообщений осуществляется только при положительном балансе. Вы всегда можете проверить текущий баланс в учетной записи вашего SMS-провайдера. Не забывайте своевременно пополнять баланс. ",
|
||||
|
@ -110,7 +110,7 @@ class SectionHeaderContent extends React.Component {
|
||||
const resultPath = locationPathname.slice(fullSettingsUrlLength + 1);
|
||||
const arrayOfParams = resultPath.split("/");
|
||||
|
||||
const key = getKeyByLink(arrayOfParams, settingsTree);
|
||||
const key = getKeyByLink(arrayOfParams, settingsTree)[0];
|
||||
const header = getTKeyByKey(key, settingsTree);
|
||||
const isCategory = checkPropertyByLink(
|
||||
arrayOfParams,
|
||||
@ -133,7 +133,7 @@ class SectionHeaderContent extends React.Component {
|
||||
componentDidUpdate() {
|
||||
const arrayOfParams = this.getArrayOfParams();
|
||||
|
||||
const key = getKeyByLink(arrayOfParams, settingsTree);
|
||||
const key = getKeyByLink(arrayOfParams, settingsTree)[0];
|
||||
const header = getTKeyByKey(key, settingsTree);
|
||||
const isCategory = checkPropertyByLink(
|
||||
arrayOfParams,
|
||||
|
@ -1,76 +0,0 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
import { isSmallTablet } from "@appserver/components/utils/device";
|
||||
|
||||
const StyledComponent = styled.div`
|
||||
.combo-button-label {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.settings-block {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.category-description {
|
||||
line-height: 20px;
|
||||
color: #657077;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* .category-item-wrapper:not(:last-child) {
|
||||
border-bottom: 1px solid #eceef1;
|
||||
margin-bottom: 24px;
|
||||
} */
|
||||
|
||||
.category-item-description {
|
||||
color: ${(props) => props.theme.studio.settings.common.descriptionColor};
|
||||
font-size: 12px;
|
||||
max-width: 1024px;
|
||||
}
|
||||
|
||||
.category-item-heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.category-item-title {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
@media (min-width: 600px) {
|
||||
.settings-block {
|
||||
max-width: 350px;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledComponent.defaultProps = { theme: Base };
|
||||
|
||||
const SettingsPageLayout = ({ children }) => {
|
||||
const [mobileView, setMobileView] = useState(true);
|
||||
|
||||
const checkInnerWidth = () => {
|
||||
if (isSmallTablet()) {
|
||||
setMobileView(true);
|
||||
} else {
|
||||
setMobileView(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("resize", checkInnerWidth);
|
||||
return () => window.removeEventListener("resize", checkInnerWidth);
|
||||
}, []);
|
||||
|
||||
const isMobile = !!(isSmallTablet() && mobileView);
|
||||
|
||||
return <>{children(isMobile)}</>;
|
||||
};
|
||||
|
||||
export default SettingsPageLayout;
|
@ -1,40 +0,0 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
|
||||
const StyledComponent = styled.div`
|
||||
.combo-button-label {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.category-item-wrapper {
|
||||
padding-top: 20px;
|
||||
|
||||
.category-item-heading {
|
||||
padding-bottom: 8px;
|
||||
svg {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.category-item-description {
|
||||
color: #657077;
|
||||
font-size: 13px;
|
||||
max-width: 1024px;
|
||||
}
|
||||
|
||||
.inherit-title-link {
|
||||
margin-right: 4px;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledComponent.defaultProps = { theme: Base };
|
||||
|
||||
const SettingsPageMobileView = ({ children }) => {
|
||||
return <StyledComponent>{children}</StyledComponent>;
|
||||
};
|
||||
|
||||
export default SettingsPageMobileView;
|
@ -0,0 +1,137 @@
|
||||
import React from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import styled from "styled-components";
|
||||
import Text from "@appserver/components/text";
|
||||
import Box from "@appserver/components/box";
|
||||
import Link from "@appserver/components/link";
|
||||
import { combineUrl } from "@appserver/common/utils";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { AppServerConfig } from "@appserver/common/constants";
|
||||
import withCultureNames from "@appserver/common/hoc/withCultureNames";
|
||||
import history from "@appserver/common/history";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
|
||||
import { StyledArrowRightIcon } from "../common/settingsCustomization/StyledSettings";
|
||||
|
||||
const StyledComponent = styled.div`
|
||||
padding-top: 13px;
|
||||
|
||||
.combo-button-label {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.category-item-wrapper {
|
||||
padding-bottom: 20px;
|
||||
|
||||
.category-item-heading {
|
||||
padding-bottom: 8px;
|
||||
svg {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.category-item-description {
|
||||
color: #657077;
|
||||
font-size: 13px;
|
||||
max-width: 1024px;
|
||||
}
|
||||
|
||||
.inherit-title-link {
|
||||
margin-right: 4px;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledComponent.defaultProps = { theme: Base };
|
||||
|
||||
const CustomizationNavbar = ({ t, theme, helpUrlCommonSettings }) => {
|
||||
const onClickLink = (e) => {
|
||||
e.preventDefault();
|
||||
history.push(e.target.pathname);
|
||||
};
|
||||
return (
|
||||
<StyledComponent>
|
||||
<div className="category-item-wrapper">
|
||||
<div className="category-item-heading">
|
||||
<Link
|
||||
className="inherit-title-link header"
|
||||
onClick={onClickLink}
|
||||
truncate={true}
|
||||
href={combineUrl(
|
||||
AppServerConfig.proxyURL,
|
||||
"/settings/common/customization/language-and-time-zone"
|
||||
)}
|
||||
>
|
||||
{t("StudioTimeLanguageSettings")}
|
||||
</Link>
|
||||
<StyledArrowRightIcon size="small" color="#333333" />
|
||||
</div>
|
||||
<Text className="category-item-description">
|
||||
{t("LanguageAndTimeZoneSettingsDescription")}
|
||||
</Text>
|
||||
<Box paddingProp="10px 0 3px 0">
|
||||
<Link
|
||||
color={theme.studio.settings.common.linkColorHelp}
|
||||
target="_blank"
|
||||
isHovered={true}
|
||||
href={helpUrlCommonSettings}
|
||||
>
|
||||
{t("Common:LearnMore")}
|
||||
</Link>
|
||||
</Box>
|
||||
</div>
|
||||
<div className="category-item-wrapper">
|
||||
<div className="category-item-heading">
|
||||
<Link
|
||||
truncate={true}
|
||||
className="inherit-title-link header"
|
||||
onClick={onClickLink}
|
||||
href={combineUrl(
|
||||
AppServerConfig.proxyURL,
|
||||
"/settings/common/customization/welcome-page-settings"
|
||||
)}
|
||||
>
|
||||
{t("CustomTitlesWelcome")}
|
||||
</Link>
|
||||
<StyledArrowRightIcon size="small" color="#333333" />
|
||||
</div>
|
||||
<Text className="category-item-description">
|
||||
{t("CustomTitlesSettingsDescription")}
|
||||
</Text>
|
||||
</div>
|
||||
<div className="category-item-wrapper">
|
||||
<div className="category-item-heading">
|
||||
<Link
|
||||
truncate={true}
|
||||
className="inherit-title-link header"
|
||||
onClick={onClickLink}
|
||||
href={combineUrl(
|
||||
AppServerConfig.proxyURL,
|
||||
"/settings/common/customization/portal-renaming"
|
||||
)}
|
||||
>
|
||||
{t("PortalRenaming")}
|
||||
</Link>
|
||||
<StyledArrowRightIcon size="small" color="#333333" />
|
||||
</div>
|
||||
<Text className="category-item-description">
|
||||
{t("PortalRenamingDescription")}
|
||||
</Text>
|
||||
</div>
|
||||
</StyledComponent>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
const { helpUrlCommonSettings, theme } = auth.settingsStore;
|
||||
return {
|
||||
theme,
|
||||
helpUrlCommonSettings,
|
||||
};
|
||||
})(
|
||||
withCultureNames(
|
||||
observer(withTranslation(["Settings", "Common"])(CustomizationNavbar))
|
||||
)
|
||||
);
|
@ -1,15 +1,14 @@
|
||||
import React from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import styled from "styled-components";
|
||||
import withCultureNames from "@appserver/common/hoc/withCultureNames";
|
||||
import LanguageAndTimeZone from "./settingsCustomization/language-and-time-zone";
|
||||
import WelcomePageSettings from "./settingsCustomization/welcome-page-settings";
|
||||
import PortalRenaming from "./settingsCustomization/portal-renaming";
|
||||
|
||||
import SettingsPageLayout from "./SettingsPageLayout";
|
||||
import SettingsPageMobileView from "./SettingsPageMobileView";
|
||||
|
||||
import { isSmallTablet } from "@appserver/components/utils/device";
|
||||
import CustomizationNavbar from "./customization-navbar";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
import { setDocumentTitle } from "../../../../../helpers/utils";
|
||||
|
||||
const StyledComponent = styled.div`
|
||||
.combo-button-label {
|
||||
@ -24,12 +23,12 @@ const StyledComponent = styled.div`
|
||||
line-height: 20px;
|
||||
color: #657077;
|
||||
margin-bottom: 20px;
|
||||
max-width: 700px;
|
||||
}
|
||||
|
||||
.category-item-wrapper:not(:last-child) {
|
||||
border-bottom: 1px solid #eceef1;
|
||||
margin-bottom: 24px;
|
||||
// Add
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
|
||||
@ -63,28 +62,42 @@ const StyledComponent = styled.div`
|
||||
StyledComponent.defaultProps = { theme: Base };
|
||||
|
||||
const Customization = ({ t }) => {
|
||||
return (
|
||||
<SettingsPageLayout>
|
||||
{(isMobile) =>
|
||||
isMobile ? (
|
||||
<SettingsPageMobileView>
|
||||
<LanguageAndTimeZone isMobileView={isMobile} />
|
||||
<WelcomePageSettings isMobileView={isMobile} />
|
||||
<PortalRenaming isMobileView={isMobile} />
|
||||
</SettingsPageMobileView>
|
||||
) : (
|
||||
<StyledComponent>
|
||||
<div className="category-description">{`${t(
|
||||
"Settings:CustomizationDescription"
|
||||
)}`}</div>
|
||||
{/* TODO: Add isMobile = false in component */}
|
||||
<LanguageAndTimeZone isMobileView={isMobile} />
|
||||
<WelcomePageSettings isMobileView={isMobile} />
|
||||
<PortalRenaming isMobileView={isMobile} />
|
||||
</StyledComponent>
|
||||
)
|
||||
}
|
||||
</SettingsPageLayout>
|
||||
const [mobileView, setMobileView] = useState(true);
|
||||
const [isLoadingCustomization, setIsLoadingCustomization] = useState(true);
|
||||
|
||||
const checkInnerWidth = () => {
|
||||
if (isSmallTablet()) {
|
||||
setMobileView(true);
|
||||
} else {
|
||||
setMobileView(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setDocumentTitle(t("Customization"));
|
||||
//TODO: add method to get the portal name
|
||||
setIsLoadingCustomization(false);
|
||||
|
||||
window.addEventListener("resize", checkInnerWidth);
|
||||
return () => window.removeEventListener("resize", checkInnerWidth);
|
||||
}, []);
|
||||
|
||||
const isMobile = !!(isSmallTablet() && mobileView);
|
||||
|
||||
return isMobile ? (
|
||||
<CustomizationNavbar />
|
||||
) : (
|
||||
<StyledComponent>
|
||||
<div className="category-description">{`${t(
|
||||
"Settings:CustomizationDescription"
|
||||
)}`}</div>
|
||||
<LanguageAndTimeZone
|
||||
isLoadingCustomization={isLoadingCustomization}
|
||||
isMobileView={isMobile}
|
||||
/>
|
||||
<WelcomePageSettings isMobileView={isMobile} />
|
||||
<PortalRenaming isMobileView={isMobile} />
|
||||
</StyledComponent>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -54,6 +54,18 @@ const StyledSettingsComponent = styled.div`
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.errorText {
|
||||
position: absolute;
|
||||
font-size: 10px;
|
||||
color: #f21c0e;
|
||||
}
|
||||
|
||||
.settings-block-description {
|
||||
line-height: 20px;
|
||||
color: #657077;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
@media (max-width: 599px) {
|
||||
${(props) =>
|
||||
props.hasScroll &&
|
||||
@ -75,6 +87,10 @@ const StyledSettingsComponent = styled.div`
|
||||
max-width: 350px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.settings-block-description {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (orientation: landscape) and (max-width: 600px) {
|
||||
|
@ -19,17 +19,10 @@ import { AppServerConfig } from "@appserver/common/constants";
|
||||
import config from "../../../../../../../package.json";
|
||||
import history from "@appserver/common/history";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
import Text from "@appserver/components/text";
|
||||
import Box from "@appserver/components/box";
|
||||
import Link from "@appserver/components/link";
|
||||
import { isSmallTablet } from "@appserver/components/utils/device";
|
||||
import checkScrollSettingsBlock from "../utils";
|
||||
import {
|
||||
StyledSettingsComponent,
|
||||
StyledScrollbar,
|
||||
StyledArrowRightIcon,
|
||||
} from "./StyledSettings";
|
||||
|
||||
import { StyledSettingsComponent, StyledScrollbar } from "./StyledSettings";
|
||||
import LoaderLngTZSettings from "../sub-components/loaderLngTZSettings";
|
||||
const mapTimezonesToArray = (timezones) => {
|
||||
return timezones.map((timezone) => {
|
||||
return { key: timezone.id, label: timezone.displayName };
|
||||
@ -80,7 +73,7 @@ class LanguageAndTimeZone extends React.Component {
|
||||
"timezoneDefault"
|
||||
);
|
||||
|
||||
setDocumentTitle(t("Customization"));
|
||||
setDocumentTitle(t("StudioTimeLanguageSettings"));
|
||||
|
||||
this.state = {
|
||||
isLoadedData: false,
|
||||
@ -90,8 +83,6 @@ class LanguageAndTimeZone extends React.Component {
|
||||
timezoneDefault: timezoneDefaultFromSessionStorage || timezone,
|
||||
language: languageFromSessionStorage || language,
|
||||
languageDefault: languageDefaultFromSessionStorage || language,
|
||||
isLoadingGreetingSave: false,
|
||||
isLoadingGreetingRestore: false,
|
||||
hasChanged: false,
|
||||
showReminder: false,
|
||||
hasScroll: false,
|
||||
@ -343,8 +334,9 @@ class LanguageAndTimeZone extends React.Component {
|
||||
theme,
|
||||
cultureNames,
|
||||
isMobileView,
|
||||
helpUrlCommonSettings,
|
||||
isLoadingCustomization,
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
isLoadedData,
|
||||
language,
|
||||
@ -359,37 +351,6 @@ class LanguageAndTimeZone extends React.Component {
|
||||
<LanguageTimeSettingsTooltip theme={theme} t={t} />
|
||||
);
|
||||
|
||||
const isMobileViewLanguageTimeSettings = (
|
||||
<div className="category-item-wrapper">
|
||||
<div className="category-item-heading">
|
||||
<Link
|
||||
className="inherit-title-link header"
|
||||
onClick={this.onClickLink}
|
||||
truncate={true}
|
||||
href={combineUrl(
|
||||
AppServerConfig.proxyURL,
|
||||
"/settings/common/customization/language-and-time-zone"
|
||||
)}
|
||||
>
|
||||
{t("StudioTimeLanguageSettings")}
|
||||
</Link>
|
||||
<StyledArrowRightIcon size="small" color="#333333" />
|
||||
</div>
|
||||
<Text className="category-item-description">
|
||||
{t("LanguageAndTimeZoneSettingsDescription")}
|
||||
</Text>
|
||||
<Box paddingProp="10px 0 3px 0">
|
||||
<Link
|
||||
color={theme.studio.settings.common.linkColorHelp}
|
||||
target="_blank"
|
||||
isHovered={true}
|
||||
href={helpUrlCommonSettings}
|
||||
>
|
||||
{t("Common:LearnMore")}
|
||||
</Link>
|
||||
</Box>
|
||||
</div>
|
||||
);
|
||||
const settingsBlock = (
|
||||
<div className="settings-block">
|
||||
<FieldContainer
|
||||
@ -440,8 +401,6 @@ class LanguageAndTimeZone extends React.Component {
|
||||
|
||||
return !isLoadedData ? (
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
) : isMobileView ? (
|
||||
isMobileViewLanguageTimeSettings
|
||||
) : (
|
||||
<StyledSettingsComponent
|
||||
hasScroll={hasScroll}
|
||||
@ -492,7 +451,6 @@ export default inject(({ auth, setup }) => {
|
||||
//getPortalCultures,
|
||||
getPortalTimezones,
|
||||
getCurrentCustomSchema,
|
||||
helpUrlCommonSettings,
|
||||
} = auth.settingsStore;
|
||||
|
||||
const { user } = auth.userStore;
|
||||
@ -514,7 +472,6 @@ export default inject(({ auth, setup }) => {
|
||||
setLanguageAndTime,
|
||||
getCurrentCustomSchema,
|
||||
getPortalTimezones,
|
||||
helpUrlCommonSettings,
|
||||
};
|
||||
})(
|
||||
withCultureNames(
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import styled from "styled-components";
|
||||
import Loader from "@appserver/components/loader";
|
||||
import toastr from "@appserver/components/toast/toastr";
|
||||
import HelpButton from "@appserver/components/help-button";
|
||||
@ -13,37 +12,12 @@ import { AppServerConfig } from "@appserver/common/constants";
|
||||
import config from "../../../../../../../package.json";
|
||||
import history from "@appserver/common/history";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
import Text from "@appserver/components/text";
|
||||
import Link from "@appserver/components/link";
|
||||
import { isSmallTablet } from "@appserver/components/utils/device";
|
||||
import checkScrollSettingsBlock from "../utils";
|
||||
import {
|
||||
StyledSettingsComponent,
|
||||
StyledScrollbar,
|
||||
StyledArrowRightIcon,
|
||||
} from "./StyledSettings";
|
||||
import { PortalRenamingTooltip } from "../sub-components/common-tooltips";
|
||||
import { StyledSettingsComponent, StyledScrollbar } from "./StyledSettings";
|
||||
import { saveToSessionStorage, getFromSessionStorage } from "../../../utils";
|
||||
|
||||
const StyledComponent = styled.div`
|
||||
.settings-block {
|
||||
margin-bottom: 70px;
|
||||
}
|
||||
|
||||
.settings-block {
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
.combo-button-label {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.error {
|
||||
font-weight: 400;
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
color: #f21c0e;
|
||||
}
|
||||
`;
|
||||
import { setDocumentTitle } from "../../../../../../helpers/utils";
|
||||
|
||||
const PortalRenaming = ({ t, setPortalRename, isMobileView }) => {
|
||||
// TODO: Change false
|
||||
@ -72,6 +46,8 @@ const PortalRenaming = ({ t, setPortalRename, isMobileView }) => {
|
||||
"The account name must be between 6 and 50 characters long";
|
||||
|
||||
useEffect(() => {
|
||||
setDocumentTitle(t("PortalRenaming"));
|
||||
|
||||
const checkScroll = checkScrollSettingsBlock();
|
||||
|
||||
window.addEventListener("resize", checkInnerWidth);
|
||||
@ -83,6 +59,15 @@ const PortalRenaming = ({ t, setPortalRename, isMobileView }) => {
|
||||
setHasScroll(scrollPortalName);
|
||||
}
|
||||
|
||||
// TODO: Remove div with height 64 and remove settings-mobile class
|
||||
const settingsMobile = document.getElementsByClassName(
|
||||
"settings-mobile"
|
||||
)[0];
|
||||
|
||||
if (settingsMobile) {
|
||||
settingsMobile.style.display = "none";
|
||||
}
|
||||
|
||||
return () =>
|
||||
window.removeEventListener(
|
||||
"resize",
|
||||
@ -135,7 +120,8 @@ const PortalRenaming = ({ t, setPortalRename, isMobileView }) => {
|
||||
saveToSessionStorage("errorValue", lengthNameError);
|
||||
break;
|
||||
default:
|
||||
setErrorValue("");
|
||||
saveToSessionStorage("errorValue", null);
|
||||
setErrorValue(null);
|
||||
}
|
||||
};
|
||||
|
||||
@ -174,94 +160,66 @@ const PortalRenaming = ({ t, setPortalRename, isMobileView }) => {
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Move to a file
|
||||
const onClickLink = (e) => {
|
||||
e.preventDefault();
|
||||
history.push(e.target.pathname);
|
||||
};
|
||||
|
||||
const isMobileViewPortalRenaming = (
|
||||
<div className="category-item-wrapper">
|
||||
<div className="category-item-heading">
|
||||
<Link
|
||||
truncate={true}
|
||||
className="inherit-title-link header"
|
||||
onClick={onClickLink}
|
||||
href={combineUrl(
|
||||
AppServerConfig.proxyURL,
|
||||
"/settings/common/customization/portal-renaming"
|
||||
)}
|
||||
>
|
||||
Portal Renaming
|
||||
{/* {t("CustomTitlesWelcome")} */}
|
||||
</Link>
|
||||
<StyledArrowRightIcon size="small" color="#333333" />
|
||||
</div>
|
||||
<Text className="category-item-description">
|
||||
{/* {t("CustomTitlesSettingsDescription")} */}
|
||||
Here you can change your portal address.
|
||||
</Text>
|
||||
</div>
|
||||
);
|
||||
|
||||
const tooltipPortalRenamingTooltip = <PortalRenamingTooltip t={t} />;
|
||||
const hasError = errorValue === null ? false : true;
|
||||
|
||||
const settingsBlock = (
|
||||
<div className="settings-block">
|
||||
<div className="settings-block-description">
|
||||
{t("PortalRenamingMobile")}
|
||||
</div>
|
||||
<FieldContainer
|
||||
id="fieldContainerWelcomePage"
|
||||
className="field-container-width"
|
||||
labelText={`${t("New portal name")}:`}
|
||||
labelText={`${t("PortalRenamingLabelText")}:`}
|
||||
isVertical={true}
|
||||
>
|
||||
<TextInput
|
||||
scale={true}
|
||||
value={portalName}
|
||||
onChange={onChangePortalName}
|
||||
// isDisabled={isLoadingGreetingSave || isLoadingGreetingRestore}
|
||||
placeholder={`${t("room")}`}
|
||||
isDisabled={isLoadingPortalNameSave}
|
||||
hasError={hasError}
|
||||
/>
|
||||
<div className="error">{errorValue}</div>
|
||||
<div className="errorText">{errorValue}</div>
|
||||
</FieldContainer>
|
||||
</div>
|
||||
);
|
||||
|
||||
return !isLoadedData ? (
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
) : isMobileView ? (
|
||||
isMobileViewPortalRenaming
|
||||
) : (
|
||||
<>
|
||||
<StyledComponent hasScroll={hasScroll} className="category-item-wrapper">
|
||||
{checkInnerWidth() && !isMobileView && (
|
||||
<div className="category-item-heading">
|
||||
<div className="category-item-title">{t("Portal Renaming")}</div>
|
||||
<HelpButton
|
||||
iconName="static/images/combined.shape.svg"
|
||||
size={12}
|
||||
// tooltipContent={tooltipCustomTitlesTooltip}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{(isMobileOnly && isSmallTablet()) || isSmallTablet() ? (
|
||||
<StyledScrollbar stype="smallBlack">{settingsBlock}</StyledScrollbar>
|
||||
) : (
|
||||
<> {settingsBlock}</>
|
||||
)}
|
||||
<SaveCancelButtons
|
||||
className="save-cancel-buttons"
|
||||
onSaveClick={onSavePortalRename}
|
||||
onCancelClick={onCancelPortalName}
|
||||
saveButtonLabel={t("Common:SaveButton")}
|
||||
cancelButtonLabel={t("Common:CancelButton")}
|
||||
showReminder={showReminder}
|
||||
reminderTest={t("YouHaveUnsavedChanges")}
|
||||
displaySettings={true}
|
||||
// hasScroll={hasScroll}
|
||||
/>
|
||||
</StyledComponent>
|
||||
</>
|
||||
<StyledSettingsComponent
|
||||
hasScroll={hasScroll}
|
||||
className="category-item-wrapper"
|
||||
>
|
||||
{checkInnerWidth() && !isMobileView && (
|
||||
<div className="category-item-heading">
|
||||
<div className="category-item-title">{t("PortalRenaming")}</div>
|
||||
<HelpButton
|
||||
iconName="static/images/combined.shape.svg"
|
||||
size={12}
|
||||
tooltipContent={tooltipPortalRenamingTooltip}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{(isMobileOnly && isSmallTablet()) || isSmallTablet() ? (
|
||||
<StyledScrollbar stype="smallBlack">{settingsBlock}</StyledScrollbar>
|
||||
) : (
|
||||
<> {settingsBlock}</>
|
||||
)}
|
||||
<SaveCancelButtons
|
||||
className="save-cancel-buttons"
|
||||
onSaveClick={onSavePortalRename}
|
||||
onCancelClick={onCancelPortalName}
|
||||
saveButtonLabel={t("Common:SaveButton")}
|
||||
cancelButtonLabel={t("Common:CancelButton")}
|
||||
showReminder={showReminder}
|
||||
reminderTest={t("YouHaveUnsavedChanges")}
|
||||
displaySettings={true}
|
||||
hasScroll={hasScroll}
|
||||
/>
|
||||
</StyledSettingsComponent>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -16,15 +16,10 @@ import { AppServerConfig } from "@appserver/common/constants";
|
||||
import config from "../../../../../../../package.json";
|
||||
import history from "@appserver/common/history";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
import Text from "@appserver/components/text";
|
||||
import Link from "@appserver/components/link";
|
||||
import { isSmallTablet } from "@appserver/components/utils/device";
|
||||
import checkScrollSettingsBlock from "../utils";
|
||||
import {
|
||||
StyledSettingsComponent,
|
||||
StyledScrollbar,
|
||||
StyledArrowRightIcon,
|
||||
} from "./StyledSettings";
|
||||
import { StyledSettingsComponent, StyledScrollbar } from "./StyledSettings";
|
||||
import LoaderLngTZSettings from "../sub-components/loaderLngTZSettings";
|
||||
|
||||
let greetingTitleFromSessionStorage = "";
|
||||
let greetingTitleDefaultFromSessionStorage = "";
|
||||
@ -47,7 +42,7 @@ class WelcomePageSettings extends React.Component {
|
||||
"isFirstWelcomePageSettings"
|
||||
);
|
||||
|
||||
setDocumentTitle(t("Customization"));
|
||||
setDocumentTitle(t("CustomTitlesWelcome"));
|
||||
|
||||
this.state = {
|
||||
isLoadedData: false,
|
||||
@ -235,29 +230,6 @@ class WelcomePageSettings extends React.Component {
|
||||
|
||||
const tooltipCustomTitlesTooltip = <CustomTitlesTooltip t={t} />;
|
||||
|
||||
// TODO: Move to a file
|
||||
const isMobileViewWelcomePageSettings = (
|
||||
<div className="category-item-wrapper">
|
||||
<div className="category-item-heading">
|
||||
<Link
|
||||
truncate={true}
|
||||
className="inherit-title-link header"
|
||||
onClick={this.onClickLink}
|
||||
href={combineUrl(
|
||||
AppServerConfig.proxyURL,
|
||||
"/settings/common/customization/welcome-page-settings"
|
||||
)}
|
||||
>
|
||||
{t("CustomTitlesWelcome")}
|
||||
</Link>
|
||||
<StyledArrowRightIcon size="small" color="#333333" />
|
||||
</div>
|
||||
<Text className="category-item-description">
|
||||
{t("CustomTitlesSettingsDescription")}
|
||||
</Text>
|
||||
</div>
|
||||
);
|
||||
|
||||
const settingsBlock = (
|
||||
<div className="settings-block">
|
||||
<FieldContainer
|
||||
@ -280,8 +252,6 @@ class WelcomePageSettings extends React.Component {
|
||||
|
||||
return !isLoadedData ? (
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
) : isMobileView ? (
|
||||
isMobileViewWelcomePageSettings
|
||||
) : (
|
||||
<StyledSettingsComponent
|
||||
hasScroll={hasScroll}
|
||||
|
@ -11,10 +11,10 @@ const StyledTooltip = styled.div`
|
||||
.bold {
|
||||
font-weight: 600;
|
||||
}
|
||||
.display {
|
||||
.display-inline {
|
||||
display: inline;
|
||||
}
|
||||
.display-link {
|
||||
.display-block {
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
@ -28,7 +28,7 @@ export const LanguageTimeSettingsTooltip = ({ t, theme }) => {
|
||||
<StyledTooltip>
|
||||
<Text className="font-size">
|
||||
<Trans ns="Settings" i18nKey="LanguageTimeSettingsTooltip" text={text}>
|
||||
<Text className="bold display font-size">{{ text }}</Text>{" "}
|
||||
<Text className="bold display-inline font-size">{{ text }}</Text>{" "}
|
||||
</Trans>
|
||||
</Text>
|
||||
<Text className="font-size">
|
||||
@ -39,10 +39,13 @@ export const LanguageTimeSettingsTooltip = ({ t, theme }) => {
|
||||
save={save}
|
||||
>
|
||||
{" "}
|
||||
<Text className="bold display font-size"> {{ save }}</Text>{" "}
|
||||
<Text className="bold display-inline font-size">
|
||||
{" "}
|
||||
{{ save }}
|
||||
</Text>{" "}
|
||||
<Link
|
||||
color={theme.studio.settings.common.linkColorHelp}
|
||||
className="display-link font-size"
|
||||
className="display-block font-size"
|
||||
isHovered={true}
|
||||
href="https://helpcenter.onlyoffice.com/administration/configuration.aspx#CustomizingPortal_block"
|
||||
>
|
||||
@ -69,9 +72,12 @@ export const CustomTitlesTooltip = ({ t }) => {
|
||||
text={text}
|
||||
from={from}
|
||||
>
|
||||
<Text className="bold display font-size"> {{ welcomeText }}</Text>{" "}
|
||||
<Text className="bold display font-size"> {{ text }}</Text>{" "}
|
||||
<Text className="bold display font-size"> {{ from }}</Text>{" "}
|
||||
<Text className="bold display-inline font-size">
|
||||
{" "}
|
||||
{{ welcomeText }}
|
||||
</Text>{" "}
|
||||
<Text className="bold display-inline font-size"> {{ text }}</Text>{" "}
|
||||
<Text className="bold display-inline font-size"> {{ from }}</Text>{" "}
|
||||
</Trans>
|
||||
</Text>
|
||||
<Text className="font-size">
|
||||
@ -81,7 +87,44 @@ export const CustomTitlesTooltip = ({ t }) => {
|
||||
header={header}
|
||||
>
|
||||
{" "}
|
||||
<Text className="bold display font-size"> {{ header }}</Text>{" "}
|
||||
<Text className="bold display-inline font-size">
|
||||
{" "}
|
||||
{{ header }}
|
||||
</Text>{" "}
|
||||
</Trans>
|
||||
</Text>
|
||||
</StyledTooltip>
|
||||
);
|
||||
};
|
||||
|
||||
export const PortalRenamingTooltip = ({ t }) => {
|
||||
const text = t("Settings:PortalRenamingDescription");
|
||||
const pleaseNote = t("Settings:PleaseNote");
|
||||
const save = t("Common:SaveButton");
|
||||
|
||||
return (
|
||||
<StyledTooltip>
|
||||
<Text className="font-size">
|
||||
<Trans
|
||||
ns="Settings"
|
||||
i18nKey="PortalRenamingSettingsTooltip"
|
||||
text={text}
|
||||
>
|
||||
<Text className="display-inline font-size"> {{ text }}</Text>{" "}
|
||||
</Trans>
|
||||
</Text>
|
||||
<Text className="font-size">
|
||||
<Trans
|
||||
ns="Settings"
|
||||
i18nKey="PleaseNoteDescription"
|
||||
pleaseNote={pleaseNote}
|
||||
save={save}
|
||||
>
|
||||
<Text className="bold display-inline font-size">
|
||||
{" "}
|
||||
{{ pleaseNote }}
|
||||
</Text>{" "}
|
||||
<Text className="bold display-inline font-size"> {{ save }}</Text>{" "}
|
||||
</Trans>
|
||||
</Text>
|
||||
</StyledTooltip>
|
||||
|
@ -0,0 +1,15 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import Loaders from "@appserver/common/components/Loaders";
|
||||
|
||||
const StyledLoader = styled.div``;
|
||||
|
||||
const LoaderLngTZSettings = () => {
|
||||
return (
|
||||
<StyledLoader>
|
||||
<Loaders.Rectangle />
|
||||
</StyledLoader>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoaderLngTZSettings;
|
@ -302,7 +302,7 @@ class WhiteLabel extends React.Component {
|
||||
} = this.state;
|
||||
console.log("WhiteLabelSettings render");
|
||||
|
||||
return <> В разработке</>;
|
||||
return <>In development</>;
|
||||
|
||||
return !isLoadedData ? (
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
|
@ -45,6 +45,12 @@ export const StyledCategoryWrapper = styled.div`
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
export const StyledTooltip = styled.div`
|
||||
.subtitle {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledMobileCategoryWrapper = styled.div`
|
||||
margin-bottom: 20px;
|
||||
|
||||
@ -115,4 +121,8 @@ export const LearnMoreWrapper = styled.div`
|
||||
flex-direction: column;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.learn-subtitle {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
`;
|
||||
|
@ -12,6 +12,7 @@ import AdminMessageSection from "./adminMessage";
|
||||
import MobileView from "./mobileView";
|
||||
import CategoryWrapper from "../sub-components/category-wrapper";
|
||||
import { size } from "@appserver/components/utils/device";
|
||||
import { getLanguage } from "@appserver/common/utils";
|
||||
|
||||
const AccessPortal = (props) => {
|
||||
const { t } = props;
|
||||
@ -30,31 +31,41 @@ const AccessPortal = (props) => {
|
||||
: setIsMobileView(false);
|
||||
};
|
||||
|
||||
const lng = getLanguage(localStorage.getItem("language") || "en");
|
||||
|
||||
if (isMobileView) return <MobileView />;
|
||||
return (
|
||||
<MainContainer className="desktop-view">
|
||||
<Text className="subtitle">{t("PortalAccessSubTitle")}</Text>
|
||||
<CategoryWrapper
|
||||
t={t}
|
||||
title={t("SettingPasswordStrength")}
|
||||
tooltipContent={t("SettingPasswordStrengthDescription")}
|
||||
tooltipTitle={t("SettingPasswordStrengthDescription")}
|
||||
tooltipUrl={`https://helpcenter.onlyoffice.com/${lng}/administration/configuration.aspx#ChangingSecuritySettings_block`}
|
||||
/>
|
||||
<PasswordStrengthSection />
|
||||
<hr />
|
||||
<CategoryWrapper
|
||||
t={t}
|
||||
title={t("TwoFactorAuth")}
|
||||
tooltipContent={t("TwoFactorAuthDescription")}
|
||||
tooltipTitle={t("TwoFactorAuthDescription")}
|
||||
tooltipUrl={`https://helpcenter.onlyoffice.com/${lng}/administration/two-factor-authentication.aspx`}
|
||||
/>
|
||||
<TfaSection />
|
||||
<hr />
|
||||
<CategoryWrapper
|
||||
t={t}
|
||||
title={t("TrustedMail")}
|
||||
tooltipContent={t("TrustedMailDescription")}
|
||||
tooltipTitle={t("TrustedMailDescription")}
|
||||
tooltipUrl={`https://helpcenter.onlyoffice.com/${lng}/administration/configuration.aspx#ChangingSecuritySettings_block`}
|
||||
/>
|
||||
<TrustedMailSection />
|
||||
<hr />
|
||||
<CategoryWrapper
|
||||
t={t}
|
||||
title={t("IPSecurity")}
|
||||
tooltipContent={t("IPSecurityDescription")}
|
||||
tooltipTitle={t("IPSecurityDescription")}
|
||||
/>
|
||||
<IpSecuritySection />
|
||||
<hr />
|
||||
|
@ -8,7 +8,6 @@ import Text from "@appserver/components/text";
|
||||
import Link from "@appserver/components/link";
|
||||
import Slider from "@appserver/components/slider";
|
||||
import Checkbox from "@appserver/components/checkbox";
|
||||
import SectionLoader from "../sub-components/section-loader";
|
||||
import { getLanguage } from "@appserver/common/utils";
|
||||
import { LearnMoreWrapper } from "../StyledSecurity";
|
||||
import toastr from "@appserver/components/toast/toastr";
|
||||
@ -20,10 +19,6 @@ import isEqual from "lodash/isEqual";
|
||||
const MainContainer = styled.div`
|
||||
width: 100%;
|
||||
|
||||
.page-subtitle {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.password-slider {
|
||||
width: 160px;
|
||||
height: 8px;
|
||||
@ -162,11 +157,11 @@ const PasswordStrength = (props) => {
|
||||
};
|
||||
|
||||
const lng = getLanguage(localStorage.getItem("language") || "en");
|
||||
if (!isLoading) return <SectionLoader />;
|
||||
|
||||
return (
|
||||
<MainContainer>
|
||||
<LearnMoreWrapper>
|
||||
<Text className="page-subtitle">
|
||||
<Text className="learn-subtitle">
|
||||
{t("SettingPasswordStrengthHelper")}
|
||||
</Text>
|
||||
<Link
|
||||
|
@ -7,23 +7,14 @@ import RadioButtonGroup from "@appserver/components/radio-button-group";
|
||||
import Text from "@appserver/components/text";
|
||||
import Link from "@appserver/components/link";
|
||||
import toastr from "@appserver/components/toast/toastr";
|
||||
import SectionLoader from "../sub-components/section-loader";
|
||||
import { getLanguage } from "@appserver/common/utils";
|
||||
import Buttons from "../sub-components/buttons";
|
||||
import { LearnMoreWrapper } from "../StyledSecurity";
|
||||
import { size } from "@appserver/components/utils/device";
|
||||
import { saveToSessionStorage, getFromSessionStorage } from "../../../utils";
|
||||
import isEqual from "lodash/isEqual";
|
||||
|
||||
const MainContainer = styled.div`
|
||||
width: 100%;
|
||||
|
||||
.page-subtitle {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.box {
|
||||
}
|
||||
`;
|
||||
|
||||
const TwoFactorAuth = (props) => {
|
||||
@ -113,11 +104,10 @@ const TwoFactorAuth = (props) => {
|
||||
};
|
||||
|
||||
const lng = getLanguage(localStorage.getItem("language") || "en");
|
||||
if (!isLoading) return <SectionLoader />;
|
||||
return (
|
||||
<MainContainer>
|
||||
<LearnMoreWrapper>
|
||||
<Text className="page-subtitle">{t("TwoFactorAuthHelper")}</Text>
|
||||
<Text className="learn-subtitle">{t("TwoFactorAuthHelper")}</Text>
|
||||
<Link
|
||||
color="#316DAA"
|
||||
target="_blank"
|
||||
|
@ -18,10 +18,6 @@ import isEqual from "lodash/isEqual";
|
||||
const MainContainer = styled.div`
|
||||
width: 100%;
|
||||
|
||||
.page-subtitle {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.user-fields {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
@ -130,7 +126,7 @@ const TrustedMail = (props) => {
|
||||
|
||||
const onSaveClick = () => {
|
||||
const valid = domains.map((domain) => regexp.test(domain));
|
||||
if (valid.includes(false)) {
|
||||
if (type === "1" && valid.includes(false)) {
|
||||
toastr.error(t("Common:IncorrectDomain"));
|
||||
return;
|
||||
}
|
||||
@ -160,7 +156,7 @@ const TrustedMail = (props) => {
|
||||
return (
|
||||
<MainContainer>
|
||||
<LearnMoreWrapper>
|
||||
<Text className="page-subtitle">{t("TrustedMailHelper")}</Text>
|
||||
<Text className="learn-subtitle">{t("TrustedMailHelper")}</Text>
|
||||
<Link
|
||||
color="#316DAA"
|
||||
target="_blank"
|
||||
@ -208,16 +204,6 @@ const TrustedMail = (props) => {
|
||||
/>
|
||||
)}
|
||||
|
||||
<Text
|
||||
color="#F21C0E"
|
||||
fontSize="16px"
|
||||
fontWeight="700"
|
||||
className="warning-text"
|
||||
>
|
||||
{t("Common:Warning")}!
|
||||
</Text>
|
||||
<Text>{t("TrustedMailWarningHelper")}</Text>
|
||||
|
||||
<Buttons
|
||||
t={t}
|
||||
showReminder={showReminder}
|
||||
@ -228,7 +214,7 @@ const TrustedMail = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ auth, setup }) => {
|
||||
export default inject(({ auth }) => {
|
||||
const {
|
||||
trustedDomainsType,
|
||||
trustedDomains,
|
||||
|
@ -1,11 +1,23 @@
|
||||
import React from "react";
|
||||
import Text from "@appserver/components/text";
|
||||
import HelpButton from "@appserver/components/help-button";
|
||||
import Link from "@appserver/components/link";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
import { StyledCategoryWrapper } from "../StyledSecurity";
|
||||
import { StyledCategoryWrapper, StyledTooltip } from "../StyledSecurity";
|
||||
|
||||
const CategoryWrapper = (props) => {
|
||||
const { title, tooltipContent, theme } = props;
|
||||
const { t, title, tooltipTitle, tooltipUrl, theme } = props;
|
||||
|
||||
const tooltip = () => (
|
||||
<StyledTooltip>
|
||||
<Text className={tooltipUrl ? "subtitle" : ""}>{tooltipTitle}</Text>
|
||||
{tooltipUrl && (
|
||||
<Link target="_blank" isHovered href={tooltipUrl}>
|
||||
{t("Common:LearnMore")}
|
||||
</Link>
|
||||
)}
|
||||
</StyledTooltip>
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledCategoryWrapper>
|
||||
@ -17,7 +29,7 @@ const CategoryWrapper = (props) => {
|
||||
displayType="dropdown"
|
||||
place="right"
|
||||
offsetRight={0}
|
||||
tooltipContent={<Text>{tooltipContent}</Text>}
|
||||
getContent={tooltip}
|
||||
tooltipColor={theme.studio.settings.security.owner.tooltipColor}
|
||||
/>
|
||||
</StyledCategoryWrapper>
|
||||
|
@ -1,26 +0,0 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import Loaders from "@appserver/common/components/Loaders";
|
||||
|
||||
const StyledLoader = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
width: 300px;
|
||||
|
||||
@media (max-width: 375px) {
|
||||
width: 100%;
|
||||
}
|
||||
`;
|
||||
|
||||
const SectionLoader = () => {
|
||||
return (
|
||||
<StyledLoader>
|
||||
<Loaders.Rectangle />
|
||||
<Loaders.Rectangle />
|
||||
<Loaders.Rectangle />
|
||||
</StyledLoader>
|
||||
);
|
||||
};
|
||||
|
||||
export default SectionLoader;
|
@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import styled from "styled-components";
|
||||
import commonIconsStyles from "@appserver/components/utils/common-icons-style";
|
||||
import { PlusIcon, TrashIcon } from "./svg";
|
||||
@ -38,6 +38,14 @@ const StyledAddWrapper = styled.div`
|
||||
cursor: pointer;
|
||||
`;
|
||||
|
||||
const usePrevious = (value) => {
|
||||
const ref = useRef();
|
||||
useEffect(() => {
|
||||
ref.current = value;
|
||||
}, [value]);
|
||||
return ref.current;
|
||||
};
|
||||
|
||||
const UserFields = (props) => {
|
||||
const {
|
||||
className,
|
||||
@ -49,6 +57,33 @@ const UserFields = (props) => {
|
||||
regexp,
|
||||
} = props;
|
||||
|
||||
const [errors, setErrors] = useState(new Array(inputs.length).fill(false));
|
||||
const prevInputs = usePrevious(inputs.length);
|
||||
|
||||
useEffect(() => {
|
||||
if (inputs.length > prevInputs) setErrors([...errors, false]);
|
||||
}, [inputs]);
|
||||
|
||||
const onBlur = (index) => {
|
||||
let newErrors = Array.from(errors);
|
||||
newErrors[index] = true;
|
||||
setErrors(newErrors);
|
||||
};
|
||||
|
||||
const onFocus = (index) => {
|
||||
let newErrors = Array.from(errors);
|
||||
newErrors[index] = false;
|
||||
setErrors(newErrors);
|
||||
};
|
||||
|
||||
const onDelete = (index) => {
|
||||
let newErrors = Array.from(errors);
|
||||
newErrors.splice(index, 1);
|
||||
setErrors(newErrors);
|
||||
|
||||
onDeleteInput(index);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
{inputs ? (
|
||||
@ -59,14 +94,14 @@ const UserFields = (props) => {
|
||||
<StyledInputWrapper key={`domain-input-${index}`}>
|
||||
<TextInput
|
||||
id={`domain-input-${index}`}
|
||||
isAutoFocussed={true}
|
||||
value={input}
|
||||
onChange={(e) => onChangeInput(e, index)}
|
||||
hasError={error}
|
||||
/>
|
||||
<StyledTrashIcon
|
||||
size="medium"
|
||||
onClick={() => onDeleteInput(index)}
|
||||
onBlur={() => onBlur(index)}
|
||||
onFocus={() => onFocus(index)}
|
||||
hasError={errors[index] && error}
|
||||
/>
|
||||
<StyledTrashIcon size="medium" onClick={() => onDelete(index)} />
|
||||
</StyledInputWrapper>
|
||||
);
|
||||
})
|
||||
|
@ -32,8 +32,8 @@ export const settingsTree = [
|
||||
{
|
||||
key: "0-0-2",
|
||||
icon: "",
|
||||
link: "team-template",
|
||||
tKey: "TeamTemplate",
|
||||
link: "portal-renaming",
|
||||
tKey: "PortalRenaming",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -238,7 +238,6 @@ const Editor = () => {
|
||||
data: "backup-restore",
|
||||
});
|
||||
socketHelper.on("restore-backup", () => {
|
||||
|
||||
setPreparationPortalDialogVisible(true);
|
||||
});
|
||||
} catch (e) {
|
||||
@ -625,20 +624,23 @@ const Editor = () => {
|
||||
const onSDKAppReady = () => {
|
||||
console.log("ONLYOFFICE Document Editor is ready");
|
||||
|
||||
const index = url.indexOf("#message/");
|
||||
if (index > -1) {
|
||||
const splitUrl = url.split("#message/");
|
||||
const message = decodeURIComponent(splitUrl[1]).replaceAll("+", " ");
|
||||
history.pushState({}, null, url.substring(0, index));
|
||||
docEditor.showMessage(message);
|
||||
} else {
|
||||
if (config?.Error) docEditor.showMessage(config.Error);
|
||||
}
|
||||
|
||||
const tempElm = document.getElementById("loader");
|
||||
if (tempElm) {
|
||||
tempElm.outerHTML = "";
|
||||
}
|
||||
|
||||
const index = url.indexOf("#message/");
|
||||
if (index > -1) {
|
||||
const splitUrl = url.split("#message/");
|
||||
if (splitUrl.length === 2) {
|
||||
let raw = splitUrl[1]?.trim();
|
||||
const message = decodeURIComponent(raw).replace(/\+/g, " ");
|
||||
docEditor.showMessage(message);
|
||||
history.pushState({}, null, url.substring(0, index));
|
||||
}
|
||||
} else {
|
||||
if (config?.Error) docEditor.showMessage(config.Error);
|
||||
}
|
||||
};
|
||||
|
||||
const onSDKInfo = (event) => {
|
||||
@ -961,7 +963,9 @@ const Editor = () => {
|
||||
)}
|
||||
|
||||
{preparationPortalDialogVisible && (
|
||||
<PreparationPortalDialog visible={preparationPortalDialogVisible} />
|
||||
<PreparationPortalDialog
|
||||
visible={preparationPortalDialogVisible}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
|
Loading…
Reference in New Issue
Block a user