add configuration option to force local translations

fix silly bug with no being able to claim ownership
continue work on configuration via webfront
This commit is contained in:
RaidMax 2019-04-11 20:43:05 -05:00
parent 52fe8fc847
commit f0fd4c66e9
14 changed files with 264 additions and 35 deletions

View File

@ -17,17 +17,20 @@ namespace IW4MAdmin.Application.Localization
string currentLocale = string.IsNullOrEmpty(customLocale) ? CultureInfo.CurrentCulture.Name : customLocale;
string[] localizationFiles = Directory.GetFiles(Path.Join(Utilities.OperatingDirectory, "Localization"), $"*.{currentLocale}.json");
try
if (!Program.ServerManager.GetApplicationSettings()?.Configuration()?.UseLocalTranslations ?? false)
{
var api = Endpoint.Get();
var localization = api.GetLocalization(currentLocale).Result;
Utilities.CurrentLocalization = localization;
return;
}
try
{
var api = Endpoint.Get();
var localization = api.GetLocalization(currentLocale).Result;
Utilities.CurrentLocalization = localization;
return;
}
catch (Exception)
{
// the online localization failed so will default to local files
catch (Exception)
{
// the online localization failed so will default to local files
}
}
// culture doesn't exist so we just want language

View File

@ -35,7 +35,7 @@ namespace SharedLibraryCore.Commands
public override async Task ExecuteAsync(GameEvent E)
{
if (await (E.Owner.Manager.GetClientService() as ClientService).GetOwnerCount() == 0 &&
!E.Target.SetLevel(EFClient.Permission.Owner, Utilities.IW4MAdminClient(E.Owner)).Failed)
!E.Origin.SetLevel(EFClient.Permission.Owner, Utilities.IW4MAdminClient(E.Owner)).Failed)
{
E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_OWNER_SUCCESS"]);
}
@ -484,7 +484,7 @@ namespace SharedLibraryCore.Commands
// we don't really want to tell them if they're demoted haha
if (newPerm > oldPerm)
{
ActiveClient.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_SUCCESS_TARGET"].FormatExt(newPerm)));
ActiveClient.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_SUCCESS_TARGET"].FormatExt(newPerm));
}
}

View File

@ -1,64 +1,92 @@
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Helpers;
using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace SharedLibraryCore.Configuration
{
public class ApplicationConfiguration : IBaseConfiguration
{
[LocalizedDisplayName("SETUP_ENABLE_WEBFRONT")]
[LinkedConfiguration("WebfrontBindUrl", "ManualWebfrontUrl")]
public bool EnableWebFront { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_BIND_URL")]
public string WebfrontBindUrl { get; set; }
[ConfigurationOptional]
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_MANUAL_URL")]
public string ManualWebfrontUrl { get; set; }
[LocalizedDisplayName("SETUP_ENABLE_MULTIOWN")]
public bool EnableMultipleOwners { get; set; }
[LocalizedDisplayName("SETUP_ENABLE_STEPPEDPRIV")]
public bool EnableSteppedHierarchy { get; set; }
[LocalizedDisplayName("SETUP_DISPLAY_SOCIAL")]
public bool EnableSocialLink { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_USE_LOCAL_TRANSLATIONS")]
public bool UseLocalTranslations { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_IGNORE_BOTS")]
public bool IgnoreBots { get; set; }
[LinkedConfiguration("CustomSayName")]
[LocalizedDisplayName("SETUP_ENABLE_CUSTOMSAY")]
public bool EnableCustomSayName { get; set; }
[LocalizedDisplayName("SETUP_SAY_NAME")]
public string CustomSayName { get; set; }
[LocalizedDisplayName("SETUP_DISPLAY_SOCIAL")]
[LinkedConfiguration("SocialLinkAddress", "SocialLinkTitle")]
public bool EnableSocialLink { get; set; }
[LocalizedDisplayName("SETUP_SOCIAL_LINK")]
public string SocialLinkAddress { get; set; }
[LocalizedDisplayName("SETUP_SOCIAL_TITLE")]
public string SocialLinkTitle { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_BIND_URL")]
public string WebfrontBindUrl { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_MANUAL_URL")]
public string ManualWebfrontUrl { get; set; }
public string WebfrontUrl => string.IsNullOrEmpty(ManualWebfrontUrl) ? WebfrontBindUrl?.Replace("0.0.0.0", "127.0.0.1") : ManualWebfrontUrl;
[LocalizedDisplayName("SETUP_USE_CUSTOMENCODING")]
[LinkedConfiguration("CustomParserEncoding")]
public bool EnableCustomParserEncoding { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_ENCODING")]
public string CustomParserEncoding { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_ENABLE_WHITELIST")]
[LinkedConfiguration("WebfrontConnectionWhitelist")]
public bool EnableWebfrontConnectionWhitelist { get; set; }
public List<string> WebfrontConnectionWhitelist { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_CUSTOM_LOCALE")]
[LinkedConfiguration("CustomLocale")]
public bool EnableCustomLocale { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_CUSTOM_LOCALE")]
public string CustomLocale { get; set; }
[ConfigurationOptional]
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_DB_PROVIDER")]
public string DatabaseProvider { get; set; } = "sqlite";
[ConfigurationOptional]
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_CONNECTION_STRING")]
public string ConnectionString { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_RCON_POLLRATE")]
public int RConPollRate { get; set; } = 5000;
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_IGNORE_BOTS")]
public bool IgnoreBots { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_MAX_TB")]
public TimeSpan MaximumTempBanTime { get; set; } = new TimeSpan(24 * 30, 0, 0);
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_ENABLE_WHITELIST")]
public bool EnableWebfrontConnectionWhitelist { get; set; }
public List<string> WebfrontConnectionWhitelist { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_USE_LOCAL_TRANSLATIONS")]
public bool UseLocalTranslations { get; set; }
public string Id { get; set; }
public List<ServerConfiguration> Servers { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_AUTOMESSAGE_PERIOD")]
public int AutoMessagePeriod { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_AUTOMESSAGES")]
public List<string> AutoMessages { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_GLOBAL_RULES")]
public List<string> GlobalRules { get; set; }
public List<MapConfiguration> Maps { get; set; }
public List<QuickMessageConfiguration> QuickMessages { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_DISALLOWED_NAMES")]
public List<string> DisallowedClientNames { get; set; }
public List<ServerConfiguration> Servers { get; set; }
[ConfigurationIgnore]
public string Id { get; set; }
[ConfigurationIgnore]
public List<MapConfiguration> Maps { get; set; }
[ConfigurationIgnore]
public List<QuickMessageConfiguration> QuickMessages { get; set; }
[ConfigurationIgnore]
public string WebfrontUrl => string.IsNullOrEmpty(ManualWebfrontUrl) ? WebfrontBindUrl?.Replace("0.0.0.0", "127.0.0.1") : ManualWebfrontUrl;
public IBaseConfiguration Generate()
{

View File

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SharedLibraryCore.Helpers
{
[AttributeUsage(AttributeTargets.Property, Inherited = false)]
public class ConfigurationIgnore : Attribute
{
}
}

View File

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SharedLibraryCore.Helpers
{
[AttributeUsage(AttributeTargets.Property, Inherited = false)]
public class ConfigurationOptional : Attribute
{
}
}

View File

@ -0,0 +1,15 @@
using System;
namespace SharedLibraryCore.Helpers
{
[AttributeUsage(AttributeTargets.Property, Inherited = false)]
public class LinkedConfiguration : Attribute
{
public string[] LinkedPropertyNames { get; set; }
public LinkedConfiguration(params string[] linkedPropertyNames)
{
LinkedPropertyNames = linkedPropertyNames;
}
}
}

View File

@ -1,8 +1,12 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using SharedLibraryCore.Configuration;
using WebfrontCore.ViewModels;
namespace WebfrontCore.Controllers
{
@ -12,5 +16,27 @@ namespace WebfrontCore.Controllers
{
return View("Index", Manager.GetApplicationSettings().Configuration());
}
[HttpPost]
public IActionResult Edit(ApplicationConfiguration config)
{
return View("Index", Manager.GetApplicationSettings().Configuration());
}
public IActionResult GetNewListItem(string propertyName, int itemCount)
{
var config = Manager.GetApplicationSettings().Configuration();
var propertyInfo = config.GetType().GetProperties().First(_prop => _prop.Name == propertyName);
var configInfo = new ConfigurationInfo()
{
Configuration = config,
PropertyValue = (IList)propertyInfo.GetValue(config),
PropertyInfo = propertyInfo,
NewItemCount = itemCount
};
return PartialView("_ListItem", configInfo);
}
}
}

View File

@ -0,0 +1,19 @@
using SharedLibraryCore.Interfaces;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace WebfrontCore.ViewModels
{
public class ConfigurationInfo
{
public string PropertyName => PropertyInfo.Name;
public PropertyInfo PropertyInfo { get; set; }
public IList PropertyValue { get; set; }
public IBaseConfiguration Configuration { get; set; }
public int NewItemCount { get; set; }
}
}

View File

@ -5,10 +5,101 @@
string optionalText = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["COMMAND_HELP_OPTIONAL"];
string advancedText = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CONFIGURATION_ADVANCED"];
string addText = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CONFIGURATION_ADD"];
var properties = Model.GetType().GetProperties();
string[] getLinkedPropertyName(System.Reflection.PropertyInfo info)
{
var test = (info.GetCustomAttributes(false)
.Where(_attr => _attr.GetType() == typeof(SharedLibraryCore.Helpers.LinkedConfiguration))
.FirstOrDefault() as SharedLibraryCore.Helpers.LinkedConfiguration);
return test?.LinkedPropertyNames ?? new string[0];
}
bool shouldIgnore(System.Reflection.PropertyInfo info) => (info.GetCustomAttributes(false)
.Where(_attr => _attr.GetType() == typeof(SharedLibraryCore.Helpers.ConfigurationIgnore))
.FirstOrDefault() as SharedLibraryCore.Helpers.ConfigurationIgnore) != null;
bool isOptional(System.Reflection.PropertyInfo info) => (info.GetCustomAttributes(false)
.Where(_attr => _attr.GetType() == typeof(SharedLibraryCore.Helpers.ConfigurationOptional))
.FirstOrDefault() as SharedLibraryCore.Helpers.ConfigurationOptional) != null;
bool hasLinkedParent(System.Reflection.PropertyInfo info)
{
return Model.GetType().GetProperties().SelectMany(_prop => getLinkedPropertyName(_prop)).Contains(info.Name);
}
}
<div class="row">
<div class="col-12 text-white-50 configuration-form">
<div class="col-12 text-white-50 ">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
@foreach (var property in properties)
{
if (shouldIgnore(property))
{
continue;
}
string[] linkedPropertyNames = getLinkedPropertyName(property);
if (property.PropertyType.Name == typeof(System.Boolean).Name)
{
var attributes = linkedPropertyNames.Length > 0 ? new { htmlAttributes = new { @class = "has-related-content", data_related_content = string.Join(',', linkedPropertyNames.Select(_id => $"#{_id}_content")) } } : null;
<div class="form-group form-check bg-primary mb-0 pl-3 pr-3 p-2">
@Html.Editor(property.Name, attributes)
@Html.Label(property.Name, null, new { @class = "form-check-label ml-1" })
</div>
}
else if (property.PropertyType.Name.Contains("List"))
{
if (hasLinkedParent(property))
{
<div id="@($"{property.Name}_content")" class="@(linkedPropertyNames.Length == 0 ? "" : "hide") bg-dark pl-3 pr-3 pb-2">
@if (linkedPropertyNames.Length == 0)
{
@Html.Label(property.Name, null, new { @class = "pt-3" })
}
@Html.Editor(property.Name, new { htmlAttributes = new { @class = $"form-group form-control bg-dark text-white-50 {(linkedPropertyNames.Length == 0 ? "mb-3" : "mb-0")}" } })
</div>
}
else
{
@Html.Label(property.Name, null, new { @class = "bg-primary pl-3 pr-3 p-2 mb-0 mt-0 w-100" })
<div id="@($"{property.Name}_content")" class="pl-3 pr-3 pt-2 pb-3 bg-dark">
@Html.Editor(property.Name, new { htmlAttributes = new { @class = "form-control bg-dark text-white-50 mt-2", placeholder = isOptional(property) ? optionalText : "" } })
<a asp-controller="Configuration" asp-action="GetNewListItem" asp-route-propertyName="@property.Name" class="btn btn-primary configuration-add-new mt-2">@addText</a>
</div>
}
}
else
{
if (hasLinkedParent(property))
{
<div id="@($"{property.Name}_content")" class="@(hasLinkedParent(property) ? "hide" : "") bg-dark pl-3 pr-3 pb-3">
@Html.Label(property.Name, null, new { @class = "pt-3" })
@Html.Editor(property.Name, new { htmlAttributes = new { @class = "form-group form-control bg-dark text-white-50 mb-0", placeholder = isOptional(property) ? optionalText : "" } })
</div>
}
else
{
}
}
}
<button asp-controller="Configuration" asp-action="Edit"></button>
</form>
</div>
<div class="col-12 text-white-50 configuration-form d-none">
<form asp-action="Index">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
@ -80,7 +171,7 @@
<div class="form-group form-check bg-primary mb-0">
<label class="form-check-label p-2 pl-4">
<input class="form-check-input" asp-for="IgnoreBots"/> @Html.DisplayNameFor(model => model.IgnoreBots)
<input class="form-check-input" asp-for="IgnoreBots" /> @Html.DisplayNameFor(model => model.IgnoreBots)
</label>
</div>

View File

@ -0,0 +1,6 @@
@model WebfrontCore.ViewModels.ConfigurationInfo
@{
int index = Model.PropertyValue.Count + (Model.NewItemCount - Model.PropertyValue.Count);
}
<input class="form-control bg-dark text-white-50 mt-2 text-box single-line" id="@($"{Model.PropertyName}_{index}_")" name="@($"{Model.PropertyName}[{index}]")" type="text" />

View File

@ -93,5 +93,9 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Views\Shared\EditorTemplates\" />
</ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties /></VisualStudio></ProjectExtensions>
</Project>

View File

@ -6465,7 +6465,7 @@ form *, select {
margin-top: -0.5rem !important; }
/* Configuration */
.configuration-form input[type='text'], .configuration-form input[type='number'] {
.configuration-form input[type='text'], .configuration-form input[type='number'], input.text-box {
border: 1px solid #fd7e14; }
.hide {

View File

@ -282,7 +282,7 @@ form *, select {
}
/* Configuration */
.configuration-form input[type='text'], .configuration-form input[type='number'] {
.configuration-form input[type='text'], .configuration-form input[type='number'], input.text-box {
border: 1px solid $orange;
}

View File

@ -1,7 +1,7 @@
$(document).ready(function() {
$.each($('.has-related-content'), function (key, value) {
value = $(value);
if (value.attr('checked').length > 0) {
if (value.attr('checked') !== undefined && value.attr('checked').length > 0) {
$(value.data('related-content')).slideDown();
}
});
@ -10,4 +10,19 @@
var isChecked = $(this).is(':checked');
isChecked ? $($(this).data('related-content')).slideDown() : $($(this).data('related-content')).slideUp();
});
$('.configuration-add-new').click(function (e) {
e.preventDefault();
//let totalItems = $(this).siblings().length;
//let inputHtml = $(this).siblings().last().get(0).outerHTML;
//inputHtml = inputHtml.replace('_' + totalItems - 1 + '_', '_' + totalItems + '_');
//inputHtml = inputHtml.replace('[' + totalItems - 1 + ']', '[' + totalItems + ']');
//$(this).parent().prepend(inputHtml);
let parentElement = $(this).parent();
$.get($(this).attr('href') + '&itemCount=' + $(this).siblings().length, function (response) {
parentElement.prepend(response);
});
});
});