From 42b3a8711ef6ecbb7e6ec095776b96ecb6d0f1d7 Mon Sep 17 00:00:00 2001 From: Taiji Uchida <63937957+uchi-ta@users.noreply.github.com> Date: Mon, 16 Oct 2023 12:52:16 +0900 Subject: [PATCH] Added new features / Bug fixed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ・組織をCSVからインポートするAPIを追加。 ・グループをCSVからインポートするAPIを追加。 ・ユーザをCSVからインポートするAPIを追加。 ・ユーザのごみ箱機能を追加。 ・タブレットPC環境のユーザビリティの向上。 ・フィルターの状態を保持を設定しているビューに切り替えた際に否定の条件が保持されない問題を解消。 ・編集画面の自動ポストバック時にサーバスクリプトの画面表示ので実行したログが出力できない問題を解消。 ・ユーザーのインポートで2段階認証の有効化、無効化の設定が反映されない問題を解消。 ・サイトのアクセス制御タブに削除された組織が表示される問題を解消。 ・一覧のカスタムデザインを使用している場合に履歴の表示でエラーが発生する問題を解消。 ・結合したタイトルが変更履歴に正しく表示されない問題を解消。 --- Implem.CodeDefiner/Implem.CodeDefiner.csproj | 8 +- .../Properties/launchSettings.json | 2 +- Implem.DefinitionAccessor/Def.cs | 18 +- .../Implem.DefinitionAccessor.csproj | 6 +- Implem.DefinitionAccessor/Initializer.cs | 5 + .../Implem.DisplayAccessor.csproj | 6 +- Implem.Factory/Implem.Factory.csproj | 6 +- Implem.Libraries/Implem.Libraries.csproj | 8 +- Implem.Libraries/Utilities/CryptographyAes.cs | 45 + Implem.Libraries/Utilities/Files.cs | 6 +- .../Implem.ParameterAccessor.csproj | 6 +- .../Parts/DataProtection.cs | 1 + .../Definition_Code/Model_Delete_Body.txt | 1 + .../Definition_Code/Model_Delete_User.json | 5 + .../Model_Delete_User_Body.txt | 6 + .../Definition_Code/Model_Utilities_Body.txt | 1 + .../Model_Utilities_Create_Body.txt | 1 + ...tilities_Create_CopyFromClearComments.json | 5 + ...ties_Create_CopyFromClearComments_Body.txt | 4 + ...l_Utilities_EditorResponse_Tables_Body.txt | 32 +- .../Model_Utilities_Histories.json | 2 +- .../Model_Utilities_Histories_Body.txt | 2 +- ...l_Utilities_Histories_ItemTitleColumn.json | 4 - ...ilities_Histories_ItemTitleColumn_Body.txt | 1 - .../Model_Utilities_Histories_Tables.json | 6 + .../Model_Utilities_Histories_Tables_Body.txt | 106 ++ .../Definition_Code/SiteSettings_Body.txt | 1 + .../SiteSettings_GetModels.json | 2 +- .../SiteSettings_GetModels_Body.txt | 1 - ...json => SiteSettings_GetModels_Users.json} | 4 +- .../SiteSettings_GetModels_Users_Body.txt | 32 + .../SiteSettings_Users_Body.txt | 19 - .../App_Data/Parameters/NavigationMenus.json | 6 + .../App_Data/Parameters/Security.json | 3 +- .../Controllers/Api/DeptsController.cs | 22 + .../Controllers/Api/GroupsController.cs | 22 + .../Controllers/Api/UsersController.cs | 22 + .../Controllers/UsersController.cs | 67 ++ Implem.Pleasanter/Implem.Pleasanter.csproj | 22 +- .../Libraries/HtmlParts/HtmlBack.cs | 4 + .../Libraries/HtmlParts/HtmlNavigationMenu.cs | 13 + .../HtmlParts/HtmlTrashBoxCommands.cs | 20 +- .../Libraries/Images/ImageData.cs | 28 +- Implem.Pleasanter/Libraries/Models/Imports.cs | 20 + .../Libraries/Requests/Calendars.cs | 2 +- .../Libraries/Requests/ImportApi.cs | 1 + Implem.Pleasanter/Libraries/Requests/Views.cs | 1 + .../AspNetCoreKeyManagemenXmltUtils.cs | 20 + .../AspNetCoreKeyManagementXmlDecryptor.cs | 19 + .../AspNetCoreKeyManagementXmlEncryptor.cs | 22 + .../AspNetCoreKeyManagementXmlRepository.cs | 81 ++ .../Libraries/Security/Permission.cs | 2 +- .../Libraries/Settings/SiteSettings.cs | 6 +- .../Settings/SiteSettingsUtilities.cs | 3 +- .../Models/Binaries/BinaryUtilities.cs | 48 +- .../Models/Binaries/BinaryValidators.cs | 4 +- .../Models/Depts/DeptUtilities.cs | 294 ++++-- .../Models/Groups/GroupUtilities.cs | 306 ++++++ .../Models/Issues/IssueUtilities.cs | 52 +- .../Models/Results/ResultUtilities.cs | 52 +- Implem.Pleasanter/Models/Users/UserModel.cs | 7 + .../Models/Users/UserUtilities.cs | 909 +++++++++++++++--- Implem.Pleasanter/Startup.cs | 11 + Implem.Pleasanter/Views/Users/TrashBox.cshtml | 4 + .../wwwroot/content/responsive.css | 498 +++++++--- .../wwwroot/content/responsive.min.css | 2 +- .../wwwroot/scripts/_elements.js | 2 +- .../wwwroot/scripts/dashboard.js | 2 +- Implem.Pleasanter/wwwroot/scripts/gantt.js | 83 +- Implem.Pleasanter/wwwroot/scripts/kamban.js | 63 +- Implem.Pleasanter/wwwroot/scripts/markdown.js | 2 +- .../wwwroot/scripts/responsive.js | 16 +- .../wwwroot/scripts/sitepackage.js | 4 +- Implem.Pleasanter/wwwroot/scripts/template.js | 2 +- Implem.Pleasanter/wwwroot/scripts/viewmode.js | 2 +- .../wwwroot/styles/responsive.css | 498 +++++++--- .../implem.TestAutomation.csproj | 16 +- Rds/Implem.IRds/Implem.IRds.csproj | 6 +- .../Implem.PostgreSql.csproj | 8 +- Rds/Implem.SqlServer/Implem.SqlServer.csproj | 6 +- 80 files changed, 2972 insertions(+), 683 deletions(-) create mode 100644 Implem.Libraries/Utilities/CryptographyAes.cs create mode 100644 Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Delete_User.json create mode 100644 Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Delete_User_Body.txt create mode 100644 Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Create_CopyFromClearComments.json create mode 100644 Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Create_CopyFromClearComments_Body.txt delete mode 100644 Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_ItemTitleColumn.json delete mode 100644 Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_ItemTitleColumn_Body.txt create mode 100644 Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_Tables.json create mode 100644 Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_Tables_Body.txt rename Implem.Pleasanter/App_Data/Definitions/Definition_Code/{SiteSettings_Users.json => SiteSettings_GetModels_Users.json} (55%) create mode 100644 Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_GetModels_Users_Body.txt delete mode 100644 Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_Users_Body.txt create mode 100644 Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagemenXmltUtils.cs create mode 100644 Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagementXmlDecryptor.cs create mode 100644 Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagementXmlEncryptor.cs create mode 100644 Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagementXmlRepository.cs create mode 100644 Implem.Pleasanter/Views/Users/TrashBox.cshtml diff --git a/Implem.CodeDefiner/Implem.CodeDefiner.csproj b/Implem.CodeDefiner/Implem.CodeDefiner.csproj index 7e935a492..884feeb0d 100644 --- a/Implem.CodeDefiner/Implem.CodeDefiner.csproj +++ b/Implem.CodeDefiner/Implem.CodeDefiner.csproj @@ -5,14 +5,14 @@ net6.0 Copyright © Implem Inc 2014 - 2023 This program does the automatic code creation and merging of existing code based on the definition. Also it will make the configuration change of sql server database. - 1.3.47.0 - 1.3.47.0 - 1.3.47.0 + 1.3.48.0 + 1.3.48.0 + 1.3.48.0 Linux - + diff --git a/Implem.CodeDefiner/Properties/launchSettings.json b/Implem.CodeDefiner/Properties/launchSettings.json index 4b04fac14..3c4bd0b59 100644 --- a/Implem.CodeDefiner/Properties/launchSettings.json +++ b/Implem.CodeDefiner/Properties/launchSettings.json @@ -1,4 +1,4 @@ -{ +{ "profiles": { "Implem.CodeDefiner": { "commandName": "Project", diff --git a/Implem.DefinitionAccessor/Def.cs b/Implem.DefinitionAccessor/Def.cs index d92bdead4..918f78814 100644 --- a/Implem.DefinitionAccessor/Def.cs +++ b/Implem.DefinitionAccessor/Def.cs @@ -413,6 +413,7 @@ public static void SetCodeDefinition() case "Model_Delete_Item": Code.Model_Delete_Item = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Delete_Item, definitionRow, CodeXls); break; case "Model_Delete_Sites": Code.Model_Delete_Sites = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Delete_Sites, definitionRow, CodeXls); break; case "Model_Delete_SitesItems": Code.Model_Delete_SitesItems = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Delete_SitesItems, definitionRow, CodeXls); break; + case "Model_Delete_User": Code.Model_Delete_User = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Delete_User, definitionRow, CodeXls); break; case "Model_DeleteAttachments": Code.Model_DeleteAttachments = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_DeleteAttachments, definitionRow, CodeXls); break; case "Model_DeleteByApiCases": Code.Model_DeleteByApiCases = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_DeleteByApiCases, definitionRow, CodeXls); break; case "Model_DeleteByServerScriptCases": Code.Model_DeleteByServerScriptCases = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_DeleteByServerScriptCases, definitionRow, CodeXls); break; @@ -746,6 +747,7 @@ public static void SetCodeDefinition() case "Model_Utilities_Create": Code.Model_Utilities_Create = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_Create, definitionRow, CodeXls); break; case "Model_Utilities_Create_CopyFrom_Item": Code.Model_Utilities_Create_CopyFrom_Item = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_Create_CopyFrom_Item, definitionRow, CodeXls); break; case "Model_Utilities_Create_CopyFrom_NotItem": Code.Model_Utilities_Create_CopyFrom_NotItem = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_Create_CopyFrom_NotItem, definitionRow, CodeXls); break; + case "Model_Utilities_Create_CopyFromClearComments": Code.Model_Utilities_Create_CopyFromClearComments = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_Create_CopyFromClearComments, definitionRow, CodeXls); break; case "Model_Utilities_Create_JoeAccountCheck": Code.Model_Utilities_Create_JoeAccountCheck = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_Create_JoeAccountCheck, definitionRow, CodeXls); break; case "Model_Utilities_Create_Models": Code.Model_Utilities_Create_Models = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_Create_Models, definitionRow, CodeXls); break; case "Model_Utilities_Create_OnCreating": Code.Model_Utilities_Create_OnCreating = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_Create_OnCreating, definitionRow, CodeXls); break; @@ -796,8 +798,8 @@ public static void SetCodeDefinition() case "Model_Utilities_GridRows_OnClick": Code.Model_Utilities_GridRows_OnClick = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_GridRows_OnClick, definitionRow, CodeXls); break; case "Model_Utilities_GridRows_OnClickItem": Code.Model_Utilities_GridRows_OnClickItem = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_GridRows_OnClickItem, definitionRow, CodeXls); break; case "Model_Utilities_Histories": Code.Model_Utilities_Histories = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_Histories, definitionRow, CodeXls); break; - case "Model_Utilities_Histories_ItemTitleColumn": Code.Model_Utilities_Histories_ItemTitleColumn = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_Histories_ItemTitleColumn, definitionRow, CodeXls); break; case "Model_Utilities_Histories_Join": Code.Model_Utilities_Histories_Join = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_Histories_Join, definitionRow, CodeXls); break; + case "Model_Utilities_Histories_Tables": Code.Model_Utilities_Histories_Tables = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_Histories_Tables, definitionRow, CodeXls); break; case "Model_Utilities_HistoriesParams": Code.Model_Utilities_HistoriesParams = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_HistoriesParams, definitionRow, CodeXls); break; case "Model_Utilities_HistoriesParams_Sites": Code.Model_Utilities_HistoriesParams_Sites = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_HistoriesParams_Sites, definitionRow, CodeXls); break; case "Model_Utilities_HistoriesSetChoiceHash": Code.Model_Utilities_HistoriesSetChoiceHash = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Model_Utilities_HistoriesSetChoiceHash, definitionRow, CodeXls); break; @@ -1037,7 +1039,7 @@ public static void SetCodeDefinition() case "SiteSettings_GetModels_Items": Code.SiteSettings_GetModels_Items = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.SiteSettings_GetModels_Items, definitionRow, CodeXls); break; case "SiteSettings_GetModels_Items_Choices": Code.SiteSettings_GetModels_Items_Choices = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.SiteSettings_GetModels_Items_Choices, definitionRow, CodeXls); break; case "SiteSettings_GetModels_Items_SiteIntegration": Code.SiteSettings_GetModels_Items_SiteIntegration = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.SiteSettings_GetModels_Items_SiteIntegration, definitionRow, CodeXls); break; - case "SiteSettings_Users": Code.SiteSettings_Users = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.SiteSettings_Users, definitionRow, CodeXls); break; + case "SiteSettings_GetModels_Users": Code.SiteSettings_GetModels_Users = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.SiteSettings_GetModels_Users, definitionRow, CodeXls); break; case "Summaries": Code.Summaries = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Summaries, definitionRow, CodeXls); break; case "Summaries_DataTablesCases": Code.Summaries_DataTablesCases = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Summaries_DataTablesCases, definitionRow, CodeXls); break; case "Summaries_ParamCases": Code.Summaries_ParamCases = definitionRow[1].ToString().NoSpace(definitionRow["NoSpace"].ToBool()); SetCodeTable(CodeTable.Summaries_ParamCases, definitionRow, CodeXls); break; @@ -6860,6 +6862,7 @@ public class CodeColumn2nd public string Model_Delete_Item; public string Model_Delete_Sites; public string Model_Delete_SitesItems; + public string Model_Delete_User; public string Model_DeleteAttachments; public string Model_DeleteByApiCases; public string Model_DeleteByServerScriptCases; @@ -7193,6 +7196,7 @@ public class CodeColumn2nd public string Model_Utilities_Create; public string Model_Utilities_Create_CopyFrom_Item; public string Model_Utilities_Create_CopyFrom_NotItem; + public string Model_Utilities_Create_CopyFromClearComments; public string Model_Utilities_Create_JoeAccountCheck; public string Model_Utilities_Create_Models; public string Model_Utilities_Create_OnCreating; @@ -7243,8 +7247,8 @@ public class CodeColumn2nd public string Model_Utilities_GridRows_OnClick; public string Model_Utilities_GridRows_OnClickItem; public string Model_Utilities_Histories; - public string Model_Utilities_Histories_ItemTitleColumn; public string Model_Utilities_Histories_Join; + public string Model_Utilities_Histories_Tables; public string Model_Utilities_HistoriesParams; public string Model_Utilities_HistoriesParams_Sites; public string Model_Utilities_HistoriesSetChoiceHash; @@ -7484,7 +7488,7 @@ public class CodeColumn2nd public string SiteSettings_GetModels_Items; public string SiteSettings_GetModels_Items_Choices; public string SiteSettings_GetModels_Items_SiteIntegration; - public string SiteSettings_Users; + public string SiteSettings_GetModels_Users; public string Summaries; public string Summaries_DataTablesCases; public string Summaries_ParamCases; @@ -7658,6 +7662,7 @@ public class CodeTable public CodeDefinition Model_Delete_Item = new CodeDefinition(); public CodeDefinition Model_Delete_Sites = new CodeDefinition(); public CodeDefinition Model_Delete_SitesItems = new CodeDefinition(); + public CodeDefinition Model_Delete_User = new CodeDefinition(); public CodeDefinition Model_DeleteAttachments = new CodeDefinition(); public CodeDefinition Model_DeleteByApiCases = new CodeDefinition(); public CodeDefinition Model_DeleteByServerScriptCases = new CodeDefinition(); @@ -7991,6 +7996,7 @@ public class CodeTable public CodeDefinition Model_Utilities_Create = new CodeDefinition(); public CodeDefinition Model_Utilities_Create_CopyFrom_Item = new CodeDefinition(); public CodeDefinition Model_Utilities_Create_CopyFrom_NotItem = new CodeDefinition(); + public CodeDefinition Model_Utilities_Create_CopyFromClearComments = new CodeDefinition(); public CodeDefinition Model_Utilities_Create_JoeAccountCheck = new CodeDefinition(); public CodeDefinition Model_Utilities_Create_Models = new CodeDefinition(); public CodeDefinition Model_Utilities_Create_OnCreating = new CodeDefinition(); @@ -8041,8 +8047,8 @@ public class CodeTable public CodeDefinition Model_Utilities_GridRows_OnClick = new CodeDefinition(); public CodeDefinition Model_Utilities_GridRows_OnClickItem = new CodeDefinition(); public CodeDefinition Model_Utilities_Histories = new CodeDefinition(); - public CodeDefinition Model_Utilities_Histories_ItemTitleColumn = new CodeDefinition(); public CodeDefinition Model_Utilities_Histories_Join = new CodeDefinition(); + public CodeDefinition Model_Utilities_Histories_Tables = new CodeDefinition(); public CodeDefinition Model_Utilities_HistoriesParams = new CodeDefinition(); public CodeDefinition Model_Utilities_HistoriesParams_Sites = new CodeDefinition(); public CodeDefinition Model_Utilities_HistoriesSetChoiceHash = new CodeDefinition(); @@ -8282,7 +8288,7 @@ public class CodeTable public CodeDefinition SiteSettings_GetModels_Items = new CodeDefinition(); public CodeDefinition SiteSettings_GetModels_Items_Choices = new CodeDefinition(); public CodeDefinition SiteSettings_GetModels_Items_SiteIntegration = new CodeDefinition(); - public CodeDefinition SiteSettings_Users = new CodeDefinition(); + public CodeDefinition SiteSettings_GetModels_Users = new CodeDefinition(); public CodeDefinition Summaries = new CodeDefinition(); public CodeDefinition Summaries_DataTablesCases = new CodeDefinition(); public CodeDefinition Summaries_ParamCases = new CodeDefinition(); diff --git a/Implem.DefinitionAccessor/Implem.DefinitionAccessor.csproj b/Implem.DefinitionAccessor/Implem.DefinitionAccessor.csproj index 668826221..102ed6c5c 100644 --- a/Implem.DefinitionAccessor/Implem.DefinitionAccessor.csproj +++ b/Implem.DefinitionAccessor/Implem.DefinitionAccessor.csproj @@ -3,9 +3,9 @@ net6.0 Copyright © Implem Inc 2014 - 2023 - 1.3.47.0 - 1.3.47.0 - 1.3.47.0 + 1.3.48.0 + 1.3.48.0 + 1.3.48.0 disable diff --git a/Implem.DefinitionAccessor/Initializer.cs b/Implem.DefinitionAccessor/Initializer.cs index b63e0d406..11bf1f1b4 100644 --- a/Implem.DefinitionAccessor/Initializer.cs +++ b/Implem.DefinitionAccessor/Initializer.cs @@ -184,6 +184,11 @@ public static void SetParameters() Parameters.Security.AspNetCoreDataProtection.KeyIdentifier, Environment.GetEnvironmentVariable($"{Parameters.Service.EnvironmentName}_Security_AspNetCoreDataProtection_KeyIdentifier"), Environment.GetEnvironmentVariable($"{Parameters.Service.Name}_Security_AspNetCoreDataProtection_KeyIdentifier")); + Parameters.Security.AspNetCoreDataProtection.XmlAesKey = Strings.CoalesceEmpty( + Parameters.Security.AspNetCoreDataProtection.XmlAesKey, + Environment.GetEnvironmentVariable($"{Parameters.Service.EnvironmentName}_Security_AspNetCoreDataProtection_XmlAesKey"), + Environment.GetEnvironmentVariable($"{Parameters.Service.Name}_Security_AspNetCoreDataProtection_XmlAesKey"), + Parameters.Service.Name); Parameters.Service.DeploymentEnvironment = Strings.CoalesceEmpty( Parameters.Service.DeploymentEnvironment, Environment.GetEnvironmentVariable($"{Parameters.Service.EnvironmentName}_Service_DeploymentEnvironment"), diff --git a/Implem.DisplayAccessor/Implem.DisplayAccessor.csproj b/Implem.DisplayAccessor/Implem.DisplayAccessor.csproj index 868e0ea86..16055a1f7 100644 --- a/Implem.DisplayAccessor/Implem.DisplayAccessor.csproj +++ b/Implem.DisplayAccessor/Implem.DisplayAccessor.csproj @@ -3,9 +3,9 @@ net6.0 Copyright © Implem Inc 2014 - 2023 - 1.3.47.0 - 1.3.47.0 - 1.3.47.0 + 1.3.48.0 + 1.3.48.0 + 1.3.48.0 disable diff --git a/Implem.Factory/Implem.Factory.csproj b/Implem.Factory/Implem.Factory.csproj index 9ca7077a5..d0daef8fd 100644 --- a/Implem.Factory/Implem.Factory.csproj +++ b/Implem.Factory/Implem.Factory.csproj @@ -3,9 +3,9 @@ net6.0 Copyright © Implem Inc 2014 - 2023 - 1.3.47.0 - 1.3.47.0 - 1.3.47.0 + 1.3.48.0 + 1.3.48.0 + 1.3.48.0 disable diff --git a/Implem.Libraries/Implem.Libraries.csproj b/Implem.Libraries/Implem.Libraries.csproj index b875590f5..d31f55b8e 100644 --- a/Implem.Libraries/Implem.Libraries.csproj +++ b/Implem.Libraries/Implem.Libraries.csproj @@ -3,9 +3,9 @@ net6.0 Copyright © Implem Inc 2014 - 2023 - 1.3.47.0 - 1.3.47.0 - 1.3.47.0 + 1.3.48.0 + 1.3.48.0 + 1.3.48.0 disable @@ -13,7 +13,7 @@ - + diff --git a/Implem.Libraries/Utilities/CryptographyAes.cs b/Implem.Libraries/Utilities/CryptographyAes.cs new file mode 100644 index 000000000..a734f4894 --- /dev/null +++ b/Implem.Libraries/Utilities/CryptographyAes.cs @@ -0,0 +1,45 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace Implem.Libraries.Utilities +{ + public class CryptographyAes + { + public static string AesEncrypt(string encryptString, string encryptKey, string aesIv) + { + if (encryptString.Trim().IsNullOrEmpty()) return null; + if (encryptKey.Trim().IsNullOrEmpty()) return null; + using (var aes = Aes.Create()) + { + using var encryptor = aes.CreateEncryptor( + Encoding.UTF8.GetBytes(encryptKey.Substring(0, 32)), + Encoding.UTF8.GetBytes(aesIv)); + using var ms = new MemoryStream(); + using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) + { + using var sw = new StreamWriter(cs); + sw.Write(encryptString); + } + return Convert.ToBase64String(ms.ToArray()); + } + } + + public static string AesDecrypt(string decryptString, string decryptKey, string aesIv) + { + if (decryptString.Trim().IsNullOrEmpty()) return null; + if (decryptKey.Trim().IsNullOrEmpty()) return null; + using (var aes = Aes.Create()) + { + using var decryptor = aes.CreateDecryptor( + Encoding.UTF8.GetBytes(decryptKey.Substring(0, 32)), + Encoding.UTF8.GetBytes(aesIv)); + using var ms = new MemoryStream(Convert.FromBase64String(decryptString)); + using var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read); + using var sr = new StreamReader(cs); + return sr.ReadToEnd(); + } + } + } +} diff --git a/Implem.Libraries/Utilities/Files.cs b/Implem.Libraries/Utilities/Files.cs index 726126090..6fad98ca1 100644 --- a/Implem.Libraries/Utilities/Files.cs +++ b/Implem.Libraries/Utilities/Files.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Imaging; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Formats; using System.IO; using System.Linq; using System.Text; @@ -83,7 +83,7 @@ public static void Write( public static void Write( this Image self, string filePath, - ImageFormat format, + IImageEncoder format, int reTryCount = 100) { var successful = false; diff --git a/Implem.ParameterAccessor/Implem.ParameterAccessor.csproj b/Implem.ParameterAccessor/Implem.ParameterAccessor.csproj index 2f062727e..3c24f19bb 100644 --- a/Implem.ParameterAccessor/Implem.ParameterAccessor.csproj +++ b/Implem.ParameterAccessor/Implem.ParameterAccessor.csproj @@ -3,9 +3,9 @@ net6.0 Copyright © Implem Inc 2014 - 2023 - 1.3.47.0 - 1.3.47.0 - 1.3.47.0 + 1.3.48.0 + 1.3.48.0 + 1.3.48.0 disable diff --git a/Implem.ParameterAccessor/Parts/DataProtection.cs b/Implem.ParameterAccessor/Parts/DataProtection.cs index 97b1dfaf2..78502a39a 100644 --- a/Implem.ParameterAccessor/Parts/DataProtection.cs +++ b/Implem.ParameterAccessor/Parts/DataProtection.cs @@ -5,5 +5,6 @@ public class AspNetCoreDataProtection public string BlobContainerUri; public string KeyIdentifier; public string KeyFileName; + public string XmlAesKey; } } diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Delete_Body.txt b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Delete_Body.txt index 3b55f0f08..0357bcdba 100644 --- a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Delete_Body.txt +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Delete_Body.txt @@ -12,6 +12,7 @@ statements.AddRange(new List { + Rds.Delete#TableName#( diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Delete_User.json b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Delete_User.json new file mode 100644 index 000000000..a54ed2f9b --- /dev/null +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Delete_User.json @@ -0,0 +1,5 @@ +{ + "Id": "Model_Delete_User", + "Indent": "4", + "Include": "Users" +} \ No newline at end of file diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Delete_User_Body.txt b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Delete_User_Body.txt new file mode 100644 index 000000000..579238099 --- /dev/null +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Delete_User_Body.txt @@ -0,0 +1,6 @@ +Rds.DeleteBinaries( + factory: context, + where: Rds.BinariesWhere() + .TenantId(context.TenantId) + .ReferenceId(UserId) + .BinaryType(value: "TenantManagementImages")), \ No newline at end of file diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Body.txt b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Body.txt index 8897f0d9b..b133eca00 100644 --- a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Body.txt +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Body.txt @@ -66,6 +66,7 @@ namespace Implem.Pleasanter.Models + diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Create_Body.txt b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Create_Body.txt index ebb0807a8..5f7b42737 100644 --- a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Create_Body.txt +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Create_Body.txt @@ -10,6 +10,7 @@ } + diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Create_CopyFromClearComments.json b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Create_CopyFromClearComments.json new file mode 100644 index 000000000..cf2930bca --- /dev/null +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Create_CopyFromClearComments.json @@ -0,0 +1,5 @@ +{ + "Id": "Model_Utilities_Create_CopyFromClearComments", + "Indent": "3", + "Include": "Issues,Results" +} \ No newline at end of file diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Create_CopyFromClearComments_Body.txt b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Create_CopyFromClearComments_Body.txt new file mode 100644 index 000000000..cdffdf21d --- /dev/null +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Create_CopyFromClearComments_Body.txt @@ -0,0 +1,4 @@ +if (copyFrom > 0) +{ + #modelName#Model.Comments.Clear(); +} \ No newline at end of file diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_EditorResponse_Tables_Body.txt b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_EditorResponse_Tables_Body.txt index 0408e1eee..95f61c86c 100644 --- a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_EditorResponse_Tables_Body.txt +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_EditorResponse_Tables_Body.txt @@ -1,8 +1,6 @@ private static ResponseCollection EditorResponse( Context context, - - - + SiteSettings ss, #ModelName#Model #modelName#Model, Message message = null, string switchTargets = null) @@ -10,22 +8,27 @@ #modelName#Model.MethodType = #modelName#Model.#ModelName#Id == 0 ? BaseModel.MethodTypes.New : BaseModel.MethodTypes.Edit; - var editInDialog = context.Forms.Bool("EditInDialog"); - return context.QueryStrings.Bool("control-auto-postback") - ? EditorFields( + if (context.QueryStrings.Bool("control-auto-postback")) + { + return EditorFields( context: context, ss: ss, - #modelName#Model: #modelName#Model) - : editInDialog + #modelName#Model: #modelName#Model); + } + else + { + var editInDialog = context.Forms.Bool("EditInDialog"); + var html = Editor( + context: context, + ss: ss, + #modelName#Model: #modelName#Model, + editInDialog: editInDialog); + return editInDialog ? new #TableName#ResponseCollection( context: context, #modelName#Model: #modelName#Model) .Response("id", #modelName#Model.#ModelName#Id.ToString()) - .Html("#EditInDialogBody", Editor( - context: context, - ss: ss, - #modelName#Model: #modelName#Model, - editInDialog: editInDialog)) + .Html("#EditInDialogBody", html) .Invoke("openEditorDialog") .Messages(context.Messages) .Events("on_editor_load") @@ -34,7 +37,7 @@ #modelName#Model: #modelName#Model) .Response("id", #modelName#Model.#ModelName#Id.ToString()) .Invoke("clearDialogs") - .ReplaceAll("#MainContainer", Editor(context, #modelName#Model)) + .ReplaceAll("#MainContainer", html) .Val("#Id", #modelName#Model.#ModelName#Id.ToString()) .Val("#SwitchTargets", switchTargets, _using: switchTargets != null) .SetMemory("formChanged", false) @@ -49,6 +52,7 @@ .Messages(context.Messages) .ClearFormData() .Events("on_editor_load"); + } } private static ResponseCollection EditorFields( diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories.json b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories.json index 48ae087cc..cdd9b9a36 100644 --- a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories.json +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories.json @@ -2,5 +2,5 @@ "Id": "Model_Utilities_Histories", "Indent": "2", "GenericUi": "1", - "Exclude": "Dashboards" + "Exclude": "Dashboards,Issues,Results" } \ No newline at end of file diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_Body.txt b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_Body.txt index d85766dee..96499b30a 100644 --- a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_Body.txt +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_Body.txt @@ -91,7 +91,7 @@ private static SqlColumnCollection HistoryColumn(List columns) .Ver(); columns.ForEach(column => sqlColumn.#TableName#Column(columnName: column.ColumnName)); - return sqlColumn; + return sqlColumn; } diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_ItemTitleColumn.json b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_ItemTitleColumn.json deleted file mode 100644 index 3cc39fe9d..000000000 --- a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_ItemTitleColumn.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "Id": "Model_Utilities_Histories_ItemTitleColumn", - "Include": "Issues,Results" -} \ No newline at end of file diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_ItemTitleColumn_Body.txt b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_ItemTitleColumn_Body.txt deleted file mode 100644 index 579aaeba3..000000000 --- a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_ItemTitleColumn_Body.txt +++ /dev/null @@ -1 +0,0 @@ -.ItemTitle(tableName: "#TableName#") \ No newline at end of file diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_Tables.json b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_Tables.json new file mode 100644 index 000000000..3f465daf4 --- /dev/null +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_Tables.json @@ -0,0 +1,6 @@ +{ + "Id": "Model_Utilities_Histories_Tables", + "Indent": "2", + "GenericUi": "1", + "Include": "Issues,Results" +} \ No newline at end of file diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_Tables_Body.txt b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_Tables_Body.txt new file mode 100644 index 000000000..d4c8b7dc6 --- /dev/null +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/Model_Utilities_Histories_Tables_Body.txt @@ -0,0 +1,106 @@ + + + + if (!context.CanRead(ss: ss)) + { + return Error.Types.HasNotPermission.MessageJson(context: context); + } + var hb = new HtmlBuilder(); + hb + .HistoryCommands(context: context, ss: ss) + .Table( + attributes: new HtmlAttributes().Class("grid history"), + action: () => hb + .THead(action: () => hb + .GridHeader( + context: context, + ss: ss, + columns: columns, + sort: false, + checkRow: true)) + .TBody(action: () => hb + .HistoriesTableBody( + context: context, + ss: ss, + columns: columns, + #modelName#Model: #modelName#Model))); + return new #TableName#ResponseCollection( + context: context, + #modelName#Model: #modelName#Model) + .Html("#FieldSetHistories", hb) + .Message(message) + .Messages(context.Messages) + .ToJson(); +} + +private static void HistoriesTableBody( + this HtmlBuilder hb, + Context context, + SiteSettings ss, + List columns, + #ModelName#Model #modelName#Model) +{ + new #ModelName#Collection( + context: context, + + + + column: HistoryColumn( + context: context, + ss: ss, + columns: columns), + + + + where: Rds.#TableName#Where().#ModelName#Id(#modelName#Model.#ModelName#Id), + orderBy: Rds.#TableName#OrderBy().Ver(SqlOrderBy.Types.desc), + tableType: Sqls.TableTypes.NormalAndHistory) + .ForEach(#modelName#ModelHistory => hb + .Tr( + attributes: new HtmlAttributes() + .Class("grid-row") + .DataAction("History") + .DataMethod("post") + .DataVer(#modelName#ModelHistory.Ver) + .DataLatest( + value: 1, + _using: #modelName#ModelHistory.Ver == #modelName#Model.Ver), + action: () => + { + + + + hb.Td( + css: "grid-check-td", + action: () => hb + .CheckBox( + controlCss: "grid-check", + _checked: false, + dataId: #modelName#ModelHistory.Ver.ToString(), + _using: #modelName#ModelHistory.Ver < #modelName#Model.Ver)); + columns.ForEach(column => hb + .TdValue( + context: context, + ss: ss, + column: column, + #modelName#Model: #modelName#ModelHistory)); + })); +} + +private static SqlColumnCollection HistoryColumn( + Context context, + SiteSettings ss, + List columns) +{ + var sqlColumn = Rds.#TableName#TitleColumn( + context: context, + ss: ss) + .#ModelName#Id() + .Ver(); + columns.ForEach(column => + sqlColumn.#TableName#Column(columnName: column.ColumnName)); + return sqlColumn; +} + + + \ No newline at end of file diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_Body.txt b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_Body.txt index 36c31f2f7..513c5a703 100644 --- a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_Body.txt +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_Body.txt @@ -105,6 +105,7 @@ namespace Implem.Pleasanter.Libraries.Settings } + diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_GetModels.json b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_GetModels.json index bef645a3d..cab7f6a67 100644 --- a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_GetModels.json +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_GetModels.json @@ -4,5 +4,5 @@ "Indent": "2", "Separator": "\\r\\n", "NotItem": "1", - "Exclude": "Permissions" + "Exclude": "Permissions,Users" } \ No newline at end of file diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_GetModels_Body.txt b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_GetModels_Body.txt index c41e3b2d0..2d168391f 100644 --- a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_GetModels_Body.txt +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_GetModels_Body.txt @@ -7,7 +7,6 @@ ss.Init(context: context); - return ss; } \ No newline at end of file diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_Users.json b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_GetModels_Users.json similarity index 55% rename from Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_Users.json rename to Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_GetModels_Users.json index a2ffeba26..bb3055bbd 100644 --- a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_Users.json +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_GetModels_Users.json @@ -1,6 +1,6 @@ { - "Id": "SiteSettings_Users", - "Indent": "3", + "Id": "SiteSettings_GetModels_Users", + "Indent": "2", "Separator": "\\r\\n", "NotItem": "1", "Include": "Users" diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_GetModels_Users_Body.txt b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_GetModels_Users_Body.txt new file mode 100644 index 000000000..62fdd15d3 --- /dev/null +++ b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_GetModels_Users_Body.txt @@ -0,0 +1,32 @@ +public static SiteSettings UsersSiteSettings(Context context, Sqls.TableTypes tableTypes = Sqls.TableTypes.Normal) +{ + var ss = new SiteSettings() + { + ReferenceType = "Users" + }; + ss.Init(context: context); + ss.SetLinks(context: context); + ss.SetChoiceHash(context: context, withLink: false); + ss.PermissionType = Permissions.Admins(context: context); + ss.TableType = tableTypes; + if (context.ContractSettings.Api == false + || (!DefinitionAccessor.Parameters.User.DisableApi && !context.DisableApi)) + { + var column = ss.GetColumn( + context: context, + columnName: "AllowApi"); + var columnAccessControl = new ColumnAccessControl() + { + No = column.No, + ColumnName = column.ColumnName, + Type = Permissions.Types.ManageService + }; + ss.CreateColumnAccessControls = ss.CreateColumnAccessControls ?? new List(); + ss.ReadColumnAccessControls = ss.ReadColumnAccessControls ?? new List(); + ss.UpdateColumnAccessControls = ss.UpdateColumnAccessControls ?? new List(); + ss.CreateColumnAccessControls.Add(columnAccessControl); + ss.ReadColumnAccessControls.Add(columnAccessControl); + ss.UpdateColumnAccessControls.Add(columnAccessControl); + } + return ss; +} \ No newline at end of file diff --git a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_Users_Body.txt b/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_Users_Body.txt deleted file mode 100644 index d50fdb0e6..000000000 --- a/Implem.Pleasanter/App_Data/Definitions/Definition_Code/SiteSettings_Users_Body.txt +++ /dev/null @@ -1,19 +0,0 @@ -if (context.ContractSettings.Api == false - || (!DefinitionAccessor.Parameters.User.DisableApi && !context.DisableApi)) -{ - var column = ss.GetColumn( - context: context, - columnName: "AllowApi"); - var columnAccessControl = new ColumnAccessControl() - { - No = column.No, - ColumnName = column.ColumnName, - Type = Permissions.Types.ManageService - }; - ss.CreateColumnAccessControls = ss.CreateColumnAccessControls ?? new List(); - ss.ReadColumnAccessControls = ss.ReadColumnAccessControls ?? new List(); - ss.UpdateColumnAccessControls = ss.UpdateColumnAccessControls ?? new List(); - ss.CreateColumnAccessControls.Add(columnAccessControl); - ss.ReadColumnAccessControls.Add(columnAccessControl); - ss.UpdateColumnAccessControls.Add(columnAccessControl); -} \ No newline at end of file diff --git a/Implem.Pleasanter/App_Data/Parameters/NavigationMenus.json b/Implem.Pleasanter/App_Data/Parameters/NavigationMenus.json index dd67c1b67..f24a7ec1f 100644 --- a/Implem.Pleasanter/App_Data/Parameters/NavigationMenus.json +++ b/Implem.Pleasanter/App_Data/Parameters/NavigationMenus.json @@ -146,6 +146,12 @@ "Name": "TrashBox", "Icon": "ui-icon ui-icon-trash", "LinkParams": [ "Items", "{SiteId}", "TrashBox" ] + }, + { + "MenuId": "SettingsMenu_UserTrashBox", + "Name": "TrashBox", + "Icon": "ui-icon ui-icon-trash", + "LinkParams": [ "Users", "TrashBox" ] } ] }, diff --git a/Implem.Pleasanter/App_Data/Parameters/Security.json b/Implem.Pleasanter/App_Data/Parameters/Security.json index 33de4249a..bf5e38e60 100644 --- a/Implem.Pleasanter/App_Data/Parameters/Security.json +++ b/Implem.Pleasanter/App_Data/Parameters/Security.json @@ -91,7 +91,8 @@ "AspNetCoreDataProtection": { "BlobContainerUri": null, "KeyIdentifier": null, - "KeyFileName": "Keys.xml" + "KeyFileName": "Keys.xml", + "XmlAesKey": null }, "HttpStrictTransportSecurity": { "Enabled": false, diff --git a/Implem.Pleasanter/Controllers/Api/DeptsController.cs b/Implem.Pleasanter/Controllers/Api/DeptsController.cs index fe08140f8..e615ce377 100644 --- a/Implem.Pleasanter/Controllers/Api/DeptsController.cs +++ b/Implem.Pleasanter/Controllers/Api/DeptsController.cs @@ -6,6 +6,8 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.IO; +using System.Linq; + namespace Implem.Pleasanter.Controllers.Api { [CheckApiContextAttributes] @@ -107,5 +109,25 @@ public ContentResult Delete(int id) responseSize: result.Content.Length); return result.ToHttpResponse(request: Request); } + + [HttpPost("Import")] + public ContentResult Import(int id) + { + var body = Request.Form["parameters"]; + var contentType = Request.ContentType.Split(';')[0].Trim(); + var context = new Context( + apiRequestBody: body, + files: Request.Form.Files.ToList(), + contentType: contentType, + api: true); + var log = new SysLogModel(context: context); + var result = context.Authenticated + ? DeptUtilities.ImportByApi( + context: context, + ss: SiteSettingsUtilities.ApiDeptsSiteSettings(context)) + : ApiResults.Unauthorized(context: context); + log.Finish(context: context, responseSize: result.Content.Length); + return result.ToHttpResponse(request: Request); + } } } \ No newline at end of file diff --git a/Implem.Pleasanter/Controllers/Api/GroupsController.cs b/Implem.Pleasanter/Controllers/Api/GroupsController.cs index 2d96fdb05..ec53c1c21 100644 --- a/Implem.Pleasanter/Controllers/Api/GroupsController.cs +++ b/Implem.Pleasanter/Controllers/Api/GroupsController.cs @@ -6,6 +6,8 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.IO; +using System.Linq; + namespace Implem.Pleasanter.Controllers.Api { [CheckApiContextAttributes] @@ -109,5 +111,25 @@ public ContentResult Delete(int id) responseSize: result.Content.Length); return result.ToHttpResponse(request: Request); } + + [HttpPost("Import")] + public ContentResult Import(int id) + { + var body = Request.Form["parameters"]; + var contentType = Request.ContentType.Split(';')[0].Trim(); + var context = new Context( + apiRequestBody: body, + files: Request.Form.Files.ToList(), + contentType: contentType, + api: true); + var log = new SysLogModel(context: context); + var result = context.Authenticated + ? GroupUtilities.ImportByApi( + context: context, + ss: SiteSettingsUtilities.ApiGroupsSiteSettings(context)) + : ApiResults.Unauthorized(context: context); + log.Finish(context: context, responseSize: result.Content.Length); + return result.ToHttpResponse(request: Request); + } } } \ No newline at end of file diff --git a/Implem.Pleasanter/Controllers/Api/UsersController.cs b/Implem.Pleasanter/Controllers/Api/UsersController.cs index 571fcefd2..45ef7d997 100644 --- a/Implem.Pleasanter/Controllers/Api/UsersController.cs +++ b/Implem.Pleasanter/Controllers/Api/UsersController.cs @@ -6,6 +6,8 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.IO; +using System.Linq; + namespace Implem.Pleasanter.Controllers.Api { [CheckApiContextAttributes] @@ -101,5 +103,25 @@ public ContentResult Delete(int id) log.Finish(context: context, responseSize: result.Content.Length); return result.ToHttpResponse(Request); } + + [HttpPost("Import")] + public ContentResult Import(int id) + { + var body = Request.Form["parameters"]; + var contentType = Request.ContentType.Split(';')[0].Trim(); + var context = new Context( + apiRequestBody: body, + files: Request.Form.Files.ToList(), + contentType: contentType, + api: true); + var log = new SysLogModel(context: context); + var result = context.Authenticated + ? UserUtilities.ImportByApi( + context: context, + ss: SiteSettingsUtilities.ApiUsersSiteSettings(context)) + : ApiResults.Unauthorized(context: context); + log.Finish(context: context, responseSize: result.Content.Length); + return result.ToHttpResponse(request: Request); + } } } \ No newline at end of file diff --git a/Implem.Pleasanter/Controllers/UsersController.cs b/Implem.Pleasanter/Controllers/UsersController.cs index 3225c5203..7480db7c1 100644 --- a/Implem.Pleasanter/Controllers/UsersController.cs +++ b/Implem.Pleasanter/Controllers/UsersController.cs @@ -655,5 +655,72 @@ public string CloseAnnouncement() log.Finish(context: context, responseSize: json.Length); return json; } + + /// + /// Fixed: + /// + [AcceptVerbs(HttpVerbs.Get, HttpVerbs.Post)] + public ActionResult TrashBox() + { + var context = new Context(); + var log = new SysLogModel(context: context); + if (!context.Ajax) + { + var html = UserUtilities.TrashBox( + context: context, + ss: SiteSettingsUtilities.UsersSiteSettings( + context: context, + tableTypes: Implem.Libraries.DataSources.SqlServer.Sqls.TableTypes.Deleted)); + ViewBag.HtmlBody = html; + log.Finish(context: context, responseSize: html.Length); + return context.RedirectData.Url.IsNullOrEmpty() + ? View() + : Redirect(context.RedirectData.Url); + } + else + { + var json = UserUtilities.TrashBoxJson( + context: context, + ss: SiteSettingsUtilities.UsersSiteSettings( + context: context, + tableTypes: Implem.Libraries.DataSources.SqlServer.Sqls.TableTypes.Deleted)); + log.Finish(context: context, responseSize: json.Length); + return Content(json); + } + } + + /// + /// Fixed: + /// + [HttpPost] + public string Restore(long id) + { + var context = new Context(); + var log = new SysLogModel(context: context); + var json = UserUtilities.Restore( + context: context, + ss: SiteSettingsUtilities.UsersSiteSettings( + context: context, + tableTypes: Implem.Libraries.DataSources.SqlServer.Sqls.TableTypes.Deleted)); + log.Finish(context: context, responseSize: json.Length); + return json; + } + + /// + /// Fixed: + /// + [HttpDelete] + public string PhysicalDelete(long id) + { + var context = new Context(); + var log = new SysLogModel(context: context); + var json = UserUtilities.PhysicalBulkDelete( + context: context, + ss: SiteSettingsUtilities.UsersSiteSettings( + context: context, + tableTypes: Implem.Libraries.DataSources.SqlServer.Sqls.TableTypes.Deleted)); + log.Finish(context: context, responseSize: json.Length); + return json; + } } } diff --git a/Implem.Pleasanter/Implem.Pleasanter.csproj b/Implem.Pleasanter/Implem.Pleasanter.csproj index cbb0c0539..67938aac8 100644 --- a/Implem.Pleasanter/Implem.Pleasanter.csproj +++ b/Implem.Pleasanter/Implem.Pleasanter.csproj @@ -5,9 +5,9 @@ Copyright © Implem Inc 2014 - 2023 Business application platform Implem.Pleasanter - 1.3.47.0 - 1.3.47.0 - 1.3.47.0 + 1.3.48.0 + 1.3.48.0 + 1.3.48.0 disable Linux ..\docker-compose.dcproj @@ -34,10 +34,10 @@ - + - + NU1701 @@ -47,15 +47,15 @@ NU1701 - + - - - + + + NU1701 - + NU1701 @@ -63,11 +63,11 @@ + - diff --git a/Implem.Pleasanter/Libraries/HtmlParts/HtmlBack.cs b/Implem.Pleasanter/Libraries/HtmlParts/HtmlBack.cs index 02fe0cac3..8003d8467 100644 --- a/Implem.Pleasanter/Libraries/HtmlParts/HtmlBack.cs +++ b/Implem.Pleasanter/Libraries/HtmlParts/HtmlBack.cs @@ -66,6 +66,10 @@ private static string BackUrl( return referer != null ? referer : Locations.Top(context: context); + case "trashbox": + return Locations.Get( + context: context, + parts: context.Controller); default: return AdminsOrTop(context: context); } diff --git a/Implem.Pleasanter/Libraries/HtmlParts/HtmlNavigationMenu.cs b/Implem.Pleasanter/Libraries/HtmlParts/HtmlNavigationMenu.cs index 43989c8cc..30c05bbe5 100644 --- a/Implem.Pleasanter/Libraries/HtmlParts/HtmlNavigationMenu.cs +++ b/Implem.Pleasanter/Libraries/HtmlParts/HtmlNavigationMenu.cs @@ -351,6 +351,9 @@ private static bool Using( var canManageTrashBox = CanManageTrashBox( context: context, ss: ss); + var canManageUserTrashBox = CanManageUserTrashBox( + context: context, + ss: ss); var canUseApi = context.UserSettings?.AllowApi(context: context) == true; var canUnlockSite = ss.LockedTable() && ss.LockedTableUser.Id == context.UserId; @@ -388,6 +391,8 @@ private static bool Using( return canManageRegistrations; case "SettingsMenu_TrashBox": return canManageTrashBox; + case "SettingsMenu_UserTrashBox": + return canManageUserTrashBox; case "SettingsMenu_TenantAdmin": return canManageTenants; case "SettingsMenu_ImportSitePackage": @@ -614,6 +619,14 @@ private static bool CanManageTrashBox(Context context, SiteSettings ss) && (context.Id != 0 || context.HasPrivilege); } + private static bool CanManageUserTrashBox(Context context, SiteSettings ss) + { + return (Parameters.Deleted.Restore || Parameters.Deleted.PhysicalDelete) + && context.Controller == "users" + && Permissions.CanManageUser(context: context) + && !ss.Locked(); + } + private static HtmlBuilder ResponsiveMenu(this HtmlBuilder hb, Context context) { return Parameters.Mobile.Responsive diff --git a/Implem.Pleasanter/Libraries/HtmlParts/HtmlTrashBoxCommands.cs b/Implem.Pleasanter/Libraries/HtmlParts/HtmlTrashBoxCommands.cs index 212ce7050..b4c7492a6 100644 --- a/Implem.Pleasanter/Libraries/HtmlParts/HtmlTrashBoxCommands.cs +++ b/Implem.Pleasanter/Libraries/HtmlParts/HtmlTrashBoxCommands.cs @@ -33,8 +33,24 @@ public static HtmlBuilder TrashBoxCommands( confirm: "ConfirmPhysicalDelete", _using: Parameters.Deleted.PhysicalDelete), _using: (Parameters.Deleted.Restore || Parameters.Deleted.PhysicalDelete) - && context.Controller == "items" - && context.CanManageSite(ss: ss)); + && Enabled(context: context, ss: ss)); + } + + private static bool Enabled(Context context, SiteSettings ss) + { + switch (context.Controller) + { + case "items": + return context.CanManageSite(ss: ss); + case "users": + return Permissions.CanManageUser(context: context); + case "groups": + return Permissions.CanEditGroup(context: context); + case "depts": + return Permissions.CanManageTenant(context: context); + default: + return false; + } } } } \ No newline at end of file diff --git a/Implem.Pleasanter/Libraries/Images/ImageData.cs b/Implem.Pleasanter/Libraries/Images/ImageData.cs index aa3107455..940f3310d 100644 --- a/Implem.Pleasanter/Libraries/Images/ImageData.cs +++ b/Implem.Pleasanter/Libraries/Images/ImageData.cs @@ -1,8 +1,10 @@ using Implem.DefinitionAccessor; using Implem.Libraries.Utilities; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; +using Org.BouncyCastle.Utilities.Zlib; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; using System.IO; namespace Implem.Pleasanter.Libraries.Images { @@ -28,7 +30,7 @@ public enum SizeTypes : int public ImageData(byte[] data, long referenceId, Types type) { - Data = Image.FromStream(new MemoryStream(data)); + Data = Image.Load(new MemoryStream(data)); ReferenceId = referenceId; Type = type; } @@ -71,7 +73,7 @@ public void WriteToLocal() private void WriteToLocal(Image image, long referenceId, Types type, SizeTypes sizeType) { - image.Write(Path(referenceId, type, sizeType), ImageFormat.Png); + Files.Write(image, Path(referenceId, type, sizeType), new PngEncoder()); } public void DeleteLocalFiles() @@ -101,7 +103,7 @@ public byte[] ReSizeBytes(SizeTypes sizeType) using (var memory = new MemoryStream()) { memory.Position = 0; - ReSize(sizeType).Save(memory, ImageFormat.Png); + ReSize(sizeType).Save(memory, new PngEncoder()); return GetByte(memory); } } @@ -131,7 +133,7 @@ public byte[] ReSizeBytes(decimal? size) using (var memory = new MemoryStream()) { memory.Position = 0; - ReSize(size).Save(memory, ImageFormat.Png); + ReSize(size).Save(memory, new PngEncoder()); return GetByte(memory); } } @@ -168,14 +170,12 @@ private Image ReSize(decimal? size) private Image GetImage(int width, int height, int x, int y) { - var resizedImage = new Bitmap(width, height); - resizedImage.MakeTransparent(); - using (var graphics = Graphics.FromImage(resizedImage)) + Data.Mutate(x => { - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.DrawImage(Data, x, y, width, height); - return resizedImage; - } + x.Resize(width, height); + }); + + return Data; } private static byte[] GetByte(MemoryStream memory) diff --git a/Implem.Pleasanter/Libraries/Models/Imports.cs b/Implem.Pleasanter/Libraries/Models/Imports.cs index d876f5142..69345501b 100644 --- a/Implem.Pleasanter/Libraries/Models/Imports.cs +++ b/Implem.Pleasanter/Libraries/Models/Imports.cs @@ -29,6 +29,26 @@ public static string ColumnValidate( return null; } + public static string ApiColumnValidate( + Context context, + SiteSettings ss, + IEnumerable headers, + params string[] columnNames) + { + foreach (var name in columnNames) + { + if (!headers.Contains(name)) + { + return Messages.NotRequiredColumn( + context: context, + data: ss.GetColumn( + context: context, + columnName: name).LabelText).Text; + } + } + return null; + } + public static string Validate(Context context, Dictionary hash, Column column) { foreach (var data in hash.Where(o => HasError(o.Value, column))) diff --git a/Implem.Pleasanter/Libraries/Requests/Calendars.cs b/Implem.Pleasanter/Libraries/Requests/Calendars.cs index cd743a05c..7becffa5c 100644 --- a/Implem.Pleasanter/Libraries/Requests/Calendars.cs +++ b/Implem.Pleasanter/Libraries/Requests/Calendars.cs @@ -4,7 +4,7 @@ using Implem.Pleasanter.Libraries.Server; using Implem.Pleasanter.Libraries.Settings; using System; -using System.Drawing; +using SixLabors.ImageSharp; namespace Implem.Pleasanter.Libraries.Requests { diff --git a/Implem.Pleasanter/Libraries/Requests/ImportApi.cs b/Implem.Pleasanter/Libraries/Requests/ImportApi.cs index 3e22594cf..08d8051f2 100644 --- a/Implem.Pleasanter/Libraries/Requests/ImportApi.cs +++ b/Implem.Pleasanter/Libraries/Requests/ImportApi.cs @@ -5,6 +5,7 @@ namespace Implem.Pleasanter.Libraries.Requests [Serializable] public class ImportApi : Api { + public bool ReplaceAllGroupMembers { get; set; } public bool UpdatableImport { get; set; } public string Encoding { get; set; } public string Key {get; set;} diff --git a/Implem.Pleasanter/Libraries/Requests/Views.cs b/Implem.Pleasanter/Libraries/Requests/Views.cs index 9b55f7dad..629b28eab 100644 --- a/Implem.Pleasanter/Libraries/Requests/Views.cs +++ b/Implem.Pleasanter/Libraries/Requests/Views.cs @@ -82,6 +82,7 @@ public static View GetBySession(Context context, SiteSettings ss, bool setSessio view.ColumnFilterHash = prevView.ColumnFilterHash; view.ColumnFilterSearchTypes = prevView.ColumnFilterSearchTypes; view.Search = prevView.Search; + view.ColumnFilterNegatives = prevView.ColumnFilterNegatives; } if (view.KeepSorterState == true) { diff --git a/Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagemenXmltUtils.cs b/Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagemenXmltUtils.cs new file mode 100644 index 000000000..378767417 --- /dev/null +++ b/Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagemenXmltUtils.cs @@ -0,0 +1,20 @@ +using Implem.DefinitionAccessor; +using System.Linq; +using System.Security.Cryptography; +using System.Text; + +namespace Implem.Pleasanter.Libraries.Security +{ + public class AspNetCoreKeyManagemenXmltUtils + { + public static string AesKey + => Parameters.Security.AspNetCoreDataProtection.XmlAesKey + GetHashStr(Parameters.Security.AspNetCoreDataProtection.XmlAesKey); + + public static string AesIv => "pleasanterimplem"; + + private static string GetHashStr(string value) + { + return string.Join("", MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(value)).Select(x => $"{x:x2}")); + } + } +} diff --git a/Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagementXmlDecryptor.cs b/Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagementXmlDecryptor.cs new file mode 100644 index 000000000..abcf08dfe --- /dev/null +++ b/Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagementXmlDecryptor.cs @@ -0,0 +1,19 @@ +using Implem.Libraries.Utilities; +using Microsoft.AspNetCore.DataProtection.XmlEncryption; +using Newtonsoft.Json; +using System.Xml.Linq; + +namespace Implem.Pleasanter.Libraries.Security +{ + public class AspNetCoreKeyManagementXmlDecryptor : IXmlDecryptor + { + public XElement Decrypt(XElement encryptedElement) + { + var jsonXmlStr = CryptographyAes.AesDecrypt( + (string)encryptedElement.Element("value"), + AspNetCoreKeyManagemenXmltUtils.AesKey, + AspNetCoreKeyManagemenXmltUtils.AesIv); + return JsonConvert.DeserializeObject(jsonXmlStr); + } + } +} diff --git a/Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagementXmlEncryptor.cs b/Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagementXmlEncryptor.cs new file mode 100644 index 000000000..70e45b86a --- /dev/null +++ b/Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagementXmlEncryptor.cs @@ -0,0 +1,22 @@ +using Implem.Libraries.Utilities; +using Microsoft.AspNetCore.DataProtection.XmlEncryption; +using Newtonsoft.Json; +using System.Xml.Linq; + +namespace Implem.Pleasanter.Libraries.Security +{ + public class AspNetCoreKeyManagementXmlEncryptor : IXmlEncryptor + { + public EncryptedXmlInfo Encrypt(XElement plaintextElement) + { + var encryptedData = CryptographyAes.AesEncrypt( + JsonConvert.SerializeObject(plaintextElement), + AspNetCoreKeyManagemenXmltUtils.AesKey, + AspNetCoreKeyManagemenXmltUtils.AesIv); + var newElement = new XElement("encryptedKey", + new XComment(" This key is encrypted with AES."), + new XElement("value", encryptedData)); + return new EncryptedXmlInfo(newElement, typeof(AspNetCoreKeyManagementXmlDecryptor)); + } + } +} diff --git a/Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagementXmlRepository.cs b/Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagementXmlRepository.cs new file mode 100644 index 000000000..27ce1fe77 --- /dev/null +++ b/Implem.Pleasanter/Libraries/Security/AspNetCoreKeyManagementXmlRepository.cs @@ -0,0 +1,81 @@ +using Implem.Libraries.Utilities; +using Implem.Pleasanter.Libraries.Requests; +using Implem.Pleasanter.Models; +using Microsoft.AspNetCore.DataProtection.Repositories; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; + +namespace Implem.Pleasanter.Libraries.Security +{ + public class AspNetCoreKeyManagementXmlRepository : IXmlRepository + { + private const string SessionGuid = "@AspNetCoreDataProtectionKeys"; + + public IReadOnlyCollection GetAllElements() + { + var context = GetContext(); + new SysLogModel( + context: context, + method: nameof(AspNetCoreKeyManagementXmlRepository) + "_" + nameof(GetAllElements), + message: new { cmd = "AspNetCoreKeyManagementXmlRepository.GetAllElements()" }.ToJson(), + sysLogType: SysLogModel.SysLogTypes.Info); + return GetKeyList(context) + .Select(v => XElement.Parse(v.Value)) + .ToList(); + } + + private static IDictionary GetKeyList(Context context) + { + return SessionUtilities.Get( + context: context, + sessionGuid: SessionGuid); + } + + public void StoreElement(XElement element, string friendlyName) + { + var context = GetContext(); + new SysLogModel( + context: context, + method: nameof(AspNetCoreKeyManagementXmlRepository) + "_" + nameof(StoreElement), + message: new { cmd = $"AspNetCoreKeyManagementXmlRepository.StoreElement(); friendlyName={friendlyName}" }.ToJson(), + sysLogType: SysLogModel.SysLogTypes.Info); + DeleteOldSessions(context); + SessionUtilities.Set( + context: context, + key: friendlyName, + value: element.ToString(SaveOptions.DisableFormatting), + sessionGuid: SessionGuid); + } + + private void DeleteOldSessions(Context context) + { + var list = GetKeyList(context) + .Where(v => (XElement.Parse(v.Value).Element("expirationDate")?.Value?.ToDateTime().AddDays(90) ?? DateTime.Now) < DateTime.Now) + .Select(v => v.Key) + .ToList(); + foreach (var item in list) + { + SessionUtilities.Remove( + context: context, + key: item, + page: false, + sessionGuid: SessionGuid); + } + } + + private Context GetContext() + { + return new Context( + request: false, + sessionData: false, + sessionStatus: false, + user: false, + setPermissions: false) + { + Controller = "AspNetCoreKeyManagementXmlRepository.cs" + }; + } + } +} \ No newline at end of file diff --git a/Implem.Pleasanter/Libraries/Security/Permission.cs b/Implem.Pleasanter/Libraries/Security/Permission.cs index 2585c4ed5..7d586dffb 100644 --- a/Implem.Pleasanter/Libraries/Security/Permission.cs +++ b/Implem.Pleasanter/Libraries/Security/Permission.cs @@ -76,7 +76,7 @@ public bool Exists(Context context) case "Dept": return SiteInfo.Dept( tenantId: context.TenantId, - deptId: Id) != null; + deptId: Id).Id == Id; case "Group": return new GroupModel( context: context, diff --git a/Implem.Pleasanter/Libraries/Settings/SiteSettings.cs b/Implem.Pleasanter/Libraries/Settings/SiteSettings.cs index 0e951e632..54bae7c3a 100644 --- a/Implem.Pleasanter/Libraries/Settings/SiteSettings.cs +++ b/Implem.Pleasanter/Libraries/Settings/SiteSettings.cs @@ -2500,7 +2500,11 @@ public List GetLinkColumns(Context context, bool checkPermission = false public List GetHistoryColumns(Context context, bool checkPermission = false) { return HistoryColumns - .Select(columnName => GetColumn(context: context, columnName: columnName)) + .Concat(IncludedColumns()) + .Distinct() + .Select(columnName => GetColumn( + context: context, + columnName: columnName)) .Where(column => column != null) .AllowedColumns( context: context, diff --git a/Implem.Pleasanter/Libraries/Settings/SiteSettingsUtilities.cs b/Implem.Pleasanter/Libraries/Settings/SiteSettingsUtilities.cs index c903dba70..1847dad1c 100644 --- a/Implem.Pleasanter/Libraries/Settings/SiteSettingsUtilities.cs +++ b/Implem.Pleasanter/Libraries/Settings/SiteSettingsUtilities.cs @@ -370,7 +370,7 @@ public static SiteSettings TenantsSiteSettings(Context context) return ss; } - public static SiteSettings UsersSiteSettings(Context context) + public static SiteSettings UsersSiteSettings(Context context, Sqls.TableTypes tableTypes = Sqls.TableTypes.Normal) { var ss = new SiteSettings() { @@ -380,6 +380,7 @@ public static SiteSettings UsersSiteSettings(Context context) ss.SetLinks(context: context); ss.SetChoiceHash(context: context, withLink: false); ss.PermissionType = Permissions.Admins(context: context); + ss.TableType = tableTypes; if (context.ContractSettings.Api == false || (!DefinitionAccessor.Parameters.User.DisableApi && !context.DisableApi)) { diff --git a/Implem.Pleasanter/Models/Binaries/BinaryUtilities.cs b/Implem.Pleasanter/Models/Binaries/BinaryUtilities.cs index 6fdb104ad..dcd11c6fa 100644 --- a/Implem.Pleasanter/Models/Binaries/BinaryUtilities.cs +++ b/Implem.Pleasanter/Models/Binaries/BinaryUtilities.cs @@ -630,6 +630,10 @@ public static ResponseFile DownloadTemp(Context context, string guid) { return null; } + if (!BinaryUtilities.ValidateDownloadTemp(context: context, guid: guid)) + { + return null; + } return FileContentResults.DownloadTemp(guid.ToUpper()); } @@ -642,10 +646,51 @@ public static string DeleteTemp(Context context) { return null; } - Libraries.DataSources.File.DeleteTemp(context.Forms.Data("Guid")); + var guid = context.Forms.Data("Guid"); + RemoveTempFileSession(context: context, guid: guid); + Libraries.DataSources.File.DeleteTemp(guid); return "[]"; } + /// + /// Fixed: + /// + private static string GetTempFileSessionKey(string guid) + { + return $"TempFile_{guid.ToUpper()}"; + } + + /// + /// Fixed: + /// + private static bool ValidateDownloadTemp(Context context, string guid) + { + return SessionUtilities.Get(context: context) + .Any(kv => kv.Key == GetTempFileSessionKey(guid)); + } + + /// + /// Fixed: + /// + private static void SaveTempFileSession(Context context, string guid) + { + SessionUtilities.Set( + context: context, + key: GetTempFileSessionKey(guid), + value: string.Empty); + } + + /// + /// Fixed: + /// + private static void RemoveTempFileSession(Context context, string guid) + { + SessionUtilities.Remove( + context: context, + key: GetTempFileSessionKey(guid), + page: false); + } + /// /// Fixed: /// @@ -794,6 +839,7 @@ public static string UploadFile( new KeyValuePair( file, saveFile)); + SaveTempFileSession(context: context, guid: fileUuid[filesIndex]); } { var invalid = ValidateFileHash(resultFileNames[0].Value, contentRange, fileHash); diff --git a/Implem.Pleasanter/Models/Binaries/BinaryValidators.cs b/Implem.Pleasanter/Models/Binaries/BinaryValidators.cs index 7eb01e99f..d80498f78 100644 --- a/Implem.Pleasanter/Models/Binaries/BinaryValidators.cs +++ b/Implem.Pleasanter/Models/Binaries/BinaryValidators.cs @@ -50,7 +50,7 @@ public static Error.Types OnUploadingSiteImage( } try { - System.Drawing.Image.FromStream(new System.IO.MemoryStream(bin)); + SixLabors.ImageSharp.Image.Load(new System.IO.MemoryStream(bin)); } catch (System.Exception) { @@ -76,7 +76,7 @@ public static Error.Types OnUploadingTenantImage( } try { - System.Drawing.Image.FromStream(new System.IO.MemoryStream(bin)); + SixLabors.ImageSharp.Image.Load(new System.IO.MemoryStream(bin)); } catch (System.Exception) { diff --git a/Implem.Pleasanter/Models/Depts/DeptUtilities.cs b/Implem.Pleasanter/Models/Depts/DeptUtilities.cs index 2f1fd6f8a..bfd3f2e4e 100644 --- a/Implem.Pleasanter/Models/Depts/DeptUtilities.cs +++ b/Implem.Pleasanter/Models/Depts/DeptUtilities.cs @@ -1917,65 +1917,170 @@ public static string Import(Context context) "DeptName" }); if (invalidColumn != null) return invalidColumn; - var deptHash = new Dictionary(); - csv.Rows.Select((o, i) => new { Row = o, Index = i }).ForEach(data => + var deptHash = CreateDeptHash( + context: context, + ss: ss, + csv: csv, + columnHash: columnHash, + idColumn: idColumn); + var insertCount = 0; + var updateCount = 0; + foreach (var deptModel in deptHash.Values) { - var deptModel = new DeptModel(); - if (idColumn > -1) + if (deptModel.AccessStatus == Databases.AccessStatuses.Selected) { - var model = new DeptModel( - context: context, - ss: ss, - deptCode: data.Row[idColumn]); - if (model.AccessStatus == Databases.AccessStatuses.Selected) + if (deptModel.Updated(context: context)) { - deptModel = model; + deptModel.VerUp = Versions.MustVerUp( + context: context, + ss: ss, + baseModel: deptModel); + var errorData = deptModel.Update( + context: context, + ss: ss, + refleshSiteInfo: false, + get: false); + switch (errorData.Type) + { + case Error.Types.None: + break; + default: + return errorData.MessageJson(context: context); + } + updateCount++; } } - columnHash.ForEach(column => + else { - var recordingData = ImportRecordingData( + var errorData = deptModel.Create( context: context, - column: column.Value.Column, - value: data.Row[column.Key], - inheritPermission: ss.InheritPermission); - switch (column.Value.Column.ColumnName) + ss: ss, + get: false); + switch (errorData.Type) { - case "DeptId": - deptModel.DeptId = recordingData.ToInt(); - break; - case "DeptCode": - deptModel.DeptCode = recordingData; - break; - case "DeptName": - deptModel.DeptName = recordingData; - break; - case "Body": - deptModel.Body = recordingData; - break; - case "Comments": - if (deptModel.AccessStatus != Databases.AccessStatuses.Selected && - !data.Row[column.Key].IsNullOrEmpty()) - { - deptModel.Comments.Prepend( - context: context, - ss: ss, - body: data.Row[column.Key]); - } - break; - case "Disabled": - deptModel.Disabled = recordingData.ToBool(); + case Error.Types.None: break; default: - deptModel.SetValue( - context: context, - column: column.Value.Column, - value: recordingData); - break; + return errorData.MessageJson(context: context); } + insertCount++; + } + } + SiteInfo.Reflesh( + context: context, + force: true); + return GridRows( + context: context, + ss: ss, + windowScrollTop: true, + message: Messages.Imported( + context: context, + data: new string[] + { + ss.Title, + insertCount.ToString(), + updateCount.ToString() + })); + } + else + { + return Messages.ResponseFileNotFound(context: context).ToJson(); + } + } + + /// + /// Fixed: + /// + public static ContentResultInheritance ImportByApi(Context context, SiteSettings ss) + { + if (!Mime.ValidateOnApi(contentType: context.ContentType, multipart: true)) + { + return ApiResults.BadRequest(context: context); + } + if (context.ContractSettings.Import == false) + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Messages.Restricted(context: context).Text)); + } + var invalid = UserValidators.OnImporting( + context: context, + ss: ss, + api: true); + switch (invalid.Type) + { + case Error.Types.None: + break; + default: + return ApiResults.Error( + context: context, + errorData: invalid); + } + var api = context.RequestDataString.Deserialize(); + var encoding = api.Encoding; + Csv csv; + try + { + csv = new Csv( + csv: context.PostedFiles.FirstOrDefault().Byte(), + encoding: encoding); + } + catch + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Messages.FailedReadFile(context: context).Text)); + } + var count = csv.Rows.Count(); + if (Parameters.General.ImportMax > 0 && Parameters.General.ImportMax < count) + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Error.Types.ImportMax.Message( + context: context, + data: Parameters.General.ImportMax.ToString()).Text)); + } + if (context.ContractSettings.ItemsLimit(context: context, siteId: ss.SiteId, number: count)) + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Error.Types.ItemsLimit.Message(context: context).Text)); + } + if (csv != null && count > 0) + { + var columnHash = ImportUtilities.GetColumnHash(ss, csv); + var idColumn = columnHash + .Where(o => + o.Value.Column.ColumnName == "DeptCode") + .Select(o => + new { Id = o.Key }) + .FirstOrDefault()?.Id ?? -1; + var invalidColumn = Imports.ApiColumnValidate( + context, + ss, + columnHash.Values.Select(o => o.Column.ColumnName), + columnNames: new string[] + { + "DeptCode", + "DeptName" }); - deptHash.Add(data.Index, deptModel); - }); + if (invalidColumn != null) + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: invalidColumn)); + } + var deptHash = CreateDeptHash( + context: context, + ss: ss, + csv: csv, + columnHash: columnHash, + idColumn: idColumn); var insertCount = 0; var updateCount = 0; foreach (var deptModel in deptHash.Values) @@ -1998,7 +2103,9 @@ public static string Import(Context context) case Error.Types.None: break; default: - return errorData.MessageJson(context: context); + return ApiResults.Error( + context: context, + errorData: errorData); } updateCount++; } @@ -2014,7 +2121,9 @@ public static string Import(Context context) case Error.Types.None: break; default: - return errorData.MessageJson(context: context); + return ApiResults.Error( + context: context, + errorData: errorData); } insertCount++; } @@ -2022,10 +2131,10 @@ public static string Import(Context context) SiteInfo.Reflesh( context: context, force: true); - return GridRows( - context: context, - ss: ss, - windowScrollTop: true, + return ApiResults.Success( + id: context.Id, + limitPerDate: context.ContractSettings.ApiLimit(), + limitRemaining: context.ContractSettings.ApiLimit() - ss.ApiCount, message: Messages.Imported( context: context, data: new string[] @@ -2033,11 +2142,14 @@ public static string Import(Context context) ss.Title, insertCount.ToString(), updateCount.ToString() - })); + }).Text); } else { - return Messages.ResponseFileNotFound(context: context).ToJson(); + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Messages.FileNotFound(context: context).Text)); } } @@ -2054,6 +2166,78 @@ private static string ImportRecordingData( return recordingData; } + /// + /// Fixed: + /// + public static Dictionary CreateDeptHash( + Context context, + SiteSettings ss, + Csv csv, + Dictionary columnHash, + int idColumn) + { + var deptHash = new Dictionary(); + csv.Rows.Select((o, i) => new { Row = o, Index = i }).ForEach(data => + { + var deptModel = new DeptModel(); + if (idColumn > -1) + { + var model = new DeptModel( + context: context, + ss: ss, + deptCode: data.Row[idColumn]); + if (model.AccessStatus == Databases.AccessStatuses.Selected) + { + deptModel = model; + } + } + columnHash.ForEach(column => + { + var recordingData = ImportRecordingData( + context: context, + column: column.Value.Column, + value: data.Row[column.Key], + inheritPermission: ss.InheritPermission); + switch (column.Value.Column.ColumnName) + { + case "DeptId": + deptModel.DeptId = recordingData.ToInt(); + break; + case "DeptCode": + deptModel.DeptCode = recordingData; + break; + case "DeptName": + deptModel.DeptName = recordingData; + break; + case "Body": + deptModel.Body = recordingData; + break; + case "Comments": + if (deptModel.AccessStatus != Databases.AccessStatuses.Selected && + !data.Row[column.Key].IsNullOrEmpty()) + { + deptModel.Comments.Prepend( + context: context, + ss: ss, + body: data.Row[column.Key]); + } + break; + case "Disabled": + deptModel.Disabled = recordingData.ToBool(); + break; + default: + deptModel.SetValue( + context: context, + column: column.Value.Column, + value: recordingData); + break; + } + }); + deptHash.Add(data.Index, deptModel); + }); + return deptHash; + } + /// /// Fixed: /// diff --git a/Implem.Pleasanter/Models/Groups/GroupUtilities.cs b/Implem.Pleasanter/Models/Groups/GroupUtilities.cs index 55498602f..518cba2b1 100644 --- a/Implem.Pleasanter/Models/Groups/GroupUtilities.cs +++ b/Implem.Pleasanter/Models/Groups/GroupUtilities.cs @@ -2092,6 +2092,292 @@ public static string Import(Context context) } } + /// + /// Fixed: + /// + public static ContentResultInheritance ImportByApi(Context context, SiteSettings ss) + { + if (!Mime.ValidateOnApi(contentType: context.ContentType, multipart: true)) + { + return ApiResults.BadRequest(context: context); + } + if (context.ContractSettings.Import == false) + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Messages.Restricted(context: context).Text)); + } + var invalid = UserValidators.OnImporting( + context: context, + ss: ss, + api: true); + switch (invalid.Type) + { + case Error.Types.None: + break; + default: + return ApiResults.Error( + context: context, + errorData: invalid); + } + var api = context.RequestDataString.Deserialize(); + var encoding = api.Encoding; + var replaceAllGroupMembers = api.ReplaceAllGroupMembers; + Csv csv; + try + { + csv = new Csv( + csv: context.PostedFiles.FirstOrDefault().Byte(), + encoding: encoding); + } + catch + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Messages.FailedReadFile(context: context).Text)); + } + var count = csv.Rows.Count(); + if (Parameters.General.ImportMax > 0 && Parameters.General.ImportMax < count) + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Error.Types.ImportMax.Message( + context: context, + data: Parameters.General.ImportMax.ToString()).Text)); + } + if (context.ContractSettings.ItemsLimit(context: context, siteId: ss.SiteId, number: count)) + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Error.Types.ItemsLimit.Message(context: context).Text)); + } + if (csv != null && count > 0) + { + var columnHash = ImportUtilities.GetColumnHash(ss, csv); + var idColumn = columnHash + .Where(o => + o.Value.Column.ColumnName == "GroupId") + .Select(o => + new { Id = o.Key }) + .FirstOrDefault()?.Id ?? -1; + var invalidColumn = Imports.ApiColumnValidate( + context, + ss, + columnHash.Values.Select(o => o.Column.ColumnName), + columnNames: "GroupName"); + if (invalidColumn != null) + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: invalidColumn)); + } + var groups = new List(); + foreach (var data in csv.Rows.Select((o, i) => + new { Row = o, Index = i })) + { + var groupModel = new GroupModel( + context: context, + ss: ss); + if (idColumn > -1) + { + var model = new GroupModel( + context: context, + ss: ss, + groupId: data.Row[idColumn].ToInt()); + if (model.AccessStatus == Databases.AccessStatuses.Selected) + { + groupModel = model; + } + } + foreach (var column in columnHash) + { + var recordingData = ImportRecordingData( + context: context, + column: column.Value.Column, + value: data.Row[column.Key], + inheritPermission: ss.InheritPermission); + switch (column.Value.Column.ColumnName) + { + case "GroupId": + groupModel.GroupId = recordingData.ToInt(); + break; + case "GroupName": + groupModel.GroupName = recordingData; + break; + case "Body": + groupModel.Body = recordingData; + break; + case "Comments": + if (groupModel.AccessStatus != Databases.AccessStatuses.Selected && + !data.Row[column.Key].IsNullOrEmpty()) + { + groupModel.Comments.Prepend( + context: context, + ss: ss, + body: data.Row[column.Key]); + } + break; + case "Disabled": + groupModel.Disabled = recordingData.ToBool(); + break; + case "MemberType": + groupModel.MemberType = recordingData.ToString(); + break; + case "MemberKey": + groupModel.MemberKey = recordingData.ToString(); + break; + case "MemberName": + groupModel.MemberName = recordingData.ToString(); + break; + case "MemberIsAdmin": + groupModel.MemberIsAdmin = recordingData.ToBool(); + break; + default: + groupModel.SetValue( + context: context, + column: column.Value.Column, + value: recordingData); + break; + } + } + var csvRowForError = data.Index + 2; + if (!ValidateMemberType(memberType: groupModel.MemberType)) + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: ApiInvalidMemberTypeError( + context: context, + errorCsvRow: csvRowForError))); + } + if (!ValidateMemberKey( + context: context, + memberType: groupModel.MemberType, + memberKey: groupModel.MemberKey)) + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: ApiInvalidMemberKeyError( + context: context, + errorCsvRow: csvRowForError))); + } + groups.Add(groupModel); + }; + if (replaceAllGroupMembers == true) + { + groups + .Select(o => o.GroupId) + .Distinct() + .ForEach(groupId => + PhysicalDeleteGroupMembers( + context: context, + groupId: groupId)); + } + var insertGroupCount = 0; + var updateGroupCount = 0; + var insertGroupMemberCount = 0; + var updateGroupMemberCount = 0; + var newGroups = new Dictionary(); + foreach (var groupModel in groups) + { + if (groupModel.AccessStatus == Databases.AccessStatuses.Selected) + { + var errorData = UpdateGroup( + context: context, + ss: ss, + groupModel: groupModel, + updateGroupCount: ref updateGroupCount); + switch (errorData.Type) + { + case Error.Types.None: + break; + default: + return ApiResults.Error( + context: context, + errorData: errorData); + } + } + else + { + if (!newGroups.ContainsKey(groupModel.GroupName)) + { + var errorData = groupModel.Create( + context: context, + ss: ss, + get: false); + switch (errorData.Type) + { + case Error.Types.None: + break; + default: + return ApiResults.Error( + context: context, + errorData: errorData); + } + insertGroupCount++; + newGroups.Add(groupModel.GroupName, groupModel); + } + else + { + groupModel.GroupId = newGroups[groupModel.GroupName].GroupId; + var errorData = UpdateGroup( + context: context, + ss: ss, + groupModel: groupModel, + updateGroupCount: ref updateGroupCount); + switch (errorData.Type) + { + case Error.Types.None: + break; + default: + return ApiResults.Error( + context: context, + errorData: errorData); + } + } + } + if (!groupModel.MemberType.IsNullOrEmpty()) + { + UpdateOrInsertGroupMember( + context: context, + groupModel: groupModel, + insertGroupMemberCount: ref insertGroupMemberCount, + updateGroupMemberCount: ref updateGroupMemberCount); + } + } + SiteInfo.Reflesh( + context: context, + force: true); + return ApiResults.Success( + id: context.Id, + limitPerDate: context.ContractSettings.ApiLimit(), + limitRemaining: context.ContractSettings.ApiLimit() - ss.ApiCount, + message: Messages.Imported( + context: context, + data: new string[] + { + ss.Title, + insertGroupCount.ToString(), + updateGroupCount.ToString(), + insertGroupMemberCount.ToString(), + updateGroupMemberCount.ToString() + }).Text); + } + else + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Messages.FileNotFound(context: context).Text)); + } + } + /// /// Fixed: /// @@ -2140,6 +2426,16 @@ private static string InvalidMemberTypeError(Context context, int errorCsvRow) data: errorCsvRow.ToString()); } + /// + /// Fixed: + /// + private static string ApiInvalidMemberTypeError(Context context, int errorCsvRow) + { + return Error.Types.InvalidMemberType.Message( + context: context, + data: errorCsvRow.ToString()).Text; + } + /// /// Fixed: /// @@ -2150,6 +2446,16 @@ private static string InvalidMemberKeyError(Context context, int errorCsvRow) data: errorCsvRow.ToString()); } + /// + /// Fixed: + /// + private static string ApiInvalidMemberKeyError(Context context, int errorCsvRow) + { + return Error.Types.InvalidMemberKey.Message( + context: context, + data: errorCsvRow.ToString()).Text; + } + /// /// Fixed: /// diff --git a/Implem.Pleasanter/Models/Issues/IssueUtilities.cs b/Implem.Pleasanter/Models/Issues/IssueUtilities.cs index 0bbefff4a..100fa58be 100644 --- a/Implem.Pleasanter/Models/Issues/IssueUtilities.cs +++ b/Implem.Pleasanter/Models/Issues/IssueUtilities.cs @@ -2335,22 +2335,27 @@ private static ResponseCollection EditorResponse( issueModel.MethodType = issueModel.IssueId == 0 ? BaseModel.MethodTypes.New : BaseModel.MethodTypes.Edit; - var editInDialog = context.Forms.Bool("EditInDialog"); - return context.QueryStrings.Bool("control-auto-postback") - ? EditorFields( + if (context.QueryStrings.Bool("control-auto-postback")) + { + return EditorFields( context: context, ss: ss, - issueModel: issueModel) - : editInDialog + issueModel: issueModel); + } + else + { + var editInDialog = context.Forms.Bool("EditInDialog"); + var html = Editor( + context: context, + ss: ss, + issueModel: issueModel, + editInDialog: editInDialog); + return editInDialog ? new IssuesResponseCollection( context: context, issueModel: issueModel) .Response("id", issueModel.IssueId.ToString()) - .Html("#EditInDialogBody", Editor( - context: context, - ss: ss, - issueModel: issueModel, - editInDialog: editInDialog)) + .Html("#EditInDialogBody", html) .Invoke("openEditorDialog") .Messages(context.Messages) .Events("on_editor_load") @@ -2359,7 +2364,7 @@ private static ResponseCollection EditorResponse( issueModel: issueModel) .Response("id", issueModel.IssueId.ToString()) .Invoke("clearDialogs") - .ReplaceAll("#MainContainer", Editor(context, ss, issueModel)) + .ReplaceAll("#MainContainer", html) .Val("#Id", issueModel.IssueId.ToString()) .Val("#SwitchTargets", switchTargets, _using: switchTargets != null) .SetMemory("formChanged", false) @@ -2374,6 +2379,7 @@ private static ResponseCollection EditorResponse( .Messages(context.Messages) .ClearFormData() .Events("on_editor_load"); + } } private static ResponseCollection EditorFields( @@ -3121,6 +3127,10 @@ public static string Create(Context context, SiteSettings ss) case Error.Types.None: break; default: return invalid.MessageJson(context: context); } + if (copyFrom > 0) + { + issueModel.Comments.Clear(); + } var processes = ss.Processes ?.Where(process => process.IsTarget(context: context)) .ToList() ?? new List(); @@ -5353,7 +5363,10 @@ private static void HistoriesTableBody( new IssueCollection( context: context, ss: ss, - column: HistoryColumn(columns), + column: HistoryColumn( + context: context, + ss: ss, + columns: columns), join: ss.Join(context: context), where: Rds.IssuesWhere().IssueId(issueModel.IssueId), orderBy: Rds.IssuesOrderBy().Ver(SqlOrderBy.Types.desc), @@ -5390,14 +5403,19 @@ private static void HistoriesTableBody( })); } - private static SqlColumnCollection HistoryColumn(List columns) + private static SqlColumnCollection HistoryColumn( + Context context, + SiteSettings ss, + List columns) { - var sqlColumn = new Rds.IssuesColumnCollection() - .IssueId() - .Ver(); + var sqlColumn = Rds.IssuesTitleColumn( + context: context, + ss: ss) + .IssueId() + .Ver(); columns.ForEach(column => sqlColumn.IssuesColumn(columnName: column.ColumnName)); - return sqlColumn.ItemTitle(tableName: "Issues"); + return sqlColumn; } public static string History(Context context, SiteSettings ss, long issueId) diff --git a/Implem.Pleasanter/Models/Results/ResultUtilities.cs b/Implem.Pleasanter/Models/Results/ResultUtilities.cs index 8b7757d80..051444eb7 100644 --- a/Implem.Pleasanter/Models/Results/ResultUtilities.cs +++ b/Implem.Pleasanter/Models/Results/ResultUtilities.cs @@ -2178,22 +2178,27 @@ private static ResponseCollection EditorResponse( resultModel.MethodType = resultModel.ResultId == 0 ? BaseModel.MethodTypes.New : BaseModel.MethodTypes.Edit; - var editInDialog = context.Forms.Bool("EditInDialog"); - return context.QueryStrings.Bool("control-auto-postback") - ? EditorFields( + if (context.QueryStrings.Bool("control-auto-postback")) + { + return EditorFields( context: context, ss: ss, - resultModel: resultModel) - : editInDialog + resultModel: resultModel); + } + else + { + var editInDialog = context.Forms.Bool("EditInDialog"); + var html = Editor( + context: context, + ss: ss, + resultModel: resultModel, + editInDialog: editInDialog); + return editInDialog ? new ResultsResponseCollection( context: context, resultModel: resultModel) .Response("id", resultModel.ResultId.ToString()) - .Html("#EditInDialogBody", Editor( - context: context, - ss: ss, - resultModel: resultModel, - editInDialog: editInDialog)) + .Html("#EditInDialogBody", html) .Invoke("openEditorDialog") .Messages(context.Messages) .Events("on_editor_load") @@ -2202,7 +2207,7 @@ private static ResponseCollection EditorResponse( resultModel: resultModel) .Response("id", resultModel.ResultId.ToString()) .Invoke("clearDialogs") - .ReplaceAll("#MainContainer", Editor(context, ss, resultModel)) + .ReplaceAll("#MainContainer", html) .Val("#Id", resultModel.ResultId.ToString()) .Val("#SwitchTargets", switchTargets, _using: switchTargets != null) .SetMemory("formChanged", false) @@ -2217,6 +2222,7 @@ private static ResponseCollection EditorResponse( .Messages(context.Messages) .ClearFormData() .Events("on_editor_load"); + } } private static ResponseCollection EditorFields( @@ -2940,6 +2946,10 @@ public static string Create(Context context, SiteSettings ss) case Error.Types.None: break; default: return invalid.MessageJson(context: context); } + if (copyFrom > 0) + { + resultModel.Comments.Clear(); + } var processes = ss.Processes ?.Where(process => process.IsTarget(context: context)) .ToList() ?? new List(); @@ -5165,7 +5175,10 @@ private static void HistoriesTableBody( new ResultCollection( context: context, ss: ss, - column: HistoryColumn(columns), + column: HistoryColumn( + context: context, + ss: ss, + columns: columns), join: ss.Join(context: context), where: Rds.ResultsWhere().ResultId(resultModel.ResultId), orderBy: Rds.ResultsOrderBy().Ver(SqlOrderBy.Types.desc), @@ -5202,14 +5215,19 @@ private static void HistoriesTableBody( })); } - private static SqlColumnCollection HistoryColumn(List columns) + private static SqlColumnCollection HistoryColumn( + Context context, + SiteSettings ss, + List columns) { - var sqlColumn = new Rds.ResultsColumnCollection() - .ResultId() - .Ver(); + var sqlColumn = Rds.ResultsTitleColumn( + context: context, + ss: ss) + .ResultId() + .Ver(); columns.ForEach(column => sqlColumn.ResultsColumn(columnName: column.ColumnName)); - return sqlColumn.ItemTitle(tableName: "Results"); + return sqlColumn; } public static string History(Context context, SiteSettings ss, long resultId) diff --git a/Implem.Pleasanter/Models/Users/UserModel.cs b/Implem.Pleasanter/Models/Users/UserModel.cs index 784314988..b671f75e9 100644 --- a/Implem.Pleasanter/Models/Users/UserModel.cs +++ b/Implem.Pleasanter/Models/Users/UserModel.cs @@ -2889,6 +2889,12 @@ public ErrorData Delete(Context context, SiteSettings ss, bool notice = false) var where = Rds.UsersWhere().UserId(UserId); statements.AddRange(new List { + Rds.DeleteBinaries( + factory: context, + where: Rds.BinariesWhere() + .TenantId(context.TenantId) + .ReferenceId(UserId) + .BinaryType(value: "TenantManagementImages")), Rds.DeleteUsers( factory: context, where: where), @@ -4914,6 +4920,7 @@ private void InitializeTimeZone() /// public string GetReturnUrl(Context context, string returnUrl) { + if (!returnUrl.StartsWith("/") && !returnUrl.StartsWith("~/")) returnUrl = string.Empty; if (Permissions.PrivilegedUsers(LoginId) && Parameters.Locations.LoginAfterUrlExcludePrivilegedUsers) { return returnUrl; diff --git a/Implem.Pleasanter/Models/Users/UserUtilities.cs b/Implem.Pleasanter/Models/Users/UserUtilities.cs index 62119cc57..eca962869 100644 --- a/Implem.Pleasanter/Models/Users/UserUtilities.cs +++ b/Implem.Pleasanter/Models/Users/UserUtilities.cs @@ -2905,25 +2905,63 @@ private static int BulkDelete( IEnumerable selected, bool negative = false) { - var where = BulkDeleteWhere( + var subWhere = Views.GetBySession( context: context, - ss: ss, - selected: selected, - negative: negative); + ss: ss) + .Where( + context: context, + ss: ss, + itemJoin: false); + var where = Rds.UsersWhere() + .UserId_In( + value: selected.Select(o => o.ToInt()).ToList(), + negative: negative, + _using: selected.Any()) + .UserId_In( + sub: Rds.SelectUsers( + column: Rds.UsersColumn().UserId(), + join: ss.Join( + context: context, + join: new IJoin[] + { + subWhere + }), + where: subWhere)); + var sub = Rds.SelectUsers( + column: Rds.UsersColumn().UserId(), + where: where); return Repository.ExecuteScalar_response( context: context, transactional: true, statements: new SqlStatement[] { + Rds.DeleteGroupMembers( + factory: context, + where: Rds.GroupMembersWhere() + .UserId_In(sub: sub)), + Rds.DeletePermissions( + factory: context, + where: Rds.PermissionsWhere() + .UserId_In(sub: sub)), + Rds.DeleteBinaries( + factory: context, + where: Rds.BinariesWhere() + .TenantId(context.TenantId) + .ReferenceId_In(sub: sub) + .BinaryType(value: "TenantManagementImages")), Rds.DeleteMailAddresses( factory: context, where: Rds.MailAddressesWhere() - .OwnerId_In(sub: Rds.SelectUsers( - column: Rds.UsersColumn().UserId(), - where: where)) + .OwnerId_In(sub: sub) .OwnerType("Users")), - Rds.DeleteUsers(factory: context, where: where), - Rds.RowCount() + Rds.DeleteUsers( + factory: context, + where: Rds.UsersWhere() + .UserId_In(sub: sub)), + Rds.RowCount(), + StatusUtilities.UpdateStatus( + tenantId: context.TenantId, + type: StatusUtilities.Types.UsersUpdated), }).Count.ToInt(); } @@ -3016,145 +3054,12 @@ public static string Import(Context context) "Name" }); if (invalidColumn != null) return invalidColumn; - var userHash = new Dictionary(); - csv.Rows.Select((o, i) => new { Row = o, Index = i }).ForEach(data => - { - var userModel = new UserModel(); - if (idColumn > -1) - { - var model = new UserModel( - context: context, - ss: ss, - loginId: data.Row[idColumn]); - if (model.AccessStatus == Databases.AccessStatuses.Selected) - { - userModel = model; - } - } - columnHash.ForEach(column => - { - var recordingData = ImportRecordingData( - context: context, - column: column.Value, - value: data.Row[column.Key], - inheritPermission: ss.InheritPermission); - switch (column.Value.ColumnName) - { - case "TenantId": - userModel.TenantId = recordingData.ToInt(); - break; - case "UserId": - userModel.UserId = recordingData.ToInt(); - break; - case "LoginId": - userModel.LoginId = recordingData; - break; - case "GlobalId": - userModel.GlobalId = recordingData.ToString(); - break; - case "Name": - userModel.Name = recordingData.ToString(); - break; - case "UserCode": - userModel.UserCode = recordingData.ToString(); - break; - case "Password": - userModel.Password = recordingData.IsNullOrEmpty() - ? userModel.Password - : recordingData.Sha512Cng(); - userModel.PasswordValidate = recordingData.ToString(); - break; - case "LastName": - userModel.LastName = recordingData.ToString(); - break; - case "FirstName": - userModel.FirstName = recordingData.ToString(); - break; - case "Birthday": - userModel.Birthday.Value = recordingData.ToDateTime(); - break; - case "Gender": - userModel.Gender = recordingData.ToString(); - break; - case "Language": - userModel.Language = recordingData.ToString(); - break; - case "TimeZone": - userModel.TimeZone = recordingData.ToString(); - break; - case "DeptId": - userModel.DeptId = recordingData.ToInt(); - break; - case "DeptCode": - userModel.DeptId = SiteInfo.Dept( - tenantId: context.TenantId, - deptCode: recordingData).Id; - break; - case "Theme": - userModel.Theme = recordingData.ToString(); - break; - case "Body": - userModel.Body = recordingData.ToString(); - break; - case "PasswordExpirationTime": - userModel.PasswordExpirationTime.Value = recordingData.ToDateTime(); - break; - case "TenantManager": - userModel.TenantManager = recordingData.ToBool(); - break; - case "ServiceManager": - userModel.ServiceManager = recordingData.ToBool(); - break; - case "AllowCreationAtTopSite": - userModel.AllowCreationAtTopSite = recordingData.ToBool(); - break; - case "AllowGroupAdministration": - userModel.AllowGroupAdministration = recordingData.ToBool(); - break; - case "AllowGroupCreation": - userModel.AllowGroupCreation = recordingData.ToBool(); - break; - case "AllowApi": - userModel.AllowApi = recordingData.ToBool(); - break; - case "Disabled": - userModel.Disabled = recordingData.ToBool(); - break; - case "Lockout": - userModel.Lockout = recordingData.ToBool(); - break; - case "ApiKey": - userModel.ApiKey = recordingData.ToString(); - break; - case "MailAddresses": - userModel.MailAddresses = recordingData.Split(',').ToList(); - break; - case "LdapSearchRoot": - userModel.LdapSearchRoot = recordingData.ToString(); - break; - case "SynchronizedTime": - userModel.SynchronizedTime = recordingData.ToDateTime(); - break; - case "Comments": - if (userModel.AccessStatus != Databases.AccessStatuses.Selected && - !data.Row[column.Key].IsNullOrEmpty()) - { - userModel.Comments.Prepend( - context: context, - ss: ss, - body: data.Row[column.Key]); - } - break; - default: - userModel.SetValue( - context: context, - column: column.Value, - value: recordingData); - break; - } - }); - userHash.Add(data.Index, userModel); - }); + var userHash = CreateUserHash( + context: context, + ss: ss, + csv: csv, + columnHash: columnHash, + idColumn: idColumn); var errorRowNo = 1; foreach (var userModel in userHash.Values) { @@ -3262,6 +3167,228 @@ public static string Import(Context context) } } + /// + /// Fixed: + /// + public static ContentResultInheritance ImportByApi(Context context, SiteSettings ss) + { + if (!Mime.ValidateOnApi(contentType: context.ContentType, multipart: true)) + { + return ApiResults.BadRequest(context: context); + } + if (context.ContractSettings.Import == false) + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Messages.Restricted(context: context).Text)); + } + var invalid = UserValidators.OnImporting( + context: context, + ss: ss, + api: true); + switch (invalid.Type) + { + case Error.Types.None: + break; + default: + return ApiResults.Error( + context: context, + errorData: invalid); + } + var api = context.RequestDataString.Deserialize(); + var encoding = api.Encoding; + Csv csv; + try + { + csv = new Csv( + csv: context.PostedFiles.FirstOrDefault().Byte(), + encoding: encoding); + } + catch + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Messages.FailedReadFile(context: context).Text)); + } + var count = csv.Rows.Count(); + if (Parameters.General.ImportMax > 0 && Parameters.General.ImportMax < count) + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Error.Types.ImportMax.Message( + context: context, + data: Parameters.General.ImportMax.ToString()).Text)); + } + if (context.ContractSettings.ItemsLimit(context: context, siteId: ss.SiteId, number: count)) + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Error.Types.ItemsLimit.Message(context: context).Text)); + } + if (csv != null && count > 0) + { + var idColumn = -1; + var columnHash = new Dictionary(); + var mailAddressHash = new Dictionary(); + csv.Headers.Select((o, i) => new { Header = o, Index = i }).ForEach(data => + { + var column = ss.Columns + .Where(o => o.LabelText == data.Header) + .Where(o => o.ColumnName != "DemoMailAddress") + .Where(o => o.TypeCs != "Attachments") + .FirstOrDefault(); + if (column?.ColumnName == "LoginId") + { + idColumn = data.Index; + } + if (column != null) columnHash.Add(data.Index, column); + }); + var invalidColumn = Imports.ApiColumnValidate( + context: context, + ss: ss, + headers: columnHash.Values.Select(o => o.ColumnName), + columnNames: new string[] + { + "LoginId", + "Name" + }); + if (invalidColumn != null) + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: invalidColumn)); + } + var userHash = CreateUserHash( + context: context, + ss: ss, + csv: csv, + columnHash: columnHash, + idColumn: idColumn); + var errorRowNo = 1; + foreach (var userModel in userHash.Values) + { + var badMailAddress = Libraries.Mails.Addresses.BadAddress( + addresses: userModel.MailAddresses.Join()); + if (!badMailAddress.IsNullOrEmpty()) + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Messages.BadMailAddress( + context: context, + data: badMailAddress).Text)); + } + if (!userModel.PasswordValidate.IsNullOrEmpty()) + { + foreach (var policy in Parameters.Security.PasswordPolicies.Where(o => o.Enabled)) + { + if (!userModel.PasswordValidate.RegexExists(policy.Regex)) + { + var badPassword = policy.Languages?.Any() == true + ? policy.Display(context: context) + : Displays.PasswordPolicyViolation( + context: context, + data: null); + var badPasswordParam = new string[] + { + errorRowNo.ToString(), + badPassword + }; + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Messages.BadPasswordWhenImporting( + context: context, + data: badPasswordParam).Text)); + } + } + } + errorRowNo++; + } + var insertCount = 0; + var updateCount = 0; + foreach (var userModel in userHash.Values) + { + if (userModel.AccessStatus == Databases.AccessStatuses.Selected) + { + var mailAddressUpdated = UpdateMailAddresses(context, userModel); + if (userModel.Updated(context: context)) + { + userModel.VerUp = Versions.MustVerUp( + context: context, + ss: ss, + baseModel: userModel); + var errorData = userModel.Update( + context: context, + ss: ss, + updateMailAddresses: false, + refleshSiteInfo: false, + get: false); + switch (errorData.Type) + { + case Error.Types.None: + break; + default: + return ApiResults.Error( + context: context, + errorData: errorData); + } + updateCount++; + } + else if (mailAddressUpdated) + { + updateCount++; + } + } + else + { + var errorData = userModel.Create( + context: context, + ss: ss, + get: false); + switch (errorData.Type) + { + case Error.Types.None: + break; + default: + return ApiResults.Error( + context: context, + errorData: errorData); + } + UpdateMailAddresses(context, userModel); + insertCount++; + } + } + SiteInfo.Reflesh( + context: context, + force: true); + return ApiResults.Success( + id: context.Id, + limitPerDate: context.ContractSettings.ApiLimit(), + limitRemaining: context.ContractSettings.ApiLimit() - ss.ApiCount, + message: Messages.Imported( + context: context, + data: new string[] + { + ss.Title, + insertCount.ToString(), + updateCount.ToString() + }).Text); + } + else + { + return ApiResults.Get(new ApiResponse( + id: context.Id, + statusCode: 500, + message: Messages.FileNotFound(context: context).Text)); + } + } + /// /// Fixed: /// @@ -3316,6 +3443,164 @@ private static string ImportRecordingData( return recordingData; } + /// + /// Fixed: + /// + public static Dictionary CreateUserHash( + Context context, + SiteSettings ss, + Csv csv, + Dictionary columnHash, + int idColumn) + { + var userHash = new Dictionary(); + csv.Rows.Select((o, i) => new { Row = o, Index = i }).ForEach(data => + { + var userModel = new UserModel(); + if (idColumn > -1) + { + var model = new UserModel( + context: context, + ss: ss, + loginId: data.Row[idColumn]); + if (model.AccessStatus == Databases.AccessStatuses.Selected) + { + userModel = model; + } + } + columnHash.ForEach(column => + { + var recordingData = ImportRecordingData( + context: context, + column: column.Value, + value: data.Row[column.Key], + inheritPermission: ss.InheritPermission); + switch (column.Value.ColumnName) + { + case "TenantId": + userModel.TenantId = recordingData.ToInt(); + break; + case "UserId": + userModel.UserId = recordingData.ToInt(); + break; + case "LoginId": + userModel.LoginId = recordingData; + break; + case "GlobalId": + userModel.GlobalId = recordingData.ToString(); + break; + case "Name": + userModel.Name = recordingData.ToString(); + break; + case "UserCode": + userModel.UserCode = recordingData.ToString(); + break; + case "Password": + userModel.Password = recordingData.IsNullOrEmpty() + ? userModel.Password + : recordingData.Sha512Cng(); + userModel.PasswordValidate = recordingData.ToString(); + break; + case "LastName": + userModel.LastName = recordingData.ToString(); + break; + case "FirstName": + userModel.FirstName = recordingData.ToString(); + break; + case "Birthday": + userModel.Birthday.Value = recordingData.ToDateTime(); + break; + case "Gender": + userModel.Gender = recordingData.ToString(); + break; + case "Language": + userModel.Language = recordingData.ToString(); + break; + case "TimeZone": + userModel.TimeZone = recordingData.ToString(); + break; + case "DeptId": + userModel.DeptId = recordingData.ToInt(); + break; + case "DeptCode": + userModel.DeptId = SiteInfo.Dept( + tenantId: context.TenantId, + deptCode: recordingData).Id; + break; + case "Theme": + userModel.Theme = recordingData.ToString(); + break; + case "Body": + userModel.Body = recordingData.ToString(); + break; + case "PasswordExpirationTime": + userModel.PasswordExpirationTime.Value = recordingData.ToDateTime(); + break; + case "TenantManager": + userModel.TenantManager = recordingData.ToBool(); + break; + case "ServiceManager": + userModel.ServiceManager = recordingData.ToBool(); + break; + case "AllowCreationAtTopSite": + userModel.AllowCreationAtTopSite = recordingData.ToBool(); + break; + case "AllowGroupAdministration": + userModel.AllowGroupAdministration = recordingData.ToBool(); + break; + case "AllowGroupCreation": + userModel.AllowGroupCreation = recordingData.ToBool(); + break; + case "AllowApi": + userModel.AllowApi = recordingData.ToBool(); + break; + case "EnableSecondaryAuthentication": + userModel.EnableSecondaryAuthentication = recordingData.ToBool(); + break; + case "DisableSecondaryAuthentication": + userModel.DisableSecondaryAuthentication = recordingData.ToBool(); + break; + case "Disabled": + userModel.Disabled = recordingData.ToBool(); + break; + case "Lockout": + userModel.Lockout = recordingData.ToBool(); + break; + case "ApiKey": + userModel.ApiKey = recordingData.ToString(); + break; + case "MailAddresses": + userModel.MailAddresses = recordingData.Split(',').ToList(); + break; + case "LdapSearchRoot": + userModel.LdapSearchRoot = recordingData.ToString(); + break; + case "SynchronizedTime": + userModel.SynchronizedTime = recordingData.ToDateTime(); + break; + case "Comments": + if (userModel.AccessStatus != Databases.AccessStatuses.Selected && + !data.Row[column.Key].IsNullOrEmpty()) + { + userModel.Comments.Prepend( + context: context, + ss: ss, + body: data.Row[column.Key]); + } + break; + default: + userModel.SetValue( + context: context, + column: column.Value, + value: recordingData); + break; + } + }); + userHash.Add(data.Index, userModel); + }); + return userHash; + } + /// /// Fixed: /// @@ -4815,5 +5100,333 @@ public static (int TenantId, ContractSettings ContractSettings) GetContractSetti var contractSettings = dataRow.String("ContractSettings").Deserialize(); return (tenantId, contractSettings); } + + /// + /// Fixed: + /// + public static string TrashBox(Context context, SiteSettings ss) + { + var hb = new HtmlBuilder(); + var view = Views.GetBySession(context: context, ss: ss); + var gridData = GetGridData(context: context, ss: ss, view: view); + var viewMode = ViewModes.GetSessionData( + context: context, + siteId: ss.SiteId); + var serverScriptModelRow = ss.GetServerScriptModelRow( + context: context, + view: view, + gridData: gridData); + return hb.ViewModeTemplate( + context: context, + ss: ss, + view: view, + viewMode: viewMode, + serverScriptModelRow: serverScriptModelRow, + viewModeBody: () => hb + .TrashBoxCommands(context: context, ss: ss) + .Grid( + context: context, + ss: ss, + gridData: gridData, + view: view, + action: "TrashBoxGridRows", + serverScriptModelRow: serverScriptModelRow)); + } + + /// + /// Fixed: + /// + public static string TrashBoxJson(Context context, SiteSettings ss) + { + var view = Views.GetBySession( + context: context, + ss: ss); + var gridData = GetGridData( + context: context, + ss: ss, + view: view); + var body = new HtmlBuilder() + .TrashBoxCommands(context: context, ss: ss) + .Grid( + context: context, + ss: ss, + gridData: gridData, + view: view, + action: "TrashBoxGridRows"); + return new ResponseCollection(context: context) + .ViewMode( + context: context, + ss: ss, + view: view, + invoke: "setGrid", + body: body) + .ToJson(); + } + + /// + /// Fixed: + /// + public static string Restore(Context context, SiteSettings ss) + { + if (!Parameters.Deleted.Restore) + { + return Error.Types.InvalidRequest.MessageJson(context: context); + } + else if (Permissions.CanManageUser(context: context)) + { + var selector = new RecordSelector(context: context); + var count = 0; + if (selector.All) + { + count = Restore( + context: context, + ss: ss, + selected: selector.Selected, + negative: true); + } + else + { + if (selector.Selected.Any()) + { + count = Restore( + context: context, + ss: ss, + selected: selector.Selected); + } + else + { + return Messages.ResponseSelectTargets(context: context).ToJson(); + } + } + Summaries.Synchronize(context: context, ss: ss); + return GridRows( + context: context, + ss: ss, + clearCheck: true, + message: Messages.BulkRestored( + context: context, + data: count.ToString())); + } + else + { + return Messages.ResponseHasNotPermission(context: context).ToJson(); + } + } + + /// + /// Fixed: + /// + public static int Restore( + Context context, SiteSettings ss, List selected, bool negative = false) + { + var subWhere = Views.GetBySession( + context: context, + ss: ss) + .Where( + context: context, + ss: ss, + itemJoin: false); + var where = Rds.UsersWhere() + .UserId_In( + value: selected.Select(o => o.ToInt()).ToList(), + tableName: "Users_Deleted", + negative: negative, + _using: selected.Any()) + .UserId_In( + tableName: "Users_Deleted", + sub: Rds.SelectUsers( + tableType: Sqls.TableTypes.Deleted, + column: Rds.UsersColumn().UserId(), + join: ss.Join( + context: context, + join: new IJoin[] + { + subWhere + }), + where: subWhere)); + var sub = Rds.SelectUsers( + tableType: Sqls.TableTypes.Deleted, + _as: "Users_Deleted", + column: Rds.UsersColumn() + .UserId(tableName: "Users_Deleted"), + where: where); + var count = Repository.ExecuteScalar_response( + context: context, + connectionString: Parameters.Rds.OwnerConnectionString, + transactional: true, + statements: new SqlStatement[] + { + Rds.RestoreGroupMembers( + factory: context, + where: Rds.GroupMembersWhere() + .UserId_In(sub: sub)), + Rds.RestorePermissions( + factory: context, + where: Rds.PermissionsWhere() + .UserId_In(sub: sub)), + Rds.RestoreBinaries( + factory: context, + where: Rds.BinariesWhere() + .TenantId(context.TenantId) + .ReferenceId_In(sub: sub) + .BinaryType(value: "TenantManagementImages")), + Rds.RestoreMailAddresses( + factory: context, + where: Rds.MailAddressesWhere() + .OwnerId_In(sub: sub) + .OwnerType("Users")), + Rds.UpdateUsers( + tableType: Sqls.TableTypes.Deleted, + where: Rds.UsersWhere() + .UserId_In(sub: sub)), + Rds.RestoreUsers( + factory: context, + where: Rds.UsersWhere() + .UserId_In(sub: sub)), + Rds.RowCount(), + StatusUtilities.UpdateStatus( + tenantId: context.TenantId, + type: StatusUtilities.Types.UsersUpdated) + }).Count.ToInt(); + return count; + } + + /// + /// Fixed: + /// + public static string PhysicalBulkDelete(Context context, SiteSettings ss) + { + if (!Parameters.Deleted.PhysicalDelete) + { + return Error.Types.InvalidRequest.MessageJson(context: context); + } + if (Permissions.CanManageUser(context: context)) + { + var selector = new RecordSelector(context: context); + var count = 0; + if (selector.All) + { + count = PhysicalBulkDelete( + context: context, + ss: ss, + selected: selector.Selected, + negative: true); + } + else + { + if (selector.Selected.Any()) + { + count = PhysicalBulkDelete( + context: context, + ss: ss, + selected: selector.Selected); + } + else + { + return Messages.ResponseSelectTargets(context: context).ToJson(); + } + } + return GridRows( + context: context, + ss: ss, + clearCheck: true, + message: Messages.PhysicalBulkDeletedFromRecycleBin( + context: context, + data: count.ToString())); + } + else + { + return Messages.ResponseHasNotPermission(context: context).ToJson(); + } + } + + /// + /// Fixed: + /// + private static int PhysicalBulkDelete( + Context context, + SiteSettings ss, + List selected = null, + SqlWhereCollection where = null, + SqlParamCollection param = null, + bool negative = false, + Sqls.TableTypes tableType = Sqls.TableTypes.Deleted) + { + var tableName = string.Empty; + switch (tableType) + { + case Sqls.TableTypes.History: + tableName = "_History"; + break; + case Sqls.TableTypes.Deleted: + tableName = "_Deleted"; + break; + default: + break; + } + where = where ?? Rds.UsersWhere() + .UserId_In( + value: selected.Select(o => o.ToInt()).ToList(), + tableName: "Users" + tableName, + negative: negative, + _using: selected.Any()) + .UserId_In( + tableName: "Users" + tableName, + sub: Rds.SelectUsers( + tableType: tableType, + column: Rds.UsersColumn().UserId(), + where: Views.GetBySession( + context: context, + ss: ss) + .Where( + context: context, + ss: ss, + itemJoin: false))); + var sub = Rds.SelectUsers( + tableType: tableType, + _as: "Users" + tableName, + column: Rds.UsersColumn() + .UserId(tableName: "Users" + tableName), + where: where, + param: param); + var dataRows = Rds.ExecuteTable( + context: context, + statements: Rds.SelectBinaries( + tableType: tableType, + column: Rds.BinariesColumn().Guid().BinaryType(), + where: Rds.BinariesWhere().ReferenceId_In(sub: sub))) + .AsEnumerable(); + var count = Repository.ExecuteScalar_response( + context: context, + transactional: true, + statements: new SqlStatement[] + { + Rds.PhysicalDeleteGroupMembers( + tableType: tableType, + where: Rds.GroupMembersWhere() + .UserId_In(sub: sub)), + Rds.PhysicalDeletePermissions( + tableType: tableType, + where: Rds.PermissionsWhere() + .UserId_In(sub: sub)), + Rds.PhysicalDeleteBinaries( + tableType: tableType, + where: Rds.BinariesWhere() + .TenantId(context.TenantId) + .ReferenceId_In(sub: sub) + .BinaryType(value: "TenantManagementImages")), + Rds.PhysicalDeleteMailAddresses( + tableType: tableType, + where: Rds.MailAddressesWhere() + .OwnerId_In(sub: sub) + .OwnerType("Users")), + Rds.PhysicalDeleteUsers( + tableType: tableType, + where: Rds.UsersWhere() + .UserId_In(sub: sub)), + Rds.RowCount() + }).Count.ToInt(); + return count; + } } } diff --git a/Implem.Pleasanter/Startup.cs b/Implem.Pleasanter/Startup.cs index 26836cc1f..89838670f 100644 --- a/Implem.Pleasanter/Startup.cs +++ b/Implem.Pleasanter/Startup.cs @@ -15,6 +15,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.DataProtection.KeyManagement; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; @@ -186,6 +187,16 @@ public void ConfigureServices(IServiceCollection services) .PersistKeysToAzureBlobStorage(blobClient) .ProtectKeysWithAzureKeyVault(new Uri(keyIdentifier), new DefaultAzureCredential()); } + else + { + services + .AddOptions() + .Configure((options, factory) => + { + options.XmlRepository = new AspNetCoreKeyManagementXmlRepository(); + options.XmlEncryptor = new AspNetCoreKeyManagementXmlEncryptor(); + }); + } if (Parameters.Security.HttpStrictTransportSecurity?.Enabled == true) { services.AddHsts(options => diff --git a/Implem.Pleasanter/Views/Users/TrashBox.cshtml b/Implem.Pleasanter/Views/Users/TrashBox.cshtml new file mode 100644 index 000000000..5edc05b54 --- /dev/null +++ b/Implem.Pleasanter/Views/Users/TrashBox.cshtml @@ -0,0 +1,4 @@ +@{ + Layout = "~/Views/Shared/_Layout.cshtml"; +} +@{ViewBag.Title = ViewBag.TITLE;}@Html.Raw(@ViewBag.HtmlBody) \ No newline at end of file diff --git a/Implem.Pleasanter/wwwroot/content/responsive.css b/Implem.Pleasanter/wwwroot/content/responsive.css index 5b1d8e0fd..829b42764 100644 --- a/Implem.Pleasanter/wwwroot/content/responsive.css +++ b/Implem.Pleasanter/wwwroot/content/responsive.css @@ -1,5 +1,4 @@ - -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #LoginFieldSet { width: 100%; @@ -89,8 +88,9 @@ height: auto; } - #Breadcrumb { display:none; } - #CopyToClipboards { display: none; } + #Breadcrumb { + font-size: 2.6vw; + } #ViewSelectorField { position: relative; margin-bottom: 5px; font-size: 2.8vw; } @@ -181,7 +181,7 @@ } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { body { min-width: 320px!important; } #Header { height: auto; position: relative; } @@ -301,7 +301,7 @@ border: 1px solid #d19405; } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #SiteMenu .nav-site { width: 20vw; @@ -477,7 +477,7 @@ overflow: hidden; #SiteMenu .nav-site.to-parent.has-image a { padding: 0 0 0 15px;} } -@media screen and (max-width: 980px) and (min-width: 0px){ +@media screen and (max-width: 1024px) and (min-width: 0px){ #EditorTabs {} #Application {} @@ -503,8 +503,8 @@ overflow: hidden; .links { overflow: auto; } - -@media screen and (max-width: 980px) and (min-width: 0px) { +} +@media screen and (max-width: 1024px) and (min-width: 0px) { #FieldSetHistories { overflow: auto; width: 100%; } #ViewModeContainer { overflow: auto; width: 100%; padding-top: 1%; } #CrosstabBody { overflow: auto; width: 100%; } @@ -585,7 +585,7 @@ overflow: hidden; #KambanBody .grid>tbody td { min-width: 10vw; white-space: nowrap; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #Header { padding: 0 calc(5vw); } @@ -613,24 +613,33 @@ overflow: hidden; .field-control .control-text, .container-normal .control-textbox, .container-normal .control-dropdown, .container-normal .control-text { + font-size: 2.6vw; min-height: unset; height: 6vw; line-height: 6vw; padding-top: 0; padding-bottom: 0; + display: flex; + align-items: center; } body { font-size: 16px; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #HeaderTitle { font-size: 16px; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 768px) { + #HeaderTitle { + font-size: 35px; + } +} + +@media screen and (max-width: 1024px) and (min-width: 0px) { .command-center { padding: 0; } @@ -643,13 +652,13 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #ViewSelector { font-size: 2.6vw; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #Logo a { align-items: center; display: flex; @@ -666,31 +675,33 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 768px) { + #Logo #ProductLogo { + padding-left: 16px; + font-size: 32px; + } +} + +@media screen and (max-width: 1024px) and (min-width: 0px) { #Editor .field-control .container-normal { - width: calc(100% - 20px); - } - #Editor .field-control .ui-icon.ui-icon-clock.current-time { - background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDI0IDI0IiBoZWlnaHQ9IjEycHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjEycHgiIGZpbGw9IiMwMDAwMDAiPjxnPjxyZWN0IGZpbGw9Im5vbmUiIGhlaWdodD0iMjQiIHdpZHRoPSIyNCIvPjwvZz48Zz48Zz48Zz48cGF0aCBkPSJNMTIsMkM2LjUsMiwyLDYuNSwyLDEyczQuNSwxMCwxMCwxMHMxMC00LjUsMTAtMTBTMTcuNSwyLDEyLDJ6IE0xNi4yLDE2LjJMMTEsMTNWN2gxLjV2NS4ybDQuNSwyLjdMMTYuMiwxNi4yeiIvPjwvZz48L2c+PC9nPjwvc3ZnPg=="); - background-position: center; - width: 12px; - height: 12px; - filter: invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%); - top: calc(3vw - 3.5px); - right: -16px; - } - #Editor .field-control .ui-icon.ui-icon-person.current-user { - background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMTJweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0xMiAxMmMyLjIxIDAgNC0xLjc5IDQtNHMtMS43OS00LTQtNC00IDEuNzktNCA0IDEuNzkgNCA0IDR6bTAgMmMtMi42NyAwLTggMS4zNC04IDR2MmgxNnYtMmMwLTIuNjYtNS4zMy00LTgtNHoiLz48L3N2Zz4="); - background-position: center; - width: 12px; - height: 12px; - filter: invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%); + width: calc(100% - 18px); + } + #Editor .field-control .ui-icon.ui-icon-clock.current-time, #Editor .field-control .ui-icon.ui-icon-person.current-user { + top: calc(3vw - 6px); + } +} + +@media screen and (max-width: 1024px) and (min-width: 768px) { + #Editor .field-control .container-normal { + width: calc(100% - 36px); + } + #Editor .field-control .ui-icon.ui-icon-clock.current-time, #Editor .field-control .ui-icon.ui-icon-person.current-user { top: calc(3vw - 3.5px); - right: -16px; + right: -30px; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #FieldSetAddressBook #OutgoingMailDestinationForm .container-left { width: 38vw; } @@ -699,7 +710,7 @@ overflow: hidden; padding: 0; } #FieldSetAddressBook #OutgoingMailDestinationForm .container-right .command-left button { - margin: 2px; + margin: 1vw 1vw 1vw 0; } #FieldSetAddressBook #OutgoingMailDestinationForm .container-right .container-selectable .wrapper { height: 40vw; @@ -709,13 +720,19 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 768px) { + #FieldSetAddressBook #OutgoingMailDestinationForm .container-left { + width: 33vw; + } +} + +@media screen and (max-width: 1024px) and (min-width: 0px) { #Issues_WorkValue { width: 100px; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { body::before { content: ''; position: fixed; @@ -738,7 +755,7 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #Users_LoginId, #Users_Password { height: 40px; @@ -774,7 +791,7 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #Editor .field-markdown > .field-label > label { font-weight: bold; } @@ -787,7 +804,7 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #GridCheckAll { margin-top: 0; } @@ -806,7 +823,18 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { + #Editor #EditorTabsContainer fieldset .wrapper { + max-height: 250px; + overflow: auto; + } + #Editor #EditorTabsContainer fieldset .container-selectable .command-left { + align-items: center; + display: flex; + } + #Editor #EditorTabsContainer fieldset:not(#FieldSetGeneral) legend.legend { + min-height: 10px; + } #SiteImageSettingsEditor .field-auto-thin, #GridSettingsEditor .field-auto-thin, #FiltersSettingsEditor .field-auto-thin, #EditorSettingsEditor .field-auto-thin, #LinksSettingsEditor .field-auto-thin, #HistoriesSettingsEditor .field-auto-thin, #FormulasSettingsEditor .field-auto-thin, #ViewsSettingsEditor .field-auto-thin, #ImportsSettingsEditor .field-auto-thin, #ExportsSettingsEditor .field-auto-thin, #CalendarSettingsEditor .field-auto-thin, #CrosstabSettingsEditor .field-auto-thin, @@ -866,9 +894,21 @@ overflow: hidden; #SiteImageSettingsEditor #SetSiteImage { margin-right: 0; } + #SearchSettingsEditor #SearchType { + margin-bottom: 10px; + } + #SearchSettingsEditor #SearchSettingsEditorFulltext legend.legend.applied, #SearchSettingsEditor #SearchSettingsEditorOperations legend.legend.applied { + margin-bottom: 10px; + } + #SearchSettingsEditor #SearchSettingsEditorFulltext { + padding-top: 10px; + } + #Editor #EditorTabsContainer .fieldset + .field-auto-thin { + margin-top: 10px; + } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #Aggregations { display: flex; flex-wrap: wrap; @@ -906,13 +946,16 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 768px) { + #Aggregations { + row-gap: 15px; + } +} + +@media screen and (max-width: 1024px) and (min-width: 0px) { #ViewModeContainer .grid { vertical-align: middle; } - #ViewModeContainer .grid tr td:first-child { - padding: 6px; - } input[type='checkbox'], .field-auto-thin input[type='checkbox'] { width: 3vw; height: 3vw; @@ -922,7 +965,7 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #SearchField #Search { font-size: 3vw; width: 100%; @@ -932,7 +975,7 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #ViewFilters #ViewFilters_Reset { margin-left: auto; margin-right: 0; @@ -994,7 +1037,7 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #EditorTabsContainer .legend.applied { display: flex; align-items: center; @@ -1037,35 +1080,21 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { thead > tr.ui-widget-header th div > span { font-size: 2.8vw; white-space: nowrap; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 768px) { #EditorTabsContainer .field-control .container-normal .ui-icon.ui-icon-pencil.button-edit-markdown { - background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMTJweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0zIDE3LjI1VjIxaDMuNzVMMTcuODEgOS45NGwtMy43NS0zLjc1TDMgMTcuMjV6TTIwLjcxIDcuMDRjLjM5LS4zOS4zOS0xLjAyIDAtMS40MWwtMi4zNC0yLjM0Yy0uMzktLjM5LTEuMDItLjM5LTEuNDEgMGwtMS44MyAxLjgzIDMuNzUgMy43NSAxLjgzLTEuODN6Ii8+PC9zdmc+"); - background-position: center; - width: 12px; - height: 12px; - filter: invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%); - top: 8px; + top: 10px; right: 4px; } - #EditorTabsContainer .field-control .container-normal .ui-icon.ui-icon-image.button-upload-image { - background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMTJweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0yMSAxOVY1YzAtMS4xLS45LTItMi0ySDVjLTEuMSAwLTIgLjktMiAydjE0YzAgMS4xLjkgMiAyIDJoMTRjMS4xIDAgMi0uOSAyLTJ6TTguNSAxMy41bDIuNSAzLjAxTDE0LjUgMTJsNC41IDZINWwzLjUtNC41eiIvPjwvc3ZnPg=="); - background-position: center; - width: 12px; - height: 12px; - filter: invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%); - position: relative; - left: -1px; - } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #EditorTabsContainer { overflow: auto; } @@ -1081,7 +1110,7 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { .is-showMenu { overflow: hidden; } @@ -1155,7 +1184,7 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #OutgoingMailsForm { width: 100%; font-size: 2.6vw; @@ -1221,13 +1250,60 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #SiteMenu li.ui-sortable-handle { touch-action: unset; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { + .xdsoft_datetimepicker span { + font-size: 2.6vw; + } + .xdsoft_datetimepicker .xdsoft_datepicker { + width: calc(42.81vw - 16px); + } + .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_today_button { + margin-left: 0; + } + .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_label.xdsoft_year { + margin-left: 0; + } + .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_year, .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_month { + width: fit-content; + } + .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_year .xdsoft_select .xdsoft_option, .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_month .xdsoft_select .xdsoft_option { + font-size: 2.6vw; + } + .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_year .xdsoft_select .xdsoft_scrollbar, .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_month .xdsoft_select .xdsoft_scrollbar { + width: 0.7vw; + } + .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_calendar table th, .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_calendar table td { + font-size: 2.6vw; + } + .xdsoft_datetimepicker .xdsoft_timepicker.active { + width: calc(12.17vw - 8px); + } + .xdsoft_datetimepicker .xdsoft_timepicker.active .xdsoft_time_box .xdsoft_time { + font-size: 2.6vw; + } +} + +@media screen and (max-width: 1024px) and (min-width: 768px) { + .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_year i, .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_month i { + transform: scale(1.6); + } + .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_year span, .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_month span { + font-size: 16px; + } +} + +@media screen and (max-width: 1024px) and (min-width: 0px) { + .message span.body { + display: flex; + align-items: center; + justify-content: center; + } .message .close { top: unset; bottom: calc(50% - 8px); @@ -1235,19 +1311,7 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { - #EditorComments #CommentField .ui-icon.ui-icon-image.button-upload-image { - background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMTJweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0yMSAxOVY1YzAtMS4xLS45LTItMi0ySDVjLTEuMSAwLTIgLjktMiAydjE0YzAgMS4xLjkgMiAyIDJoMTRjMS4xIDAgMi0uOSAyLTJ6TTguNSAxMy41bDIuNSAzLjAxTDE0LjUgMTJsNC41IDZINWwzLjUtNC41eiIvPjwvc3ZnPg=="); - background-position: center; - width: 12px; - height: 12px; - filter: invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%); - position: relative; - left: 0px; - } -} - -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #Navigations.open { overflow-y: scroll; } @@ -1260,11 +1324,17 @@ overflow: hidden; } #Navigations #NavigationMenu li.sub-menu .ui-menu-item .ui-menu-item-wrapper { font-size: 3vw; - padding-left: 6vw; + padding-left: 5vw; + } +} + +@media screen and (max-width: 1024px) and (min-width: 768px) { + #Navigations #NavigationMenu li.sub-menu .ui-menu-item .ui-menu-item-wrapper { + padding-left: 4vw; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #Editor .field-normal .field-control .container-normal input[type='checkbox'].control-checkbox { position: relative; margin-right: 6px; @@ -1272,7 +1342,13 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 768px) { + #Editor .field-normal .field-control .container-normal input[type='checkbox'].control-checkbox { + margin-right: 12px; + } +} + +@media screen and (max-width: 1024px) and (min-width: 0px) { #Editor #EditorTabsContainer .field-normal, #Editor #EditorTabsContainer .field-wide, #Editor #EditorTabsContainer .field-markdown { display: inline-block; margin-top: 8px; @@ -1280,29 +1356,31 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #ViewModeContainer #Calendar.both select { font-size: 2.6vw; + height: 6vw; } #ViewModeContainer #Calendar.both .field-label { - min-width: 30%; - margin-right: 15px; + min-width: 16%; + margin-right: 0px; } #ViewModeContainer #Calendar.both .field-auto-thin .field-control .container-normal { display: flex; align-items: center; } - #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) { - flex: 0 1 calc(64%); + #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(1), #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(2), #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) { + flex: 0 1 calc(47%); + flex-wrap: nowrap; } - #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) .field-label { - min-width: 22%; + #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(1) .field-label, #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(2) .field-label, #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) .field-label { + min-width: 16%; } - #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) .field-control { - width: 74%; + #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(1) .field-control, #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(2) .field-control, #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) .field-control { + width: 84%; } #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(4) { - flex: 0 1 calc(33% + 1px); + width: 47%; padding-top: 2%; } #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(4) .field-control .container-normal { @@ -1310,9 +1388,12 @@ overflow: hidden; } #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(4) .field-control .container-normal #CalendarDate { margin-right: 0; - width: 98%; + width: 100%; font-size: 2.6vw; } + #ViewModeContainer #Calendar.both .field-auto-thin input[type='checkbox'] { + margin-left: 2px; + } #ViewModeContainer #Calendar.both button { flex: 1 0 calc((100% / 3) - 32px); margin: 2% 10px 2% 10px; @@ -1322,35 +1403,27 @@ overflow: hidden; } #ViewModeContainer .grid.fixed tbody tr td.container .item { touch-action: auto; - min-height: 50px; - } - #ViewModeContainer .grid.fixed tbody tr td.container .item .title .ui-icon.ui-icon-pencil { - margin-right: 5px; - background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMzBweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMzBweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0zIDE3LjI1VjIxaDMuNzVMMTcuODEgOS45NGwtMy43NS0zLjc1TDMgMTcuMjV6TTIwLjcxIDcuMDRjLjM5LS4zOS4zOS0xLjAyIDAtMS40MWwtMi4zNC0yLjM0Yy0uMzktLjM5LTEuMDItLjM5LTEuNDEgMGwtMS44MyAxLjgzIDMuNzUgMy43NSAxLjgzLTEuODN6Ii8+PC9zdmc+"); - background-position: center; - width: 36px; - height: 36px; - filter: invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%); + min-height: 4vw; + margin-top: 5px; + margin-bottom: 5px; + height: 4vw; } #ViewModeContainer .grid.fixed tbody tr td.container .item .connection { - min-height: 50px; + min-height: 4vw; + height: 4vw; } #ViewModeContainer .grid.fixed tbody tr td.container .dummy { - height: 50px; - } - #ViewModeContainer .grid.fixed tbody tr td.container:first-child .item { - margin-top: 0; - margin-bottom: 5px; + height: 4vw; } - #ViewModeContainer .grid.fixed tbody tr td.container:not(:first-child) .item { - margin-top: 5px; + #ViewModeContainer .grid.fixed tbody .title { + padding: 0; } thead th.calendar-header { overflow-x: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #ViewModeContainer .both { column-gap: 16px; } @@ -1409,6 +1482,10 @@ overflow: hidden; #GanttBody { max-height: 70vh; } + #GanttBody #Gantt { + font-size: 2.6vw; + width: 500%; + } #GanttBody text { font-size: 2.6vw; } @@ -1416,12 +1493,13 @@ overflow: hidden; font-size: 3vw; } #GanttBody #GanttAxis { - left: auto; + left: -2px; position: sticky; + width: 500%; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #ViewModeContainer #Kamban.both .field-auto-thin select { font-size: 2.6vw; } @@ -1465,27 +1543,50 @@ overflow: hidden; align-items: center; } #ViewModeContainer #Kamban.both #KambanBody #Grid tbody .kamban-row .kamban-container .kamban-item { + height: 4vw; + padding: 0px 16px 0px 5px; overflow: hidden; - padding: 6px 30px 6px 5px; white-space: pre-line; touch-action: auto; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; } +} + +@media screen and (max-width: 1024px) and (min-width: 768px) { #ViewModeContainer #Kamban.both #KambanBody #Grid tbody .kamban-row .kamban-container .kamban-item .ui-icon.ui-icon-pencil { - background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMTJweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTMgMTcuNDZ2My4wNGMwIC4yOC4yMi41LjUuNWgzLjA0Yy4xMyAwIC4yNi0uMDUuMzUtLjE1TDE3LjgxIDkuOTRsLTMuNzUtMy43NUwzLjE1IDE3LjFjLS4xLjEtLjE1LjIyLS4xNS4zNnpNMjAuNzEgNy4wNGMuMzktLjM5LjM5LTEuMDIgMC0xLjQxbC0yLjM0LTIuMzRjLS4zOS0uMzktMS4wMi0uMzktMS40MSAwbC0xLjgzIDEuODMgMy43NSAzLjc1IDEuODMtMS44M3oiLz48L3N2Zz4="); - background-position: center; - width: 36px; - height: 36px; - filter: invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%); - margin-right: 0; - top: -7px; - right: -11px; + width: 16px; + height: 16px; + top: 10px; + right: 4px; + } +} + +@media screen and (max-width: 1024px) and (min-width: 0px) { + #ViewModeContainer #Calendar #FullCalendar.fc .fc-header-toolbar .fc-toolbar-chunk:last-child .fc-button-group { + display: flex; + flex-wrap: wrap; + margin: 0; + } + #ViewModeContainer #Calendar #FullCalendar.fc .fc-header-toolbar .fc-toolbar-chunk:last-child .fc-button-group button:nth-child(3) { + border-radius: 0 0.25em 0.25em 0; + } + #ViewModeContainer #Calendar #FullCalendar.fc .fc-header-toolbar .fc-toolbar-chunk:last-child .fc-button-group button:last-child { + border-radius: 0.25em; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 768px) and (min-width: 0px) { + #ViewModeContainer #Calendar #FullCalendar.fc .fc-header-toolbar .fc-toolbar-chunk:last-child .fc-button-group button:nth-child(odd) { + border-radius: 0.25em 0 0 0.25em; + } + #ViewModeContainer #Calendar #FullCalendar.fc .fc-header-toolbar .fc-toolbar-chunk:last-child .fc-button-group button:nth-child(even) { + border-radius: 0 0.25em 0.25em 0; + } +} + +@media screen and (max-width: 1024px) and (min-width: 0px) { #RecordSwitchers { display: flex; align-items: center; @@ -1495,9 +1596,23 @@ overflow: hidden; display: flex; align-items: center; } + #Editor fieldset .command-left { + width: 100%; + } + table.grid tbody tr td svg { + margin-top: calc(3.2vw - 13px); + overflow: unset; + } + table.grid tbody tr td .user { + display: flex; + align-items: center; + } + table.grid tbody tr td .user .ui-icon-person { + margin-top: 0.15vw; + } } -@media screen and (max-width: 980px) and (min-width: 0) { +@media screen and (max-width: 1024px) and (min-width: 0) { #Editor #RecordHeader .user { display: flex; align-items: center; @@ -1505,9 +1620,29 @@ overflow: hidden; #Editor #RecordHeader .user .ui-icon-person { margin-right: 0.6vw; } + #EditorTabsContainer #Users_DeptIdField .ui-icon-person { + top: calc(3vw - 6.5px); + } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 768px) { + .ui-icon { + transform: scale(1.6); + margin-right: 4px; + } + #Editor .ui-button-icon-space { + width: 1vw; + } + #Editor #RecordHeader .user .ui-icon-person { + margin: auto 4px; + } + #EditorTabsContainer #Users_DeptIdField .ui-icon-person { + top: calc(3vw - 3.5px); + right: -30px; + } +} + +@media screen and (max-width: 1024px) and (min-width: 0px) { #OutgoingMailDialog .field-wide { padding-bottom: 5px; } @@ -1526,14 +1661,17 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { .show-password { - top: calc(50% - 10px); + top: calc(50% - 12px); right: 10px; } #LoginFieldSet input[type=checkbox] { transform: scale(1.2); } + #LoginFieldSet input { + height: 10vw; + } #LoginFieldSet input, #LoginFieldSet select { font-size: 4vw; @@ -1544,13 +1682,19 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 768px) { + .show-password { + transform: scale(1.5); + } +} + +@media screen and (max-width: 1024px) and (min-width: 0px) { #Navigations.open { padding-top: 18vw; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #ViewModeContainer .field-auto-thin > .field-label { padding: 7px 2vw 7px 0; } @@ -1577,13 +1721,16 @@ overflow: hidden; height: 4vw; margin-left: 2px; } + #ViewModeContainer #Crosstab .field-control .control-dropdown { + font-size: 2.6vw; + } #CrosstabBody .grid > thead > tr:first-child > th:not(:first-child), #KambanBody .grid > thead > tr:first-child > th:not(:first-child) { white-space: nowrap; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #ImportSettingsDialog .control-checkbox + label { margin: 1.8vw 0 0 1vw; } @@ -1599,20 +1746,32 @@ overflow: hidden; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #ExportSelectorDialog .command-center { padding: 2vw 0; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { + #ViewModeContainer #Grid .control-dropdown, #ViewModeContainer #Grid .datepicker { - width: 35vw; - font-size: 4vw; + width: 25vw; + text-overflow: ellipsis; + white-space: nowrap; + } + #ViewModeContainer #Grid .current-user, + #ViewModeContainer #Grid .current-time { + display: none; + } + #ViewModeContainer #Grid .ui-spinner { + height: 6vw; + max-height: 6vw; + display: flex; + align-items: center; } } -@media screen and (max-width: 980px) and (min-width: 0px) { +@media screen and (max-width: 1024px) and (min-width: 0px) { #ViewModeContainer .both #TimeSeriesValueField, #ViewModeContainer .both #TimeSeriesChartTypeField, #ViewModeContainer .both #TimeSeriesHorizontalAxisField { @@ -1625,11 +1784,14 @@ overflow: hidden; } #ViewModeContainer .both .field-auto-thin:first-child, #ViewModeContainer .both .field-auto-thin:nth-child(2) { - flex: 0 1 calc(100%); + flex: 0 1 calc(50% - 8px); } #ViewModeContainer .both .field-auto-thin:first-child .field-label, #ViewModeContainer .both .field-auto-thin:nth-child(2) .field-label { - min-width: 30%; + min-width: 29%; + } + #ViewModeContainer .both .field-auto-thin:nth-child(3) .field-label { + min-width: 13%; } #ViewModeContainer .both .field-auto-thin select { max-width: 100%; @@ -1637,4 +1799,54 @@ overflow: hidden; #ViewModeContainer .both .field-auto-thin > .field-control { min-width: 68%; } -} \ No newline at end of file +} + +@media screen and (max-width: 1024px) and (min-width: 0px) { + #ApiEditorCommands { + display: flex; + justify-content: center; + padding: 10vw 0; + } +} + +@media screen and (max-width: 1024px) and (min-width: 0px) { + #Editor #TenantForm #EditorTabsContainer .fieldset .field-auto-thin { + width: 100%; + height: 7vw; + margin: 0; + } + #Editor #TenantForm #EditorTabsContainer .fieldset .field-auto-thin .field-control { + width: 100%; + } + #Editor #TenantForm #EditorTabsContainer .fieldset .field-auto-thin .field-control .container-normal label { + padding: 0; + } + #Editor #TenantForm #EditorTabsContainer .fieldset .field-auto-thin .field-control .container-normal #TenantImage { + height: auto; + } + #Editor #TenantForm #EditorTabsContainer .fieldset .button-icon { + margin-top: 5vw; + } + #Editor #TenantForm #EditorTabsContainer .fieldset #StyleField .field-textarea > .field-label, + #Editor #TenantForm #EditorTabsContainer .fieldset #ScriptField .field-textarea > .field-label { + width: 100%; + text-align: left; + } +} + +@media screen and (max-width: 1024px) and (min-width: 0) { + #Versions span { + margin: 20px 10px 20px 0; + } +} + +@media screen and (max-width: 767px) and (min-width: 0) { + #Versions { + font-size: 2.6vw; + width: auto; + padding: 4vw 5vw 4vw 7vw; + } + #Versions span { + margin: 0 10px 0 0; + } +} diff --git a/Implem.Pleasanter/wwwroot/content/responsive.min.css b/Implem.Pleasanter/wwwroot/content/responsive.min.css index 88f929d1f..e0205c2f8 100644 --- a/Implem.Pleasanter/wwwroot/content/responsive.min.css +++ b/Implem.Pleasanter/wwwroot/content/responsive.min.css @@ -1 +1 @@ -@media screen and (max-width:980px) and (min-width:0){#LoginFieldSet{width:100%;padding:10px;font-size:4vw}#LoginFieldSet input,#LoginFieldSet select{font-size:5vw;padding:10px}#LoginFieldSet input[type=checkbox]{transform:scale(2);margin:20px 0 0 10px}#LoginFieldSet button{font-size:4vw}#LoginFieldSet .container-normal{margin-left:0}#LoginFieldSet .field-wide,#LoginFieldSet .field-normal{width:100%;margin:10px 0;float:left}#LoginFieldSet .field-normal .control-checkbox+label{width:auto;margin:0 0 0 30px}#Logins .field-label{width:auto;padding:4px}#LoginMessage{width:100%}#Demo{width:100%;padding:10px;font-size:4vw}#DemoFields .field-label{width:auto;padding:4px}#DemoFields input{font-size:5vw;padding:10px}#DemoFields button{font-size:4vw;float:right;margin-top:10px}#DemoFields .container-normal{margin-left:0}#DemoFields .field-normal{width:100%;margin:10px 0;float:left}#StartGuide{display:none}.container-normal>#ApiKey{word-break:break-all}div[role="dialog"]{width:98% !important;z-index:999}#EnterPriseBanner,#SupportBanner,#CasesBanner{display:none}#EditorTabsContainer>fieldset{display:contents}#EditorTabsContainer>fieldset>fieldset{display:contents}#TenantImage{width:100%}#Search{width:auto;height:auto}#Breadcrumb{display:none}#CopyToClipboards{display:none}#ViewSelectorField{position:relative;margin-bottom:5px;font-size:2.8vw}#HeaderTitleContainer{margin-bottom:3%}#ViewFilters{font-size:2.6vw;padding-bottom:2%}#Aggregations{font-size:2.6vw}#ViewFilters_Reset{float:none}#ViewFilters.reduced,#Aggregations.reduced{border-bottom:1px solid #aaa;margin-bottom:2%;padding:2%}#Aggregations .label{height:auto}#ViewFilters>.field-auto-thin{height:6vw;padding:0;margin:2% 0 0 0;line-height:1;width:49%;display:flex;justify-content:start;align-items:center}#ViewFilters>.field-auto-thin>.field-control{width:100%}#ViewFilters>.field-auto-thin>.field-label{width:30%;text-align:left}#ViewFilters>.field-auto-thin>.field-label+.field-control{width:70%}.ui-multiselect{width:100% !important;height:6vw}.field-auto-thin input[type="checkbox"],.field-auto-thin input[type="radio"]{height:2.6vw;width:2.6vw;margin-right:1vw}.control-checkbox{margin:0}.control-checkbox+label{margin:0}.field-auto-thin>.field-label{padding:0}#RecordInfo div{clear:both;margin-right:0}#RecordInfo div p{font-size:2.6vw}#Application{padding-bottom:15%}#MainForm{display:flex;flex-direction:column}#RecordInfo{margin-bottom:2%}#RecordSwitchers{font-size:2.6vw;width:100%}.ui-button,#RecordSwitchers .current{height:auto;padding:2%!important;line-height:1;margin-right:2%}#EditorComments{width:100%;order:3;font-size:2.6vw}#EditorTabsContainer{width:100%}.fieldset.ui-tabs-panel.ui-widget-content{font-size:2.6vw}.ui-tabs .ui-tabs-panel{padding:1%}.field-wide,.field-markdown{width:100%;min-height:5vw;float:none;padding:0 0 3% 0;clear:both}.field-normal{width:100%;height:auto;padding:0}.field-normal.right-align{text-align:left}.field-markdown>.field-label,.field-normal>.field-label,.field-wide>.field-label{width:100%;clear:both;margin-left:0;padding:1%;font-weight:bold;text-align:left;text-align-last:left}.field-normal>.field-label label,.field-wide>.field-label label{font-weight:bold}.field-normal .container-normal,.field-control .container-normal{margin-left:0}.control-dropdown{height:auto}.ui-spinner a.ui-spinner-button{height:50%}.field-normal .control-text{width:100%;height:auto;padding:1%;line-height:1}.control-textbox{height:auto}.ui-widget.ui-widget-content{font-size:2.6vw}#Guide{font-size:2.6vw}.alert-success,.alert-warning,.alert-error{height:auto;font-size:2.6vw}#MainCommandsContainer{height:auto;padding:2vw 0;font-size:2.6vw;z-index:200}#Footer{z-index:102}.ui-tabs .ui-tabs-nav{padding:1%;font-size:2.6vw}.ui-tabs .ui-tabs-nav li{margin-bottom:1%;padding-bottom:0;border-radius:4px}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:1%;padding-bottom:0;border-radius:4px}.message{bottom:140px}}@media screen and (max-width:980px) and (min-width:0){body{min-width:320px!important}#Header{height:auto;position:relative}#CorpLogo{float:none;width:30%}#MainContainer{min-height:100vh}#Header a#navtgl{position:absolute;display:block;padding:1.6vw 1.4vw;border:.4vw solid #d19405;border-radius:1vw;top:1.4vw;right:4vw;height:8vw;width:8vw;z-index:101;background:#fece2f}#Header a#navtgl::before{content:'';display:block;height:1.3vw;border-top:.4vw solid #333;border-bottom:.4vw solid #333}#Header a#navtgl::after{content:'';display:block;height:1.4vw;border-bottom:.4vw solid #333}* #Navigations{box-sizing:border-box}#Navigations{width:100%;max-height:0;overflow:hidden;margin:0;padding:0 5%;border:none;position:relative;top:0;right:0;border-radius:0;z-index:100;font-size:3.2vw;line-height:7vw;transition:.5s}#Navigations.open{max-height:none;height:auto;overflow:visible;margin-top:2%;margin-bottom:5%;padding:5%;transition:.5s}#NavigationMenu>li.sub-menu>div.hover{background:none}#NavigationMenu{float:none;margin-right:0;margin-bottom:3%}#SearchField{float:none;margin:0;color:#000}#NavigationMenu>li{width:100%;height:auto;display:block;float:none;position:relative}#NavigationMenu>li>div{height:auto;text-align:left;line-height:7vw;font-weight:bold}#NavigationMenu>li>div:hover{background:none}#NavigationMenu>li>div>a{height:auto;display:block;text-decoration:none;font-weight:bold}#NavigationMenu .menu{width:100%;border-top:none !important;position:relative;top:0;right:0;border-radius:0;z-index:3}.pc-dn{display:block!important}#NavigationMenu .menu>li>a.ui-state-active{font-weight:normal;text-decoration:none}.ui-menu .ui-menu-item{border-top:1px solid #d19405}#NewMenuContainer{border:1px solid #d19405;background:#fff}}@media screen and (max-width:980px) and (min-width:0){#SiteMenu .nav-site{width:20vw;height:20vw;text-align:center;border-radius:.5vw;float:none;margin:6%}#SiteMenu .sortable{display:flex;justify-content:flex-start;align-items:flex-start;flex-wrap:wrap}#SiteMenu .nav-site.sites{width:20vw!important;height:20vw!important;background:#fff;border-radius:5px}#SiteMenu .nav-site .heading{width:8vw;height:3vw;top:-3vw}#SiteMenu .nav-site.sites.to-parent{height:auto!important;box-shadow:none;margin-top:3%;margin-bottom:0}#SiteMenu .nav-site.sites.to-parent span.title{position:relative;top:0;text-align:left;width:100%;margin-left:0}#SiteMenu .nav-site.sites.to-parent .heading{display:none}#SiteMenu .nav-site a{padding:0;overflow:inherit}#SiteMenu .nav-site .site-image-thumbnail{position:relative;top:inherit;left:inherit;max-width:inherit;border-radius:unset;width:90%;z-index:1;margin:0 auto;display:block}#SiteMenu .nav-site span.title::before{content:'';display:block;height:0}#SiteMenu .nav-site span.title{margin-left:0;font-size:14px}#SiteMenu .nav-site.has-image a{padding:1vw 0 0}#SiteMenu .nav-site .conditions{position:absolute;top:-2.4vw;right:-2.4vw;z-index:2}#SiteMenu .nav-site .conditions .elapsed-time{display:none}#SiteMenu .nav-site .conditions .count{display:none}#SiteMenu .nav-site .conditions .overdue{height:6vw;min-width:6vw;line-height:6vw;font-size:2.6vw;border-radius:3vw;font-weight:bold;padding:0}#SiteMenu .nav-site[data-type="Wikis"]{border-radius:2px;position:relative;width:20vw;border:2px solid #ccc}#SiteMenu .nav-site[data-type="Wikis"] a::before,#SiteMenu .nav-site[data-type="Wikis"] a::after{content:'';display:block;position:absolute;height:20%;width:80%;left:10%;border-top:2px solid #ccc;border-bottom:2px solid #ccc}#SiteMenu .nav-site[data-type="Wikis"] a::before{top:20%}#SiteMenu .nav-site[data-type="Wikis"] a::after{top:60%}#SiteMenu .nav-site[data-type="Wikis"] a img{margin-top:15%}#SiteMenu .nav-site.sites.to-parent{height:auto!important;border:none;background:none;text-align:left}#SiteMenu .nav-site.to-parent .ui-icon{display:none}#SiteMenu .nav-site.to-parent a{position:relative;display:inline-block;padding:0 0 0 16px;color:#000;vertical-align:middle;text-decoration:none;font-size:15px}#SiteMenu .nav-site.to-parent a::before,#SiteMenu .nav-site.to-parent a::after{position:absolute;top:0;bottom:0;left:0;margin:auto;content:"";vertical-align:middle}#SiteMenu .nav-site.to-parent a::before{left:5px;width:7px;height:3px;background:#7a0}#SiteMenu .nav-site.to-parent a::after{left:2px;width:6px;height:6px;border-bottom:3px solid #7a0;border-left:3px solid #7a0;-webkit-transform:rotate(45deg);transform:rotate(45deg)}#SiteMenu .nav-site span.title{margin-left:0;font-size:2.6vw;top:22vw;position:absolute;display:block;text-align:center;width:140%;margin-left:-20%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#SiteMenu .nav-site .stacking1{width:20vw;height:20vw;border-bottom:solid 1px #c0c0c0;border-right:solid 1px #c0c0c0;position:absolute;top:1px;left:1px;border-radius:5px}#SiteMenu .nav-site .stacking2{width:20vw;height:20vw;border-bottom:solid 1px #c0c0c0;border-right:solid 1px #c0c0c0;position:absolute;top:4px;left:4px;border-radius:5px}#SiteMenu .nav-sites .to-parent a img{display:none}#SiteMenu .nav-site.to-parent.has-image a{padding:0 0 0 15px}}@media screen and (max-width:980px) and (min-width:0){#FieldSetStandard{display:flex;flex-direction:column}.legend{order:2}#StandardTemplatesViewer{order:3}.template-selectable{order:1;float:none}.template-viewer-container{float:none;margin:0}.template-viewer{margin:0}.template-selectable{width:100%}.template-tab-container{min-height:10px}.field-vertical{width:100%;float:none;padding:0 0 20px 0}.container-selectable .wrapper{min-height:auto}.h350{height:auto}#EditInDialogBody{padding-bottom:15%}.links{overflow:auto}@media screen and (max-width:980px) and (min-width:0){#FieldSetHistories{overflow:auto;width:100%}#ViewModeContainer{overflow:auto;width:100%;padding-top:1%}#CrosstabBody{overflow:auto;width:100%}#GanttBody{overflow:auto;width:100%;padding-top:5%}.grid{font-size:2.8vw;width:98%}.grid>thead th{min-width:10vw;white-space:nowrap}.grid>tbody td{min-width:10vw;white-space:nowrap}.grid>thead th:nth-child(1),.grid>tbody td:nth-child(1){min-width:1vw}.grid>tbody td p{white-space:nowrap}#Calendar{font-size:2.6vw}#Calendar button{margin-bottom:2%}#CalendarBody #Grid thead{background:#fff}#CalendarMonth{display:block}#Calendar .field-auto-thin{display:flex;align-items:center;width:33%;margin:0;padding:0;margin-bottom:2%!important}#Calendar .field-auto-thin p{margin-right:1%}#Calendar .field-auto-thin select{max-width:none}#CalendarTimePeriod,#CalendarFromTo,#CalendarMonth{height:auto}#CalendarMonth{margin-bottom:2%}.w100{width:auto}#CrosstabBody{margin-top:3%}#CrosstabBody #Grid{table-layout:auto}#CrosstabBody .grid>thead>tr>th,#CrosstabBody .grid>tbody>tr>th{white-space:nowrap}#CrosstabBody .grid>thead th{min-width:10vw;white-space:nowrap}#CrosstabBody .grid>tbody td{min-width:10vw;white-space:nowrap}#Crosstab{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center}#Crosstab .field-auto-thin{display:flex;align-items:center;width:48%;margin:0;padding:0;font-size:2.6vw}#Crosstab .field-auto-thin#CrosstabTimePeriodField{width:48%}#Crosstab .field-auto-thin p{width:100%;margin-right:2%;white-space:nowrap}#Crosstab .field-auto-thin select{max-width:none}#Crosstab #CrosstabMonth{width:48%;margin-top:2%;margin-right:0;font-size:2.6vw}#Crosstab button{font-size:2.6vw;margin-top:1%}.svg-crosstab{display:block}#ViewModeContainer .both{display:flex;align-items:center;flex-wrap:wrap}#ViewModeContainer .both .field-auto-thin{display:flex;align-items:center;width:48%;margin:0;padding:0;font-size:2.6vw;height:auto;padding-top:2%}#ViewModeContainer .both .field-auto-thin .field-auto-thin{width:30%}#ViewModeContainer .both .field-auto-thin:nth-child(3){width:100%}#ViewModeContainer .both .field-auto-thin:nth-child(3) .field-auto-thin{width:48%;display:block}#ViewModeContainer .field-auto-thin p{margin-right:2%;white-space:nowrap;text-align:left}#GanttAxis{width:1500px;position:relative;left:0;bottom:0}#Gantt{width:1500px}#BurnDown{width:1500px}#TimeSeriesBody{padding-top:5%;margin-left:-5%;width:1500px}#TimeSeries{width:1500px}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(3){width:48%}#ViewModeContainer #Kamban.both .field-auto-thin .field-control{width:100%}#KambanBody{margin-top:3%}#KambanBody #Grid{table-layout:auto}#KambanBody .grid>thead>tr>th,#KambanBody .grid>tbody>tr>th{white-space:nowrap}#KambanBody .grid>thead th{min-width:10vw;white-space:nowrap}#KambanBody .grid>tbody td{min-width:10vw;white-space:nowrap}}@media screen and (max-width:980px) and (min-width:0){#Header{padding:0 calc(5vw)}#Header a#navtgl{right:5vw}#Application,#Footer{padding-left:5vw;padding-right:5vw}#SiteMenu .nav-site{margin:5%}:not(td)>div.field-control .container-normal{margin-left:0}*{line-height:1.4}.field-normal .control-textbox,.field-normal .control-dropdown,.field-normal .control-text,.field-control .control-textbox,.field-control .control-dropdown,.field-control .control-text,.container-normal .control-textbox,.container-normal .control-dropdown,.container-normal .control-text{min-height:unset;height:6vw;line-height:6vw;padding-top:0;padding-bottom:0}body{font-size:16px}}@media screen and (max-width:980px) and (min-width:0){#HeaderTitle{font-size:16px}}@media screen and (max-width:980px) and (min-width:0){.command-center{padding:0}.ui-dialog .ui-dialog-titlebar-close{top:0;bottom:0;width:5vw;height:5vw;margin:auto 0}}@media screen and (max-width:980px) and (min-width:0){#ViewSelector{font-size:2.6vw}}@media screen and (max-width:980px) and (min-width:0){#Logo a{align-items:center;display:flex}#Logo #ProductLogo{font-size:18px;padding-left:8px}#CorpLogo{float:none;height:calc(8vw + 10px);width:unset;margin-top:0}}@media screen and (max-width:980px) and (min-width:0){#Editor .field-control .container-normal{width:calc(100% - 20px)}#Editor .field-control .ui-icon.ui-icon-clock.current-time{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDI0IDI0IiBoZWlnaHQ9IjEycHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjEycHgiIGZpbGw9IiMwMDAwMDAiPjxnPjxyZWN0IGZpbGw9Im5vbmUiIGhlaWdodD0iMjQiIHdpZHRoPSIyNCIvPjwvZz48Zz48Zz48Zz48cGF0aCBkPSJNMTIsMkM2LjUsMiwyLDYuNSwyLDEyczQuNSwxMCwxMCwxMHMxMC00LjUsMTAtMTBTMTcuNSwyLDEyLDJ6IE0xNi4yLDE2LjJMMTEsMTNWN2gxLjV2NS4ybDQuNSwyLjdMMTYuMiwxNi4yeiIvPjwvZz48L2c+PC9nPjwvc3ZnPg==");background-position:center;width:12px;height:12px;filter:invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%);top:calc(3vw - 3.5px);right:-16px}#Editor .field-control .ui-icon.ui-icon-person.current-user{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMTJweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0xMiAxMmMyLjIxIDAgNC0xLjc5IDQtNHMtMS43OS00LTQtNC00IDEuNzktNCA0IDEuNzkgNCA0IDR6bTAgMmMtMi42NyAwLTggMS4zNC04IDR2MmgxNnYtMmMwLTIuNjYtNS4zMy00LTgtNHoiLz48L3N2Zz4=");background-position:center;width:12px;height:12px;filter:invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%);top:calc(3vw - 3.5px);right:-16px}}@media screen and (max-width:980px) and (min-width:0){#FieldSetAddressBook #OutgoingMailDestinationForm .container-left{width:38vw}#FieldSetAddressBook #OutgoingMailDestinationForm .container-right .command-left{float:unset;padding:0}#FieldSetAddressBook #OutgoingMailDestinationForm .container-right .command-left button{margin:2px}#FieldSetAddressBook #OutgoingMailDestinationForm .container-right .container-selectable .wrapper{height:40vw}#FieldSetAddressBook #OutgoingMailDestinationForm .container-right>*{margin-left:40vw}}@media screen and (max-width:980px) and (min-width:0){#Issues_WorkValue{width:100px}}@media screen and (max-width:980px) and (min-width:0){body::before{content:'';position:fixed;width:5vw;height:50vh;top:0;left:0;background:#fff;z-index:200}body::after{content:'';position:fixed;width:5vw;height:50vh;top:0;right:0;background:#fff;z-index:700}}@media screen and (max-width:980px) and (min-width:0){#Users_LoginId,#Users_Password{height:40px}#LoginMessage span{font-size:3.5vw}#PortalLink{font-size:3.5vw;top:3vw}#LoginFieldSet{margin:65px auto 20px auto}#LoginFieldSet input[type=checkbox]{margin:auto 0;margin-left:1.2vw}#LoginFieldSet button{margin-top:0}#LoginFieldSet .field-wide,#LoginFieldSet .field-normal{margin:0 0}#LoginFieldSet .field-normal .control-checkbox+label{margin:auto 0;margin-left:4vw;padding:0}#Logins .field-label{width:100%}}@media screen and (max-width:980px) and (min-width:0){#Editor .field-markdown>.field-label>label{font-weight:bold}#Editor .field-control .unit{font-size:2.6vw;padding-top:calc((18px - 1.4em)/2)}#Editor .ui-spinner .control-spinner{height:100%}}@media screen and (max-width:980px) and (min-width:0){#GridCheckAll{margin-top:0}label[for="GridCheckAll"]{margin:0}#Footer{font-size:2.8vw;height:auto}#MainCommandsContainer{bottom:calc(2.8vw*1.4 + 10px)}body>thead>tr{font-size:.75em}}@media screen and (max-width:980px) and (min-width:0){#SiteImageSettingsEditor .field-auto-thin,#GridSettingsEditor .field-auto-thin,#FiltersSettingsEditor .field-auto-thin,#EditorSettingsEditor .field-auto-thin,#LinksSettingsEditor .field-auto-thin,#HistoriesSettingsEditor .field-auto-thin,#FormulasSettingsEditor .field-auto-thin,#ViewsSettingsEditor .field-auto-thin,#ImportsSettingsEditor .field-auto-thin,#ExportsSettingsEditor .field-auto-thin,#CalendarSettingsEditor .field-auto-thin,#CrosstabSettingsEditor .field-auto-thin,#GanttSettingsEditor .field-auto-thin,#BurnDownSettingsEditor .field-auto-thin,#TimeSeriesSettingsEditor .field-auto-thin,#KambanSettingsEditor .field-auto-thin,#ImageLibSettingsEditor .field-auto-thin,#SearchSettingsEditor .field-auto-thin,#StylesSettingsEditor .field-auto-thin,#ScriptsSettingsEditor .field-auto-thin,#PublishSettingsEditor .field-auto-thin,#FieldSetSiteAccessControl .field-auto-thin{padding-right:0;height:auto;display:flex;align-items:center;clear:both}#SiteImageSettingsEditor .field-auto-thin .container-normal,#GridSettingsEditor .field-auto-thin .container-normal,#FiltersSettingsEditor .field-auto-thin .container-normal,#EditorSettingsEditor .field-auto-thin .container-normal,#LinksSettingsEditor .field-auto-thin .container-normal,#HistoriesSettingsEditor .field-auto-thin .container-normal,#FormulasSettingsEditor .field-auto-thin .container-normal,#ViewsSettingsEditor .field-auto-thin .container-normal,#ImportsSettingsEditor .field-auto-thin .container-normal,#ExportsSettingsEditor .field-auto-thin .container-normal,#CalendarSettingsEditor .field-auto-thin .container-normal,#CrosstabSettingsEditor .field-auto-thin .container-normal,#GanttSettingsEditor .field-auto-thin .container-normal,#BurnDownSettingsEditor .field-auto-thin .container-normal,#TimeSeriesSettingsEditor .field-auto-thin .container-normal,#KambanSettingsEditor .field-auto-thin .container-normal,#ImageLibSettingsEditor .field-auto-thin .container-normal,#SearchSettingsEditor .field-auto-thin .container-normal,#StylesSettingsEditor .field-auto-thin .container-normal,#ScriptsSettingsEditor .field-auto-thin .container-normal,#PublishSettingsEditor .field-auto-thin .container-normal,#FieldSetSiteAccessControl .field-auto-thin .container-normal{width:100%}#SiteImageSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#GridSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#FiltersSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#EditorSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#LinksSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#HistoriesSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#FormulasSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#ViewsSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#ImportsSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#ExportsSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#CalendarSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#CrosstabSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#GanttSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#BurnDownSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#TimeSeriesSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#KambanSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#ImageLibSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#SearchSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#StylesSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#ScriptsSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#PublishSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#FieldSetSiteAccessControl .field-auto-thin .container-normal .control-checkbox~label{display:unset;float:unset;width:auto}#SiteImageSettingsEditor .field-auto-thin .field-label~.field-control,#GridSettingsEditor .field-auto-thin .field-label~.field-control,#FiltersSettingsEditor .field-auto-thin .field-label~.field-control,#EditorSettingsEditor .field-auto-thin .field-label~.field-control,#LinksSettingsEditor .field-auto-thin .field-label~.field-control,#HistoriesSettingsEditor .field-auto-thin .field-label~.field-control,#FormulasSettingsEditor .field-auto-thin .field-label~.field-control,#ViewsSettingsEditor .field-auto-thin .field-label~.field-control,#ImportsSettingsEditor .field-auto-thin .field-label~.field-control,#ExportsSettingsEditor .field-auto-thin .field-label~.field-control,#CalendarSettingsEditor .field-auto-thin .field-label~.field-control,#CrosstabSettingsEditor .field-auto-thin .field-label~.field-control,#GanttSettingsEditor .field-auto-thin .field-label~.field-control,#BurnDownSettingsEditor .field-auto-thin .field-label~.field-control,#TimeSeriesSettingsEditor .field-auto-thin .field-label~.field-control,#KambanSettingsEditor .field-auto-thin .field-label~.field-control,#ImageLibSettingsEditor .field-auto-thin .field-label~.field-control,#SearchSettingsEditor .field-auto-thin .field-label~.field-control,#StylesSettingsEditor .field-auto-thin .field-label~.field-control,#ScriptsSettingsEditor .field-auto-thin .field-label~.field-control,#PublishSettingsEditor .field-auto-thin .field-label~.field-control,#FieldSetSiteAccessControl .field-auto-thin .field-label~.field-control{margin-left:10px}#SiteImageSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#GridSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#FiltersSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#EditorSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#LinksSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#HistoriesSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#FormulasSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#ViewsSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#ImportsSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#ExportsSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#CalendarSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#CrosstabSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#GanttSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#BurnDownSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#TimeSeriesSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#KambanSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#ImageLibSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#SearchSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#StylesSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#ScriptsSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#PublishSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#FieldSetSiteAccessControl .field-auto-thin .field-label~.field-control .container-normal{width:100%}#FieldSetGeneral .field-control .container-normal .control-checkbox~label{width:auto}#GridSettingsEditor #GridEditorType{max-width:unset}#SiteImageSettingsEditor #SiteImage{width:100%;height:7vw}#SiteImageSettingsEditor #SetSiteImage{margin-right:0}}@media screen and (max-width:980px) and (min-width:0){#Aggregations{display:flex;flex-wrap:wrap;row-gap:5px;justify-content:flex-start;align-items:center}#Aggregations span.label{flex:1 0 auto;margin:0;text-align:center;align-self:stretch;display:flex;align-items:center;justify-content:flex-start}#Aggregations span.data{flex:1 0 auto;margin:0;align-self:stretch;display:flex;align-items:center;justify-content:flex-start;height:auto}#Aggregations span.data.no-choice{flex-basis:auto;align-self:stretch}#Aggregations span.data.link span{font-weight:bold}#Aggregations #ReduceAggregations{width:100%}}@media screen and (max-width:980px) and (min-width:0){#ViewModeContainer .grid{vertical-align:middle}#ViewModeContainer .grid tr td:first-child{padding:6px}input[type='checkbox'],.field-auto-thin input[type='checkbox']{width:3vw;height:3vw}.field-auto-thin input[type='checkbox']+label{padding-top:2px}}@media screen and (max-width:980px) and (min-width:0){#SearchField #Search{font-size:3vw;width:100%}#SearchField #Search::placeholder{font-size:3vw}}@media screen and (max-width:980px) and (min-width:0){#ViewFilters #ViewFilters_Reset{margin-left:auto;margin-right:0}#ViewFilters .field-auto-thin{width:50%}#ViewFilters .field-auto-thin .field-control .container-normal{display:flex;align-items:center}#ViewFilters .field-auto-thin .field-control .container-normal input[type='checkbox']{margin-right:4px;margin-top:1px}#ViewFilters .field-auto-thin .field-control .container-normal .ui-widget.ui-state-default.ui-multiselect,#ViewFilters .field-auto-thin .field-control .container-normal .control-textbox{height:6vw;font-size:2.6vw}#ViewFilters #ViewFilters_SearchField{width:100%}#ViewFilters #ViewFilters_SearchField p.field-label{width:17%}#ViewFilters #ViewFilters_SearchField .field-control{width:100%}#ViewFilters>.field-auto-thin:nth-child(odd){padding-right:2px}#ViewFilters>.field-auto-thin:nth-child(even){padding-left:2px}.ui-multiselect-menu .ui-helper-reset{position:relative}.ui-multiselect-menu .ui-helper-reset li{width:100%}.ui-multiselect-menu .ui-helper-reset li>label span{position:relative;top:-4px}.ui-multiselect-menu .ui-helper-reset li .ui-multiselect-all,.ui-multiselect-menu .ui-helper-reset li .ui-multiselect-none{width:100%;display:flex;align-items:center}.ui-multiselect-menu .ui-helper-reset li .ui-multiselect-all span:last-child,.ui-multiselect-menu .ui-helper-reset li .ui-multiselect-none span:last-child{padding-left:10px}.ui-multiselect-menu .ui-helper-reset li .ui-multiselect-close{position:absolute;top:8px;right:0}}@media screen and (max-width:980px) and (min-width:0){#EditorTabsContainer .legend.applied{display:flex;align-items:center;font-weight:bold}#EditorTabsContainer #PermissionEditor .field-vertical:first-child>.field-control{border-bottom:1px solid #d19405;padding-bottom:2vw}#EditorTabsContainer #PermissionEditor .field-control .container-selectable .command-left{display:flex;align-items:center;flex-wrap:wrap;width:100%}#EditorTabsContainer #PermissionEditor .field-control .container-selectable .command-left #SearchPermissionElements{margin:2px 1vw 2px 6vw;height:7vw}#EditorTabsContainer #PermissionEditor .field-control .container-selectable .command-left button{align-self:stretch;display:flex;align-items:center;justify-content:center;white-space:nowrap}#EditorTabsContainer #PermissionEditor .field-control .container-selectable .command-left button .ui-icon{position:relative;top:.5vw;width:18px;height:18px;margin-right:0}#EditorTabsContainer #PermissionEditor .field-control .container-selectable .command-left #OpenPermissionsDialog,#EditorTabsContainer #PermissionEditor .field-control .container-selectable .command-left #DeletePermissions{line-height:1.5}#EditorTabsContainer #PermissionEditor .field-control .container-selectable #CurrentPermissionsWrapper{min-height:15vw}}@media screen and (max-width:980px) and (min-width:0){thead>tr.ui-widget-header th div>span{font-size:2.8vw;white-space:nowrap}}@media screen and (max-width:980px) and (min-width:0){#EditorTabsContainer .field-control .container-normal .ui-icon.ui-icon-pencil.button-edit-markdown{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMTJweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0zIDE3LjI1VjIxaDMuNzVMMTcuODEgOS45NGwtMy43NS0zLjc1TDMgMTcuMjV6TTIwLjcxIDcuMDRjLjM5LS4zOS4zOS0xLjAyIDAtMS40MWwtMi4zNC0yLjM0Yy0uMzktLjM5LTEuMDItLjM5LTEuNDEgMGwtMS44MyAxLjgzIDMuNzUgMy43NSAxLjgzLTEuODN6Ii8+PC9zdmc+");background-position:center;width:12px;height:12px;filter:invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%);top:8px;right:4px}#EditorTabsContainer .field-control .container-normal .ui-icon.ui-icon-image.button-upload-image{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMTJweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0yMSAxOVY1YzAtMS4xLS45LTItMi0ySDVjLTEuMSAwLTIgLjktMiAydjE0YzAgMS4xLjkgMiAyIDJoMTRjMS4xIDAgMi0uOSAyLTJ6TTguNSAxMy41bDIuNSAzLjAxTDE0LjUgMTJsNC41IDZINWwzLjUtNC41eiIvPjwvc3ZnPg==");background-position:center;width:12px;height:12px;filter:invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%);position:relative;left:-1px}}@media screen and (max-width:980px) and (min-width:0){#EditorTabsContainer{overflow:auto}#EditorComments{padding:0;margin:0}#EditorComments #CommentField .control-textarea{height:15vw}#EditorComments #CommentField .control-textarea::placeholder{font-size:2.6vw}}@media screen and (max-width:980px) and (min-width:0){.is-showMenu{overflow:hidden}.is-showMenu body{position:fixed;overflow:hidden}.bg-overlay{background:rgba(0,0,0,.5);position:fixed;top:0;left:0;z-index:301;width:100%;height:100%;display:none}#MainContainer{overflow:hidden}header#Header{position:fixed;top:0;z-index:1000;background-color:#fff;transition:all .5s ease}header#Header a#navtgl{top:8px;z-index:1000;transition:all .5s ease}header#Header a#navtgl::after{transition:all .5s ease}header#Header a#navtgl.on{transition:all .5s ease;position:fixed}header#Header a#navtgl.on::before{transition:all .5s ease;border-top:none;transform:translate(12.5%,50%) rotate(50deg)}header#Header a#navtgl.on::after{transition:all .5s ease;transform:translate(12.5%,0%) rotate(126deg)}#Navigations{transition:all .5s ease;max-height:100vh;height:100vh;position:absolute;top:0;right:-1000px;z-index:999;padding:5%;width:70%;padding-top:112px;opacity:0}#Navigations.open{opacity:1;padding-top:112px;right:0;height:100vh;margin:0;position:fixed;top:0;z-index:1000}}@media screen and (max-width:980px) and (min-width:0){#OutgoingMailsForm{width:100%;font-size:2.6vw}#OutgoingMailsForm .item h3.title-header{height:auto}#OutgoingMailsForm .item .content{padding:.2em;margin:0}#OutgoingMailsForm .item .content .field-auto,#OutgoingMailsForm .item .content .field-auto-thin{width:100%;margin-right:0;padding-right:0;padding-bottom:0;display:flex;flex-direction:column;height:auto}#OutgoingMailsForm .item .content .field-auto .field-label,#OutgoingMailsForm .item .content .field-auto-thin .field-label{float:none;padding:7px 7px 7px 0;width:100%;text-align:left;display:block}#OutgoingMailsForm .item .content .field-auto .field-label label,#OutgoingMailsForm .item .content .field-auto-thin .field-label label{font-weight:bold}#OutgoingMailsForm .item .content .field-auto .field-control,#OutgoingMailsForm .item .content .field-auto-thin .field-control{float:none;width:100%}#OutgoingMailsForm .item .content .field-auto .field-control .container-normal,#OutgoingMailsForm .item .content .field-auto-thin .field-control .container-normal{margin-right:0;width:100%}#OutgoingMailsForm .item .content .field-auto .field-control .container-normal .control-text,#OutgoingMailsForm .item .content .field-auto-thin .field-control .container-normal .control-text{min-height:0;height:auto}#OutgoingMailsForm .item .content .field-auto-thin{margin-left:0}#OutgoingMailsForm .item .content .field-wide{display:flex;flex-direction:column;padding:0}#OutgoingMailsForm .item .content .field-wide .field-label{padding:7px 0}#OutgoingMailsForm .item .content .field-wide .field-control .container-normal{margin-right:0;width:100%}}@media screen and (max-width:980px) and (min-width:0){#SiteMenu li.ui-sortable-handle{touch-action:unset}}@media screen and (max-width:980px) and (min-width:0){.message .close{top:unset;bottom:calc(50% - 8px);margin:auto}}@media screen and (max-width:980px) and (min-width:0){#EditorComments #CommentField .ui-icon.ui-icon-image.button-upload-image{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMTJweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0yMSAxOVY1YzAtMS4xLS45LTItMi0ySDVjLTEuMSAwLTIgLjktMiAydjE0YzAgMS4xLjkgMiAyIDJoMTRjMS4xIDAgMi0uOSAyLTJ6TTguNSAxMy41bDIuNSAzLjAxTDE0LjUgMTJsNC41IDZINWwzLjUtNC41eiIvPjwvc3ZnPg==");background-position:center;width:12px;height:12px;filter:invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%);position:relative;left:0}}@media screen and (max-width:980px) and (min-width:0){#Navigations.open{overflow-y:scroll}#Navigations #NavigationMenu #NewMenuContainer{background:unset;border:none}#Navigations #NavigationMenu #NewMenuContainer a{line-height:7vw}#Navigations #NavigationMenu li.sub-menu .ui-menu-item .ui-menu-item-wrapper{font-size:3vw;padding-left:6vw}}@media screen and (max-width:980px) and (min-width:0){#Editor .field-normal .field-control .container-normal input[type='checkbox'].control-checkbox{position:relative;margin-right:6px;margin-top:.3vw}}@media screen and (max-width:980px) and (min-width:0){#Editor #EditorTabsContainer .field-normal,#Editor #EditorTabsContainer .field-wide,#Editor #EditorTabsContainer .field-markdown{display:inline-block;margin-top:8px;padding-bottom:0}}@media screen and (max-width:980px) and (min-width:0){#ViewModeContainer #Calendar.both select{font-size:2.6vw}#ViewModeContainer #Calendar.both .field-label{min-width:30%;margin-right:15px}#ViewModeContainer #Calendar.both .field-auto-thin .field-control .container-normal{display:flex;align-items:center}#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3){flex:0 1 calc(64%)}#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) .field-label{min-width:22%}#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) .field-control{width:74%}#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(4){flex:0 1 calc(33% + 1px);padding-top:2%}#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(4) .field-control .container-normal{justify-content:flex-end}#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(4) .field-control .container-normal #CalendarDate{margin-right:0;width:98%;font-size:2.6vw}#ViewModeContainer #Calendar.both button{flex:1 0 calc((100%/3) - 32px);margin:2% 10px 2% 10px}#ViewModeContainer .grid.fixed{width:100%}#ViewModeContainer .grid.fixed tbody tr td.container .item{touch-action:auto;min-height:50px}#ViewModeContainer .grid.fixed tbody tr td.container .item .title .ui-icon.ui-icon-pencil{margin-right:5px;background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMzBweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMzBweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0zIDE3LjI1VjIxaDMuNzVMMTcuODEgOS45NGwtMy43NS0zLjc1TDMgMTcuMjV6TTIwLjcxIDcuMDRjLjM5LS4zOS4zOS0xLjAyIDAtMS40MWwtMi4zNC0yLjM0Yy0uMzktLjM5LTEuMDItLjM5LTEuNDEgMGwtMS44MyAxLjgzIDMuNzUgMy43NSAxLjgzLTEuODN6Ii8+PC9zdmc+");background-position:center;width:36px;height:36px;filter:invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%)}#ViewModeContainer .grid.fixed tbody tr td.container .item .connection{min-height:50px}#ViewModeContainer .grid.fixed tbody tr td.container .dummy{height:50px}#ViewModeContainer .grid.fixed tbody tr td.container:first-child .item{margin-top:0;margin-bottom:5px}#ViewModeContainer .grid.fixed tbody tr td.container:not(:first-child) .item{margin-top:5px}thead th.calendar-header{overflow-x:hidden}}@media screen and (max-width:980px) and (min-width:0){#ViewModeContainer .both{column-gap:16px}#ViewModeContainer .both .field-auto-thin:first-child,#ViewModeContainer .both .field-auto-thin:nth-child(2){flex:0 1 calc(50% - 8px)}#ViewModeContainer .both .field-auto-thin:first-child .field-control,#ViewModeContainer .both .field-auto-thin:nth-child(2) .field-control{flex:1}#ViewModeContainer .both .field-auto-thin:first-child .field-control select,#ViewModeContainer .both .field-auto-thin:nth-child(2) .field-control select{max-width:100%}#ViewModeContainer .both .field-auto-thin:nth-child(3){row-gap:12px;flex-wrap:wrap}#ViewModeContainer .both .field-auto-thin:nth-child(3) .field-label{min-width:15%}#ViewModeContainer .both .field-auto-thin:nth-child(3) .field-auto-thin{display:flex;align-items:center;flex:1 0 100%}#ViewModeContainer .both .field-auto-thin:nth-child(3) .field-auto-thin #GanttStartDate{width:100%;font-size:2.6vw;margin-right:0}#ViewModeContainer .both .field-auto-thin:nth-child(3) button{flex:1}#ViewModeContainer .both .field-auto-thin:nth-child(3) button:last-child{margin-right:8px}#ViewModeContainer .both .field-auto-thin:nth-child(4){width:100%;padding-top:12px}#ViewModeContainer .both .field-auto-thin:nth-child(4) .field-control{width:100%}#ViewModeContainer .both .field-auto-thin:nth-child(4) .field-control .container-normal{width:100%;display:flex;align-items:center;column-gap:32px}#ViewModeContainer .both .field-auto-thin:nth-child(4) .field-control .container-normal #GanttPeriod\,ui{width:99%;margin-top:0}#ViewModeContainer .both .field-auto-thin:nth-child(4) .field-control .container-normal #GanttPeriod{margin:0}#GanttBody{max-height:70vh}#GanttBody text{font-size:2.6vw}#GanttBody .title text.summary{font-size:3vw}#GanttBody #GanttAxis{left:auto;position:sticky}}@media screen and (max-width:980px) and (min-width:0){#ViewModeContainer #Kamban.both .field-auto-thin select{font-size:2.6vw}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(1),#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(2),#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(3),#ViewModeContainer #Kamban.both .field-auto-thin#KambanValueField{width:100%;flex:0 1 calc(50% - 8px);flex-wrap:wrap;display:flex;row-gap:0}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(1) .field-label,#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(2) .field-label,#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(3) .field-label,#ViewModeContainer #Kamban.both .field-auto-thin#KambanValueField .field-label{width:100%}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(1) select,#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(2) select,#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(3) select,#ViewModeContainer #Kamban.both .field-auto-thin#KambanValueField select{max-width:100%}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(3){padding-top:4%}#ViewModeContainer #Kamban.both .field-auto-thin#KambanValueField{padding-top:4%}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(5){display:block;width:100%;padding-top:4%}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(5) .field-label{min-width:50%;margin-right:10px}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(5) select{max-width:100%}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(6),#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(7){width:calc(50% - 8px);padding-top:4%}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(6) .container-normal,#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(7) .container-normal{display:flex;align-items:center}#ViewModeContainer #Kamban.both #KambanBody #Grid tbody .kamban-row .kamban-container .kamban-item{overflow:hidden;padding:6px 30px 6px 5px;white-space:pre-line;touch-action:auto;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical}#ViewModeContainer #Kamban.both #KambanBody #Grid tbody .kamban-row .kamban-container .kamban-item .ui-icon.ui-icon-pencil{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMTJweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTMgMTcuNDZ2My4wNGMwIC4yOC4yMi41LjUuNWgzLjA0Yy4xMyAwIC4yNi0uMDUuMzUtLjE1TDE3LjgxIDkuOTRsLTMuNzUtMy43NUwzLjE1IDE3LjFjLS4xLjEtLjE1LjIyLS4xNS4zNnpNMjAuNzEgNy4wNGMuMzktLjM5LjM5LTEuMDIgMC0xLjQxbC0yLjM0LTIuMzRjLS4zOS0uMzktMS4wMi0uMzktMS40MSAwbC0xLjgzIDEuODMgMy43NSAzLjc1IDEuODMtMS44M3oiLz48L3N2Zz4=");background-position:center;width:36px;height:36px;filter:invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%);margin-right:0;top:-7px;right:-11px}}@media screen and (max-width:980px) and (min-width:0){#RecordSwitchers{display:flex;align-items:center}#RecordSwitchers #CurrentIndex{height:7.5vw;display:flex;align-items:center}}@media screen and (max-width:980px) and (min-width:0){#Editor #RecordHeader .user{display:flex;align-items:center}#Editor #RecordHeader .user .ui-icon-person{margin-right:.6vw}}@media screen and (max-width:980px) and (min-width:0){#OutgoingMailDialog .field-wide{padding-bottom:5px}#OutgoingMailDialog .field-wide .field-label{width:auto}#OutgoingMailDialog .field-wide .field-control{float:none}#OutgoingMailDialog .field-wide .control-basket,#OutgoingMailDialog .field-wide .container-normal{margin-left:15vw}#OutgoingMailDialog textarea{height:20vw}}@media screen and (max-width:980px) and (min-width:0){.show-password{top:calc(50% - 10px);right:10px}#LoginFieldSet input[type=checkbox]{transform:scale(1.2)}#LoginFieldSet input,#LoginFieldSet select{font-size:4vw}#Users_RememberMeField .container-normal{display:flex;align-items:center}}@media screen and (max-width:980px) and (min-width:0){#Navigations.open{padding-top:18vw}}@media screen and (max-width:980px) and (min-width:0){#ViewModeContainer .field-auto-thin>.field-label{padding:7px 2vw 7px 0}#CrosstabValueField .field-control{width:70%}#Crosstab .field-auto-thin p{margin-right:0%}#ViewModeContainer #Crosstab .field-auto-thin{width:100%;flex:0 1 calc(100%);padding-top:1vw}#ViewModeContainer #Crosstab .field-auto-thin .field-label{width:30%}#ViewModeContainer #Crosstab .field-auto-thin .field-control{width:70%}#ViewModeContainer #Crosstab .field-auto-thin .field-control input[type='checkbox'],#ViewModeContainer #Crosstab .field-auto-thin .field-control .field-auto-thin input[type='checkbox']{width:4vw;height:4vw;margin-left:2px}#CrosstabBody .grid>thead>tr:first-child>th:not(:first-child),#KambanBody .grid>thead>tr:first-child>th:not(:first-child){white-space:nowrap}}@media screen and (max-width:980px) and (min-width:0){#ImportSettingsDialog .control-checkbox+label{margin:1.8vw 0 0 1vw}#ImportSettingsDialog .control-checkbox{margin:2vw 0 2vw 2px}#ImportSettingsDialog .control-textbox{height:7vw;line-height:6.5vw}#ImportSettingsDialog .command-center{padding:2vw 0}}@media screen and (max-width:980px) and (min-width:0){#ExportSelectorDialog .command-center{padding:2vw 0}}@media screen and (max-width:980px) and (min-width:0){#ViewModeContainer #Grid .datepicker{width:35vw;font-size:4vw}}@media screen and (max-width:980px) and (min-width:0){#ViewModeContainer .both #TimeSeriesValueField,#ViewModeContainer .both #TimeSeriesChartTypeField,#ViewModeContainer .both #TimeSeriesHorizontalAxisField{width:100%}#ViewModeContainer .both #TimeSeriesValueField .field-label,#ViewModeContainer .both #TimeSeriesChartTypeField .field-label,#ViewModeContainer .both #TimeSeriesHorizontalAxisField .field-label{min-width:30%}#ViewModeContainer .both .field-auto-thin:first-child,#ViewModeContainer .both .field-auto-thin:nth-child(2){flex:0 1 calc(100%)}#ViewModeContainer .both .field-auto-thin:first-child .field-label,#ViewModeContainer .both .field-auto-thin:nth-child(2) .field-label{min-width:30%}#ViewModeContainer .both .field-auto-thin select{max-width:100%}#ViewModeContainer .both .field-auto-thin>.field-control{min-width:68%}} \ No newline at end of file +@media screen and (max-width:1024px) and (min-width:0){#LoginFieldSet{width:100%;padding:10px;font-size:4vw}#LoginFieldSet input,#LoginFieldSet select{font-size:5vw;padding:10px}#LoginFieldSet input[type=checkbox]{transform:scale(2);margin:20px 0 0 10px}#LoginFieldSet button{font-size:4vw}#LoginFieldSet .container-normal{margin-left:0}#LoginFieldSet .field-wide,#LoginFieldSet .field-normal{width:100%;margin:10px 0;float:left}#LoginFieldSet .field-normal .control-checkbox+label{width:auto;margin:0 0 0 30px}#Logins .field-label{width:auto;padding:4px}#LoginMessage{width:100%}#Demo{width:100%;padding:10px;font-size:4vw}#DemoFields .field-label{width:auto;padding:4px}#DemoFields input{font-size:5vw;padding:10px}#DemoFields button{font-size:4vw;float:right;margin-top:10px}#DemoFields .container-normal{margin-left:0}#DemoFields .field-normal{width:100%;margin:10px 0;float:left}#StartGuide{display:none}.container-normal>#ApiKey{word-break:break-all}div[role="dialog"]{width:98% !important;z-index:999}#EnterPriseBanner,#SupportBanner,#CasesBanner{display:none}#EditorTabsContainer>fieldset{display:contents}#EditorTabsContainer>fieldset>fieldset{display:contents}#TenantImage{width:100%}#Search{width:auto;height:auto}#Breadcrumb{font-size:2.6vw}#ViewSelectorField{position:relative;margin-bottom:5px;font-size:2.8vw}#HeaderTitleContainer{margin-bottom:3%}#ViewFilters{font-size:2.6vw;padding-bottom:2%}#Aggregations{font-size:2.6vw}#ViewFilters_Reset{float:none}#ViewFilters.reduced,#Aggregations.reduced{border-bottom:1px solid #aaa;margin-bottom:2%;padding:2%}#Aggregations .label{height:auto}#ViewFilters>.field-auto-thin{height:6vw;padding:0;margin:2% 0 0 0;line-height:1;width:49%;display:flex;justify-content:start;align-items:center}#ViewFilters>.field-auto-thin>.field-control{width:100%}#ViewFilters>.field-auto-thin>.field-label{width:30%;text-align:left}#ViewFilters>.field-auto-thin>.field-label+.field-control{width:70%}.ui-multiselect{width:100% !important;height:6vw}.field-auto-thin input[type="checkbox"],.field-auto-thin input[type="radio"]{height:2.6vw;width:2.6vw;margin-right:1vw}.control-checkbox{margin:0}.control-checkbox+label{margin:0}.field-auto-thin>.field-label{padding:0}#RecordInfo div{clear:both;margin-right:0}#RecordInfo div p{font-size:2.6vw}#Application{padding-bottom:15%}#MainForm{display:flex;flex-direction:column}#RecordInfo{margin-bottom:2%}#RecordSwitchers{font-size:2.6vw;width:100%}.ui-button,#RecordSwitchers .current{height:auto;padding:2%!important;line-height:1;margin-right:2%}#EditorComments{width:100%;order:3;font-size:2.6vw}#EditorTabsContainer{width:100%}.fieldset.ui-tabs-panel.ui-widget-content{font-size:2.6vw}.ui-tabs .ui-tabs-panel{padding:1%}.field-wide,.field-markdown{width:100%;min-height:5vw;float:none;padding:0 0 3% 0;clear:both}.field-normal{width:100%;height:auto;padding:0}.field-normal.right-align{text-align:left}.field-markdown>.field-label,.field-normal>.field-label,.field-wide>.field-label{width:100%;clear:both;margin-left:0;padding:1%;font-weight:bold;text-align:left;text-align-last:left}.field-normal>.field-label label,.field-wide>.field-label label{font-weight:bold}.field-normal .container-normal,.field-control .container-normal{margin-left:0}.control-dropdown{height:auto}.ui-spinner a.ui-spinner-button{height:50%}.field-normal .control-text{width:100%;height:auto;padding:1%;line-height:1}.control-textbox{height:auto}.ui-widget.ui-widget-content{font-size:2.6vw}#Guide{font-size:2.6vw}.alert-success,.alert-warning,.alert-error{height:auto;font-size:2.6vw}#MainCommandsContainer{height:auto;padding:2vw 0;font-size:2.6vw;z-index:200}#Footer{z-index:102}.ui-tabs .ui-tabs-nav{padding:1%;font-size:2.6vw}.ui-tabs .ui-tabs-nav li{margin-bottom:1%;padding-bottom:0;border-radius:4px}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:1%;padding-bottom:0;border-radius:4px}.message{bottom:140px}}@media screen and (max-width:1024px) and (min-width:0){body{min-width:320px!important}#Header{height:auto;position:relative}#CorpLogo{float:none;width:30%}#MainContainer{min-height:100vh}#Header a#navtgl{position:absolute;display:block;padding:1.6vw 1.4vw;border:.4vw solid #d19405;border-radius:1vw;top:1.4vw;right:4vw;height:8vw;width:8vw;z-index:101;background:#fece2f}#Header a#navtgl::before{content:'';display:block;height:1.3vw;border-top:.4vw solid #333;border-bottom:.4vw solid #333}#Header a#navtgl::after{content:'';display:block;height:1.4vw;border-bottom:.4vw solid #333}* #Navigations{box-sizing:border-box}#Navigations{width:100%;max-height:0;overflow:hidden;margin:0;padding:0 5%;border:none;position:relative;top:0;right:0;border-radius:0;z-index:100;font-size:3.2vw;line-height:7vw;transition:.5s}#Navigations.open{max-height:none;height:auto;overflow:visible;margin-top:2%;margin-bottom:5%;padding:5%;transition:.5s}#NavigationMenu>li.sub-menu>div.hover{background:none}#NavigationMenu{float:none;margin-right:0;margin-bottom:3%}#SearchField{float:none;margin:0;color:#000}#NavigationMenu>li{width:100%;height:auto;display:block;float:none;position:relative}#NavigationMenu>li>div{height:auto;text-align:left;line-height:7vw;font-weight:bold}#NavigationMenu>li>div:hover{background:none}#NavigationMenu>li>div>a{height:auto;display:block;text-decoration:none;font-weight:bold}#NavigationMenu .menu{width:100%;border-top:none !important;position:relative;top:0;right:0;border-radius:0;z-index:3}.pc-dn{display:block!important}#NavigationMenu .menu>li>a.ui-state-active{font-weight:normal;text-decoration:none}.ui-menu .ui-menu-item{border-top:1px solid #d19405}#NewMenuContainer{border:1px solid #d19405;background:#fff}}@media screen and (max-width:1024px) and (min-width:0){#SiteMenu .nav-site{width:20vw;height:20vw;text-align:center;border-radius:.5vw;float:none;margin:6%}#SiteMenu .sortable{display:flex;justify-content:flex-start;align-items:flex-start;flex-wrap:wrap}#SiteMenu .nav-site.sites{width:20vw!important;height:20vw!important;background:#fff;border-radius:5px}#SiteMenu .nav-site .heading{width:8vw;height:3vw;top:-3vw}#SiteMenu .nav-site.sites.to-parent{height:auto!important;box-shadow:none;margin-top:3%;margin-bottom:0}#SiteMenu .nav-site.sites.to-parent span.title{position:relative;top:0;text-align:left;width:100%;margin-left:0}#SiteMenu .nav-site.sites.to-parent .heading{display:none}#SiteMenu .nav-site a{padding:0;overflow:inherit}#SiteMenu .nav-site .site-image-thumbnail{position:relative;top:inherit;left:inherit;max-width:inherit;border-radius:unset;width:90%;z-index:1;margin:0 auto;display:block}#SiteMenu .nav-site span.title::before{content:'';display:block;height:0}#SiteMenu .nav-site span.title{margin-left:0;font-size:14px}#SiteMenu .nav-site.has-image a{padding:1vw 0 0}#SiteMenu .nav-site .conditions{position:absolute;top:-2.4vw;right:-2.4vw;z-index:2}#SiteMenu .nav-site .conditions .elapsed-time{display:none}#SiteMenu .nav-site .conditions .count{display:none}#SiteMenu .nav-site .conditions .overdue{height:6vw;min-width:6vw;line-height:6vw;font-size:2.6vw;border-radius:3vw;font-weight:bold;padding:0}#SiteMenu .nav-site[data-type="Wikis"]{border-radius:2px;position:relative;width:20vw;border:2px solid #ccc}#SiteMenu .nav-site[data-type="Wikis"] a::before,#SiteMenu .nav-site[data-type="Wikis"] a::after{content:'';display:block;position:absolute;height:20%;width:80%;left:10%;border-top:2px solid #ccc;border-bottom:2px solid #ccc}#SiteMenu .nav-site[data-type="Wikis"] a::before{top:20%}#SiteMenu .nav-site[data-type="Wikis"] a::after{top:60%}#SiteMenu .nav-site[data-type="Wikis"] a img{margin-top:15%}#SiteMenu .nav-site.sites.to-parent{height:auto!important;border:none;background:none;text-align:left}#SiteMenu .nav-site.to-parent .ui-icon{display:none}#SiteMenu .nav-site.to-parent a{position:relative;display:inline-block;padding:0 0 0 16px;color:#000;vertical-align:middle;text-decoration:none;font-size:15px}#SiteMenu .nav-site.to-parent a::before,#SiteMenu .nav-site.to-parent a::after{position:absolute;top:0;bottom:0;left:0;margin:auto;content:"";vertical-align:middle}#SiteMenu .nav-site.to-parent a::before{left:5px;width:7px;height:3px;background:#7a0}#SiteMenu .nav-site.to-parent a::after{left:2px;width:6px;height:6px;border-bottom:3px solid #7a0;border-left:3px solid #7a0;-webkit-transform:rotate(45deg);transform:rotate(45deg)}#SiteMenu .nav-site span.title{margin-left:0;font-size:2.6vw;top:22vw;position:absolute;display:block;text-align:center;width:140%;margin-left:-20%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#SiteMenu .nav-site .stacking1{width:20vw;height:20vw;border-bottom:solid 1px #c0c0c0;border-right:solid 1px #c0c0c0;position:absolute;top:1px;left:1px;border-radius:5px}#SiteMenu .nav-site .stacking2{width:20vw;height:20vw;border-bottom:solid 1px #c0c0c0;border-right:solid 1px #c0c0c0;position:absolute;top:4px;left:4px;border-radius:5px}#SiteMenu .nav-sites .to-parent a img{display:none}#SiteMenu .nav-site.to-parent.has-image a{padding:0 0 0 15px}}@media screen and (max-width:1024px) and (min-width:0){#FieldSetStandard{display:flex;flex-direction:column}.legend{order:2}#StandardTemplatesViewer{order:3}.template-selectable{order:1;float:none}.template-viewer-container{float:none;margin:0}.template-viewer{margin:0}.template-selectable{width:100%}.template-tab-container{min-height:10px}.field-vertical{width:100%;float:none;padding:0 0 20px 0}.container-selectable .wrapper{min-height:auto}.h350{height:auto}#EditInDialogBody{padding-bottom:15%}.links{overflow:auto}}@media screen and (max-width:1024px) and (min-width:0){#FieldSetHistories{overflow:auto;width:100%}#ViewModeContainer{overflow:auto;width:100%;padding-top:1%}#CrosstabBody{overflow:auto;width:100%}#GanttBody{overflow:auto;width:100%;padding-top:5%}.grid{font-size:2.8vw;width:98%}.grid>thead th{min-width:10vw;white-space:nowrap}.grid>tbody td{min-width:10vw;white-space:nowrap}.grid>thead th:nth-child(1),.grid>tbody td:nth-child(1){min-width:1vw}.grid>tbody td p{white-space:nowrap}#Calendar{font-size:2.6vw}#Calendar button{margin-bottom:2%}#CalendarBody #Grid thead{background:#fff}#CalendarMonth{display:block}#Calendar .field-auto-thin{display:flex;align-items:center;width:33%;margin:0;padding:0;margin-bottom:2%!important}#Calendar .field-auto-thin p{margin-right:1%}#Calendar .field-auto-thin select{max-width:none}#CalendarTimePeriod,#CalendarFromTo,#CalendarMonth{height:auto}#CalendarMonth{margin-bottom:2%}.w100{width:auto}#CrosstabBody{margin-top:3%}#CrosstabBody #Grid{table-layout:auto}#CrosstabBody .grid>thead>tr>th,#CrosstabBody .grid>tbody>tr>th{white-space:nowrap}#CrosstabBody .grid>thead th{min-width:10vw;white-space:nowrap}#CrosstabBody .grid>tbody td{min-width:10vw;white-space:nowrap}#Crosstab{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center}#Crosstab .field-auto-thin{display:flex;align-items:center;width:48%;margin:0;padding:0;font-size:2.6vw}#Crosstab .field-auto-thin#CrosstabTimePeriodField{width:48%}#Crosstab .field-auto-thin p{width:100%;margin-right:2%;white-space:nowrap}#Crosstab .field-auto-thin select{max-width:none}#Crosstab #CrosstabMonth{width:48%;margin-top:2%;margin-right:0;font-size:2.6vw}#Crosstab button{font-size:2.6vw;margin-top:1%}.svg-crosstab{display:block}#ViewModeContainer .both{display:flex;align-items:center;flex-wrap:wrap}#ViewModeContainer .both .field-auto-thin{display:flex;align-items:center;width:48%;margin:0;padding:0;font-size:2.6vw;height:auto;padding-top:2%}#ViewModeContainer .both .field-auto-thin .field-auto-thin{width:30%}#ViewModeContainer .both .field-auto-thin:nth-child(3){width:100%}#ViewModeContainer .both .field-auto-thin:nth-child(3) .field-auto-thin{width:48%;display:block}#ViewModeContainer .field-auto-thin p{margin-right:2%;white-space:nowrap;text-align:left}#GanttAxis{width:1500px;position:relative;left:0;bottom:0}#Gantt{width:1500px}#BurnDown{width:1500px}#TimeSeriesBody{padding-top:5%;margin-left:-5%;width:1500px}#TimeSeries{width:1500px}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(3){width:48%}#ViewModeContainer #Kamban.both .field-auto-thin .field-control{width:100%}#KambanBody{margin-top:3%}#KambanBody #Grid{table-layout:auto}#KambanBody .grid>thead>tr>th,#KambanBody .grid>tbody>tr>th{white-space:nowrap}#KambanBody .grid>thead th{min-width:10vw;white-space:nowrap}#KambanBody .grid>tbody td{min-width:10vw;white-space:nowrap}}@media screen and (max-width:1024px) and (min-width:0){#Header{padding:0 calc(5vw)}#Header a#navtgl{right:5vw}#Application,#Footer{padding-left:5vw;padding-right:5vw}#SiteMenu .nav-site{margin:5%}:not(td)>div.field-control .container-normal{margin-left:0}*{line-height:1.4}.field-normal .control-textbox,.field-normal .control-dropdown,.field-normal .control-text,.field-control .control-textbox,.field-control .control-dropdown,.field-control .control-text,.container-normal .control-textbox,.container-normal .control-dropdown,.container-normal .control-text{font-size:2.6vw;min-height:unset;height:6vw;line-height:6vw;padding-top:0;padding-bottom:0;display:flex;align-items:center}body{font-size:16px}}@media screen and (max-width:1024px) and (min-width:0){#HeaderTitle{font-size:16px}}@media screen and (max-width:1024px) and (min-width:768px){#HeaderTitle{font-size:35px}}@media screen and (max-width:1024px) and (min-width:0){.command-center{padding:0}.ui-dialog .ui-dialog-titlebar-close{top:0;bottom:0;width:5vw;height:5vw;margin:auto 0}}@media screen and (max-width:1024px) and (min-width:0){#ViewSelector{font-size:2.6vw}}@media screen and (max-width:1024px) and (min-width:0){#Logo a{align-items:center;display:flex}#Logo #ProductLogo{font-size:18px;padding-left:8px}#CorpLogo{float:none;height:calc(8vw + 10px);width:unset;margin-top:0}}@media screen and (max-width:1024px) and (min-width:768px){#Logo #ProductLogo{padding-left:16px;font-size:32px}}@media screen and (max-width:1024px) and (min-width:0){#Editor .field-control .container-normal{width:calc(100% - 18px)}#Editor .field-control .ui-icon.ui-icon-clock.current-time,#Editor .field-control .ui-icon.ui-icon-person.current-user{top:calc(3vw - 6px)}}@media screen and (max-width:1024px) and (min-width:768px){#Editor .field-control .container-normal{width:calc(100% - 36px)}#Editor .field-control .ui-icon.ui-icon-clock.current-time,#Editor .field-control .ui-icon.ui-icon-person.current-user{top:calc(3vw - 3.5px);right:-30px}}@media screen and (max-width:1024px) and (min-width:0){#FieldSetAddressBook #OutgoingMailDestinationForm .container-left{width:38vw}#FieldSetAddressBook #OutgoingMailDestinationForm .container-right .command-left{float:unset;padding:0}#FieldSetAddressBook #OutgoingMailDestinationForm .container-right .command-left button{margin:1vw 1vw 1vw 0}#FieldSetAddressBook #OutgoingMailDestinationForm .container-right .container-selectable .wrapper{height:40vw}#FieldSetAddressBook #OutgoingMailDestinationForm .container-right>*{margin-left:40vw}}@media screen and (max-width:1024px) and (min-width:768px){#FieldSetAddressBook #OutgoingMailDestinationForm .container-left{width:33vw}}@media screen and (max-width:1024px) and (min-width:0){#Issues_WorkValue{width:100px}}@media screen and (max-width:1024px) and (min-width:0){body::before{content:'';position:fixed;width:5vw;height:50vh;top:0;left:0;background:#fff;z-index:200}body::after{content:'';position:fixed;width:5vw;height:50vh;top:0;right:0;background:#fff;z-index:700}}@media screen and (max-width:1024px) and (min-width:0){#Users_LoginId,#Users_Password{height:40px}#LoginMessage span{font-size:3.5vw}#PortalLink{font-size:3.5vw;top:3vw}#LoginFieldSet{margin:65px auto 20px auto}#LoginFieldSet input[type=checkbox]{margin:auto 0;margin-left:1.2vw}#LoginFieldSet button{margin-top:0}#LoginFieldSet .field-wide,#LoginFieldSet .field-normal{margin:0 0}#LoginFieldSet .field-normal .control-checkbox+label{margin:auto 0;margin-left:4vw;padding:0}#Logins .field-label{width:100%}}@media screen and (max-width:1024px) and (min-width:0){#Editor .field-markdown>.field-label>label{font-weight:bold}#Editor .field-control .unit{font-size:2.6vw;padding-top:calc((18px - 1.4em)/2)}#Editor .ui-spinner .control-spinner{height:100%}}@media screen and (max-width:1024px) and (min-width:0){#GridCheckAll{margin-top:0}label[for="GridCheckAll"]{margin:0}#Footer{font-size:2.8vw;height:auto}#MainCommandsContainer{bottom:calc(2.8vw*1.4 + 10px)}body>thead>tr{font-size:.75em}}@media screen and (max-width:1024px) and (min-width:0){#Editor #EditorTabsContainer fieldset .wrapper{max-height:250px;overflow:auto}#Editor #EditorTabsContainer fieldset .container-selectable .command-left{align-items:center;display:flex}#Editor #EditorTabsContainer fieldset:not(#FieldSetGeneral) legend.legend{min-height:10px}#SiteImageSettingsEditor .field-auto-thin,#GridSettingsEditor .field-auto-thin,#FiltersSettingsEditor .field-auto-thin,#EditorSettingsEditor .field-auto-thin,#LinksSettingsEditor .field-auto-thin,#HistoriesSettingsEditor .field-auto-thin,#FormulasSettingsEditor .field-auto-thin,#ViewsSettingsEditor .field-auto-thin,#ImportsSettingsEditor .field-auto-thin,#ExportsSettingsEditor .field-auto-thin,#CalendarSettingsEditor .field-auto-thin,#CrosstabSettingsEditor .field-auto-thin,#GanttSettingsEditor .field-auto-thin,#BurnDownSettingsEditor .field-auto-thin,#TimeSeriesSettingsEditor .field-auto-thin,#KambanSettingsEditor .field-auto-thin,#ImageLibSettingsEditor .field-auto-thin,#SearchSettingsEditor .field-auto-thin,#StylesSettingsEditor .field-auto-thin,#ScriptsSettingsEditor .field-auto-thin,#PublishSettingsEditor .field-auto-thin,#FieldSetSiteAccessControl .field-auto-thin{padding-right:0;height:auto;display:flex;align-items:center;clear:both}#SiteImageSettingsEditor .field-auto-thin .container-normal,#GridSettingsEditor .field-auto-thin .container-normal,#FiltersSettingsEditor .field-auto-thin .container-normal,#EditorSettingsEditor .field-auto-thin .container-normal,#LinksSettingsEditor .field-auto-thin .container-normal,#HistoriesSettingsEditor .field-auto-thin .container-normal,#FormulasSettingsEditor .field-auto-thin .container-normal,#ViewsSettingsEditor .field-auto-thin .container-normal,#ImportsSettingsEditor .field-auto-thin .container-normal,#ExportsSettingsEditor .field-auto-thin .container-normal,#CalendarSettingsEditor .field-auto-thin .container-normal,#CrosstabSettingsEditor .field-auto-thin .container-normal,#GanttSettingsEditor .field-auto-thin .container-normal,#BurnDownSettingsEditor .field-auto-thin .container-normal,#TimeSeriesSettingsEditor .field-auto-thin .container-normal,#KambanSettingsEditor .field-auto-thin .container-normal,#ImageLibSettingsEditor .field-auto-thin .container-normal,#SearchSettingsEditor .field-auto-thin .container-normal,#StylesSettingsEditor .field-auto-thin .container-normal,#ScriptsSettingsEditor .field-auto-thin .container-normal,#PublishSettingsEditor .field-auto-thin .container-normal,#FieldSetSiteAccessControl .field-auto-thin .container-normal{width:100%}#SiteImageSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#GridSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#FiltersSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#EditorSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#LinksSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#HistoriesSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#FormulasSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#ViewsSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#ImportsSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#ExportsSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#CalendarSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#CrosstabSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#GanttSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#BurnDownSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#TimeSeriesSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#KambanSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#ImageLibSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#SearchSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#StylesSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#ScriptsSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#PublishSettingsEditor .field-auto-thin .container-normal .control-checkbox~label,#FieldSetSiteAccessControl .field-auto-thin .container-normal .control-checkbox~label{display:unset;float:unset;width:auto}#SiteImageSettingsEditor .field-auto-thin .field-label~.field-control,#GridSettingsEditor .field-auto-thin .field-label~.field-control,#FiltersSettingsEditor .field-auto-thin .field-label~.field-control,#EditorSettingsEditor .field-auto-thin .field-label~.field-control,#LinksSettingsEditor .field-auto-thin .field-label~.field-control,#HistoriesSettingsEditor .field-auto-thin .field-label~.field-control,#FormulasSettingsEditor .field-auto-thin .field-label~.field-control,#ViewsSettingsEditor .field-auto-thin .field-label~.field-control,#ImportsSettingsEditor .field-auto-thin .field-label~.field-control,#ExportsSettingsEditor .field-auto-thin .field-label~.field-control,#CalendarSettingsEditor .field-auto-thin .field-label~.field-control,#CrosstabSettingsEditor .field-auto-thin .field-label~.field-control,#GanttSettingsEditor .field-auto-thin .field-label~.field-control,#BurnDownSettingsEditor .field-auto-thin .field-label~.field-control,#TimeSeriesSettingsEditor .field-auto-thin .field-label~.field-control,#KambanSettingsEditor .field-auto-thin .field-label~.field-control,#ImageLibSettingsEditor .field-auto-thin .field-label~.field-control,#SearchSettingsEditor .field-auto-thin .field-label~.field-control,#StylesSettingsEditor .field-auto-thin .field-label~.field-control,#ScriptsSettingsEditor .field-auto-thin .field-label~.field-control,#PublishSettingsEditor .field-auto-thin .field-label~.field-control,#FieldSetSiteAccessControl .field-auto-thin .field-label~.field-control{margin-left:10px}#SiteImageSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#GridSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#FiltersSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#EditorSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#LinksSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#HistoriesSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#FormulasSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#ViewsSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#ImportsSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#ExportsSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#CalendarSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#CrosstabSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#GanttSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#BurnDownSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#TimeSeriesSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#KambanSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#ImageLibSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#SearchSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#StylesSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#ScriptsSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#PublishSettingsEditor .field-auto-thin .field-label~.field-control .container-normal,#FieldSetSiteAccessControl .field-auto-thin .field-label~.field-control .container-normal{width:100%}#FieldSetGeneral .field-control .container-normal .control-checkbox~label{width:auto}#GridSettingsEditor #GridEditorType{max-width:unset}#SiteImageSettingsEditor #SiteImage{width:100%;height:7vw}#SiteImageSettingsEditor #SetSiteImage{margin-right:0}#SearchSettingsEditor #SearchType{margin-bottom:10px}#SearchSettingsEditor #SearchSettingsEditorFulltext legend.legend.applied,#SearchSettingsEditor #SearchSettingsEditorOperations legend.legend.applied{margin-bottom:10px}#SearchSettingsEditor #SearchSettingsEditorFulltext{padding-top:10px}#Editor #EditorTabsContainer .fieldset+.field-auto-thin{margin-top:10px}}@media screen and (max-width:1024px) and (min-width:0){#Aggregations{display:flex;flex-wrap:wrap;row-gap:5px;justify-content:flex-start;align-items:center}#Aggregations span.label{flex:1 0 auto;margin:0;text-align:center;align-self:stretch;display:flex;align-items:center;justify-content:flex-start}#Aggregations span.data{flex:1 0 auto;margin:0;align-self:stretch;display:flex;align-items:center;justify-content:flex-start;height:auto}#Aggregations span.data.no-choice{flex-basis:auto;align-self:stretch}#Aggregations span.data.link span{font-weight:bold}#Aggregations #ReduceAggregations{width:100%}}@media screen and (max-width:1024px) and (min-width:768px){#Aggregations{row-gap:15px}}@media screen and (max-width:1024px) and (min-width:0){#ViewModeContainer .grid{vertical-align:middle}input[type='checkbox'],.field-auto-thin input[type='checkbox']{width:3vw;height:3vw}.field-auto-thin input[type='checkbox']+label{padding-top:2px}}@media screen and (max-width:1024px) and (min-width:0){#SearchField #Search{font-size:3vw;width:100%}#SearchField #Search::placeholder{font-size:3vw}}@media screen and (max-width:1024px) and (min-width:0){#ViewFilters #ViewFilters_Reset{margin-left:auto;margin-right:0}#ViewFilters .field-auto-thin{width:50%}#ViewFilters .field-auto-thin .field-control .container-normal{display:flex;align-items:center}#ViewFilters .field-auto-thin .field-control .container-normal input[type='checkbox']{margin-right:4px;margin-top:1px}#ViewFilters .field-auto-thin .field-control .container-normal .ui-widget.ui-state-default.ui-multiselect,#ViewFilters .field-auto-thin .field-control .container-normal .control-textbox{height:6vw;font-size:2.6vw}#ViewFilters #ViewFilters_SearchField{width:100%}#ViewFilters #ViewFilters_SearchField p.field-label{width:17%}#ViewFilters #ViewFilters_SearchField .field-control{width:100%}#ViewFilters>.field-auto-thin:nth-child(odd){padding-right:2px}#ViewFilters>.field-auto-thin:nth-child(even){padding-left:2px}.ui-multiselect-menu .ui-helper-reset{position:relative}.ui-multiselect-menu .ui-helper-reset li{width:100%}.ui-multiselect-menu .ui-helper-reset li>label span{position:relative;top:-4px}.ui-multiselect-menu .ui-helper-reset li .ui-multiselect-all,.ui-multiselect-menu .ui-helper-reset li .ui-multiselect-none{width:100%;display:flex;align-items:center}.ui-multiselect-menu .ui-helper-reset li .ui-multiselect-all span:last-child,.ui-multiselect-menu .ui-helper-reset li .ui-multiselect-none span:last-child{padding-left:10px}.ui-multiselect-menu .ui-helper-reset li .ui-multiselect-close{position:absolute;top:8px;right:0}}@media screen and (max-width:1024px) and (min-width:0){#EditorTabsContainer .legend.applied{display:flex;align-items:center;font-weight:bold}#EditorTabsContainer #PermissionEditor .field-vertical:first-child>.field-control{border-bottom:1px solid #d19405;padding-bottom:2vw}#EditorTabsContainer #PermissionEditor .field-control .container-selectable .command-left{display:flex;align-items:center;flex-wrap:wrap;width:100%}#EditorTabsContainer #PermissionEditor .field-control .container-selectable .command-left #SearchPermissionElements{margin:2px 1vw 2px 6vw;height:7vw}#EditorTabsContainer #PermissionEditor .field-control .container-selectable .command-left button{align-self:stretch;display:flex;align-items:center;justify-content:center;white-space:nowrap}#EditorTabsContainer #PermissionEditor .field-control .container-selectable .command-left button .ui-icon{position:relative;top:.5vw;width:18px;height:18px;margin-right:0}#EditorTabsContainer #PermissionEditor .field-control .container-selectable .command-left #OpenPermissionsDialog,#EditorTabsContainer #PermissionEditor .field-control .container-selectable .command-left #DeletePermissions{line-height:1.5}#EditorTabsContainer #PermissionEditor .field-control .container-selectable #CurrentPermissionsWrapper{min-height:15vw}}@media screen and (max-width:1024px) and (min-width:0){thead>tr.ui-widget-header th div>span{font-size:2.8vw;white-space:nowrap}}@media screen and (max-width:1024px) and (min-width:768px){#EditorTabsContainer .field-control .container-normal .ui-icon.ui-icon-pencil.button-edit-markdown{top:10px;right:4px}}@media screen and (max-width:1024px) and (min-width:0){#EditorTabsContainer{overflow:auto}#EditorComments{padding:0;margin:0}#EditorComments #CommentField .control-textarea{height:15vw}#EditorComments #CommentField .control-textarea::placeholder{font-size:2.6vw}}@media screen and (max-width:1024px) and (min-width:0){.is-showMenu{overflow:hidden}.is-showMenu body{position:fixed;overflow:hidden}.bg-overlay{background:rgba(0,0,0,.5);position:fixed;top:0;left:0;z-index:301;width:100%;height:100%;display:none}#MainContainer{overflow:hidden}header#Header{position:fixed;top:0;z-index:1000;background-color:#fff;transition:all .5s ease}header#Header a#navtgl{top:8px;z-index:1000;transition:all .5s ease}header#Header a#navtgl::after{transition:all .5s ease}header#Header a#navtgl.on{transition:all .5s ease;position:fixed}header#Header a#navtgl.on::before{transition:all .5s ease;border-top:none;transform:translate(12.5%,50%) rotate(50deg)}header#Header a#navtgl.on::after{transition:all .5s ease;transform:translate(12.5%,0%) rotate(126deg)}#Navigations{transition:all .5s ease;max-height:100vh;height:100vh;position:absolute;top:0;right:-1000px;z-index:999;padding:5%;width:70%;padding-top:112px;opacity:0}#Navigations.open{opacity:1;padding-top:112px;right:0;height:100vh;margin:0;position:fixed;top:0;z-index:1000}}@media screen and (max-width:1024px) and (min-width:0){#OutgoingMailsForm{width:100%;font-size:2.6vw}#OutgoingMailsForm .item h3.title-header{height:auto}#OutgoingMailsForm .item .content{padding:.2em;margin:0}#OutgoingMailsForm .item .content .field-auto,#OutgoingMailsForm .item .content .field-auto-thin{width:100%;margin-right:0;padding-right:0;padding-bottom:0;display:flex;flex-direction:column;height:auto}#OutgoingMailsForm .item .content .field-auto .field-label,#OutgoingMailsForm .item .content .field-auto-thin .field-label{float:none;padding:7px 7px 7px 0;width:100%;text-align:left;display:block}#OutgoingMailsForm .item .content .field-auto .field-label label,#OutgoingMailsForm .item .content .field-auto-thin .field-label label{font-weight:bold}#OutgoingMailsForm .item .content .field-auto .field-control,#OutgoingMailsForm .item .content .field-auto-thin .field-control{float:none;width:100%}#OutgoingMailsForm .item .content .field-auto .field-control .container-normal,#OutgoingMailsForm .item .content .field-auto-thin .field-control .container-normal{margin-right:0;width:100%}#OutgoingMailsForm .item .content .field-auto .field-control .container-normal .control-text,#OutgoingMailsForm .item .content .field-auto-thin .field-control .container-normal .control-text{min-height:0;height:auto}#OutgoingMailsForm .item .content .field-auto-thin{margin-left:0}#OutgoingMailsForm .item .content .field-wide{display:flex;flex-direction:column;padding:0}#OutgoingMailsForm .item .content .field-wide .field-label{padding:7px 0}#OutgoingMailsForm .item .content .field-wide .field-control .container-normal{margin-right:0;width:100%}}@media screen and (max-width:1024px) and (min-width:0){#SiteMenu li.ui-sortable-handle{touch-action:unset}}@media screen and (max-width:1024px) and (min-width:0){.xdsoft_datetimepicker span{font-size:2.6vw}.xdsoft_datetimepicker .xdsoft_datepicker{width:calc(42.81vw - 16px)}.xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_today_button{margin-left:0}.xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_label.xdsoft_year{margin-left:0}.xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_year,.xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_month{width:fit-content}.xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_year .xdsoft_select .xdsoft_option,.xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_month .xdsoft_select .xdsoft_option{font-size:2.6vw}.xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_year .xdsoft_select .xdsoft_scrollbar,.xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_month .xdsoft_select .xdsoft_scrollbar{width:.7vw}.xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_calendar table th,.xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_calendar table td{font-size:2.6vw}.xdsoft_datetimepicker .xdsoft_timepicker.active{width:calc(12.17vw - 8px)}.xdsoft_datetimepicker .xdsoft_timepicker.active .xdsoft_time_box .xdsoft_time{font-size:2.6vw}}@media screen and (max-width:1024px) and (min-width:768px){.xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_year i,.xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_month i{transform:scale(1.6)}.xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_year span,.xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_month span{font-size:16px}}@media screen and (max-width:1024px) and (min-width:0){.message span.body{display:flex;align-items:center;justify-content:center}.message .close{top:unset;bottom:calc(50% - 8px);margin:auto}}@media screen and (max-width:1024px) and (min-width:0){#Navigations.open{overflow-y:scroll}#Navigations #NavigationMenu #NewMenuContainer{background:unset;border:none}#Navigations #NavigationMenu #NewMenuContainer a{line-height:7vw}#Navigations #NavigationMenu li.sub-menu .ui-menu-item .ui-menu-item-wrapper{font-size:3vw;padding-left:5vw}}@media screen and (max-width:1024px) and (min-width:768px){#Navigations #NavigationMenu li.sub-menu .ui-menu-item .ui-menu-item-wrapper{padding-left:4vw}}@media screen and (max-width:1024px) and (min-width:0){#Editor .field-normal .field-control .container-normal input[type='checkbox'].control-checkbox{position:relative;margin-right:6px;margin-top:.3vw}}@media screen and (max-width:1024px) and (min-width:768px){#Editor .field-normal .field-control .container-normal input[type='checkbox'].control-checkbox{margin-right:12px}}@media screen and (max-width:1024px) and (min-width:0){#Editor #EditorTabsContainer .field-normal,#Editor #EditorTabsContainer .field-wide,#Editor #EditorTabsContainer .field-markdown{display:inline-block;margin-top:8px;padding-bottom:0}}@media screen and (max-width:1024px) and (min-width:0){#ViewModeContainer #Calendar.both select{font-size:2.6vw;height:6vw}#ViewModeContainer #Calendar.both .field-label{min-width:16%;margin-right:0}#ViewModeContainer #Calendar.both .field-auto-thin .field-control .container-normal{display:flex;align-items:center}#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(1),#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(2),#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3){flex:0 1 calc(47%);flex-wrap:nowrap}#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(1) .field-label,#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(2) .field-label,#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) .field-label{min-width:16%}#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(1) .field-control,#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(2) .field-control,#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) .field-control{width:84%}#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(4){width:47%;padding-top:2%}#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(4) .field-control .container-normal{justify-content:flex-end}#ViewModeContainer #Calendar.both .field-auto-thin:nth-child(4) .field-control .container-normal #CalendarDate{margin-right:0;width:100%;font-size:2.6vw}#ViewModeContainer #Calendar.both .field-auto-thin input[type='checkbox']{margin-left:2px}#ViewModeContainer #Calendar.both button{flex:1 0 calc((100%/3) - 32px);margin:2% 10px 2% 10px}#ViewModeContainer .grid.fixed{width:100%}#ViewModeContainer .grid.fixed tbody tr td.container .item{touch-action:auto;min-height:4vw;margin-top:5px;margin-bottom:5px;height:4vw}#ViewModeContainer .grid.fixed tbody tr td.container .item .connection{min-height:4vw;height:4vw}#ViewModeContainer .grid.fixed tbody tr td.container .dummy{height:4vw}#ViewModeContainer .grid.fixed tbody .title{padding:0}thead th.calendar-header{overflow-x:hidden}}@media screen and (max-width:1024px) and (min-width:0){#ViewModeContainer .both{column-gap:16px}#ViewModeContainer .both .field-auto-thin:first-child,#ViewModeContainer .both .field-auto-thin:nth-child(2){flex:0 1 calc(50% - 8px)}#ViewModeContainer .both .field-auto-thin:first-child .field-control,#ViewModeContainer .both .field-auto-thin:nth-child(2) .field-control{flex:1}#ViewModeContainer .both .field-auto-thin:first-child .field-control select,#ViewModeContainer .both .field-auto-thin:nth-child(2) .field-control select{max-width:100%}#ViewModeContainer .both .field-auto-thin:nth-child(3){row-gap:12px;flex-wrap:wrap}#ViewModeContainer .both .field-auto-thin:nth-child(3) .field-label{min-width:15%}#ViewModeContainer .both .field-auto-thin:nth-child(3) .field-auto-thin{display:flex;align-items:center;flex:1 0 100%}#ViewModeContainer .both .field-auto-thin:nth-child(3) .field-auto-thin #GanttStartDate{width:100%;font-size:2.6vw;margin-right:0}#ViewModeContainer .both .field-auto-thin:nth-child(3) button{flex:1}#ViewModeContainer .both .field-auto-thin:nth-child(3) button:last-child{margin-right:8px}#ViewModeContainer .both .field-auto-thin:nth-child(4){width:100%;padding-top:12px}#ViewModeContainer .both .field-auto-thin:nth-child(4) .field-control{width:100%}#ViewModeContainer .both .field-auto-thin:nth-child(4) .field-control .container-normal{width:100%;display:flex;align-items:center;column-gap:32px}#ViewModeContainer .both .field-auto-thin:nth-child(4) .field-control .container-normal #GanttPeriod\,ui{width:99%;margin-top:0}#ViewModeContainer .both .field-auto-thin:nth-child(4) .field-control .container-normal #GanttPeriod{margin:0}#GanttBody{max-height:70vh}#GanttBody #Gantt{font-size:2.6vw;width:500%}#GanttBody text{font-size:2.6vw}#GanttBody .title text.summary{font-size:3vw}#GanttBody #GanttAxis{left:-2px;position:sticky;width:500%}}@media screen and (max-width:1024px) and (min-width:0){#ViewModeContainer #Kamban.both .field-auto-thin select{font-size:2.6vw}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(1),#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(2),#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(3),#ViewModeContainer #Kamban.both .field-auto-thin#KambanValueField{width:100%;flex:0 1 calc(50% - 8px);flex-wrap:wrap;display:flex;row-gap:0}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(1) .field-label,#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(2) .field-label,#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(3) .field-label,#ViewModeContainer #Kamban.both .field-auto-thin#KambanValueField .field-label{width:100%}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(1) select,#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(2) select,#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(3) select,#ViewModeContainer #Kamban.both .field-auto-thin#KambanValueField select{max-width:100%}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(3){padding-top:4%}#ViewModeContainer #Kamban.both .field-auto-thin#KambanValueField{padding-top:4%}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(5){display:block;width:100%;padding-top:4%}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(5) .field-label{min-width:50%;margin-right:10px}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(5) select{max-width:100%}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(6),#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(7){width:calc(50% - 8px);padding-top:4%}#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(6) .container-normal,#ViewModeContainer #Kamban.both .field-auto-thin:nth-child(7) .container-normal{display:flex;align-items:center}#ViewModeContainer #Kamban.both #KambanBody #Grid tbody .kamban-row .kamban-container .kamban-item{height:4vw;padding:0 16px 0 5px;overflow:hidden;white-space:pre-line;touch-action:auto;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical}}@media screen and (max-width:1024px) and (min-width:768px){#ViewModeContainer #Kamban.both #KambanBody #Grid tbody .kamban-row .kamban-container .kamban-item .ui-icon.ui-icon-pencil{width:16px;height:16px;top:10px;right:4px}}@media screen and (max-width:1024px) and (min-width:0){#ViewModeContainer #Calendar #FullCalendar.fc .fc-header-toolbar .fc-toolbar-chunk:last-child .fc-button-group{display:flex;flex-wrap:wrap;margin:0}#ViewModeContainer #Calendar #FullCalendar.fc .fc-header-toolbar .fc-toolbar-chunk:last-child .fc-button-group button:nth-child(3){border-radius:0 .25em .25em 0}#ViewModeContainer #Calendar #FullCalendar.fc .fc-header-toolbar .fc-toolbar-chunk:last-child .fc-button-group button:last-child{border-radius:.25em}}@media screen and (max-width:768px) and (min-width:0){#ViewModeContainer #Calendar #FullCalendar.fc .fc-header-toolbar .fc-toolbar-chunk:last-child .fc-button-group button:nth-child(odd){border-radius:.25em 0 0 .25em}#ViewModeContainer #Calendar #FullCalendar.fc .fc-header-toolbar .fc-toolbar-chunk:last-child .fc-button-group button:nth-child(even){border-radius:0 .25em .25em 0}}@media screen and (max-width:1024px) and (min-width:0){#RecordSwitchers{display:flex;align-items:center}#RecordSwitchers #CurrentIndex{height:7.5vw;display:flex;align-items:center}#Editor fieldset .command-left{width:100%}table.grid tbody tr td svg{margin-top:calc(3.2vw - 13px);overflow:unset}table.grid tbody tr td .user{display:flex;align-items:center}table.grid tbody tr td .user .ui-icon-person{margin-top:.15vw}}@media screen and (max-width:1024px) and (min-width:0){#Editor #RecordHeader .user{display:flex;align-items:center}#Editor #RecordHeader .user .ui-icon-person{margin-right:.6vw}#EditorTabsContainer #Users_DeptIdField .ui-icon-person{top:calc(3vw - 6.5px)}}@media screen and (max-width:1024px) and (min-width:768px){.ui-icon{transform:scale(1.6);margin-right:4px}#Editor .ui-button-icon-space{width:1vw}#Editor #RecordHeader .user .ui-icon-person{margin:auto 4px}#EditorTabsContainer #Users_DeptIdField .ui-icon-person{top:calc(3vw - 3.5px);right:-30px}}@media screen and (max-width:1024px) and (min-width:0){#OutgoingMailDialog .field-wide{padding-bottom:5px}#OutgoingMailDialog .field-wide .field-label{width:auto}#OutgoingMailDialog .field-wide .field-control{float:none}#OutgoingMailDialog .field-wide .control-basket,#OutgoingMailDialog .field-wide .container-normal{margin-left:15vw}#OutgoingMailDialog textarea{height:20vw}}@media screen and (max-width:1024px) and (min-width:0){.show-password{top:calc(50% - 12px);right:10px}#LoginFieldSet input[type=checkbox]{transform:scale(1.2)}#LoginFieldSet input{height:10vw}#LoginFieldSet input,#LoginFieldSet select{font-size:4vw}#Users_RememberMeField .container-normal{display:flex;align-items:center}}@media screen and (max-width:1024px) and (min-width:768px){.show-password{transform:scale(1.5)}}@media screen and (max-width:1024px) and (min-width:0){#Navigations.open{padding-top:18vw}}@media screen and (max-width:1024px) and (min-width:0){#ViewModeContainer .field-auto-thin>.field-label{padding:7px 2vw 7px 0}#CrosstabValueField .field-control{width:70%}#Crosstab .field-auto-thin p{margin-right:0%}#ViewModeContainer #Crosstab .field-auto-thin{width:100%;flex:0 1 calc(100%);padding-top:1vw}#ViewModeContainer #Crosstab .field-auto-thin .field-label{width:30%}#ViewModeContainer #Crosstab .field-auto-thin .field-control{width:70%}#ViewModeContainer #Crosstab .field-auto-thin .field-control input[type='checkbox'],#ViewModeContainer #Crosstab .field-auto-thin .field-control .field-auto-thin input[type='checkbox']{width:4vw;height:4vw;margin-left:2px}#ViewModeContainer #Crosstab .field-control .control-dropdown{font-size:2.6vw}#CrosstabBody .grid>thead>tr:first-child>th:not(:first-child),#KambanBody .grid>thead>tr:first-child>th:not(:first-child){white-space:nowrap}}@media screen and (max-width:1024px) and (min-width:0){#ImportSettingsDialog .control-checkbox+label{margin:1.8vw 0 0 1vw}#ImportSettingsDialog .control-checkbox{margin:2vw 0 2vw 2px}#ImportSettingsDialog .control-textbox{height:7vw;line-height:6.5vw}#ImportSettingsDialog .command-center{padding:2vw 0}}@media screen and (max-width:1024px) and (min-width:0){#ExportSelectorDialog .command-center{padding:2vw 0}}@media screen and (max-width:1024px) and (min-width:0){#ViewModeContainer #Grid .control-dropdown,#ViewModeContainer #Grid .datepicker{width:25vw;text-overflow:ellipsis;white-space:nowrap}#ViewModeContainer #Grid .current-user,#ViewModeContainer #Grid .current-time{display:none}#ViewModeContainer #Grid .ui-spinner{height:6vw;max-height:6vw;display:flex;align-items:center}}@media screen and (max-width:1024px) and (min-width:0){#ViewModeContainer .both #TimeSeriesValueField,#ViewModeContainer .both #TimeSeriesChartTypeField,#ViewModeContainer .both #TimeSeriesHorizontalAxisField{width:100%}#ViewModeContainer .both #TimeSeriesValueField .field-label,#ViewModeContainer .both #TimeSeriesChartTypeField .field-label,#ViewModeContainer .both #TimeSeriesHorizontalAxisField .field-label{min-width:30%}#ViewModeContainer .both .field-auto-thin:first-child,#ViewModeContainer .both .field-auto-thin:nth-child(2){flex:0 1 calc(50% - 8px)}#ViewModeContainer .both .field-auto-thin:first-child .field-label,#ViewModeContainer .both .field-auto-thin:nth-child(2) .field-label{min-width:29%}#ViewModeContainer .both .field-auto-thin:nth-child(3) .field-label{min-width:13%}#ViewModeContainer .both .field-auto-thin select{max-width:100%}#ViewModeContainer .both .field-auto-thin>.field-control{min-width:68%}}@media screen and (max-width:1024px) and (min-width:0){#ApiEditorCommands{display:flex;justify-content:center;padding:10vw 0}}@media screen and (max-width:1024px) and (min-width:0){#Editor #TenantForm #EditorTabsContainer .fieldset .field-auto-thin{width:100%;height:7vw;margin:0}#Editor #TenantForm #EditorTabsContainer .fieldset .field-auto-thin .field-control{width:100%}#Editor #TenantForm #EditorTabsContainer .fieldset .field-auto-thin .field-control .container-normal label{padding:0}#Editor #TenantForm #EditorTabsContainer .fieldset .field-auto-thin .field-control .container-normal #TenantImage{height:auto}#Editor #TenantForm #EditorTabsContainer .fieldset .button-icon{margin-top:5vw}#Editor #TenantForm #EditorTabsContainer .fieldset #StyleField .field-textarea>.field-label,#Editor #TenantForm #EditorTabsContainer .fieldset #ScriptField .field-textarea>.field-label{width:100%;text-align:left}}@media screen and (max-width:1024px) and (min-width:0){#Versions span{margin:20px 10px 20px 0}}@media screen and (max-width:767px) and (min-width:0){#Versions{font-size:2.6vw;width:auto;padding:4vw 5vw 4vw 7vw}#Versions span{margin:0 10px 0 0}} \ No newline at end of file diff --git a/Implem.Pleasanter/wwwroot/scripts/_elements.js b/Implem.Pleasanter/wwwroot/scripts/_elements.js index e375744d5..653a51033 100644 --- a/Implem.Pleasanter/wwwroot/scripts/_elements.js +++ b/Implem.Pleasanter/wwwroot/scripts/_elements.js @@ -1,5 +1,5 @@ $p.responsive = function () { - return $('#Responsive').val() === '1'; + return $('#Responsive[type="hidden"]').val() === '1'; } $p.id = function () { diff --git a/Implem.Pleasanter/wwwroot/scripts/dashboard.js b/Implem.Pleasanter/wwwroot/scripts/dashboard.js index 8249f19f4..817cd4f72 100644 --- a/Implem.Pleasanter/wwwroot/scripts/dashboard.js +++ b/Implem.Pleasanter/wwwroot/scripts/dashboard.js @@ -4,7 +4,7 @@ $p.gridstackInstance = GridStack.init({ column: 20, cellHeight: 16, - oneColumnSize: 980, + oneColumnSize: 1024, draggable: { cancel: ".no-drag" }, disableDrag: isMobile, }); diff --git a/Implem.Pleasanter/wwwroot/scripts/gantt.js b/Implem.Pleasanter/wwwroot/scripts/gantt.js index 202c324af..d523e277e 100644 --- a/Implem.Pleasanter/wwwroot/scripts/gantt.js +++ b/Implem.Pleasanter/wwwroot/scripts/gantt.js @@ -8,6 +8,36 @@ } $p.drawGantt = function () { + let spacing = 25; + let heightPlaned = 23; + let heightEarned = 23; + let fontSize = 'inherit'; + let dYText = 16; + let heightGantt = 45; + let dYFirstLineAxis = 20; + let dYSecondLineAxis = 40; + let heightAxis = 20; + if (window.matchMedia("(max-width: 1024px)").matches) { + spacing = 50; + heightPlaned = 40; + heightEarned = 40; + dYText = 29; + heightGantt = 60; + dYFirstLineAxis = 20; + dYSecondLineAxis = 40; + heightAxis = 20; + } + if (window.matchMedia("(max-width: 767px)").matches) { + spacing = 30; + heightPlaned = 23; + heightEarned = 23; + fontSize = '2.6vw'; + dYText = 16; + heightGantt = 45; + dYFirstLineAxis = 20; + dYSecondLineAxis = 40; + heightAxis = 20; + } var $gantt = $('#Gantt'); var $axis = $('#GanttAxis'); if ($gantt.length !== 1) { @@ -49,10 +79,10 @@ $p.drawGantt = function () { .data(days) .enter() .append('rect') - .attr('x', function (d) { return 30 + xScale(d) }) + .attr('x', function (d) { return 23 + xScale(d) }) .attr('y', 25) .attr('width', xScale(days[1])) - .attr('height', 20) + .attr('height', heightAxis) .attr('class', function (d) { switch (d.getDay()) { case 0: return 'sunday'; @@ -62,9 +92,9 @@ $p.drawGantt = function () { }); var currentDate = minDate; while (currentDate <= maxDate) { - var axisLine = [[30 + xScale(currentDate), 25], [30 + xScale(currentDate), 45]]; + var axisLine = [[30 + xScale(currentDate), 25], [30 + xScale(currentDate), 60]]; var line = d3.line() - .x(function (d) { return d[0]; }) + .x(function (d) { return d[0] - 8; }) .y(function (d) { return d[1]; }); axis.append('g').attr('class', 'date').append('path').attr('d', line(axisLine)); currentDate = $p.dateAdd('d', 1, currentDate); @@ -77,9 +107,10 @@ $p.drawGantt = function () { .append('text') .attr('text-anchor', 'middle') .attr('x', function (d) { - return 30 + xScale(d) + (xScale($p.dateAdd('d', 1, d)) - xScale(d)) / 2; + return 22 + xScale(d) + (xScale($p.dateAdd('d', 1, d)) - xScale(d)) / 2; }) - .attr('y', 20) + .attr('y', dYFirstLineAxis) + .style('font-size', fontSize) .text(function (d) { return d.getMonth() + 1; }); @@ -93,9 +124,10 @@ $p.drawGantt = function () { .append('text') .attr('text-anchor', 'middle') .attr('x', function (d) { - return 30 + xScale(d) + (xScale($p.dateAdd('d', 1, d)) - xScale(d)) / 2; + return 22 + xScale(d) + (xScale($p.dateAdd('d', 1, d)) - xScale(d)) / 2; }) - .attr('y', 40) + .attr('y', dYSecondLineAxis) + .style('font-size', fontSize) .text(function (d) { return d.getDate(); }); @@ -105,9 +137,9 @@ $p.drawGantt = function () { : -1; $.each(json, function (i, d) { if (d.GroupSummary) groupCount++; - d.Y = padding + i * 25 + groupCount * 25; + d.Y = padding + i * spacing + groupCount * 25; }); - $('#Gantt').css('height', d3.max(json, function (d) { return d.Y }) + 45); + $('#Gantt').css('height', d3.max(json, function (d) { return d.Y }) + heightGantt); svg.append('g') .selectAll('rect') .data(days.filter(function (d) { @@ -150,7 +182,7 @@ $p.drawGantt = function () { return xScale($p.transferedDate(format, d.CompletionTime)) - xScale($p.transferedDate(format, d.StartTime)) }) - .attr('height', 23) + .attr('height', heightPlaned) .attr('class', function (d) { var ret = d.Completed ? 'completed' @@ -180,12 +212,12 @@ $p.drawGantt = function () { - xScale($p.transferedDate(format, d.StartTime))) * d.ProgressRate * 0.01 }) - .attr('height', 23) + .attr('height', heightEarned) .attr('class', function (d) { var ret = d.ProgressRate < 100 && (padding + xScale($p.transferedDate(format, d.StartTime)) + - ((xScale($p.transferedDate(format, d.CompletionTime)) - xScale($p.transferedDate(format, d.StartTime))) - * d.ProgressRate * 0.01)) < now + ((xScale($p.transferedDate(format, d.CompletionTime)) - xScale($p.transferedDate(format, d.StartTime))) + * d.ProgressRate * 0.01)) < now ? 'delay' : d.ProgressRate === 100 && d.Completed ? 'completed' @@ -211,19 +243,19 @@ $p.drawGantt = function () { : padding + xScale($p.transferedDate(format, d.StartTime)) + 5 }) .attr('y', function (d) { - return d.Y + 16; + return d.Y + dYText; }) .attr('width', function (d) { return (xScale($p.transferedDate(format, d.CompletionTime)) - xScale($p.transferedDate(format, d.StartTime))) * d.ProgressRate * 0.01 }) - .attr('height', 23) + .attr('height', 50) .attr('class', function (d) { var ret = d.ProgressRate < 100 && (padding + xScale($p.transferedDate(format, d.StartTime)) + - ((xScale($p.transferedDate(format, d.CompletionTime)) - xScale($p.transferedDate(format, d.StartTime))) - * d.ProgressRate * 0.01)) < now && + ((xScale($p.transferedDate(format, d.CompletionTime)) - xScale($p.transferedDate(format, d.StartTime))) + * d.ProgressRate * 0.01)) < now && ($('#ShowGanttProgressRate').val() === '1' || !d.Completed) ? 'delay' : ''; @@ -235,8 +267,21 @@ $p.drawGantt = function () { return 'start'; }) .attr('data-id', function (d) { return d.Id; }) + .style('font-size', fontSize) .text(function (d) { - return d.Title; + if (window.matchMedia("(max-width: 1024px)").matches) { + let labelRange = 0; + let span = (xScale($p.transferedDate(format, d.CompletionTime)) + - xScale($p.transferedDate(format, d.StartTime))) + * d.ProgressRate * 0.01 + let task = d.Title; + let label; + (span > labelRange) ? labelRange = span : labelRange; + (task.length * 7 > span) ? label = task.substring(0, 50) + "..." : label = task; + return label; + } else { + return d.Title; + } }) .append('title') .text(function (d) { diff --git a/Implem.Pleasanter/wwwroot/scripts/kamban.js b/Implem.Pleasanter/wwwroot/scripts/kamban.js index 4f72a7d2c..f2fe20fcf 100644 --- a/Implem.Pleasanter/wwwroot/scripts/kamban.js +++ b/Implem.Pleasanter/wwwroot/scripts/kamban.js @@ -17,7 +17,7 @@ var dataX = $(this).attr('data-x'); var dataY = $(this).attr('data-y'); data["KambanId"] = $(ui.draggable).attr('data-id'); - if (dataX !== undefined){ + if (dataX !== undefined) { data[tableNamePrefix + $('#KambanGroupByX').val()] = dataX; } if (dataY !== undefined) { @@ -26,4 +26,65 @@ $p.send($('#KambanBody')); } }); + $('#KambanBody .kamban-item').each(function () { + let offsetX, offsetY; + $(this).on('touchstart', function (e) { + const touch = e.touches[0]; + offsetX = touch.clientX; + offsetY = touch.clientY; + }); + $(this).on('touchmove', function (e) { + e.preventDefault(); + const touch = e.touches[0]; + const x = touch.clientX - offsetX; + const y = touch.clientY - offsetY; + const rectDraggable = this.getBoundingClientRect(); + $(this).css('z-index', 2); + $('#KambanBody .kamban-container').each(function () { + const rectDroppable = this.getBoundingClientRect(); + if ( + rectDraggable.left >= rectDroppable.left && + rectDraggable.left <= rectDroppable.right && + rectDraggable.top >= rectDroppable.top && + rectDraggable.top <= rectDroppable.bottom + ) { + $(this).css('background-color', '#f5f5f5'); + } else { + $(this).css('background-color', 'unset'); + } + }); + $(this).css('transform', `translate(${x}px, ${y}px)`); + }); + $(this).on('touchend', function () { + const rectDraggable = this.getBoundingClientRect(); + const id = $(this).attr('data-id'); + let isDroppableIntoKambanContainer = false; + $('#KambanBody .kamban-container').each(function () { + const rectDroppable = this.getBoundingClientRect(); + if ( + rectDraggable.left >= rectDroppable.left && + rectDraggable.left <= rectDroppable.right && + rectDraggable.top >= rectDroppable.top && + rectDraggable.top <= rectDroppable.bottom + ) { + var data = $p.getData($('.main-form')); + var tableNamePrefix = $('#TableName').val() + '_'; + var dataX = $(this).attr('data-x'); + var dataY = $(this).attr('data-y'); + data["KambanId"] = id; + if (dataX !== undefined) { + data[tableNamePrefix + $('#KambanGroupByX').val()] = dataX; + } + if (dataY !== undefined) { + data[tableNamePrefix + $('#KambanGroupByY').val()] = dataY; + } + $p.send($('#KambanBody')); + isDroppableIntoKambanContainer = true; + } + }); + if (!isDroppableIntoKambanContainer) { + $(this).css('transform', 'unset'); + } + }); + }); } \ No newline at end of file diff --git a/Implem.Pleasanter/wwwroot/scripts/markdown.js b/Implem.Pleasanter/wwwroot/scripts/markdown.js index dd6b7833a..941280454 100644 --- a/Implem.Pleasanter/wwwroot/scripts/markdown.js +++ b/Implem.Pleasanter/wwwroot/scripts/markdown.js @@ -49,7 +49,7 @@ $p.markup = function (markdownValue, encoded) { text = replaceUnc(text); return text.indexOf('[md]') === 0 ? '
' + marked(text.substring(4)) + '
' - : replaceUrl(markedUp(text)); + : markedUp(replaceUrl(text)); function markedUp(text) { var $html = $('
')
diff --git a/Implem.Pleasanter/wwwroot/scripts/responsive.js b/Implem.Pleasanter/wwwroot/scripts/responsive.js
index 35b9a3ac7..c69fe9708 100644
--- a/Implem.Pleasanter/wwwroot/scripts/responsive.js
+++ b/Implem.Pleasanter/wwwroot/scripts/responsive.js
@@ -29,7 +29,7 @@
 }
 
 $(document).ready(function () {
-    if ($p.responsive() && screen.width < 981) {
+    if ($p.responsive() && screen.width < 1025) {
         const heightHeader = $('#Header').length > 0 ? $('#Header').height() : 100;
         $('#Application').css({
             'padding-top': `${heightHeader}px`
@@ -96,7 +96,7 @@ $.each($toggleBtns, function (i, el) {
     });
 });
 
-if (screen.width < 981) {
+if (screen.width < 1025) {
     $p.send($('#ReduceViewFilters'));
     $p.send($('#ReduceAggregations'));
 }
@@ -122,17 +122,17 @@ $(document).ready(function () {
             }
         }
     }
-    if ($p.responsive() && screen.width < 981) {
+    if ($p.responsive() && screen.width < 1025) {
         handleSMobileViewport();
     }
     window.addEventListener('resize', function () {
-        if ($p.responsive()  && screen.width < 981) {
+        if ($p.responsive() && screen.width < 1025) {
             handleSMobileViewport();
         }
     });
 });
 
-if ($p.responsive() && screen.width < 981) {
+if ($p.responsive() && screen.width < 1025) {
     $('#ViewModeContainer').on('scroll', function () {
         let scrollLeft = $(this).scrollLeft();
         if ($(this).scrollLeft() > 0) {
@@ -142,3 +142,9 @@ if ($p.responsive() && screen.width < 981) {
         }
     });
 }
+
+if(navigator.userAgent.indexOf('iPhone') > -1 ) {
+    document
+      .querySelector("[name=viewport]")
+      .setAttribute("content","width=device-width, initial-scale=1, maximum-scale=1");
+}
\ No newline at end of file
diff --git a/Implem.Pleasanter/wwwroot/scripts/sitepackage.js b/Implem.Pleasanter/wwwroot/scripts/sitepackage.js
index 6d35419c3..58af8fe87 100644
--- a/Implem.Pleasanter/wwwroot/scripts/sitepackage.js
+++ b/Implem.Pleasanter/wwwroot/scripts/sitepackage.js
@@ -6,7 +6,7 @@
             width: '520px'
         });
     }
-    if ($p.responsive() && screen.width < 981) {
+    if ($p.responsive() && screen.width < 1025) {
         $p.openResponsiveMenu();
     }
 }
@@ -47,7 +47,7 @@ $p.openExportSitePackageDialog = function ($control) {
             }
         });
     }
-    if ($p.responsive() && screen.width < 981) {
+    if ($p.responsive() && screen.width < 1025) {
         $p.openResponsiveMenu();
     }
 }
diff --git a/Implem.Pleasanter/wwwroot/scripts/template.js b/Implem.Pleasanter/wwwroot/scripts/template.js
index e0479fd32..560e1c65d 100644
--- a/Implem.Pleasanter/wwwroot/scripts/template.js
+++ b/Implem.Pleasanter/wwwroot/scripts/template.js
@@ -1,6 +1,6 @@
 $p.templates = function ($control) {
     $p.send($control, 'MainForm');
-    if ($p.responsive() && screen.width < 981) {
+    if ($p.responsive() && screen.width < 1025) {
         $p.openResponsiveMenu();
     }
 }
diff --git a/Implem.Pleasanter/wwwroot/scripts/viewmode.js b/Implem.Pleasanter/wwwroot/scripts/viewmode.js
index dcff850ea..6db316512 100644
--- a/Implem.Pleasanter/wwwroot/scripts/viewmode.js
+++ b/Implem.Pleasanter/wwwroot/scripts/viewmode.js
@@ -3,7 +3,7 @@
         .replace('_action_', $control.attr('data-action').toLowerCase());
     $p.ajax(url, 'post', $p.getData($control), $control);
     history.pushState(null, null, url);
-    if ($p.responsive() && screen.width < 981) {
+    if ($p.responsive() && screen.width < 1025) {
         $p.openResponsiveMenu();
     }
 }
diff --git a/Implem.Pleasanter/wwwroot/styles/responsive.css b/Implem.Pleasanter/wwwroot/styles/responsive.css
index b1ad0bd02..d988ba16b 100644
--- a/Implem.Pleasanter/wwwroot/styles/responsive.css
+++ b/Implem.Pleasanter/wwwroot/styles/responsive.css
@@ -1,5 +1,4 @@
-
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
 
     #LoginFieldSet {
         width: 100%;
@@ -89,8 +88,9 @@
         height: auto;
     }
 
-	#Breadcrumb { display:none; }
-    #CopyToClipboards { display: none; }
+    #Breadcrumb {
+        font-size: 2.6vw;
+    }
 
 #ViewSelectorField { position: relative; margin-bottom: 5px; font-size: 2.8vw; }
 
@@ -181,7 +181,7 @@
 }
 
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
 
 body { min-width: 320px!important; }
 #Header { height: auto; position: relative; }
@@ -301,7 +301,7 @@ border: 1px solid #d19405;
 
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
 
 #SiteMenu .nav-site {
 width: 20vw;
@@ -477,7 +477,7 @@ overflow: hidden;
 #SiteMenu .nav-site.to-parent.has-image a { padding: 0 0 0 15px;}
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px){
+@media screen and (max-width: 1024px) and (min-width: 0px){
 
 #EditorTabs {}
 #Application {}
@@ -503,8 +503,8 @@ overflow: hidden;
 .links {
     overflow: auto;
 }
-
-@media screen and (max-width: 980px) and (min-width: 0px) {
+}
+@media screen and (max-width: 1024px) and (min-width: 0px) {
 #FieldSetHistories { overflow: auto; width: 100%; }
 #ViewModeContainer { overflow: auto; width: 100%; padding-top: 1%; }
     #CrosstabBody { overflow: auto; width: 100%; }
@@ -585,7 +585,7 @@ overflow: hidden;
     #KambanBody .grid>tbody td { min-width: 10vw; white-space: nowrap; }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #Header {
     padding: 0 calc(5vw);
   }
@@ -613,24 +613,33 @@ overflow: hidden;
   .field-control .control-text, .container-normal .control-textbox,
   .container-normal .control-dropdown,
   .container-normal .control-text {
+    font-size: 2.6vw;
     min-height: unset;
     height: 6vw;
     line-height: 6vw;
     padding-top: 0;
     padding-bottom: 0;
+    display: flex;
+    align-items: center;
   }
   body {
     font-size: 16px;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #HeaderTitle {
     font-size: 16px;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 768px) {
+  #HeaderTitle {
+    font-size: 35px;
+  }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   .command-center {
     padding: 0;
   }
@@ -643,13 +652,13 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #ViewSelector {
     font-size: 2.6vw;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #Logo a {
     align-items: center;
     display: flex;
@@ -666,31 +675,33 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 768px) {
+  #Logo #ProductLogo {
+    padding-left: 16px;
+    font-size: 32px;
+  }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #Editor .field-control .container-normal {
-    width: calc(100% - 20px);
-  }
-  #Editor .field-control .ui-icon.ui-icon-clock.current-time {
-    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDI0IDI0IiBoZWlnaHQ9IjEycHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjEycHgiIGZpbGw9IiMwMDAwMDAiPjxnPjxyZWN0IGZpbGw9Im5vbmUiIGhlaWdodD0iMjQiIHdpZHRoPSIyNCIvPjwvZz48Zz48Zz48Zz48cGF0aCBkPSJNMTIsMkM2LjUsMiwyLDYuNSwyLDEyczQuNSwxMCwxMCwxMHMxMC00LjUsMTAtMTBTMTcuNSwyLDEyLDJ6IE0xNi4yLDE2LjJMMTEsMTNWN2gxLjV2NS4ybDQuNSwyLjdMMTYuMiwxNi4yeiIvPjwvZz48L2c+PC9nPjwvc3ZnPg==");
-    background-position: center;
-    width: 12px;
-    height: 12px;
-    filter: invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%);
-    top: calc(3vw - 3.5px);
-    right: -16px;
-  }
-  #Editor .field-control .ui-icon.ui-icon-person.current-user {
-    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMTJweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0xMiAxMmMyLjIxIDAgNC0xLjc5IDQtNHMtMS43OS00LTQtNC00IDEuNzktNCA0IDEuNzkgNCA0IDR6bTAgMmMtMi42NyAwLTggMS4zNC04IDR2MmgxNnYtMmMwLTIuNjYtNS4zMy00LTgtNHoiLz48L3N2Zz4=");
-    background-position: center;
-    width: 12px;
-    height: 12px;
-    filter: invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%);
+    width: calc(100% - 18px);
+  }
+  #Editor .field-control .ui-icon.ui-icon-clock.current-time, #Editor .field-control .ui-icon.ui-icon-person.current-user {
+    top: calc(3vw - 6px);
+  }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 768px) {
+  #Editor .field-control .container-normal {
+    width: calc(100% - 36px);
+  }
+  #Editor .field-control .ui-icon.ui-icon-clock.current-time, #Editor .field-control .ui-icon.ui-icon-person.current-user {
     top: calc(3vw - 3.5px);
-    right: -16px;
+    right: -30px;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #FieldSetAddressBook #OutgoingMailDestinationForm .container-left {
     width: 38vw;
   }
@@ -699,7 +710,7 @@ overflow: hidden;
     padding: 0;
   }
   #FieldSetAddressBook #OutgoingMailDestinationForm .container-right .command-left button {
-    margin: 2px;
+    margin: 1vw 1vw 1vw 0;
   }
   #FieldSetAddressBook #OutgoingMailDestinationForm .container-right .container-selectable .wrapper {
     height: 40vw;
@@ -709,13 +720,19 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 768px) {
+  #FieldSetAddressBook #OutgoingMailDestinationForm .container-left {
+    width: 33vw;
+  }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #Issues_WorkValue {
     width: 100px;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   body::before {
     content: '';
     position: fixed;
@@ -738,7 +755,7 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #Users_LoginId,
   #Users_Password {
     height: 40px;
@@ -774,7 +791,7 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #Editor .field-markdown > .field-label > label {
     font-weight: bold;
   }
@@ -787,7 +804,7 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #GridCheckAll {
     margin-top: 0;
   }
@@ -806,7 +823,18 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
+  #Editor #EditorTabsContainer fieldset .wrapper {
+    max-height: 250px;
+    overflow: auto;
+  }
+  #Editor #EditorTabsContainer fieldset .container-selectable .command-left {
+    align-items: center;
+    display: flex;
+  }
+  #Editor #EditorTabsContainer fieldset:not(#FieldSetGeneral) legend.legend {
+    min-height: 10px;
+  }
   #SiteImageSettingsEditor .field-auto-thin, #GridSettingsEditor .field-auto-thin, #FiltersSettingsEditor .field-auto-thin, #EditorSettingsEditor .field-auto-thin,
   #LinksSettingsEditor .field-auto-thin, #HistoriesSettingsEditor .field-auto-thin, #FormulasSettingsEditor .field-auto-thin, #ViewsSettingsEditor .field-auto-thin,
   #ImportsSettingsEditor .field-auto-thin, #ExportsSettingsEditor .field-auto-thin, #CalendarSettingsEditor .field-auto-thin, #CrosstabSettingsEditor .field-auto-thin,
@@ -866,9 +894,21 @@ overflow: hidden;
   #SiteImageSettingsEditor #SetSiteImage {
     margin-right: 0;
   }
+  #SearchSettingsEditor #SearchType {
+    margin-bottom: 10px;
+  }
+  #SearchSettingsEditor #SearchSettingsEditorFulltext legend.legend.applied, #SearchSettingsEditor #SearchSettingsEditorOperations legend.legend.applied {
+    margin-bottom: 10px;
+  }
+  #SearchSettingsEditor #SearchSettingsEditorFulltext {
+    padding-top: 10px;
+  }
+  #Editor #EditorTabsContainer .fieldset + .field-auto-thin {
+    margin-top: 10px;
+  }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #Aggregations {
     display: flex;
     flex-wrap: wrap;
@@ -906,13 +946,16 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 768px) {
+  #Aggregations {
+    row-gap: 15px;
+  }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #ViewModeContainer .grid {
     vertical-align: middle;
   }
-  #ViewModeContainer .grid tr td:first-child {
-    padding: 6px;
-  }
   input[type='checkbox'], .field-auto-thin input[type='checkbox'] {
     width: 3vw;
     height: 3vw;
@@ -922,7 +965,7 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #SearchField #Search {
     font-size: 3vw;
     width: 100%;
@@ -932,7 +975,7 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #ViewFilters #ViewFilters_Reset {
     margin-left: auto;
     margin-right: 0;
@@ -994,7 +1037,7 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #EditorTabsContainer .legend.applied {
     display: flex;
     align-items: center;
@@ -1037,35 +1080,21 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   thead > tr.ui-widget-header th div > span {
     font-size: 2.8vw;
     white-space: nowrap;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 768px) {
   #EditorTabsContainer .field-control .container-normal .ui-icon.ui-icon-pencil.button-edit-markdown {
-    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMTJweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0zIDE3LjI1VjIxaDMuNzVMMTcuODEgOS45NGwtMy43NS0zLjc1TDMgMTcuMjV6TTIwLjcxIDcuMDRjLjM5LS4zOS4zOS0xLjAyIDAtMS40MWwtMi4zNC0yLjM0Yy0uMzktLjM5LTEuMDItLjM5LTEuNDEgMGwtMS44MyAxLjgzIDMuNzUgMy43NSAxLjgzLTEuODN6Ii8+PC9zdmc+");
-    background-position: center;
-    width: 12px;
-    height: 12px;
-    filter: invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%);
-    top: 8px;
+    top: 10px;
     right: 4px;
   }
-  #EditorTabsContainer .field-control .container-normal .ui-icon.ui-icon-image.button-upload-image {
-    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMTJweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0yMSAxOVY1YzAtMS4xLS45LTItMi0ySDVjLTEuMSAwLTIgLjktMiAydjE0YzAgMS4xLjkgMiAyIDJoMTRjMS4xIDAgMi0uOSAyLTJ6TTguNSAxMy41bDIuNSAzLjAxTDE0LjUgMTJsNC41IDZINWwzLjUtNC41eiIvPjwvc3ZnPg==");
-    background-position: center;
-    width: 12px;
-    height: 12px;
-    filter: invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%);
-    position: relative;
-    left: -1px;
-  }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #EditorTabsContainer {
     overflow: auto;
   }
@@ -1081,7 +1110,7 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   .is-showMenu {
     overflow: hidden;
   }
@@ -1155,7 +1184,7 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #OutgoingMailsForm {
     width: 100%;
     font-size: 2.6vw;
@@ -1221,13 +1250,60 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #SiteMenu li.ui-sortable-handle {
     touch-action: unset;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
+  .xdsoft_datetimepicker span {
+    font-size: 2.6vw;
+  }
+  .xdsoft_datetimepicker .xdsoft_datepicker {
+    width: calc(42.81vw - 16px);
+  }
+  .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_today_button {
+    margin-left: 0;
+  }
+  .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_label.xdsoft_year {
+    margin-left: 0;
+  }
+  .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_year, .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_month {
+    width: fit-content;
+  }
+  .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_year .xdsoft_select .xdsoft_option, .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_month .xdsoft_select .xdsoft_option {
+    font-size: 2.6vw;
+  }
+  .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_year .xdsoft_select .xdsoft_scrollbar, .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_month .xdsoft_select .xdsoft_scrollbar {
+    width: 0.7vw;
+  }
+  .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_calendar table th, .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_calendar table td {
+    font-size: 2.6vw;
+  }
+  .xdsoft_datetimepicker .xdsoft_timepicker.active {
+    width: calc(12.17vw - 8px);
+  }
+  .xdsoft_datetimepicker .xdsoft_timepicker.active .xdsoft_time_box .xdsoft_time {
+    font-size: 2.6vw;
+  }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 768px) {
+  .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_year i, .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_month i {
+    transform: scale(1.6);
+  }
+  .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_year span, .xdsoft_datetimepicker .xdsoft_datepicker .xdsoft_monthpicker .xdsoft_month span {
+    font-size: 16px;
+  }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 0px) {
+  .message span.body {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
   .message .close {
     top: unset;
     bottom: calc(50% - 8px);
@@ -1235,19 +1311,7 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
-  #EditorComments #CommentField .ui-icon.ui-icon-image.button-upload-image {
-    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMTJweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0yMSAxOVY1YzAtMS4xLS45LTItMi0ySDVjLTEuMSAwLTIgLjktMiAydjE0YzAgMS4xLjkgMiAyIDJoMTRjMS4xIDAgMi0uOSAyLTJ6TTguNSAxMy41bDIuNSAzLjAxTDE0LjUgMTJsNC41IDZINWwzLjUtNC41eiIvPjwvc3ZnPg==");
-    background-position: center;
-    width: 12px;
-    height: 12px;
-    filter: invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%);
-    position: relative;
-    left: 0px;
-  }
-}
-
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #Navigations.open {
     overflow-y: scroll;
   }
@@ -1260,11 +1324,17 @@ overflow: hidden;
   }
   #Navigations #NavigationMenu li.sub-menu .ui-menu-item .ui-menu-item-wrapper {
     font-size: 3vw;
-    padding-left: 6vw;
+    padding-left: 5vw;
+  }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 768px) {
+  #Navigations #NavigationMenu li.sub-menu .ui-menu-item .ui-menu-item-wrapper {
+    padding-left: 4vw;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #Editor .field-normal .field-control .container-normal input[type='checkbox'].control-checkbox {
     position: relative;
     margin-right: 6px;
@@ -1272,7 +1342,13 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 768px) {
+  #Editor .field-normal .field-control .container-normal input[type='checkbox'].control-checkbox {
+    margin-right: 12px;
+  }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #Editor #EditorTabsContainer .field-normal, #Editor #EditorTabsContainer .field-wide, #Editor #EditorTabsContainer .field-markdown {
     display: inline-block;
     margin-top: 8px;
@@ -1280,29 +1356,31 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #ViewModeContainer #Calendar.both select {
     font-size: 2.6vw;
+    height: 6vw;
   }
   #ViewModeContainer #Calendar.both .field-label {
-    min-width: 30%;
-    margin-right: 15px;
+    min-width: 16%;
+    margin-right: 0px;
   }
   #ViewModeContainer #Calendar.both .field-auto-thin .field-control .container-normal {
     display: flex;
     align-items: center;
   }
-  #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) {
-    flex: 0 1 calc(64%);
+  #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(1), #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(2), #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) {
+    flex: 0 1 calc(47%);
+    flex-wrap: nowrap;
   }
-  #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) .field-label {
-    min-width: 22%;
+  #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(1) .field-label, #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(2) .field-label, #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) .field-label {
+    min-width: 16%;
   }
-  #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) .field-control {
-    width: 74%;
+  #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(1) .field-control, #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(2) .field-control, #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(3) .field-control {
+    width: 84%;
   }
   #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(4) {
-    flex: 0 1 calc(33% + 1px);
+    width: 47%;
     padding-top: 2%;
   }
   #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(4) .field-control .container-normal {
@@ -1310,9 +1388,12 @@ overflow: hidden;
   }
   #ViewModeContainer #Calendar.both .field-auto-thin:nth-child(4) .field-control .container-normal #CalendarDate {
     margin-right: 0;
-    width: 98%;
+    width: 100%;
     font-size: 2.6vw;
   }
+  #ViewModeContainer #Calendar.both .field-auto-thin input[type='checkbox'] {
+    margin-left: 2px;
+  }
   #ViewModeContainer #Calendar.both button {
     flex: 1 0 calc((100% / 3) - 32px);
     margin: 2% 10px 2% 10px;
@@ -1322,35 +1403,27 @@ overflow: hidden;
   }
   #ViewModeContainer .grid.fixed tbody tr td.container .item {
     touch-action: auto;
-    min-height: 50px;
-  }
-  #ViewModeContainer .grid.fixed tbody tr td.container .item .title .ui-icon.ui-icon-pencil {
-    margin-right: 5px;
-    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMzBweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMzBweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGQ9Ik0zIDE3LjI1VjIxaDMuNzVMMTcuODEgOS45NGwtMy43NS0zLjc1TDMgMTcuMjV6TTIwLjcxIDcuMDRjLjM5LS4zOS4zOS0xLjAyIDAtMS40MWwtMi4zNC0yLjM0Yy0uMzktLjM5LTEuMDItLjM5LTEuNDEgMGwtMS44MyAxLjgzIDMuNzUgMy43NSAxLjgzLTEuODN6Ii8+PC9zdmc+");
-    background-position: center;
-    width: 36px;
-    height: 36px;
-    filter: invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%);
+    min-height: 4vw;
+    margin-top: 5px;
+    margin-bottom: 5px;
+    height: 4vw;
   }
   #ViewModeContainer .grid.fixed tbody tr td.container .item .connection {
-    min-height: 50px;
+    min-height: 4vw;
+    height: 4vw;
   }
   #ViewModeContainer .grid.fixed tbody tr td.container .dummy {
-    height: 50px;
-  }
-  #ViewModeContainer .grid.fixed tbody tr td.container:first-child .item {
-    margin-top: 0;
-    margin-bottom: 5px;
+    height: 4vw;
   }
-  #ViewModeContainer .grid.fixed tbody tr td.container:not(:first-child) .item {
-    margin-top: 5px;
+  #ViewModeContainer .grid.fixed tbody .title {
+    padding: 0;
   }
   thead th.calendar-header {
     overflow-x: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #ViewModeContainer .both {
     column-gap: 16px;
   }
@@ -1409,6 +1482,10 @@ overflow: hidden;
   #GanttBody {
     max-height: 70vh;
   }
+  #GanttBody #Gantt {
+    font-size: 2.6vw;
+    width: 500%;
+  }
   #GanttBody text {
     font-size: 2.6vw;
   }
@@ -1416,12 +1493,13 @@ overflow: hidden;
     font-size: 3vw;
   }
   #GanttBody #GanttAxis {
-    left: auto;
+    left: -2px;
     position: sticky;
+    width: 500%;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #ViewModeContainer #Kamban.both .field-auto-thin select {
     font-size: 2.6vw;
   }
@@ -1465,27 +1543,50 @@ overflow: hidden;
     align-items: center;
   }
   #ViewModeContainer #Kamban.both #KambanBody #Grid tbody .kamban-row .kamban-container .kamban-item {
+    height: 4vw;
+    padding: 0px 16px 0px 5px;
     overflow: hidden;
-    padding: 6px 30px 6px 5px;
     white-space: pre-line;
     touch-action: auto;
     display: -webkit-box;
     -webkit-line-clamp: 1;
     -webkit-box-orient: vertical;
   }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 768px) {
   #ViewModeContainer #Kamban.both #KambanBody #Grid tbody .kamban-row .kamban-container .kamban-item .ui-icon.ui-icon-pencil {
-    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMTJweCIgZmlsbD0iIzAwMDAwMCI+PHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTMgMTcuNDZ2My4wNGMwIC4yOC4yMi41LjUuNWgzLjA0Yy4xMyAwIC4yNi0uMDUuMzUtLjE1TDE3LjgxIDkuOTRsLTMuNzUtMy43NUwzLjE1IDE3LjFjLS4xLjEtLjE1LjIyLS4xNS4zNnpNMjAuNzEgNy4wNGMuMzktLjM5LjM5LTEuMDIgMC0xLjQxbC0yLjM0LTIuMzRjLS4zOS0uMzktMS4wMi0uMzktMS40MSAwbC0xLjgzIDEuODMgMy43NSAzLjc1IDEuODMtMS44M3oiLz48L3N2Zz4=");
-    background-position: center;
-    width: 36px;
-    height: 36px;
-    filter: invert(69%) sepia(77%) saturate(3818%) hue-rotate(12deg) brightness(97%) contrast(96%);
-    margin-right: 0;
-    top: -7px;
-    right: -11px;
+    width: 16px;
+    height: 16px;
+    top: 10px;
+    right: 4px;
+  }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 0px) {
+  #ViewModeContainer #Calendar #FullCalendar.fc .fc-header-toolbar .fc-toolbar-chunk:last-child .fc-button-group {
+    display: flex;
+    flex-wrap: wrap;
+    margin: 0;
+  }
+  #ViewModeContainer #Calendar #FullCalendar.fc .fc-header-toolbar .fc-toolbar-chunk:last-child .fc-button-group button:nth-child(3) {
+    border-radius: 0 0.25em 0.25em 0;
+  }
+  #ViewModeContainer #Calendar #FullCalendar.fc .fc-header-toolbar .fc-toolbar-chunk:last-child .fc-button-group button:last-child {
+    border-radius: 0.25em;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 768px) and (min-width: 0px) {
+  #ViewModeContainer #Calendar #FullCalendar.fc .fc-header-toolbar .fc-toolbar-chunk:last-child .fc-button-group button:nth-child(odd) {
+    border-radius: 0.25em 0 0 0.25em;
+  }
+  #ViewModeContainer #Calendar #FullCalendar.fc .fc-header-toolbar .fc-toolbar-chunk:last-child .fc-button-group button:nth-child(even) {
+    border-radius: 0 0.25em 0.25em 0;
+  }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #RecordSwitchers {
     display: flex;
     align-items: center;
@@ -1495,9 +1596,23 @@ overflow: hidden;
     display: flex;
     align-items: center;
   }
+  #Editor fieldset .command-left {
+    width: 100%;
+  }
+  table.grid tbody tr td svg {
+    margin-top: calc(3.2vw - 13px);
+    overflow: unset;
+  }
+  table.grid tbody tr td .user {
+    display: flex;
+    align-items: center;
+  }
+  table.grid tbody tr td .user .ui-icon-person {
+    margin-top: 0.15vw;
+  }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0) {
+@media screen and (max-width: 1024px) and (min-width: 0) {
   #Editor #RecordHeader .user {
     display: flex;
     align-items: center;
@@ -1505,9 +1620,29 @@ overflow: hidden;
   #Editor #RecordHeader .user .ui-icon-person {
     margin-right: 0.6vw;
   }
+  #EditorTabsContainer #Users_DeptIdField .ui-icon-person {
+    top: calc(3vw - 6.5px);
+  }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 768px) {
+  .ui-icon {
+    transform: scale(1.6);
+    margin-right: 4px;
+  }
+  #Editor .ui-button-icon-space {
+    width: 1vw;
+  }
+  #Editor #RecordHeader .user .ui-icon-person {
+    margin: auto 4px;
+  }
+  #EditorTabsContainer #Users_DeptIdField .ui-icon-person {
+    top: calc(3vw - 3.5px);
+    right: -30px;
+  }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #OutgoingMailDialog .field-wide {
     padding-bottom: 5px;
   }
@@ -1526,14 +1661,17 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   .show-password {
-    top: calc(50% - 10px);
+    top: calc(50% - 12px);
     right: 10px;
   }
   #LoginFieldSet input[type=checkbox] {
     transform: scale(1.2);
   }
+  #LoginFieldSet input {
+    height: 10vw;
+  }
   #LoginFieldSet input,
   #LoginFieldSet select {
     font-size: 4vw;
@@ -1544,13 +1682,19 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 768px) {
+  .show-password {
+    transform: scale(1.5);
+  }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #Navigations.open {
     padding-top: 18vw;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #ViewModeContainer .field-auto-thin > .field-label {
     padding: 7px 2vw 7px 0;
   }
@@ -1577,13 +1721,16 @@ overflow: hidden;
     height: 4vw;
     margin-left: 2px;
   }
+  #ViewModeContainer #Crosstab .field-control .control-dropdown {
+    font-size: 2.6vw;
+  }
   #CrosstabBody .grid > thead > tr:first-child > th:not(:first-child),
   #KambanBody .grid > thead > tr:first-child > th:not(:first-child) {
     white-space: nowrap;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #ImportSettingsDialog .control-checkbox + label {
     margin: 1.8vw 0 0 1vw;
   }
@@ -1599,20 +1746,32 @@ overflow: hidden;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #ExportSelectorDialog .command-center {
     padding: 2vw 0;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
+  #ViewModeContainer #Grid .control-dropdown,
   #ViewModeContainer #Grid .datepicker {
-    width: 35vw;
-    font-size: 4vw;
+    width: 25vw;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  #ViewModeContainer #Grid .current-user,
+  #ViewModeContainer #Grid .current-time {
+    display: none;
+  }
+  #ViewModeContainer #Grid .ui-spinner {
+    height: 6vw;
+    max-height: 6vw;
+    display: flex;
+    align-items: center;
   }
 }
 
-@media screen and (max-width: 980px) and (min-width: 0px) {
+@media screen and (max-width: 1024px) and (min-width: 0px) {
   #ViewModeContainer .both #TimeSeriesValueField,
   #ViewModeContainer .both #TimeSeriesChartTypeField,
   #ViewModeContainer .both #TimeSeriesHorizontalAxisField {
@@ -1625,11 +1784,14 @@ overflow: hidden;
   }
   #ViewModeContainer .both .field-auto-thin:first-child,
   #ViewModeContainer .both .field-auto-thin:nth-child(2) {
-    flex: 0 1 calc(100%);
+    flex: 0 1 calc(50% - 8px);
   }
   #ViewModeContainer .both .field-auto-thin:first-child .field-label,
   #ViewModeContainer .both .field-auto-thin:nth-child(2) .field-label {
-    min-width: 30%;
+    min-width: 29%;
+  }
+  #ViewModeContainer .both .field-auto-thin:nth-child(3) .field-label {
+    min-width: 13%;
   }
   #ViewModeContainer .both .field-auto-thin select {
     max-width: 100%;
@@ -1637,4 +1799,54 @@ overflow: hidden;
   #ViewModeContainer .both .field-auto-thin > .field-control {
     min-width: 68%;
   }
-}
\ No newline at end of file
+}
+
+@media screen and (max-width: 1024px) and (min-width: 0px) {
+  #ApiEditorCommands {
+    display: flex;
+    justify-content: center;
+    padding: 10vw 0;
+  }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 0px) {
+  #Editor #TenantForm #EditorTabsContainer .fieldset .field-auto-thin {
+    width: 100%;
+    height: 7vw;
+    margin: 0;
+  }
+  #Editor #TenantForm #EditorTabsContainer .fieldset .field-auto-thin .field-control {
+    width: 100%;
+  }
+  #Editor #TenantForm #EditorTabsContainer .fieldset .field-auto-thin .field-control .container-normal label {
+    padding: 0;
+  }
+  #Editor #TenantForm #EditorTabsContainer .fieldset .field-auto-thin .field-control .container-normal #TenantImage {
+    height: auto;
+  }
+  #Editor #TenantForm #EditorTabsContainer .fieldset .button-icon {
+    margin-top: 5vw;
+  }
+  #Editor #TenantForm #EditorTabsContainer .fieldset #StyleField .field-textarea > .field-label,
+  #Editor #TenantForm #EditorTabsContainer .fieldset #ScriptField .field-textarea > .field-label {
+    width: 100%;
+    text-align: left;
+  }
+}
+
+@media screen and (max-width: 1024px) and (min-width: 0) {
+  #Versions span {
+    margin: 20px 10px 20px 0;
+  }
+}
+
+@media screen and (max-width: 767px) and (min-width: 0) {
+  #Versions {
+    font-size: 2.6vw;
+    width: auto;
+    padding: 4vw 5vw 4vw 7vw;
+  }
+  #Versions span {
+    margin: 0 10px 0 0;
+  }
+}
diff --git a/Implem.TestAutomation/implem.TestAutomation.csproj b/Implem.TestAutomation/implem.TestAutomation.csproj
index 8629e360a..5cfd65b59 100644
--- a/Implem.TestAutomation/implem.TestAutomation.csproj
+++ b/Implem.TestAutomation/implem.TestAutomation.csproj
@@ -4,9 +4,9 @@
     Exe
     net6.0
     Copyright © Implem Inc 2014 - 2023
-    1.3.47.0
-    1.3.47.0
-    1.3.47.0
+    1.3.48.0
+    1.3.48.0
+    1.3.48.0
     Linux  
   
 
@@ -25,13 +25,13 @@
     
     
     
-    
-    
-    
+    
+    
+    
     
-    
+    
     
-    
+    
     
   
 
diff --git a/Rds/Implem.IRds/Implem.IRds.csproj b/Rds/Implem.IRds/Implem.IRds.csproj
index 868e0ea86..16055a1f7 100644
--- a/Rds/Implem.IRds/Implem.IRds.csproj
+++ b/Rds/Implem.IRds/Implem.IRds.csproj
@@ -3,9 +3,9 @@
   
     net6.0
     Copyright © Implem Inc 2014 - 2023
-    1.3.47.0
-    1.3.47.0
-    1.3.47.0
+    1.3.48.0
+    1.3.48.0
+    1.3.48.0
     disable
   
 
diff --git a/Rds/Implem.PostgreSql/Implem.PostgreSql.csproj b/Rds/Implem.PostgreSql/Implem.PostgreSql.csproj
index a0ecc9983..695a03358 100644
--- a/Rds/Implem.PostgreSql/Implem.PostgreSql.csproj
+++ b/Rds/Implem.PostgreSql/Implem.PostgreSql.csproj
@@ -3,14 +3,14 @@
   
     net6.0
     Copyright © Implem Inc 2014 - 2023
-    1.3.47.0
-    1.3.47.0
-    1.3.47.0
+    1.3.48.0
+    1.3.48.0
+    1.3.48.0
     disable
   
 
   
-    
+    
   
 
   
diff --git a/Rds/Implem.SqlServer/Implem.SqlServer.csproj b/Rds/Implem.SqlServer/Implem.SqlServer.csproj
index b7880a036..211ec45ec 100644
--- a/Rds/Implem.SqlServer/Implem.SqlServer.csproj
+++ b/Rds/Implem.SqlServer/Implem.SqlServer.csproj
@@ -3,9 +3,9 @@
   
     net6.0
     Copyright © Implem Inc 2014 - 2023
-    1.3.47.0
-    1.3.47.0
-    1.3.47.0
+    1.3.48.0
+    1.3.48.0
+    1.3.48.0
     disable