diff --git a/build/install/win/Apache Kafka.aip b/build/install/win/Apache Kafka.aip deleted file mode 100644 index 731c6efca2..0000000000 --- a/build/install/win/Apache Kafka.aip +++ /dev/null @@ -1,266 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/install/win/Apache ZooKeeper.aip b/build/install/win/Apache ZooKeeper.aip deleted file mode 100644 index 07f73daf62..0000000000 --- a/build/install/win/Apache ZooKeeper.aip +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/install/win/CustomActions/C#/Utils/CustomAction.cs b/build/install/win/CustomActions/C#/Utils/CustomAction.cs index 45b43184c3..843e2a1210 100644 --- a/build/install/win/CustomActions/C#/Utils/CustomAction.cs +++ b/build/install/win/CustomActions/C#/Utils/CustomAction.cs @@ -1,11 +1,113 @@ using System; +using System.Collections.Generic; +using System.Text; +using System.Web; using System.Net.Sockets; using Microsoft.Deployment.WindowsInstaller; +using RabbitMQ.Client; namespace Utils { public class CustomActions { + public static string CreateAuthToken(string pkey, string machinekey) + { + using (var hasher = new System.Security.Cryptography.HMACSHA1(Encoding.UTF8.GetBytes(machinekey))) + { + var now = DateTime.UtcNow.ToString("yyyyMMddHHmmss"); + var hash = System.Web.HttpServerUtility.UrlTokenEncode(hasher.ComputeHash(Encoding.UTF8.GetBytes(string.Join("\n", now, pkey)))); + return string.Format("ASC {0}:{1}:{2}", pkey, now, hash); + } + } + + [CustomAction] + public static ActionResult SetVersionReleaseDateSign(Session session) + { + var pkey = Convert.ToString(session["VERSION.RELEASE_DATE"]); + var machineKey = Convert.ToString(session["MACHINE_KEY"]); + + session.Log("SetVersionReleaseDateSign: pkey {0}, machineKey {1}", pkey, machineKey); + + session["VERSION.RELEASE_DATE.SIGN"] = CreateAuthToken(pkey, machineKey); + + session.Log("SetVersionReleaseDateSign End: {0}", session["VERSION.RELEASE_DATE.SIGN"]); + + return ActionResult.Success; + } + + + [CustomAction] + public static ActionResult TestRedisServerConnection(Session session) + { + try + { + using (var redis = new Redis(session["REDIS_HOST_PROP"], Convert.ToInt32(session["REDIS_PORT_PROP"]))) + { + + if (!String.IsNullOrEmpty(session["REDIS_PASSWORD_PROP"].Trim())) + redis.Password = session["REDIS_PASSWORD_PROP"]; + + var pong = redis.Ping("ONLYOFFICE"); + + session.Log("Redis Status: IsConnected is {0}", !String.IsNullOrEmpty(pong)); + session["RedisServerConnectionError"] = !String.IsNullOrEmpty(pong) ? "" : String.Format("Connection Refused HOST:{0},PORT:{1},PASS:{2}", session["REDIS_HOST_PROP"], session["REDIS_PORT_PROP"], session["REDIS_PASSWORD_PROP"]); + + } + } + catch (Exception ex) + { + session.Log("RedisConnectionException '{0}'", ex.Message); + session["RedisServerConnectionError"] = String.Format("Connection Refused HOST:{0},PORT:{1},PASS:{2}", session["REDIS_HOST_PROP"], session["REDIS_PORT_PROP"], session["REDIS_PASSWORD_PROP"]); + } + + return ActionResult.Success; + } + + + [CustomAction] + public static ActionResult TestRabbitMQConnection(Session session) + { + ConnectionFactory factory = new ConnectionFactory(); + + factory.HostName = session["RABBITMQ_HOSTNAME_PROP"]; + factory.Port = Convert.ToInt32(session["RABBITMQ_PORT_PROP"]); + factory.VirtualHost = session["RABBITMQ_VIRTUALHOST_PROP"]; + factory.UserName = session["RABBITMQ_USERNAME_PROP"]; + factory.Password = session["RABBITMQ_PASSWORD_PROP"]; + + try + { + using (IConnection conn = factory.CreateConnection()) + { + session.Log("RabbitMQ Status: IsConnected is {0}", conn.IsOpen); + + session["RabbitMQServerConnectionError"] = conn.IsOpen ? "" : String.Format("Connection Refused HOST:{0}, PORT:{1}, VirtualHost:{2}, UserName:{3}, PASS:{4}", + session["RABBITMQ_HOSTNAME_PROP"], + session["RABBITMQ_PORT_PROP"], + session["RABBITMQ_VIRTUALHOST_PROP"], + session["RABBITMQ_USERNAME_PROP"], + session["RABBITMQ_PASSWORD_PROP"] + ); + } + } + catch (Exception ex) + { + + session.Log("RabbitMQ.Client.Exceptions.BrokerUnreachableException {0}", ex.Message); + session["RabbitMQServerConnectionError"] = String.Format("Connection Refused HOST:{0}, PORT:{1}, VirtualHost:{2}, UserName:{3}, PASS:{4}", + session["RABBITMQ_HOSTNAME_PROP"], + session["RABBITMQ_PORT_PROP"], + session["RABBITMQ_VIRTUALHOST_PROP"], + session["RABBITMQ_USERNAME_PROP"], + session["RABBITMQ_PASSWORD_PROP"] + ); + + } + + return ActionResult.Success; + + } + [CustomAction] public static ActionResult CheckTCPAvailability(Session session) { diff --git a/build/install/win/CustomActions/C#/Utils/Properties/AssemblyInfo.cs b/build/install/win/CustomActions/C#/Utils/Properties/AssemblyInfo.cs index 1c22b2f432..9be1eb3545 100644 --- a/build/install/win/CustomActions/C#/Utils/Properties/AssemblyInfo.cs +++ b/build/install/win/CustomActions/C#/Utils/Properties/AssemblyInfo.cs @@ -1,4 +1,5 @@ using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/build/install/win/CustomActions/C#/Utils/Utils.csproj b/build/install/win/CustomActions/C#/Utils/Utils.csproj index 2506c1d8be..d6d06a4b91 100644 --- a/build/install/win/CustomActions/C#/Utils/Utils.csproj +++ b/build/install/win/CustomActions/C#/Utils/Utils.csproj @@ -32,6 +32,9 @@ 4 + + packages\RabbitMQ.Client.3.6.5\lib\net45\RabbitMQ.Client.dll + @@ -46,8 +49,12 @@ + + + + \ No newline at end of file diff --git a/build/install/win/CustomActions/C#/Utils/packages.config b/build/install/win/CustomActions/C#/Utils/packages.config new file mode 100644 index 0000000000..97a4445b50 --- /dev/null +++ b/build/install/win/CustomActions/C#/Utils/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/build/install/win/CustomActions/C#/Utils/redis-sharp.cs b/build/install/win/CustomActions/C#/Utils/redis-sharp.cs new file mode 100644 index 0000000000..f0f9eedd1f --- /dev/null +++ b/build/install/win/CustomActions/C#/Utils/redis-sharp.cs @@ -0,0 +1,937 @@ +// +// redis-sharp.cs: ECMA CLI Binding to the Redis key-value storage system +// +// Authors: +// Miguel de Icaza (miguel@gnome.org) +// +// Copyright 2010 Novell, Inc. +// +// Licensed under the same terms of reddis: new BSD license. +// +#define DEBUG + +using System; +using System.IO; +using System.Collections.Generic; +using System.Net.Sockets; +using System.Text; +using System.Diagnostics; +using System.Linq; + +public class Redis : IDisposable { + Socket socket; + BufferedStream bstream; + + public enum KeyType { + None, String, List, Set + } + + public class ResponseException : Exception { + public ResponseException (string code) : base ("Response error") + { + Code = code; + } + + public string Code { get; private set; } + } + + public Redis (string host, int port) + { + if (host == null) + throw new ArgumentNullException ("host"); + + Host = host; + Port = port; + SendTimeout = -1; + } + + public Redis (string host) : this (host, 6379) + { + } + + public Redis () : this ("localhost", 6379) + { + } + + public string Host { get; private set; } + public int Port { get; private set; } + public int RetryTimeout { get; set; } + public int RetryCount { get; set; } + public int SendTimeout { get; set; } + public string Password { get; set; } + + int db; + public int Db { + get { + return db; + } + + set { + db = value; + SendExpectSuccess ("SELECT", db); + } + } + + public string this [string key] { + get { return GetString (key); } + set { Set (key, value); } + } + + public void Set (string key, string value) + { + if (key == null) + throw new ArgumentNullException ("key"); + if (value == null) + throw new ArgumentNullException ("value"); + + Set (key, Encoding.UTF8.GetBytes (value)); + } + + + public void Set (string key, byte [] value) + { + if (key == null) + throw new ArgumentNullException ("key"); + if (value == null) + throw new ArgumentNullException ("value"); + + if (value.Length > 1073741824) + throw new ArgumentException ("value exceeds 1G", "value"); + + if (!SendDataCommand (value, "SET", key)) + throw new Exception ("Unable to connect"); + ExpectSuccess (); + } + + public bool SetNX (string key, string value) + { + if (key == null) + throw new ArgumentNullException ("key"); + if (value == null) + throw new ArgumentNullException ("value"); + + return SetNX (key, Encoding.UTF8.GetBytes (value)); + } + + public bool SetNX (string key, byte [] value) + { + if (key == null) + throw new ArgumentNullException ("key"); + if (value == null) + throw new ArgumentNullException ("value"); + + if (value.Length > 1073741824) + throw new ArgumentException ("value exceeds 1G", "value"); + + return SendDataExpectInt (value, "SETNX", key) > 0 ? true : false; + } + + public void Set (IDictionary dict) + { + if (dict == null) + throw new ArgumentNullException ("dict"); + + Set (dict.ToDictionary(k => k.Key, v => Encoding.UTF8.GetBytes(v.Value))); + } + + public void Set (IDictionary dict) + { + if (dict == null) + throw new ArgumentNullException ("dict"); + + MSet (dict.Keys.ToArray (), dict.Values.ToArray ()); + } + + public void MSet (string [] keys, byte [][] values) + { + if (keys.Length != values.Length) + throw new ArgumentException ("keys and values must have the same size"); + + byte [] nl = Encoding.UTF8.GetBytes ("\r\n"); + MemoryStream ms = new MemoryStream (); + + for (int i = 0; i < keys.Length; i++) { + byte [] key = Encoding.UTF8.GetBytes(keys[i]); + byte [] val = values[i]; + byte [] kLength = Encoding.UTF8.GetBytes ("$" + key.Length + "\r\n"); + byte [] k = Encoding.UTF8.GetBytes (keys[i] + "\r\n"); + byte [] vLength = Encoding.UTF8.GetBytes ("$" + val.Length + "\r\n"); + ms.Write (kLength, 0, kLength.Length); + ms.Write (k, 0, k.Length); + ms.Write (vLength, 0, vLength.Length); + ms.Write (val, 0, val.Length); + ms.Write (nl, 0, nl.Length); + } + + SendDataRESP (ms.ToArray (), "*" + (keys.Length * 2 + 1) + "\r\n$4\r\nMSET\r\n"); + ExpectSuccess (); + } + + public byte [] Get (string key) + { + if (key == null) + throw new ArgumentNullException ("key"); + return SendExpectData ("GET", key); + } + + public string Ping(String key) + { + return Encoding.UTF8.GetString (SendExpectData("PING", key)); + } + + public string GetString (string key) + { + if (key == null) + throw new ArgumentNullException ("key"); + return Encoding.UTF8.GetString (Get (key)); + } + + public byte [][] Sort (SortOptions options) + { + return Sort (options.Key, options.StoreInKey, options.ToArgs()); + } + + public byte [][] Sort (string key, string destination, params object [] options) + { + if (key == null) + throw new ArgumentNullException ("key"); + + int offset = string.IsNullOrEmpty (destination) ? 1 : 3; + object [] args = new object [offset + options.Length]; + + args [0] = key; + Array.Copy (options, 0, args, offset, options.Length); + if (offset == 1) { + return SendExpectDataArray ("SORT", args); + } + else { + args [1] = "STORE"; + args [2] = destination; + int n = SendExpectInt ("SORT", args); + return new byte [n][]; + } + } + + public byte [] GetSet (string key, byte [] value) + { + if (key == null) + throw new ArgumentNullException ("key"); + if (value == null) + throw new ArgumentNullException ("value"); + + if (value.Length > 1073741824) + throw new ArgumentException ("value exceeds 1G", "value"); + + if (!SendDataCommand (value, "GETSET", key)) + throw new Exception ("Unable to connect"); + + return ReadData (); + } + + public string GetSet (string key, string value) + { + if (key == null) + throw new ArgumentNullException ("key"); + if (value == null) + throw new ArgumentNullException ("value"); + return Encoding.UTF8.GetString (GetSet (key, Encoding.UTF8.GetBytes (value))); + } + + string ReadLine () + { + StringBuilder sb = new StringBuilder (); + int c; + + while ((c = bstream.ReadByte ()) != -1){ + if (c == '\r') + continue; + if (c == '\n') + break; + sb.Append ((char) c); + } + return sb.ToString (); + } + + void Connect () + { + socket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + socket.NoDelay = true; + socket.SendTimeout = SendTimeout; + socket.Connect (Host, Port); + if (!socket.Connected){ + socket.Close (); + socket = null; + return; + } + bstream = new BufferedStream (new NetworkStream (socket), 16*1024); + + if (Password != null) + SendExpectSuccess ("AUTH", Password); + } + + byte [] end_data = new byte [] { (byte) '\r', (byte) '\n' }; + + bool SendDataCommand (byte [] data, string cmd, params object [] args) + { + string resp = "*" + (1 + args.Length + 1).ToString () + "\r\n"; + resp += "$" + cmd.Length + "\r\n" + cmd + "\r\n"; + foreach (object arg in args) { + string argStr = arg.ToString (); + int argStrLength = Encoding.UTF8.GetByteCount(argStr); + resp += "$" + argStrLength + "\r\n" + argStr + "\r\n"; + } + resp += "$" + data.Length + "\r\n"; + + return SendDataRESP (data, resp); + } + + bool SendDataRESP (byte [] data, string resp) + { + if (socket == null) + Connect (); + if (socket == null) + return false; + + byte [] r = Encoding.UTF8.GetBytes (resp); + try { + Log ("C", resp); + socket.Send (r); + if (data != null){ + socket.Send (data); + socket.Send (end_data); + } + } catch (SocketException){ + // timeout; + socket.Close (); + socket = null; + + return false; + } + return true; + } + + bool SendCommand (string cmd, params object [] args) + { + if (socket == null) + Connect (); + if (socket == null) + return false; + + string resp = "*" + (1 + args.Length).ToString () + "\r\n"; + resp += "$" + cmd.Length + "\r\n" + cmd + "\r\n"; + foreach (object arg in args) { + string argStr = arg.ToString (); + int argStrLength = Encoding.UTF8.GetByteCount(argStr); + resp += "$" + argStrLength + "\r\n" + argStr + "\r\n"; + } + + byte [] r = Encoding.UTF8.GetBytes (resp); + try { + Log ("C", resp); + socket.Send (r); + } catch (SocketException){ + // timeout; + socket.Close (); + socket = null; + + return false; + } + return true; + } + + [Conditional ("DEBUG")] + void Log (string id, string message) + { + Console.WriteLine(id + ": " + message.Trim().Replace("\r\n", " ")); + } + + void ExpectSuccess () + { + int c = bstream.ReadByte (); + if (c == -1) + throw new ResponseException ("No more data"); + + string s = ReadLine (); + Log ("S", (char)c + s); + if (c == '-') + throw new ResponseException (s.StartsWith ("ERR ") ? s.Substring (4) : s); + } + + void SendExpectSuccess (string cmd, params object [] args) + { + if (!SendCommand (cmd, args)) + throw new Exception ("Unable to connect"); + + ExpectSuccess (); + } + + int SendDataExpectInt (byte[] data, string cmd, params object [] args) + { + if (!SendDataCommand (data, cmd, args)) + throw new Exception ("Unable to connect"); + + int c = bstream.ReadByte (); + if (c == -1) + throw new ResponseException ("No more data"); + + string s = ReadLine (); + Log ("S", (char)c + s); + if (c == '-') + throw new ResponseException (s.StartsWith ("ERR ") ? s.Substring (4) : s); + if (c == ':'){ + int i; + if (int.TryParse (s, out i)) + return i; + } + throw new ResponseException ("Unknown reply on integer request: " + c + s); + } + + int SendExpectInt (string cmd, params object [] args) + { + if (!SendCommand (cmd, args)) + throw new Exception ("Unable to connect"); + + int c = bstream.ReadByte (); + if (c == -1) + throw new ResponseException ("No more data"); + + string s = ReadLine (); + Log ("S", (char)c + s); + if (c == '-') + throw new ResponseException (s.StartsWith ("ERR ") ? s.Substring (4) : s); + if (c == ':'){ + int i; + if (int.TryParse (s, out i)) + return i; + } + throw new ResponseException ("Unknown reply on integer request: " + c + s); + } + + string SendExpectString (string cmd, params object [] args) + { + if (!SendCommand (cmd, args)) + throw new Exception ("Unable to connect"); + + int c = bstream.ReadByte (); + if (c == -1) + throw new ResponseException ("No more data"); + + string s = ReadLine (); + Log ("S", (char)c + s); + if (c == '-') + throw new ResponseException (s.StartsWith ("ERR ") ? s.Substring (4) : s); + if (c == '+') + return s; + + throw new ResponseException ("Unknown reply on integer request: " + c + s); + } + + // + // This one does not throw errors + // + string SendGetString (string cmd, params object [] args) + { + if (!SendCommand (cmd, args)) + throw new Exception ("Unable to connect"); + + return ReadLine (); + } + + byte [] SendExpectData (string cmd, params object [] args) + { + if (!SendCommand (cmd, args)) + throw new Exception ("Unable to connect"); + + return ReadData (); + } + + byte [] ReadData () + { + string s = ReadLine (); + Log ("S", s); + if (s.Length == 0) + throw new ResponseException ("Zero length respose"); + + char c = s [0]; + if (c == '-') + throw new ResponseException (s.StartsWith ("-ERR ") ? s.Substring (5) : s.Substring (1)); + + if (c == '$'){ + if (s == "$-1") + return null; + int n; + + if (Int32.TryParse (s.Substring (1), out n)){ + byte [] retbuf = new byte [n]; + + int bytesRead = 0; + do { + int read = bstream.Read (retbuf, bytesRead, n - bytesRead); + if (read < 1) + throw new ResponseException("Invalid termination mid stream"); + bytesRead += read; + } + while (bytesRead < n); + if (bstream.ReadByte () != '\r' || bstream.ReadByte () != '\n') + throw new ResponseException ("Invalid termination"); + return retbuf; + } + throw new ResponseException ("Invalid length"); + } + + /* don't treat arrays here because only one element works -- use DataArray! + //returns the number of matches + if (c == '*') { + int n; + if (Int32.TryParse(s.Substring(1), out n)) + return n <= 0 ? new byte [0] : ReadData(); + + throw new ResponseException ("Unexpected length parameter" + r); + } + */ + + throw new ResponseException ("Unexpected reply: " + s); + } + + public bool ContainsKey (string key) + { + if (key == null) + throw new ArgumentNullException ("key"); + return SendExpectInt ("EXISTS", key) == 1; + } + + public bool Remove (string key) + { + if (key == null) + throw new ArgumentNullException ("key"); + return SendExpectInt ("DEL", key) == 1; + } + + public int Remove (params string [] args) + { + if (args == null) + throw new ArgumentNullException ("args"); + return SendExpectInt ("DEL", args); + } + + public int Increment (string key) + { + if (key == null) + throw new ArgumentNullException ("key"); + return SendExpectInt ("INCR", key); + } + + public int Increment (string key, int count) + { + if (key == null) + throw new ArgumentNullException ("key"); + return SendExpectInt ("INCRBY", key, count); + } + + public int Decrement (string key) + { + if (key == null) + throw new ArgumentNullException ("key"); + return SendExpectInt ("DECR", key); + } + + public int Decrement (string key, int count) + { + if (key == null) + throw new ArgumentNullException ("key"); + return SendExpectInt ("DECRBY", key, count); + } + + public KeyType TypeOf (string key) + { + if (key == null) + throw new ArgumentNullException ("key"); + switch (SendExpectString ("TYPE", key)) { + case "none": + return KeyType.None; + case "string": + return KeyType.String; + case "set": + return KeyType.Set; + case "list": + return KeyType.List; + } + throw new ResponseException ("Invalid value"); + } + + public string RandomKey () + { + return SendExpectString ("RANDOMKEY"); + } + + public bool Rename (string oldKeyname, string newKeyname) + { + if (oldKeyname == null) + throw new ArgumentNullException ("oldKeyname"); + if (newKeyname == null) + throw new ArgumentNullException ("newKeyname"); + return SendGetString ("RENAME", oldKeyname, newKeyname) [0] == '+'; + } + + public bool Expire (string key, int seconds) + { + if (key == null) + throw new ArgumentNullException ("key"); + return SendExpectInt ("EXPIRE", key, seconds) == 1; + } + + public bool ExpireAt (string key, int time) + { + if (key == null) + throw new ArgumentNullException ("key"); + return SendExpectInt ("EXPIREAT", key, time) == 1; + } + + public int TimeToLive (string key) + { + if (key == null) + throw new ArgumentNullException ("key"); + return SendExpectInt ("TTL", key); + } + + public int DbSize { + get { + return SendExpectInt ("DBSIZE"); + } + } + + public void Save () + { + SendExpectSuccess ("SAVE"); + } + + public void BackgroundSave () + { + SendExpectSuccess ("BGSAVE"); + } + + public void Shutdown () + { + SendCommand ("SHUTDOWN"); + try { + // the server may return an error + string s = ReadLine (); + Log ("S", s); + if (s.Length == 0) + throw new ResponseException ("Zero length respose"); + throw new ResponseException (s.StartsWith ("-ERR ") ? s.Substring (5) : s.Substring (1)); + } catch (IOException) { + // this is the expected good result + socket.Close (); + socket = null; + } + } + + public void FlushAll () + { + SendExpectSuccess ("FLUSHALL"); + } + + public void FlushDb () + { + SendExpectSuccess ("FLUSHDB"); + } + + const long UnixEpoch = 621355968000000000L; + + public DateTime LastSave { + get { + int t = SendExpectInt ("LASTSAVE"); + + return new DateTime (UnixEpoch) + TimeSpan.FromSeconds (t); + } + } + + public Dictionary GetInfo () + { + byte [] r = SendExpectData ("INFO"); + var dict = new Dictionary(); + + foreach (var line in Encoding.UTF8.GetString (r).Split ('\n')){ + int p = line.IndexOf (':'); + if (p == -1) + continue; + dict.Add (line.Substring (0, p), line.Substring (p+1)); + } + return dict; + } + + public string [] Keys { + get { + return GetKeys("*"); + } + } + + public string [] GetKeys (string pattern) + { + if (pattern == null) + throw new ArgumentNullException ("pattern"); + + return SendExpectStringArray ("KEYS", pattern); + } + + public byte [][] MGet (params string [] keys) + { + if (keys == null) + throw new ArgumentNullException ("keys"); + if (keys.Length == 0) + throw new ArgumentException ("keys"); + + return SendExpectDataArray ("MGET", keys); + } + + + public string [] SendExpectStringArray (string cmd, params object [] args) + { + byte [][] reply = SendExpectDataArray (cmd, args); + string [] keys = new string [reply.Length]; + for (int i = 0; i < reply.Length; i++) + keys[i] = Encoding.UTF8.GetString (reply[i]); + return keys; + } + + public byte[][] SendExpectDataArray (string cmd, params object [] args) + { + if (!SendCommand (cmd, args)) + throw new Exception("Unable to connect"); + int c = bstream.ReadByte(); + if (c == -1) + throw new ResponseException("No more data"); + + string s = ReadLine(); + Log("S", (char)c + s); + if (c == '-') + throw new ResponseException(s.StartsWith("ERR ") ? s.Substring(4) : s); + if (c == '*') { + int count; + if (int.TryParse (s, out count)) { + byte [][] result = new byte [count][]; + + for (int i = 0; i < count; i++) + result[i] = ReadData(); + + return result; + } + } + throw new ResponseException("Unknown reply on multi-request: " + c + s); + } + + #region List commands + public byte[][] ListRange(string key, int start, int end) + { + return SendExpectDataArray ("LRANGE", key, start, end); + } + + public void LeftPush(string key, string value) + { + LeftPush(key, Encoding.UTF8.GetBytes (value)); + } + + public void LeftPush(string key, byte [] value) + { + SendDataCommand (value, "LPUSH", key); + ExpectSuccess(); + } + + public void RightPush(string key, string value) + { + RightPush(key, Encoding.UTF8.GetBytes (value)); + } + + public void RightPush(string key, byte [] value) + { + SendDataCommand (value, "RPUSH", key); + ExpectSuccess(); + } + + public int ListLength (string key) + { + return SendExpectInt ("LLEN", key); + } + + public byte[] ListIndex (string key, int index) + { + SendCommand ("LINDEX", key, index); + return ReadData (); + } + + public byte[] LeftPop(string key) + { + SendCommand ("LPOP", key); + return ReadData (); + } + + public byte[] RightPop(string key) + { + SendCommand ("RPOP", key); + return ReadData (); + } + #endregion + + #region Set commands + public bool AddToSet (string key, byte[] member) + { + return SendDataExpectInt(member, "SADD", key) > 0; + } + + public bool AddToSet (string key, string member) + { + return AddToSet (key, Encoding.UTF8.GetBytes(member)); + } + + public int CardinalityOfSet (string key) + { + return SendExpectInt ("SCARD", key); + } + + public bool IsMemberOfSet (string key, byte[] member) + { + return SendDataExpectInt (member, "SISMEMBER", key) > 0; + } + + public bool IsMemberOfSet(string key, string member) + { + return IsMemberOfSet(key, Encoding.UTF8.GetBytes(member)); + } + + public byte[][] GetMembersOfSet (string key) + { + return SendExpectDataArray ("SMEMBERS", key); + } + + public byte[] GetRandomMemberOfSet (string key) + { + return SendExpectData ("SRANDMEMBER", key); + } + + public byte[] PopRandomMemberOfSet (string key) + { + return SendExpectData ("SPOP", key); + } + + public bool RemoveFromSet (string key, byte[] member) + { + return SendDataExpectInt (member, "SREM", key) > 0; + } + + public bool RemoveFromSet (string key, string member) + { + return RemoveFromSet (key, Encoding.UTF8.GetBytes(member)); + } + + public byte[][] GetUnionOfSets (params string[] keys) + { + if (keys == null) + throw new ArgumentNullException(); + + return SendExpectDataArray ("SUNION", keys); + + } + + void StoreSetCommands (string cmd, params string[] keys) + { + if (String.IsNullOrEmpty(cmd)) + throw new ArgumentNullException ("cmd"); + + if (keys == null) + throw new ArgumentNullException ("keys"); + + SendExpectSuccess (cmd, keys); + } + + public void StoreUnionOfSets (params string[] keys) + { + StoreSetCommands ("SUNIONSTORE", keys); + } + + public byte[][] GetIntersectionOfSets (params string[] keys) + { + if (keys == null) + throw new ArgumentNullException(); + + return SendExpectDataArray ("SINTER", keys); + } + + public void StoreIntersectionOfSets (params string[] keys) + { + StoreSetCommands ("SINTERSTORE", keys); + } + + public byte[][] GetDifferenceOfSets (params string[] keys) + { + if (keys == null) + throw new ArgumentNullException(); + + return SendExpectDataArray ("SDIFF", keys); + } + + public void StoreDifferenceOfSets (params string[] keys) + { + StoreSetCommands ("SDIFFSTORE", keys); + } + + public bool MoveMemberToSet (string srcKey, string destKey, byte[] member) + { + return SendDataExpectInt (member, "SMOVE", srcKey, destKey) > 0; + } + #endregion + + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + + ~Redis () + { + Dispose (false); + } + + protected virtual void Dispose (bool disposing) + { + if (disposing){ + SendCommand ("QUIT"); + ExpectSuccess (); + socket.Close (); + socket = null; + } + } +} + +public class SortOptions { + public string Key { get; set; } + public bool Descending { get; set; } + public bool Lexographically { get; set; } + public Int32 LowerLimit { get; set; } + public Int32 UpperLimit { get; set; } + public string By { get; set; } + public string StoreInKey { get; set; } + public string Get { get; set; } + + public object [] ToArgs () + { + System.Collections.ArrayList args = new System.Collections.ArrayList(); + + if (LowerLimit != 0 || UpperLimit != 0) { + args.Add ("LIMIT"); + args.Add (LowerLimit); + args.Add (UpperLimit); + } + if (Lexographically) + args.Add("ALPHA"); + if (!string.IsNullOrEmpty (By)) { + args.Add("BY"); + args.Add(By); + } + if (!string.IsNullOrEmpty (Get)) { + args.Add("GET"); + args.Add(Get); + } + return args.ToArray (); + } +} diff --git a/build/install/win/DocSpace.aip b/build/install/win/DocSpace.aip index 30308dae5f..bf153527c1 100644 --- a/build/install/win/DocSpace.aip +++ b/build/install/win/DocSpace.aip @@ -28,7 +28,9 @@ + + @@ -56,8 +58,10 @@ + + @@ -71,8 +75,11 @@ + + + @@ -83,82 +90,163 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -174,20 +262,17 @@ - - + - - - - + + @@ -222,15 +307,79 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -255,7 +404,6 @@ - @@ -265,6 +413,7 @@ + @@ -578,12 +727,72 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -594,6 +803,7 @@ + @@ -620,13 +830,17 @@ + + + + @@ -639,9 +853,10 @@ + - + @@ -675,8 +890,7 @@ - - + @@ -691,8 +905,68 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -702,8 +976,8 @@ - - + + @@ -724,35 +998,42 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - + + + - + + @@ -762,6 +1043,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -795,12 +1143,14 @@ + + - + @@ -811,35 +1161,38 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - + + + + + - + @@ -847,25 +1200,28 @@ + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + @@ -930,19 +1286,15 @@ - - - - - + + + - - - - - + + + diff --git a/build/install/win/backend-build.bat b/build/install/win/backend-build.bat index f30c9733ca..f7f5256ec3 100644 --- a/build/install/win/backend-build.bat +++ b/build/install/win/backend-build.bat @@ -4,14 +4,12 @@ echo ##################### echo # build backend # echo ##################### +set SRC_PATH=%~s2 + pushd %~1 - call dotnet build ASC.Web.sln - - echo "== Build ASC.Thumbnails ==" - pushd common\ASC.Thumbnails - call yarn install --frozen-lockfile - popd + call dotnet build ASC.Web.slnf + call dotnet build ASC.Migrations.sln -o %SRC_PATH%\services\ASC.Migration.Runner\service echo "== Build ASC.UrlShortener ==" pushd common\ASC.UrlShortener diff --git a/build/install/win/build-batch.bat b/build/install/win/build-batch.bat index 91a8546f6c..efe031de69 100644 --- a/build/install/win/build-batch.bat +++ b/build/install/win/build-batch.bat @@ -1,88 +1,61 @@ REM echo ######## Set variables ######## set "publisher="Ascensio System SIA"" -set "zookeeper_version=3.7.1" -set "kafka_version=2.8.0" set "nginx_version=1.21.1" -set "scala_version=2.12" +set "nuget="%cd%\thirdparty\SimpleRestServices\src\.nuget\NuGet.exe"" REM echo ######## Extracting and preparing files to build ######## %sevenzip% x build\install\win\nginx-%nginx_version%.zip -o"build\install\win\Files" -y xcopy "build\install\win\Files\nginx-%nginx_version%" "build\install\win\Files\nginx" /s /y /b /i rmdir build\install\win\Files\nginx-%nginx_version% /s /q -rmdir build\install\win\kafka-zookeeper /s /q -md build\install\win\kafka-zookeeper md build\install\win\Files\nginx\temp md build\install\win\Files\nginx\logs -%tar% -xvf build\install\win\apache-zookeeper-%zookeeper_version%-bin.tar.gz -C build\install\win\kafka-zookeeper -%tar% -xvf build\install\win\kafka_%scala_version%-%kafka_version%.tgz -C build\install\win\kafka-zookeeper -ren build\install\win\kafka-zookeeper\apache-zookeeper-%zookeeper_version%-bin zookeeper -ren build\install\win\kafka-zookeeper\kafka_%scala_version%-%kafka_version% kafka -md build\install\win\kafka-zookeeper\kafka\tools md build\install\win\Files\tools -copy build\install\win\WinSW.NET4new.exe "build\install\win\kafka-zookeeper\kafka\tools\kafka.exe" /y -copy build\install\win\WinSW.NET4new.exe "build\install\win\kafka-zookeeper\kafka\tools\zookeeper.exe" /y -copy build\install\win\tools\zookeeper.xml "build\install\win\kafka-zookeeper\kafka\tools\zookeeper.xml" /y -copy build\install\win\tools\kafka.xml "build\install\win\kafka-zookeeper\kafka\tools\kafka.xml" /y -del /f /q build\install\win\apache-zookeeper-%zookeeper_version%-bin.* -del /f /q build\install\win\kafka_%scala_version%-%kafka_version%.* -copy build\install\win\WinSW.NET4.exe "build\install\win\Files\tools\proxy.exe" /y -copy build\install\win\tools\proxy.xml "build\install\win\Files\tools\proxy.xml" /y +md build\install\win\Files\Logs +md build\install\win\Files\service\ +md build\install\win\Files\products\ASC.Files\server\temp +md build\install\win\Files\products\ASC.People\server\temp +md build\install\win\Files\services\ASC.Data.Backup\service\temp +md build\install\win\Files\services\ASC.Files.Service\service\temp +md build\install\win\Files\services\ASC.Notify\service\temp +md build\install\win\Files\services\ASC.Studio.Notify\service\temp +md build\install\win\Files\services\ASC.TelegramService\service\temp +md build\install\win\Files\services\ASC.Data.Backup.BackgroundTasks\service\temp +md build\install\win\Files\services\ASC.ClearEvents\service\temp +md build\install\win\Files\services\ASC.Migration\service\temp +md build\install\win\Files\services\ASC.Webhooks.Service\service\temp +md build\install\win\Files\services\ASC.Web.Api\service\temp +md build\install\win\Files\services\ASC.Web.Studio\service\temp +copy build\install\win\WinSW.NET4.exe "build\install\win\Files\tools\Proxy.exe" /y +copy build\install\win\tools\Proxy.xml "build\install\win\Files\tools\Proxy.xml" /y +copy build\install\win\WinSW3.0.0.exe "build\install\win\Files\tools\Socket.IO.exe" /y +copy build\install\win\tools\Socket.IO.xml "build\install\win\Files\tools\Socket.IO.xml" /y +copy build\install\win\WinSW3.0.0.exe "build\install\win\Files\tools\UrlShortener.exe" /y +copy build\install\win\tools\UrlShortener.xml "build\install\win\Files\tools\UrlShortener.xml" /y +copy build\install\win\WinSW3.0.0.exe "build\install\win\Files\tools\SsoAuth.exe" /y +copy build\install\win\tools\SsoAuth.xml "build\install\win\Files\tools\SsoAuth.xml" /y +copy build\install\win\WinSW3.0.0.exe "build\install\win\Files\tools\DocEditor.exe" /y +copy build\install\win\tools\DocEditor.xml "build\install\win\Files\tools\DocEditor.xml" /y +copy build\install\win\WinSW3.0.0.exe "build\install\win\Files\tools\Login.exe" /y +copy build\install\win\tools\Login.xml "build\install\win\Files\tools\Login.xml" /y copy "build\install\win\nginx.conf" "build\install\win\Files\nginx\conf\nginx.conf" /y -copy "build\install\win\kafka-zookeeper\zookeeper\conf\zoo_sample.cfg" "build\install\win\kafka-zookeeper\zookeeper\conf\zoo.cfg" /y -del /f /q "build\install\win\kafka-zookeeper\zookeeper\conf\zoo_sample.cfg" rmdir build\install\win\publish /s /q +del /f /q build\install\win\Files\nginx\conf\onlyoffice-login.conf + REM echo ######## Build Utils ######## +%nuget% install %cd%\build\install\win\CustomActions\C#\Utils\packages.config -OutputDirectory %cd%\build\install\win\CustomActions\C#\Utils\packages %msbuild% build\install\win\CustomActions\C#\Utils\Utils.csproj copy build\install\win\CustomActions\C#\Utils\bin\Debug\Utils.CA.dll build\install\win\Utils.CA.dll /y rmdir build\install\win\CustomActions\C#\Utils\bin /s /q rmdir build\install\win\CustomActions\C#\Utils\obj /s /q -REM echo ######## Edit zookeeper/kafka cfg and proprties files ######## -%sed% -i "s/\(dataDir\).*/\1=.\/..\/zookeeper\/Data/g" build/install/win/kafka-zookeeper/zookeeper/conf/zoo.cfg -%sed% -i "s/\(log.dirs\)=.*/\1=kafka-logs/g" build/install/win/kafka-zookeeper/kafka/config/server.properties -%sed% -i "s/\(zookeeper.connect\)=.*/\1=localhost:2181/g" build/install/win/kafka-zookeeper/kafka/config/server.properties -%sed% -i "s/\(clientPort\)=.*/\1=2181/g" build/install/win/kafka-zookeeper/kafka/config/zookeeper.properties -%sed% -i "s/\(dataDir\).*/\1=.\/..\/zookeeper\/Data/g" build/install/win/kafka-zookeeper/kafka/config/zookeeper.properties -%sed% -i "s/\(bootstrap.servers\)=.*/\1=localhost:9092/g" build/install/win/kafka-zookeeper/kafka/config/consumer.properties -%sed% -i "s/\(bootstrap.servers\)=.*/\1=localhost:9092/g" build/install/win/kafka-zookeeper/kafka/config/connect-standalone.properties -%sed% -i "s/\(offset.storage.file.filename\)=.*/\1=kafka-offsets/g" build/install/win/kafka-zookeeper/kafka/config/connect-standalone.properties -%sed% -i "s/\(logger.kafka.controller\)=.*,/\1=INFO,/g" build/install/win/kafka-zookeeper/kafka/config/log4j.properties -%sed% -i "s/\(logger.state.change.logger\)=.*,/\1=INFO,/g" build/install/win/kafka-zookeeper/kafka/config/log4j.properties -echo log4j.logger.kafka.producer.async.DefaultEventHandler=INFO, kafkaAppender >> build/install/win/kafka-zookeeper/kafka/config/log4j.properties -echo exit /b 1 >> build/install/win/kafka-zookeeper/kafka/bin/windows/zookeeper-server-start.bat -echo exit /b 1 >> build/install/win/kafka-zookeeper/kafka/bin/windows/kafka-server-start.bat - -REM echo ######## Edit nginx conf files ######## -%sed% -i "s!#rewrite!rewrite!g" build/install/win/Files/nginx/conf/onlyoffice.conf -%sed% -i "s!/etc/nginx/includes!includes!g" build/install/win/Files/nginx/conf/onlyoffice.conf -%sed% -i "s!/var/www!..!g" build/install/win/Files/nginx/conf/onlyoffice-*.conf -%sed% -i "s!/var/www!..!g" build/install/win/Files/nginx/conf/includes/onlyoffice-*.conf - -REM echo ######## Edit json files ######## -%sed% -i "s!\(\"machinekey\":\).\".*\"!\1 \"1123askdasjklasbnd\"!g" build/install/win/Files/config/appsettings*.json -%sed% -i "s!\(\"folder\":\).\".*\"!\1 \"{APPDIRCONF}products\"!g" build/install/win/Files/config/appsettings*.json -%sed% -i "s!\(\"path\":\).\".*\"!\1 \"{APPDIRCONF}services\/ASC.Socket.IO\/service\"!g" build/install/win/Files/config/socket*.json -%sed% -i "s!\(\"path\":\).\".*\"!\1 \"{APPDIRCONF}services\/ASC.Thumbnails\/service\"!g" build/install/win/Files/config/thumb*.json -%sed% -i "s!\(\"path\":\).\".*\"!\1 \"{APPDIRCONF}services\/ASC.UrlShortener\/service\/index.js\"!g" build/install/win/Files/config/urlshortener*.json -%sed% -i "s!\(\"path\":\).\".*\"!\1 \"{APPDIRCONF}services\/ASC.SsoAuth\/service\"!g" build/install/win/Files/config/ssoauth*.json -%sed% -i "s!\(\"path\":\).\".*\"!\1 \"{APPDIRCONF}services\/ASC.UrlShortener\/service\/index.js\"!g" build/install/win/Files/config/appsettings.services.json -%sed% -i "s!\(\"log\":\).\".*\"!\1 \"{APPDIRCONF}Logs\/urlshortener.log\"!g" build/install/win/Files/config/appsettings.services.json - REM echo ######## Delete temp files ######## del /f /q build\install\win\Files\config\sed* del /f /q build\install\win\Files\nginx\conf\sed* del /f /q build\install\win\Files\nginx\conf\includes\sed* -del /f /q build\install\win\kafka-zookeeper\zookeeper\conf\sed* -del /f /q build\install\win\kafka-zookeeper\kafka\config\sed* +del /f /q build\install\win\Files\services\*\service\config\sed* del /f /q build\install\win\*.back.* -REM echo ######## Build kafka/zookeeper ######## -%AdvancedInstaller% /rebuild "build\install\win\Apache ZooKeeper.aip" -copy "build\install\win\publish\Apache ZooKeeper.msi" "build\install\win\Apache ZooKeeper.msi" /y -%AdvancedInstaller% /rebuild "build\install\win\Apache Kafka.aip" -copy "build\install\win\publish\Apache Kafka.msi" "build\install\win\Apache Kafka.msi" /y - REM echo ######## Build MySQL Server Installer ######## iscc /Qp /S"byparam="signtool" sign /a /n "%publisher%" /t http://timestamp.digicert.com $f" "build\install\win\MySQL Server Installer Runner.iss" diff --git a/build/install/win/build-download-prereq.ps1 b/build/install/win/build-download-prereq.ps1 index 0e1eb64c36..e7d48bdf35 100644 --- a/build/install/win/build-download-prereq.ps1 +++ b/build/install/win/build-download-prereq.ps1 @@ -29,9 +29,6 @@ function DownloadComponents { } } -$zookeeper_version = '3.7.1' -$kafka_version = '2.8.0' -$scala_version = '2.12' $nginx_version = '1.21.1' $path_prereq = "${pwd}\build\install\win\" @@ -43,17 +40,6 @@ $prerequisites = @( link = "https://nginx.org/download/nginx-${nginx_version}.zip"; } - @{ - download_allways = $false; - name = "apache-zookeeper-${zookeeper_version}-bin.tar.gz"; - link = "https://dlcdn.apache.org/zookeeper/zookeeper-${zookeeper_version}/apache-zookeeper-${zookeeper_version}-bin.tar.gz"; - } - @{ - download_allways = $false; - name = "kafka_${scala_version}-${kafka_version}.tgz"; - link = "https://archive.apache.org/dist/kafka/${kafka_version}/kafka_${scala_version}-${kafka_version}.tgz"; - } - @{ download_allways = $false; name = "WinSW.NET4new.exe"; @@ -61,4 +47,16 @@ $prerequisites = @( } ) +$path_nuget_packages = "${pwd}\.nuget\packages\" + +$nuget_packages = @( + @{ + download_allways = $false; + name = "rabbitmq.client.3.6.5.nupkg"; + link = "https://www.nuget.org/api/v2/package/RabbitMQ.Client/3.6.5"; + } +) + DownloadComponents $prerequisites $path_prereq + +DownloadComponents $nuget_packages $path_nuget_packages diff --git a/build/install/win/frontend-build.bat b/build/install/win/frontend-build.bat index 5719cddbab..86fd784611 100644 --- a/build/install/win/frontend-build.bat +++ b/build/install/win/frontend-build.bat @@ -4,9 +4,12 @@ echo ###################### echo # build frontend # echo ###################### -pushd %~1 +set DEBUG_INFO=%~2 + +pushd %~s1 call yarn install + if "%DEBUG_INFO%"=="true" yarn debug-info call yarn build call yarn deploy diff --git a/build/install/win/frontend-copy.bat b/build/install/win/frontend-copy.bat index 4703698f89..2fb192bb0d 100644 --- a/build/install/win/frontend-copy.bat +++ b/build/install/win/frontend-copy.bat @@ -17,10 +17,6 @@ if defined SecondArg ( ) xcopy "%PathToRepository%\build\deploy\public" "%PathToAppFolder%\public" /s /y /b /i -xcopy "%PathToRepository%\build\deploy\studio\client" "%PathToAppFolder%\studio\client" /s /y /b /i -xcopy "%PathToRepository%\build\deploy\studio\login" "%PathToAppFolder%\studio\login" /s /y /b /i -xcopy "%PathToRepository%\build\deploy\products\ASC.Files\client" "%PathToAppFolder%\products\ASC.Files\client" /s /y /b /i -xcopy "%PathToRepository%\build\deploy\products\ASC.Files\editor" "%PathToAppFolder%\products\ASC.Files\editor" /s /y /b /i -xcopy "%PathToRepository%\build\deploy\products\ASC.People\client" "%PathToAppFolder%\products\ASC.People\client" /s /y /b /i +xcopy "%PathToRepository%\build\deploy\client" "%PathToAppFolder%\client" /s /y /b /i xcopy "%PathToRepository%\config\nginx" "%PathToAppFolder%\nginx\conf" /s /y /b /i xcopy "%PathToRepository%\config\*" "%PathToAppFolder%\config" /y /b /i diff --git a/build/install/win/nginx.conf b/build/install/win/nginx.conf index e345859092..0044e55a8c 100644 --- a/build/install/win/nginx.conf +++ b/build/install/win/nginx.conf @@ -32,54 +32,7 @@ http { keepalive_timeout 65; #gzip on; - - server { - - set $public_root ../public; - listen 80; - server_name localhost; - - #charset koi8-r; - - #access_log logs/host.access.log main; - - location / { - root html; - index index.html index.htm; - } - - #error_page 404 /404.html; - - # redirect server error pages to the static page /50x.html - # - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root html; - } - } include onlyoffice.conf; include onlyoffice-*.conf; - - # HTTPS server - # - #server { - # listen 443 ssl; - # server_name localhost; - - # ssl_certificate cert.pem; - # ssl_certificate_key cert.key; - - # ssl_session_cache shared:SSL:1m; - # ssl_session_timeout 5m; - - # ssl_ciphers HIGH:!aNULL:!MD5; - # ssl_prefer_server_ciphers on; - - # location / { - # root html; - # index index.html index.htm; - # } - #} - } diff --git a/build/install/win/publish-script.bat b/build/install/win/publish-script.bat index 462d4af518..e406797a56 100644 --- a/build/install/win/publish-script.bat +++ b/build/install/win/publish-script.bat @@ -16,34 +16,24 @@ if defined SecondArg ( set PathToAppFolder=%FirstArg%\publish ) -rem publish in directory 'products' -REM dotnet publish "%PathToRepository%\products\ASC.Calendar\server\ASC.Calendar.csproj" -c Release --self-contained false -o "%PathToAppFolder%\products\ASC.Calendar\server" -REM dotnet publish "%PathToRepository%\products\ASC.CRM\server\ASC.CRM.csproj" -c Release --self-contained false -o "%PathToAppFolder%\products\ASC.CRM\server" +rem backend services (dotnet) in directory 'products' dotnet publish "%PathToRepository%\products\ASC.Files\server\ASC.Files.csproj" -c Release --self-contained false -o "%PathToAppFolder%\products\ASC.Files\server" -REM dotnet publish "%PathToRepository%\products\ASC.Mail\server\ASC.Mail.csproj" -c Release --self-contained false -o "%PathToAppFolder%\products\ASC.Mail\server" dotnet publish "%PathToRepository%\products\ASC.People\server\ASC.People.csproj" -c Release --self-contained false -o "%PathToAppFolder%\products\ASC.People\server" -REM dotnet publish "%PathToRepository%\products\ASC.Projects\server\ASC.Projects.csproj" -c Release --self-contained false -o "%PathToAppFolder%\products\ASC.Projects\server" -rem publish in directory 'services' -dotnet publish "%PathToRepository%\common\services\ASC.ApiSystem\ASC.ApiSystem.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.ApiSystem\service" +rem backend services (dotnet) in directory 'services' dotnet publish "%PathToRepository%\common\services\ASC.Data.Backup\ASC.Data.Backup.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Data.Backup\service" -dotnet publish "%PathToRepository%\common\services\ASC.Data.Storage.Encryption\ASC.Data.Storage.Encryption.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Data.Storage.Encryption\service" dotnet publish "%PathToRepository%\products\ASC.Files\service\ASC.Files.Service.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Files.Service\service" -dotnet publish "%PathToRepository%\common\services\ASC.Data.Storage.Migration\ASC.Data.Storage.Migration.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Data.Storage.Migration\service" dotnet publish "%PathToRepository%\common\services\ASC.Notify\ASC.Notify.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Notify\service" -dotnet publish "%PathToRepository%\common\services\ASC.Socket.IO.Svc\ASC.Socket.IO.Svc.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Socket.IO.Svc\service" dotnet publish "%PathToRepository%\common\services\ASC.Studio.Notify\ASC.Studio.Notify.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Studio.Notify\service" dotnet publish "%PathToRepository%\common\services\ASC.TelegramService\ASC.TelegramService.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.TelegramService\service" -dotnet publish "%PathToRepository%\common\services\ASC.Thumbnails.Svc\ASC.Thumbnails.Svc.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Thumbnails.Svc\service" -dotnet publish "%PathToRepository%\common\services\ASC.UrlShortener.Svc\ASC.UrlShortener.Svc.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.UrlShortener.Svc\service" +dotnet publish "%PathToRepository%\common\services\ASC.Data.Backup.BackgroundTasks\ASC.Data.Backup.BackgroundTasks.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Data.Backup.BackgroundTasks\service" +dotnet publish "%PathToRepository%\common\services\ASC.ClearEvents\ASC.ClearEvents.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.ClearEvents\service" +dotnet publish "%PathToRepository%\common\ASC.Migration\ASC.Migration.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Migration\service" +dotnet publish "%PathToRepository%\common\services\ASC.Webhooks.Service\ASC.Webhooks.Service.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Webhooks.Service\service" dotnet publish "%PathToRepository%\web\ASC.Web.Api\ASC.Web.Api.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Web.Api\service" dotnet publish "%PathToRepository%\web\ASC.Web.Studio\ASC.Web.Studio.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.Web.Studio\service" -dotnet publish "%PathToRepository%\common\services\ASC.SsoAuth.Svc\ASC.SsoAuth.Svc.csproj" -c Release --self-contained false -o "%PathToAppFolder%\services\ASC.SsoAuth.Svc\service" - -rem Publish backend services (Nodejs) -mkdir "%PathToAppFolder%\services\ASC.Thumbnails\service" -xcopy "%PathToRepository%\common\ASC.Thumbnails" "%PathToAppFolder%\services\ASC.Thumbnails\service" /s /y /b /i +rem backend services (Nodejs) in directory 'services' mkdir "%PathToAppFolder%\services\ASC.UrlShortener\service" xcopy "%PathToRepository%\common\ASC.UrlShortener" "%PathToAppFolder%\services\ASC.UrlShortener\service" /s /y /b /i @@ -52,3 +42,10 @@ xcopy "%PathToRepository%\common\ASC.Socket.IO" "%PathToAppFolder%\services\ASC. mkdir "%PathToAppFolder%\services\ASC.SsoAuth\service" xcopy "%PathToRepository%\common\ASC.SsoAuth" "%PathToAppFolder%\services\ASC.SsoAuth\service" /s /y /b /i + +rem backend services (Nodejs) in directory 'products' +mkdir "%PathToAppFolder%\products\ASC.Login\login" +xcopy "%PathToRepository%\build\deploy\login" "%PathToAppFolder%\products\ASC.Login\login" /s /y /b /i + +mkdir "%PathToAppFolder%\products\ASC.Files\editor" +xcopy "%PathToRepository%\build\deploy\editor" "%PathToAppFolder%\products\ASC.Files\editor" /s /y /b /i diff --git a/build/install/win/tools/DocEditor.xml b/build/install/win/tools/DocEditor.xml new file mode 100644 index 0000000000..c6d4b9665f --- /dev/null +++ b/build/install/win/tools/DocEditor.xml @@ -0,0 +1,14 @@ + + ASC.DocEditor + ASC.DocEditor + This service runs ASC.DocEditor + RealTime + Automatic + + node + "{APPDIR}products\ASC.Files\editor\server.js" + + 10240 + 8 + + \ No newline at end of file diff --git a/build/install/win/tools/Login.xml b/build/install/win/tools/Login.xml new file mode 100644 index 0000000000..d1dedd1284 --- /dev/null +++ b/build/install/win/tools/Login.xml @@ -0,0 +1,14 @@ + + ASC.Login + ASC.Login + This service runs ASC.Login + RealTime + Automatic + + node + "{APPDIR}products\ASC.Login\login\server.js" + + 10240 + 8 + + \ No newline at end of file diff --git a/build/install/win/tools/Socket.IO.xml b/build/install/win/tools/Socket.IO.xml new file mode 100644 index 0000000000..bc17e822f9 --- /dev/null +++ b/build/install/win/tools/Socket.IO.xml @@ -0,0 +1,14 @@ + + ASC.Socket.IO + ASC.Socket.IO + This service runs ASC.Socket.IO + RealTime + Automatic + + node + "{APPDIR}services\ASC.Socket.IO\service\server.js" + + 10240 + 8 + + \ No newline at end of file diff --git a/build/install/win/tools/SsoAuth.xml b/build/install/win/tools/SsoAuth.xml new file mode 100644 index 0000000000..0b724a9a34 --- /dev/null +++ b/build/install/win/tools/SsoAuth.xml @@ -0,0 +1,14 @@ + + ASC.SsoAuth + ASC.SsoAuth + This service runs ASC.SsoAuth + RealTime + Automatic + + node + "{APPDIR}services\ASC.SsoAuth\service\app.js" + + 10240 + 8 + + \ No newline at end of file diff --git a/build/install/win/tools/UrlShortener.xml b/build/install/win/tools/UrlShortener.xml new file mode 100644 index 0000000000..d30234fabb --- /dev/null +++ b/build/install/win/tools/UrlShortener.xml @@ -0,0 +1,14 @@ + + ASC.UrlShortener + ASC.UrlShortener + This service runs ASC.UrlShortener + RealTime + Automatic + + node + "{APPDIR}services\ASC.UrlShortener\service\index.js" + + 10240 + 8 + + \ No newline at end of file diff --git a/build/install/win/tools/kafka.xml b/build/install/win/tools/kafka.xml deleted file mode 100644 index 5667b177a4..0000000000 --- a/build/install/win/tools/kafka.xml +++ /dev/null @@ -1,15 +0,0 @@ - - kafka - kafka - This service runs kafka - RealTime - Automatic - - {WindowsVolume}Apache\kafka\bin\windows\kafka-server-start.bat - {WindowsVolume}Apache\kafka\config\server.properties - {WindowsVolume}Apache\kafka - - 10240 - 8 - - \ No newline at end of file diff --git a/build/install/win/tools/zookeeper.xml b/build/install/win/tools/zookeeper.xml deleted file mode 100644 index 9a8d0a8f3d..0000000000 --- a/build/install/win/tools/zookeeper.xml +++ /dev/null @@ -1,15 +0,0 @@ - - zookeeper - zookeeper - This service runs zookeeper - RealTime - Automatic - - {WindowsVolume}Apache\kafka\bin\windows\zookeeper-server-start.bat - {WindowsVolume}Apache\kafka\config\zookeeper.properties - {WindowsVolume}Apache\kafka - - 10240 - 8 - - \ No newline at end of file diff --git a/packages/client/src/components/EmptyContainer/EmptyContainer.js b/packages/client/src/components/EmptyContainer/EmptyContainer.js index 49017bf364..85e7fab37e 100644 --- a/packages/client/src/components/EmptyContainer/EmptyContainer.js +++ b/packages/client/src/components/EmptyContainer/EmptyContainer.js @@ -72,6 +72,9 @@ const EmptyFolderWrapper = styled.div` line-height: unset; ${NoUserSelect} } + .empty-folder_container_up-image { + ${NoUserSelect} + } .empty-folder_container-icon { height: 20px; diff --git a/packages/client/src/components/EmptyContainer/EmptyFolderContainer.js b/packages/client/src/components/EmptyContainer/EmptyFolderContainer.js index 0787be9a55..47e5943878 100644 --- a/packages/client/src/components/EmptyContainer/EmptyFolderContainer.js +++ b/packages/client/src/components/EmptyContainer/EmptyFolderContainer.js @@ -93,9 +93,11 @@ export default inject(({ filesStore, selectedFolderStore }) => { let isRootRoom, isRoom, id; if (navigationPath && navigationPath.length) { - isRootRoom = navigationPath[navigationPath.length - 1].isRootRoom; - isRoom = navigationPath[navigationPath.length - 1].isRoom; - id = navigationPath[navigationPath.length - 1].id; + const elem = navigationPath[0]; + + isRootRoom = elem.isRootRoom; + isRoom = elem.isRoom; + id = elem.id; } return { diff --git a/packages/client/src/components/EmptyContainer/RootFolderContainer.js b/packages/client/src/components/EmptyContainer/RootFolderContainer.js index 25e4caadc9..b957fd30b1 100644 --- a/packages/client/src/components/EmptyContainer/RootFolderContainer.js +++ b/packages/client/src/components/EmptyContainer/RootFolderContainer.js @@ -69,6 +69,8 @@ const RootFolderContainer = (props) => { t("PrivateRoomDescriptionUnbreakable"), ]; + const roomHeader = "Welcome to DocSpace"; + const [showLoader, setShowLoader] = React.useState(false); React.useEffect(() => { @@ -164,7 +166,7 @@ const RootFolderContainer = (props) => { }; case FolderType.Rooms: return { - headerText: "Welcome to DocSpace!", + headerText: roomHeader, descriptionText: roomsDescription, imageSrc: "images/empty_screen_corporate.png", buttons: roomsButtons, @@ -277,7 +279,7 @@ const RootFolderContainer = (props) => { alt="plus_icon" /> - Create room + {t("CreateEditRoomDialog:CreateRoom")} ); @@ -391,4 +393,8 @@ export default inject( setIsEmptyPage, }; } -)(withTranslation("Files")(observer(RootFolderContainer))); +)( + withTranslation(["Files", "CreateEditRoomDialog"])( + observer(RootFolderContainer) + ) +); diff --git a/packages/client/src/components/FilesPanels/index.js b/packages/client/src/components/FilesPanels/index.js index 09b6f11c0c..e2f1cd60bb 100644 --- a/packages/client/src/components/FilesPanels/index.js +++ b/packages/client/src/components/FilesPanels/index.js @@ -101,7 +101,7 @@ const Panels = (props) => { onSelectFile={createMasterForm} isPanelVisible={selectFileDialogVisible} onClose={onClose} - foldersType="exceptPrivacyTrashFolders" + filteredType="exceptPrivacyTrashArchiveFolders" ByExtension searchParam={".docx"} dialogName={t("Translations:CreateMasterFormFromFile")} diff --git a/packages/client/src/components/FolderTreeBody/TreeFolders.js b/packages/client/src/components/FolderTreeBody/TreeFolders.js index 4e867d6300..148f6bab15 100644 --- a/packages/client/src/components/FolderTreeBody/TreeFolders.js +++ b/packages/client/src/components/FolderTreeBody/TreeFolders.js @@ -2,21 +2,12 @@ import React from "react"; import TreeMenu from "@docspace/components/tree-menu"; import TreeNode from "@docspace/components/tree-menu/sub-components/tree-node"; import styled from "styled-components"; -import { - ConflictResolveType, - FolderType, - ShareAccessRights, -} from "@docspace/common/constants"; -import toastr from "@docspace/components/toast/toastr"; - +import { FolderType, ShareAccessRights } from "@docspace/common/constants"; import { onConvertFiles } from "../../helpers/files-converter"; import { ReactSVG } from "react-svg"; import ExpanderDownIcon from "PUBLIC_DIR/images/expander-down.react.svg"; import ExpanderRightIcon from "PUBLIC_DIR/images/expander-right.react.svg"; import commonIconsStyles from "@docspace/components/utils/common-icons-style"; -import withLoader from "../../HOCs/withLoader"; -import Loaders from "@docspace/common/components/Loaders"; - import { observer, inject } from "mobx-react"; import { runInAction } from "mobx"; import { withTranslation } from "react-i18next"; @@ -83,7 +74,7 @@ class TreeFolders extends React.Component { constructor(props) { super(props); - this.state = { isExpand: false }; + this.state = { isExpand: false, isLoading: false }; this.selectionFoldersId = []; } @@ -107,7 +98,7 @@ class TreeFolders extends React.Component { }; getFolderIcon = (item) => { - let iconUrl = "images/catalog.folder.react.svg"; + let iconUrl = "/static/images/catalog.folder.react.svg"; switch (item.rootFolderType) { case FolderType.USER: @@ -181,14 +172,7 @@ class TreeFolders extends React.Component { }; showDragItems = (item) => { - const { - isAdmin, - myId, - commonId, - //rootFolderType, - currentId, - draggableItems, - } = this.props; + const { isAdmin, myId, commonId, currentId, draggableItems } = this.props; if (item.id === currentId) { return false; } @@ -196,10 +180,6 @@ class TreeFolders extends React.Component { if (!draggableItems || draggableItems.find((x) => x.id === item.id)) return false; - // const isMy = rootFolderType === FolderType.USER; - // const isCommon = rootFolderType === FolderType.COMMON; - // const isShare = rootFolderType === FolderType.SHARE; - if ( item.rootFolderType === FolderType.SHARE && item.access === ShareAccessRights.FullAccess @@ -208,7 +188,6 @@ class TreeFolders extends React.Component { } if (isAdmin) { - //if (isMy || isCommon || isShare) { if ( (item.pathParts && (item.pathParts[0] === myId || item.pathParts[0] === commonId)) || @@ -217,24 +196,19 @@ class TreeFolders extends React.Component { ) { return true; } - //} } else { - //if (isMy || isCommon || isShare) { if ( (item.pathParts && item.pathParts[0] === myId) || item.rootFolderType === FolderType.USER ) { return true; } - //} } return false; }; getItems = (data) => { - const { theme } = this.props; - return data.map((item) => { const dragging = this.props.dragging ? this.showDragItems(item) : false; const showBadge = false; @@ -245,9 +219,18 @@ class TreeFolders extends React.Component { disableNodeValue = ""; if (dragging) value = `${item.id} dragging ${provider}`; + const { roomsFolderId, expandedPanelKeys } = this.props; + + let isDisabledNode = false; + if (item.id == roomsFolderId) { + isDisabledNode = expandedPanelKeys?.includes(roomsFolderId + ""); + } + if (this.selectionFoldersId && this.selectionFoldersId.includes(item.id)) disableNodeValue = "disable-node"; + if (isDisabledNode) disableNodeValue += " disable-folder "; + if ((item.folders && item.folders.length > 0) || serviceFolder) { return ( { - const { data: incomingDate, certainFolders } = this.props; + const { data: incomingDate, certainFolders, roomsFolderId } = this.props; isExpand && this.setState({ isExpand: true }); - this.props.setIsLoading && this.props.setIsLoading(true); //console.log("load data...", treeNode); + this.setState({ + isLoading: true, + }); + if (this.state.isExpand && !isExpand) { return Promise.resolve(); } @@ -418,25 +404,47 @@ class TreeFolders extends React.Component { this.getNewTreeData(treeData, listIds, data.folders, data.level); !certainFolders && this.props.setTreeFolders(treeData); + + if (data.listIds[0] == roomsFolderId && this.props.onSelect) { + const roomsIndex = treeData.findIndex((f) => f.id == roomsFolderId); + const firstRoomsNodeId = treeData[roomsIndex]?.folders[0]?.id; + this.props.onSelect([firstRoomsNodeId], treeNode); + } }) .catch((err) => console.log("err", err)) .finally(() => { - this.setState({ isExpand: false }); - this.props.setIsLoading && this.props.setIsLoading(false); + this.setState({ isExpand: false, isLoading: false }); }); }; - onExpand = (expandedKeys, treeNode) => { + onExpand = (expandedKeys, treeNode, isRoom = false) => { this.expand = true; if (treeNode.node && !treeNode.node.children) { if (treeNode.expanded) { this.onLoadData(treeNode.node, true); } + } else if (isRoom) { + this.props.onSelect([treeNode.node.children[0].id], treeNode); } this.props.setExpandedPanelKeys(expandedKeys); }; + onSelect = (folder, treeNode) => { + const { onSelect, expandedPanelKeys, roomsFolderId } = this.props; + + const newExpandedPanelKeys = JSON.parse(JSON.stringify(expandedPanelKeys)); + newExpandedPanelKeys.push(folder[0]); + + if (folder[0] == roomsFolderId) { + this.onExpand(newExpandedPanelKeys, treeNode, true); + + return; + } + + onSelect && onSelect(folder, treeNode); + }; + onDragOver = (data) => { const parentElement = data.event.target.parentElement; const existElement = parentElement.classList.contains( @@ -486,22 +494,21 @@ class TreeFolders extends React.Component { firstLoadScroll(); } }; + render() { const { selectedKeys, - isLoading, - onSelect, dragging, - expandedPanelKeys, treeFolders, data, disabled, - theme, isPanel, isLoadingNodes, } = this.props; + const { isLoading } = this.state; + return ( { - const { - selection, - setIsLoading, - isLoading, - dragging, - setDragging, - } = filesStore; + const { selection, dragging, setDragging } = filesStore; const { treeFolders, setTreeFolders, myFolderId, commonFolderId, - isPrivacyFolder, setExpandedPanelKeys, getSubfolders, setIsLoadingNodes, isLoadingNodes, + roomsFolderId, } = treeFoldersStore; - const { - id, - parentId: selectedNodeParentId /* rootFolderType */, - } = selectedFolderStore; + const { id, parentId: selectedNodeParentId } = selectedFolderStore; return { isAdmin: auth.isAdmin, isDesktop: auth.settingsStore.isDesktopClient, dragging, - //rootFolderType, currentId: id, myId: myFolderId, commonId: commonFolderId, - isPrivacy: isPrivacyFolder, draggableItems: dragging ? selection : null, treeFolders, - isLoading, selectedKeys: useDefaultSelectedKeys ? treeFoldersStore.selectedKeys : selectedKeys, setDragging, - setIsLoading, setTreeFolders, setExpandedPanelKeys, getSubfolders, setIsLoadingNodes, isLoadingNodes, selectedNodeParentId, + roomsFolderId, }; } )(withTranslation(["Files", "Common"])(observer(TreeFolders))); diff --git a/packages/client/src/components/GlobalEvents/CreateEvent.js b/packages/client/src/components/GlobalEvents/CreateEvent.js index c49763e2bd..72b8c86d46 100644 --- a/packages/client/src/components/GlobalEvents/CreateEvent.js +++ b/packages/client/src/components/GlobalEvents/CreateEvent.js @@ -46,8 +46,10 @@ const CreateEvent = ({ replaceFileStream, setEncryptionAccess, + + setEventDialogVisible, + eventDialogVisible, }) => { - const [visible, setVisible] = React.useState(false); const [headerTitle, setHeaderTitle] = React.useState(null); const [startValue, setStartValue] = React.useState(""); @@ -65,7 +67,7 @@ const CreateEvent = ({ } setHeaderTitle(defaultName); - setVisible(true); + setEventDialogVisible(true); }, [extension, title, fromTemplate]); const onSave = (e, value, open = true) => { @@ -132,7 +134,7 @@ const CreateEvent = ({ toastr.error(t("Translations:FileProtected"), t("Common:Warning")); - setVisible(false); + setEventDialogVisible(false); setFormCreationInfo({ newTitle: `${newValue}.${extension}`, @@ -233,7 +235,7 @@ const CreateEvent = ({ return ( { - const [visible, setVisible] = React.useState(false); + setEventDialogVisible, + eventDialogVisible, +}) => { const [startValue, setStartValue] = React.useState(""); const { t } = useTranslation(["Files"]); @@ -31,7 +32,7 @@ const RenameEvent = ({ React.useEffect(() => { setStartValue(getTitleWithoutExst(item, false)); - setVisible(true); + setEventDialogVisible(true); }, [item]); const onUpdate = React.useCallback((e, value) => { @@ -47,6 +48,8 @@ const RenameEvent = ({ if (isSameTitle) { setStartValue(originalTitle); + setIsLoading(false); + onClose(); return editCompleteAction(item, type); } else { @@ -112,7 +115,7 @@ const RenameEvent = ({ return ( { - const { setIsLoading, addActiveItems, updateFile, renameFolder } = filesStore; +export default inject( + ({ filesStore, filesActionsStore, uploadDataStore, dialogsStore }) => { + const { + setIsLoading, + addActiveItems, + updateFile, + renameFolder, + } = filesStore; - const { editCompleteAction } = filesActionsStore; + const { editCompleteAction } = filesActionsStore; - const { clearActiveOperations } = uploadDataStore; + const { clearActiveOperations } = uploadDataStore; + const { setEventDialogVisible, eventDialogVisible } = dialogsStore; - return { - setIsLoading, - addActiveItems, - updateFile, - renameFolder, + return { + setIsLoading, + addActiveItems, + updateFile, + renameFolder, - editCompleteAction, + editCompleteAction, - clearActiveOperations, - }; -})(observer(RenameEvent)); + clearActiveOperations, + setEventDialogVisible, + eventDialogVisible, + }; + } +)(observer(RenameEvent)); diff --git a/packages/client/src/components/GlobalEvents/sub-components/Dialog.js b/packages/client/src/components/GlobalEvents/sub-components/Dialog.js index ee4a0b4bdd..6ce44093fd 100644 --- a/packages/client/src/components/GlobalEvents/sub-components/Dialog.js +++ b/packages/client/src/components/GlobalEvents/sub-components/Dialog.js @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect, useCallback, useState } from "react"; import { inject, observer } from "mobx-react"; import toastr from "@docspace/components/toast/toastr"; @@ -6,6 +6,7 @@ import ModalDialog from "@docspace/components/modal-dialog"; import TextInput from "@docspace/components/text-input"; import Button from "@docspace/components/button"; import ComboBox from "@docspace/components/combobox"; +import { isSafari, isTablet } from "react-device-detect"; const Dialog = ({ t, @@ -20,14 +21,29 @@ const Dialog = ({ onCancel, onClose, }) => { - const [value, setValue] = React.useState(""); - const [isDisabled, setIsDisabled] = React.useState(false); + const [value, setValue] = useState(""); + const [isDisabled, setIsDisabled] = useState(false); - React.useEffect(() => { + useEffect(() => { if (startValue) setValue(startValue); }, [startValue]); - const onChange = React.useCallback((e) => { + const onKeyUpHandler = useCallback( + (e) => { + if (e.keyCode === 27) onCancelAction(e); + if (e.keyCode === 13) onSaveAction(e); + }, + [value] + ); + useEffect(() => { + document.addEventListener("keyup", onKeyUpHandler, false); + + return () => { + document.removeEventListener("keyup", onKeyUpHandler, false); + }; + }, [onKeyUpHandler]); + + const onChange = useCallback((e) => { let newValue = e.target.value; if (newValue.match(folderFormValidation)) { @@ -39,28 +55,39 @@ const Dialog = ({ setValue(newValue); }, []); - const onFocus = React.useCallback((e) => { + const onFocus = useCallback((e) => { e.target.select(); }, []); - const onSaveAction = React.useCallback( + const returnWindowPositionAfterKeyboard = () => { + isSafari && isTablet && window.scrollTo(0, 0); + }; + + const onSaveAction = useCallback( (e) => { + returnWindowPositionAfterKeyboard(); setIsDisabled(true); onSave && onSave(e, value); }, [onSave, value] ); - const onCancelAction = React.useCallback((e) => { + const onCancelAction = useCallback((e) => { + returnWindowPositionAfterKeyboard(); onCancel && onCancel(e); }, []); + const onCloseAction = useCallback((e) => { + returnWindowPositionAfterKeyboard(); + onClose && onClose(e); + }, []); + return ( {title} diff --git a/packages/client/src/components/NavMenu/sub-components/nav.js b/packages/client/src/components/NavMenu/sub-components/nav.js index 49da9d4c05..09151e0cad 100644 --- a/packages/client/src/components/NavMenu/sub-components/nav.js +++ b/packages/client/src/components/NavMenu/sub-components/nav.js @@ -2,7 +2,7 @@ import React from "react"; import PropTypes from "prop-types"; import styled from "styled-components"; import Scrollbar from "@docspace/components/scrollbar"; -import { isMobileOnly, isDesktop } from "react-device-detect"; +import { isMobileOnly, isMobile } from "react-device-detect"; import { Base } from "@docspace/components/themes"; const StyledNav = styled.nav` @@ -29,7 +29,7 @@ const StyledNav = styled.nav` ${(props) => props.numberOfModules && `@media (max-height: ${props.numberOfModules * 52 + 80}px) { - position: ${isDesktop && "relative"}; + position: ${!isMobile && "relative"}; margin-top: 16px; }`} diff --git a/packages/client/src/components/dialogs/BackupCodesDialog/index.js b/packages/client/src/components/dialogs/BackupCodesDialog/index.js index 1d8cad282f..b25d8f604e 100644 --- a/packages/client/src/components/dialogs/BackupCodesDialog/index.js +++ b/packages/client/src/components/dialogs/BackupCodesDialog/index.js @@ -8,7 +8,7 @@ import { withTranslation } from "react-i18next"; import ModalDialogContainer from "../ModalDialogContainer"; import toastr from "@docspace/components/toast/toastr"; import Link from "@docspace/components/link"; -import { isDesktop } from "react-device-detect"; +import { isMobile } from "react-device-detect"; const StyledModal = styled(ModalDialogContainer)` .backup-codes-counter { @@ -118,7 +118,7 @@ class BackupCodesDialogComponent extends React.Component { size="normal" onClick={this.props.onClose} /> - {isDesktop && ( + {!isMobile && (
{ diff --git a/packages/client/src/components/panels/SelectFileDialog/ModalView.js b/packages/client/src/components/panels/SelectFileDialog/ModalView.js deleted file mode 100644 index e211695539..0000000000 --- a/packages/client/src/components/panels/SelectFileDialog/ModalView.js +++ /dev/null @@ -1,280 +0,0 @@ -import React from "react"; -import { StyledAsidePanel, StyledSelectFilePanel } from "../StyledPanels"; -import ModalDialog from "@docspace/components/modal-dialog"; -import SelectFolderDialog from "../SelectFolderDialog"; -import FolderTreeBody from "../../FolderTreeBody"; -import FilesListBody from "./FilesListBody"; -import Button from "@docspace/components/button"; -import Text from "@docspace/components/text"; -import { isArrayEqual } from "@docspace/components/utils/array"; -import { getFoldersTree } from "@docspace/common/api/files"; -import { - exceptSortedByTagsFolders, - exceptPrivacyTrashFolders, -} from "../SelectFolderDialog/ExceptionFoldersConstants"; - -class SelectFileDialogModalView extends React.Component { - constructor(props) { - super(props); - this.state = { - isLoading: true, - isAvailable: true, - }; - this.folderList = ""; - this.noTreeSwitcher = false; - } - - componentDidMount() { - const { onSetLoadingData } = this.props; - this.setState({ isLoadingData: true }, function () { - onSetLoadingData && onSetLoadingData(true); - - this.trySwitch(); - }); - } - trySwitch = async () => { - const { - foldersType, - onSelectFolder, - selectedFolder, - passedId, - foldersList, - } = this.props; - switch (foldersType) { - case "exceptSortedByTags": - try { - const foldersTree = await getFoldersTree(); - [ - this.folderList, - this.noTreeSwitcher, - ] = SelectFolderDialog.convertFolders( - foldersTree, - exceptSortedByTagsFolders - ); - this.onSetSelectedFolder(); - } catch (err) { - console.error(err); - } - - this.loadersCompletes(); - break; - case "exceptPrivacyTrashFolders": - try { - const foldersTree = await getFoldersTree(); - [ - this.folderList, - this.noTreeSwitcher, - ] = SelectFolderDialog.convertFolders( - foldersTree, - exceptPrivacyTrashFolders - ); - this.onSetSelectedFolder(); - } catch (err) { - console.error(err); - } - this.loadersCompletes(); - break; - case "common": - try { - this.folderList = await SelectFolderDialog.getCommonFolders(); - - !selectedFolder && - onSelectFolder && - onSelectFolder( - `${ - selectedFolder - ? selectedFolder - : passedId - ? passedId - : this.folderList[0].id - }` - ); - } catch (err) { - console.error(err); - } - - this.loadersCompletes(); - break; - case "third-party": - try { - this.folderList = foldersList - ? foldersList - : await SelectFolderDialog.getCommonThirdPartyList(); - this.folderList.length !== 0 - ? this.onSetSelectedFolder() - : this.setState({ isAvailable: false }); - } catch (err) { - console.error(err); - } - - this.loadersCompletes(); - break; - } - }; - - loadersCompletes = () => { - const { onSetLoadingData } = this.props; - onSetLoadingData && onSetLoadingData(false); - - this.setState({ - isLoading: false, - }); - }; - - onSetSelectedFolder = () => { - const { onSelectFolder, selectedFolder, passedId } = this.props; - - onSelectFolder && - onSelectFolder( - `${ - selectedFolder - ? selectedFolder - : passedId - ? passedId - : this.folderList[0].id - }` - ); - }; - onSelect = (folder) => { - const { onSelectFolder, selectedFolder } = this.props; - - if (isArrayEqual([folder[0]], [selectedFolder])) { - return; - } - - onSelectFolder && onSelectFolder(folder[0]); - }; - - onMouseEvent = (event) => { - event.stopPropagation(); - }; - render() { - const { - t, - isPanelVisible, - onClose, - zIndex, - withoutProvider, - expandedKeys, - filter, - onSelectFile, - filesList, - hasNextPage, - isNextPageLoading, - loadNextPage, - selectedFolder, - titleFilesList, - loadingText, - selectedFile, - onClickSave, - headerName, - primaryButtonName, - theme, - } = this.props; - - const { isLoading, isAvailable } = this.state; - - const isHeaderChildren = !!titleFilesList; - - return ( - - - - {headerName ? headerName : t("SelectFile")} - - - -
-
- -
-
- <> - {titleFilesList && ( - - {titleFilesList} - - )} - {selectedFolder && ( - - )} - -
-
-
-
- -
diff --git a/packages/client/src/pages/PortalSettings/categories/data-management/backup/auto-backup/sub-components/ThirdPartyModule.js b/packages/client/src/pages/PortalSettings/categories/data-management/backup/auto-backup/sub-components/ThirdPartyModule.js index 455dec81d6..b7ba5eaf0b 100644 --- a/packages/client/src/pages/PortalSettings/categories/data-management/backup/auto-backup/sub-components/ThirdPartyModule.js +++ b/packages/client/src/pages/PortalSettings/categories/data-management/backup/auto-backup/sub-components/ThirdPartyModule.js @@ -55,39 +55,16 @@ class ThirdPartyModule extends React.PureComponent { isError, isLoadingData, isReset, - isSuccessSave, + passedId, //commonThirdPartyList, isResourcesDefault, - isResetProcess, - isSavingProcess, t, ...rest } = this.props; return ( <> - {/* {!isDocSpace ? ( -
- -
- ) : ( */} - - {/* )} */} -
@@ -115,8 +90,6 @@ export default inject(({ backup }) => { defaultStorageType, commonThirdPartyList, defaultFolderId, - isResetProcess, - isSavingProcess, } = backup; const isResourcesDefault = @@ -124,8 +97,6 @@ export default inject(({ backup }) => { const passedId = isResourcesDefault ? defaultFolderId : ""; return { - isResetProcess, - isSavingProcess, setSelectedFolder, passedId, commonThirdPartyList, diff --git a/packages/client/src/pages/PortalSettings/categories/data-management/backup/common-container/DirectThirdPartyConnection.js b/packages/client/src/pages/PortalSettings/categories/data-management/backup/common-container/DirectThirdPartyConnection.js index e419c613aa..ade0c237f1 100644 --- a/packages/client/src/pages/PortalSettings/categories/data-management/backup/common-container/DirectThirdPartyConnection.js +++ b/packages/client/src/pages/PortalSettings/categories/data-management/backup/common-container/DirectThirdPartyConnection.js @@ -33,8 +33,6 @@ const DirectThirdPartyConnection = (props) => { isPanelVisible, isError, id, - isReset, - isSuccessSave, withoutBasicSelection, onSelectFile, isFileSelection = false, @@ -337,7 +335,7 @@ const DirectThirdPartyConnection = (props) => { {isFileSelection ? ( { } isPanelVisible={isPanelVisible} isError={isError} - foldersList={[folderList]} + passedFoldersTree={[folderList]} withoutBasicSelection={withoutBasicSelection} - isReset={isReset} - isSuccessSave={isSuccessSave} isWaitingUpdate={isInitialLoading || isUpdatingInfo ? true : false} /> )} diff --git a/packages/client/src/pages/PortalSettings/categories/data-management/backup/manual-backup/sub-components/RoomsModule.js b/packages/client/src/pages/PortalSettings/categories/data-management/backup/manual-backup/sub-components/RoomsModule.js index 8ce73ca695..693a73132b 100644 --- a/packages/client/src/pages/PortalSettings/categories/data-management/backup/manual-backup/sub-components/RoomsModule.js +++ b/packages/client/src/pages/PortalSettings/categories/data-management/backup/manual-backup/sub-components/RoomsModule.js @@ -80,7 +80,7 @@ class RoomsModule extends React.Component { onClickInput={this.onClickInput} isPanelVisible={isPanelVisible} isDisabled={isModuleDisabled} - foldersType="exceptSortedByTags" + filteredType="exceptSortedByTags" {...(selectedFolder && { id: selectedFolder })} withoutBasicSelection={selectedFolder ? false : true} /> diff --git a/packages/client/src/pages/PortalSettings/categories/data-management/backup/manual-backup/sub-components/ThirdPartyModule.js b/packages/client/src/pages/PortalSettings/categories/data-management/backup/manual-backup/sub-components/ThirdPartyModule.js index 9d7fd8ef5e..a3464778fd 100644 --- a/packages/client/src/pages/PortalSettings/categories/data-management/backup/manual-backup/sub-components/ThirdPartyModule.js +++ b/packages/client/src/pages/PortalSettings/categories/data-management/backup/manual-backup/sub-components/ThirdPartyModule.js @@ -122,42 +122,6 @@ class ThirdPartyModule extends React.Component { const isModuleDisabled = !isMaxProgress || isStartCopy || isLoadingData; return ( - // !isDocSpace ? ( - // <> - //
- // - //
- //
- //
- // - // ) : (
diff --git a/packages/client/src/pages/PortalSettings/categories/data-management/backup/restore-backup/sub-components/LocalFileModule.js b/packages/client/src/pages/PortalSettings/categories/data-management/backup/restore-backup/sub-components/LocalFileModule.js index 3792bd279c..9edea936e8 100644 --- a/packages/client/src/pages/PortalSettings/categories/data-management/backup/restore-backup/sub-components/LocalFileModule.js +++ b/packages/client/src/pages/PortalSettings/categories/data-management/backup/restore-backup/sub-components/LocalFileModule.js @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect } from "react"; import FileInput from "@docspace/components/file-input"; const LocalFile = ({ onSelectLocalFile, hasError }) => { @@ -8,6 +8,12 @@ const LocalFile = ({ onSelectLocalFile, hasError }) => { onSelectLocalFile(data); }; + + useEffect(() => { + return () => { + onSelectLocalFile(""); + }; + }, []); return ( diff --git a/packages/client/src/pages/PortalSettings/categories/data-management/backup/restore-backup/sub-components/ThirdPartyResourcesModule.js b/packages/client/src/pages/PortalSettings/categories/data-management/backup/restore-backup/sub-components/ThirdPartyResourcesModule.js index adb03e2820..2f435b0d80 100644 --- a/packages/client/src/pages/PortalSettings/categories/data-management/backup/restore-backup/sub-components/ThirdPartyResourcesModule.js +++ b/packages/client/src/pages/PortalSettings/categories/data-management/backup/restore-backup/sub-components/ThirdPartyResourcesModule.js @@ -4,18 +4,6 @@ import DirectThirdPartyConnection from "../../common-container/DirectThirdPartyC const ThirdPartyResources = (props) => { return ( - // return !isDocSpace ? ( - // - // ) : (
{ const { load, serviceProviderSettings, spMetadata } = props; const { t } = useTranslation("SingleSignOn"); - if (!isDesktop) return ; + if (isMobile) return ; useEffect(() => { load(); diff --git a/packages/client/src/pages/PortalSettings/index.js b/packages/client/src/pages/PortalSettings/index.js index afa4d187d1..4c4a027656 100644 --- a/packages/client/src/pages/PortalSettings/index.js +++ b/packages/client/src/pages/PortalSettings/index.js @@ -4,6 +4,8 @@ import { withRouter } from "react-router"; import Layout from "./Layout"; import { combineUrl } from "@docspace/common/utils"; import AppServerConfig from "@docspace/common/constants/AppServerConfig"; +import Panels from "../../components/FilesPanels"; + const SecuritySettings = lazy(() => import("./categories/security/index.js")); const TfaPage = lazy(() => import("./categories/security/access-portal/tfa")); @@ -159,6 +161,7 @@ const ERROR_404_URL = combineUrl(AppServerConfig.proxyURL, "/error/404"); const Settings = () => { return ( + diff --git a/packages/client/src/pages/Profile/Section/Header/index.js b/packages/client/src/pages/Profile/Section/Header/index.js index edd7cd7ef7..a5066aef86 100644 --- a/packages/client/src/pages/Profile/Section/Header/index.js +++ b/packages/client/src/pages/Profile/Section/Header/index.js @@ -22,7 +22,9 @@ const Header = (props) => { history, isAdmin, filter, + setFilter, + profile, isMe, setChangeEmailVisible, @@ -80,9 +82,9 @@ const Header = (props) => { return ( - {!profile.isVisitor && ( + {isAdmin && ( { export default withRouter( inject(({ auth, peopleStore }) => { const { isAdmin } = auth; + const { targetUserStore, filterStore } = peopleStore; const { filter, setFilterParams } = filterStore; @@ -137,7 +140,9 @@ export default withRouter( return { isAdmin, filter, + setFilter: setFilterParams, + profile: targetUser, isMe, setChangeEmailVisible, diff --git a/packages/client/src/store/BackupStore.js b/packages/client/src/store/BackupStore.js index 7101ed5004..62fd973616 100644 --- a/packages/client/src/store/BackupStore.js +++ b/packages/client/src/store/BackupStore.js @@ -62,9 +62,6 @@ class BackupStore { selectedEnableSchedule = false; defaultEnableSchedule = false; - isSavingProcess = false; - isResetProcess = false; - storageRegions = []; constructor() { @@ -574,13 +571,6 @@ class BackupStore { const isEnable = this.selectedEnableSchedule; this.selectedEnableSchedule = !isEnable; }; - setSavingProcess = (process) => { - if (process !== this.isSavingProcess) this.isSavingProcess = process; - }; - - setResetProcess = (process) => { - if (process !== this.isResetProcess) this.isResetProcess = process; - }; convertServiceName = (serviceName) => { //Docusign, OneDrive, Wordpress diff --git a/packages/client/src/store/DialogsStore.js b/packages/client/src/store/DialogsStore.js index b863ad7a8c..8a5f1e6290 100644 --- a/packages/client/src/store/DialogsStore.js +++ b/packages/client/src/store/DialogsStore.js @@ -29,6 +29,7 @@ class DialogsStore { isFolderActions = false; roomCreation = false; restoreAllPanelVisible = false; + eventDialogVisible = false; removeItem = null; connectItem = null; @@ -116,6 +117,10 @@ class DialogsStore { this.deleteDialogVisible = deleteDialogVisible; }; + setEventDialogVisible = (eventDialogVisible) => { + this.eventDialogVisible = eventDialogVisible; + }; + setDownloadDialogVisible = (downloadDialogVisible) => { !downloadDialogVisible && this.deselectActiveFiles(); this.downloadDialogVisible = downloadDialogVisible; @@ -263,7 +268,8 @@ class DialogsStore { this.convertDialogVisible || this.selectFileDialogVisible || this.authStore.settingsStore.hotkeyPanelVisible || - this.versionHistoryStore.isVisible + this.versionHistoryStore.isVisible || + this.eventDialogVisible ); } diff --git a/packages/client/src/store/FilesActionsStore.js b/packages/client/src/store/FilesActionsStore.js index 7087421e2f..6671f9f0c4 100644 --- a/packages/client/src/store/FilesActionsStore.js +++ b/packages/client/src/store/FilesActionsStore.js @@ -689,17 +689,13 @@ class FilesActionStore { }; finalizeVersionAction = (id) => { - const { setFile, setIsLoading } = this.filesStore; + const { setFile } = this.filesStore; - setIsLoading(true); - - return finalizeVersion(id, 0, false) - .then((res) => { - if (res && res[0]) { - setFile(res[0]); - } - }) - .finally(() => setIsLoading(false)); + return finalizeVersion(id, 0, false).then((res) => { + if (res && res[0]) { + setFile(res[0]); + } + }); }; duplicateAction = (item, label) => { @@ -1159,8 +1155,6 @@ class FilesActionStore { const { userAccess } = this.filesStore; switch (option) { - case "share": - return isAccessedSelected && !personal; //isFavoritesFolder ||isRecentFolder case "showInfo": case "copy": case "download": @@ -1276,16 +1270,6 @@ class FilesActionStore { } = this.dialogsStore; switch (option) { - case "share": - if (!this.isAvailableOption("share")) return null; - else - return { - label: t("Share"), - onClick: () => setSharingPanelVisible(true), - iconUrl: "/static/images/share.react.svg", - title: t("Translations:ButtonShareAccess"), - }; - case "copy": if (!this.isAvailableOption("copy")) return null; else @@ -1416,7 +1400,6 @@ class FilesActionStore { }; getAnotherFolderOptions = (itemsCollection, t) => { - const share = this.getOption("share", t); const download = this.getOption("download", t); const downloadAs = this.getOption("downloadAs", t); const moveTo = this.getOption("moveTo", t); @@ -1425,7 +1408,6 @@ class FilesActionStore { const showInfo = this.getOption("showInfo", t); itemsCollection - .set("share", share) .set("download", download) .set("downloadAs", downloadAs) .set("moveTo", moveTo) @@ -1437,14 +1419,13 @@ class FilesActionStore { }; getRecentFolderOptions = (itemsCollection, t) => { - const share = this.getOption("share", t); 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) @@ -1456,14 +1437,13 @@ class FilesActionStore { getShareFolderOptions = (itemsCollection, t) => { const { setDeleteDialogVisible, setUnsubscribe } = this.dialogsStore; - const share = this.getOption("share", t); 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) @@ -1497,15 +1477,12 @@ class FilesActionStore { getFavoritesFolderOptions = (itemsCollection, t) => { const { selection } = this.filesStore; - - const share = this.getOption("share", t); 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) diff --git a/packages/client/src/store/FilesStore.js b/packages/client/src/store/FilesStore.js index f47f7ab9c6..52d52dc9de 100644 --- a/packages/client/src/store/FilesStore.js +++ b/packages/client/src/store/FilesStore.js @@ -2598,13 +2598,13 @@ class FilesStore { // const filterTotal = isRoom ? this.roomsFilterTotal : this.filterTotal; const filterTotal = isRooms ? this.roomsFilter.total : this.filter.total; - console.log("hasMoreFiles isRooms", isRooms); - console.log("hasMoreFiles filesList", this.filesList.length); - console.log("hasMoreFiles this.filterTotal", this.filterTotal); - console.log("hasMoreFiles this.roomsFilterTotal", this.roomsFilterTotal); - console.log("hasMoreFiles filterTotal", filterTotal); - console.log("hasMoreFiles", this.filesList.length < filterTotal); - console.log("----------------------------"); + // console.log("hasMoreFiles isRooms", isRooms); + // console.log("hasMoreFiles filesList", this.filesList.length); + // console.log("hasMoreFiles this.filterTotal", this.filterTotal); + // console.log("hasMoreFiles this.roomsFilterTotal", this.roomsFilterTotal); + // console.log("hasMoreFiles filterTotal", filterTotal); + // console.log("hasMoreFiles", this.filesList.length < filterTotal); + // console.log("----------------------------"); if (this.isLoading) return false; return this.filesList.length < filterTotal; diff --git a/packages/client/src/store/HotkeyStore.js b/packages/client/src/store/HotkeyStore.js index d225a22381..4f66a5649e 100644 --- a/packages/client/src/store/HotkeyStore.js +++ b/packages/client/src/store/HotkeyStore.js @@ -580,6 +580,10 @@ class HotkeyStore { // } } + if (nextForTileDown.isFolder === undefined) { + nextForTileDown.isFolder = !!nextForTileDown.parentId; + } + return nextForTileDown; } @@ -611,6 +615,11 @@ class HotkeyStore { } else if (!prevTileFile) { prevForTileUp = hotkeyCaret; } + + if (prevForTileUp.isFolder === undefined) { + prevForTileUp.isFolder = !!prevForTileUp.parentId; + } + return prevForTileUp; } diff --git a/packages/client/src/store/ProfileActionsStore.js b/packages/client/src/store/ProfileActionsStore.js index 747af1612a..59cda303a6 100644 --- a/packages/client/src/store/ProfileActionsStore.js +++ b/packages/client/src/store/ProfileActionsStore.js @@ -60,8 +60,14 @@ class ProfileActionsStore { }; onProfileClick = () => { - this.selectedFolderStore.setSelectedFolder(null); - this.treeFoldersStore.setSelectedNode(["accounts"]); + //TODO: add check manager + const { isAdmin, isOwner } = this.authStore.userStore.user; + + if (isAdmin || isOwner) { + this.selectedFolderStore.setSelectedFolder(null); + this.treeFoldersStore.setSelectedNode(["accounts"]); + } + history.push(PROFILE_SELF_URL); }; diff --git a/packages/client/src/store/SelectFileDialogStore.js b/packages/client/src/store/SelectFileDialogStore.js index 55374d483e..acb6f76f8b 100644 --- a/packages/client/src/store/SelectFileDialogStore.js +++ b/packages/client/src/store/SelectFileDialogStore.js @@ -1,17 +1,11 @@ -import { makeObservable, action, observable } from "mobx"; +import { makeAutoObservable } from "mobx"; class SelectFileDialogStore { folderId = null; - fileInfo = null; + fileInfo = {}; constructor() { - makeObservable(this, { - fileInfo: observable, - folderId: observable, - - setFolderId: action, - setFile: action, - }); + makeAutoObservable(this); } setFolderId = (id) => { diff --git a/packages/client/src/store/SelectFolderDialogStore.js b/packages/client/src/store/SelectFolderDialogStore.js index cd8ef2c852..0bd2c2f967 100644 --- a/packages/client/src/store/SelectFolderDialogStore.js +++ b/packages/client/src/store/SelectFolderDialogStore.js @@ -1,27 +1,55 @@ -import { makeObservable, action, observable } from "mobx"; +import { makeAutoObservable } from "mobx"; class SelectFolderDialogStore { - folderId = null; + resultingFolderId = null; fileInfo = null; folderTitle = ""; providerKey = null; baseFolderPath = ""; + newFolderPath = ""; + isPathError = false; + isLoading = false; + resultingFolderTree = []; constructor() { - makeObservable(this, { - fileInfo: observable, - folderId: observable, - folderTitle: observable, - providerKey: observable, - - setFolderId: action, - setProviderKey: action, - setFolderTitle: action, - }); + makeAutoObservable(this); } - setFolderId = (id) => { - this.folderId = id; + toDefault = () => { + this.resultingFolderId = null; + this.resultingFolderTree = []; + this.baseFolderPath = ""; + this.newFolderPath = ""; + this.folderTitle = ""; + this.isLoading = false; + this.isPathError = false; + this.setProviderKey(null); + }; + + updateBaseFolderPath = () => { + this.baseFolderPath = this.newFolderPath; + this.setIsPathError(false); + }; + + resetNewFolderPath = (id) => { + this.newFolderPath = this.baseFolderPath; + this.setIsPathError(false); + this.setResultingFolderId(id); + }; + + setBaseFolderPath = (baseFolderPath) => { + this.baseFolderPath = baseFolderPath; + }; + + setIsPathError = (isPathError) => { + this.isPathError = isPathError; + }; + + setNewFolderPath = (newFolderPath) => { + this.newFolderPath = newFolderPath; + }; + setResultingFolderId = (id) => { + this.resultingFolderId = id; }; setFolderTitle = (title) => { @@ -31,6 +59,14 @@ class SelectFolderDialogStore { setProviderKey = (providerKey) => { this.providerKey = providerKey; }; + + setIsLoading = (isLoading) => { + this.isLoading = isLoading; + }; + + setResultingFoldersTree = (tree) => { + this.resultingFolderTree = tree; + }; } export default new SelectFolderDialogStore(); diff --git a/packages/common/components/Article/styled-article.js b/packages/common/components/Article/styled-article.js index 0d0246af55..b09577b127 100644 --- a/packages/common/components/Article/styled-article.js +++ b/packages/common/components/Article/styled-article.js @@ -1,11 +1,6 @@ import styled, { css } from "styled-components"; -import { - isMobile, - isMobileOnly, - isTablet, - isDesktop, -} from "react-device-detect"; +import { isMobile, isMobileOnly, isTablet } from "react-device-detect"; import { mobile, tablet, @@ -82,7 +77,6 @@ const StyledArticle = styled.article` .scroll-body { overflow-x: hidden !important; height: calc(100% - 200px); - ${!isDesktop && "padding-top: 16px"}; padding: 0 20px; @media ${tablet} { diff --git a/packages/common/components/FilterInput/StyledFilterInput.js b/packages/common/components/FilterInput/StyledFilterInput.js index c01f46a81b..9684102fb5 100644 --- a/packages/common/components/FilterInput/StyledFilterInput.js +++ b/packages/common/components/FilterInput/StyledFilterInput.js @@ -1,7 +1,4 @@ import styled, { css } from "styled-components"; - -import { isDesktop } from "react-device-detect"; - import SearchInput from "@docspace/components/search-input"; const StyledFilterInput = styled.div` diff --git a/packages/common/components/FloatingButton/StyledFloatingButton.js b/packages/common/components/FloatingButton/StyledFloatingButton.js index 23c9a97bb8..8624293985 100644 --- a/packages/common/components/FloatingButton/StyledFloatingButton.js +++ b/packages/common/components/FloatingButton/StyledFloatingButton.js @@ -1,7 +1,7 @@ import Base from "@docspace/components/themes/base"; import styled, { keyframes, css } from "styled-components"; import { desktop, tablet } from "@docspace/components/utils/device"; -import { isDesktop } from "react-device-detect"; +import { isMobile } from "react-device-detect"; const StyledFloatingButtonWrapper = styled.div` @media ${desktop} { @@ -10,7 +10,7 @@ const StyledFloatingButtonWrapper = styled.div` right: 0; bottom: 0; - ${isDesktop && + ${!isMobile && css` width: 100px; height: 70px; diff --git a/packages/common/components/Section/sub-components/section-body.js b/packages/common/components/Section/sub-components/section-body.js index 3974ab43b0..6d476c516b 100644 --- a/packages/common/components/Section/sub-components/section-body.js +++ b/packages/common/components/Section/sub-components/section-body.js @@ -3,7 +3,7 @@ import PropTypes from "prop-types"; import styled, { css } from "styled-components"; //import equal from "fast-deep-equal/react"; //import { LayoutContextConsumer } from "client/Layout/context"; -import { isMobile, isMobileOnly, isDesktop } from "react-device-detect"; +import { isMobile, isMobileOnly } from "react-device-detect"; import { inject, observer } from "mobx-react"; import Scrollbar from "@docspace/components/scrollbar"; @@ -110,7 +110,7 @@ const commonStyles = css` .files-row-container { margin-top: -22px; - ${isDesktop && + ${!isMobile && css` margin-top: -17px; `} diff --git a/packages/components/avatar/styled-avatar.js b/packages/components/avatar/styled-avatar.js index 37c3d9b1de..8d1b1696a6 100644 --- a/packages/components/avatar/styled-avatar.js +++ b/packages/components/avatar/styled-avatar.js @@ -139,6 +139,8 @@ const StyledAvatar = styled.div` font-family: ${(props) => props.theme.fontFamily}; font-style: normal; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + .admin_icon { rect:nth-child(1) { fill: ${(props) => props.theme.avatar.administrator.fill}; diff --git a/packages/components/infinite-loader/StyledInfiniteLoader.js b/packages/components/infinite-loader/StyledInfiniteLoader.js index b93f40f77a..a1165903aa 100644 --- a/packages/components/infinite-loader/StyledInfiniteLoader.js +++ b/packages/components/infinite-loader/StyledInfiniteLoader.js @@ -31,23 +31,39 @@ const StyledScroll = styled.div` const rowStyles = css` margin-left: -20px; - width: ${({ width }) => width + 20 + "px !important"}; + width: ${({ width }) => width + 36 + "px !important"}; .ReactVirtualized__Grid__innerScrollContainer { - max-width: ${({ width }) => width + 20 + "px !important"}; + max-width: ${({ width }) => width + 36 + "px !important"}; + } + + @media ${tablet} { + width: ${({ width }) => width + 36 + "px !important"}; + + .ReactVirtualized__Grid__innerScrollContainer { + max-width: ${({ width }) => width + 36 + "px !important"}; + } + } + + @media ${mobile} { + width: ${({ width }) => width + 28 + "px !important"}; + + .ReactVirtualized__Grid__innerScrollContainer { + max-width: ${({ width }) => width + 28 + "px !important"}; + } } .row-list-item { padding-left: 16px; - width: calc(100% - 16px) !important; + width: calc(100% - 32px) !important; @media ${tablet} { padding-left: 20px; - width: calc(100% - 20px) !important; + width: calc(100% - 36px) !important; } @media ${mobile} { - width: calc(100% - 20px) !important; + width: calc(100% - 28px) !important; } } `; diff --git a/packages/components/infinite-loader/infiniteLoaderUtils.js b/packages/components/infinite-loader/infiniteLoaderUtils.js index 64468785ba..4398ecfe91 100644 --- a/packages/components/infinite-loader/infiniteLoaderUtils.js +++ b/packages/components/infinite-loader/infiniteLoaderUtils.js @@ -2,7 +2,7 @@ let timer = null; const startInterval = () => { const elem = document.getElementById("infinite-page-loader"); - elem.style.display = "block"; + if (elem) elem.style.display = "block"; }; export function showLoader() { diff --git a/packages/components/row/styled-row.js b/packages/components/row/styled-row.js index 17dd659d62..d26709c10f 100644 --- a/packages/components/row/styled-row.js +++ b/packages/components/row/styled-row.js @@ -77,6 +77,8 @@ const StyledCheckbox = styled.div` justify-content: center; align-items: center; + min-width: 41px; + width: 41px; ${(props) => props.mode == "modern" && !isMobile && diff --git a/packages/components/tree-menu/index.js b/packages/components/tree-menu/index.js index 862d6d508f..a018cceb55 100644 --- a/packages/components/tree-menu/index.js +++ b/packages/components/tree-menu/index.js @@ -8,6 +8,11 @@ import Badge from "../badge"; import Base from "../themes/base"; const StyledTree = styled(Tree)` + span.rc-tree-node-content-wrapper, + span.rc-tree-switcher { + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + } + .rc-tree-list-holder-inner { .disable-node { span.rc-tree-node-content-wrapper { @@ -33,6 +38,22 @@ const StyledTree = styled(Tree)` } } + .disable-folder { + span.rc-tree-node-content-wrapper { + pointer-events: none; + span.rc-tree-iconEle { + svg { + path { + fill: ${(props) => props.theme.treeNode.disableColor}; + } + } + } + span.rc-tree-title { + color: ${(props) => props.theme.treeNode.disableColor} !important; + } + } + } + .rc-tree-treenode { height: 36px; display: flex; diff --git a/packages/editor/src/client/components/SelectFileDialog.js b/packages/editor/src/client/components/SelectFileDialog.js index 19043d2317..49824d6803 100644 --- a/packages/editor/src/client/components/SelectFileDialog.js +++ b/packages/editor/src/client/components/SelectFileDialog.js @@ -22,7 +22,7 @@ const SelectFileDialog = ({ module: "./SelectFileDialog", }} resetTreeFolders - foldersType="exceptPrivacyTrashFolders" + filteredType="exceptPrivacyTrashArchiveFolders" isPanelVisible={isVisible} onClose={onCloseFileDialog} onSelectFile={onSelectFile} diff --git a/packages/editor/src/client/components/SelectFolderDialog.js b/packages/editor/src/client/components/SelectFolderDialog.js index 82dab51862..51f8a0c74c 100644 --- a/packages/editor/src/client/components/SelectFolderDialog.js +++ b/packages/editor/src/client/components/SelectFolderDialog.js @@ -63,7 +63,7 @@ const SelectFolderDialog = ({ folderId={folderId} isPanelVisible={isVisible} onClose={onCloseFolderDialog} - foldersType="exceptSortedByTags" + filteredType="exceptSortedByTags" onSave={onClickSaveSelectFolder} isDisableButton={!titleSelectorFolder.trim()} {...headerProps}