feat: Add InputData to all settings & Render correct inputs

This commit is contained in:
IceToast 2023-02-09 22:34:34 +01:00 committed by IceToast
parent 1011e2dcc4
commit ac5fa6c25c
13 changed files with 663 additions and 85 deletions

View file

@ -29,17 +29,25 @@ class SettingsController extends Controller
$className = 'App\\Settings\\' . str_replace('.php', '', $file);
$options = (new $className())->toArray();
if (method_exists($className, 'getOptionInputData')) {
$optionInputData = $className::getOptionInputData();
} else {
$optionInputData = [];
}
$optionsData = [];
foreach ($options as $key => $value) {
$options[$key] = [
$optionsData[$key] = [
'value' => $value,
'label' => ucwords(str_replace('_', ' ', $key))
'label' => $optionInputData[$key]['label'] ?? ucwords(str_replace('_', ' ', $key)),
'type' => $optionInputData[$key]['type'] ?? 'string',
'description' => $optionInputData[$key]['description'] ?? '',
'options' => $optionInputData[$key]['options'] ?? [],
];
}
$settings[str_replace('Settings.php', '', $file)] = $options;
$settings[str_replace('Settings.php', '', $file)] = $optionsData;
}
$settings->sort();

View file

@ -15,7 +15,7 @@ class DiscordSettings extends Settings
public ?string $guild_id;
public ?string $invite_url;
public ?string $role_id;
public static function group(): string
@ -31,4 +31,45 @@ class DiscordSettings extends Settings
'client_secret'
];
}
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'bot_token' => [
'label' => 'Bot Token',
'type' => 'string',
'description' => 'The bot token for your Discord bot.',
],
'client_id' => [
'label' => 'Client ID',
'type' => 'string',
'description' => 'The client ID for your Discord bot.',
],
'client_secret' => [
'label' => 'Client Secret',
'type' => 'string',
'description' => 'The client secret for your Discord bot.',
],
'guild_id' => [
'label' => 'Guild ID',
'type' => 'string',
'description' => 'The guild ID for your Discord server.',
],
'invite_url' => [
'label' => 'Invite URL',
'type' => 'string',
'description' => 'The invite URL for your Discord server.',
],
'role_id' => [
'label' => 'Role ID',
'type' => 'string',
'description' => 'The role ID for your Discord server.',
],
];
}
}

View file

@ -6,29 +6,17 @@ use Spatie\LaravelSettings\Settings;
class GeneralSettings extends Settings
{
public string $main_site;
public string $credits_display_name;
public float $initial_user_credits;
public int $initial_server_limit;
public string $recaptcha_site_key;
public string $recaptcha_secret_key;
public bool $recaptcha_enabled;
public string $recaptcha_site_key;
public string $recaptcha_secret_key;
public string $phpmyadmin_url;
public bool $alert_enabled;
public string $alert_type;
public string $alert_message;
public string $theme;
//public int $initial_user_role; wait for Roles & Permissions PR.
@ -56,4 +44,87 @@ class GeneralSettings extends Settings
'initial_server_limit' => 'required|numeric',
];
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'main_site' => [
'type' => 'string',
'label' => 'Main Site URL',
'description' => 'The URL of your main site.'
],
'credits_display_name' => [
'type' => 'string',
'label' => 'Credits Display Name',
'description' => 'The name of the currency used.'
],
'initial_user_credits' => [
'type' => 'number',
'label' => 'Initial User Credits',
'description' => 'The amount of credits a user gets when they register.'
],
'initial_server_limit' => [
'type' => 'number',
'label' => 'Initial Server Limit',
'description' => 'The amount of servers a user can create when they register.'
],
'recaptcha_enabled' => [
'type' => 'boolean',
'label' => 'Enable reCAPTCHA',
'description' => 'Enable reCAPTCHA on the login page.'
],
'recaptcha_site_key' => [
'type' => 'string',
'label' => 'reCAPTCHA Site Key',
'description' => 'The site key for reCAPTCHA.'
],
'recaptcha_secret_key' => [
'type' => 'string',
'label' => 'reCAPTCHA Secret Key',
'description' => 'The secret key for reCAPTCHA.'
],
'phpmyadmin_url' => [
'type' => 'string',
'label' => 'phpMyAdmin URL',
'description' => 'The URL of your phpMyAdmin installation.'
],
'alert_enabled' => [
'type' => 'boolean',
'label' => 'Enable Alert',
'description' => 'Enable an alert to be displayed on the home page.'
],
'alert_type' => [
'type' => 'select',
'label' => 'Alert Type',
'options' => [
'primary' => 'Blue',
'secondary' => 'Grey',
'success' => 'Green',
'danger' => 'Red',
'warning' => 'Orange',
'info' => 'Cyan',
],
'description' => 'The type of alert to display.'
],
'alert_message' => [
'type' => 'string',
'label' => 'Alert Message',
'description' => 'The message to display in the alert.'
],
'theme' => [
'type' => 'select',
'label' => 'Theme',
'options' => [
'default' => 'Default',
'BlueInfinity' => 'Blue Infinity',
],
'description' => 'The theme to use for the site.'
],
];
}
}

View file

@ -26,4 +26,55 @@ class InvoiceSettings extends Settings
{
return 'invoice';
}
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'company_address' => [
'label' => 'Company Address',
'type' => 'string',
'description' => 'The address of your company.',
],
'company_mail' => [
'label' => 'Company Mail',
'type' => 'string',
'description' => 'The mail of your company.',
],
'company_name' => [
'label' => 'Company Name',
'type' => 'string',
'description' => 'The name of your company.',
],
'company_phone' => [
'label' => 'Company Phone',
'type' => 'string',
'description' => 'The phone of your company.',
],
'company_vat' => [
'label' => 'Company VAT',
'type' => 'string',
'description' => 'The VAT of your company.',
],
'company_website' => [
'label' => 'Company Website',
'type' => 'string',
'description' => 'The website of your company.',
],
'enabled' => [
'label' => 'Enabled',
'type' => 'boolean',
'description' => 'Enable or disable invoices.',
],
'prefix' => [
'label' => 'Prefix',
'type' => 'string',
'description' => 'The prefix of your invoices.',
],
];
}
}

View file

@ -15,9 +15,47 @@ class LocaleSettings extends Settings
public string $default;
public bool $dynamic;
public static function group(): string
{
return 'locale';
}
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'available' => [
'label' => 'Available Locales',
'type' => 'multiselect',
'description' => 'The locales that are available for the user to choose from.',
'options' => config('app.available_locales'),
],
'clients_can_change' => [
'label' => 'Clients Can Change',
'type' => 'boolean',
'description' => 'Whether clients can change their locale.',
],
'datatables' => [
'label' => 'Datatables Locale',
'type' => 'string',
'description' => 'The datatables lang-code. <br><strong>Example:</strong> en-gb, fr_fr, de_de<br>More Information: <a href="https://datatables.net/plug-ins/i18n/">https://datatables.net/plug-ins/i18n/</a>',
],
'default' => [
'label' => 'Default Locale',
'type' => 'select',
'description' => 'The default locale to use.',
'options' => config('app.available_locales'),
],
'dynamic' => [
'label' => 'Dynamic Locale',
'type' => 'boolean',
'description' => 'Whether to use the dynamic locale.',
],
];
}
}

View file

@ -23,7 +23,7 @@ class MailSettings extends Settings
public ?string $mail_mailer;
public ?bool $mail_enabled;
public static function group(): string
{
return 'mail';
@ -47,7 +47,61 @@ class MailSettings extends Settings
config()->set('mail.from.address', $this->mail_from_address);
config()->set('mail.from.name', $this->mail_from_name);
} catch (\Exception) {
}
}
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'mail_host' => [
'label' => 'Mail Host',
'type' => 'string',
'description' => 'The host of your mail server.',
],
'mail_port' => [
'label' => 'Mail Port',
'type' => 'int',
'description' => 'The port of your mail server.',
],
'mail_username' => [
'label' => 'Mail Username',
'type' => 'string',
'description' => 'The username of your mail server.',
],
'mail_password' => [
'label' => 'Mail Password',
'type' => 'string',
'description' => 'The password of your mail server.',
],
'mail_encryption' => [
'label' => 'Mail Encryption',
'type' => 'string',
'description' => 'The encryption of your mail server.',
],
'mail_from_address' => [
'label' => 'Mail From Address',
'type' => 'string',
'description' => 'The from address of your mail server.',
],
'mail_from_name' => [
'label' => 'Mail From Name',
'type' => 'string',
'description' => 'The from name of your mail server.',
],
'mail_mailer' => [
'label' => 'Mail Mailer',
'type' => 'string',
'description' => 'The mailer of your mail server.',
],
'mail_enabled' => [
'label' => 'Mail Enabled',
'type' => 'boolean',
],
];
}
}

View file

@ -36,4 +36,35 @@ class PterodactylSettings extends Settings
{
return str_ends_with($this->panel_url, '/') ? $this->panel_url : $this->panel_url . '/';
}
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'panel_url' => [
'label' => 'Panel URL',
'type' => 'string',
'description' => 'The URL to your Pterodactyl panel.',
],
'admin_token' => [
'label' => 'Admin Token',
'type' => 'string',
'description' => 'The admin user token for your Pterodactyl panel.',
],
'user_token' => [
'label' => 'User Token',
'type' => 'string',
'description' => 'The user token for your Pterodactyl panel.',
],
'per_page_limit' => [
'label' => 'Per Page Limit',
'type' => 'number',
'description' => 'The number of servers to show per page.',
],
];
}
}

View file

@ -22,4 +22,54 @@ class ReferralSettings extends Settings
{
return 'referral';
}
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'allowed' => [
'label' => 'Allowed',
'type' => 'select',
'description' => 'Who is allowed to see their referral-URL',
'options' => [
'everyone' => 'Everyone',
'clients' => 'Clients',
],
],
'always_give_commission' => [
'label' => 'Always Give Commission',
'type' => 'boolean',
'description' => 'Always give commission to the referrer.',
],
'enabled' => [
'label' => 'Enabled',
'type' => 'boolean',
'description' => 'Enable referral system.',
],
'reward' => [
'label' => 'Reward',
'type' => 'number',
'description' => 'Reward for the referrer.',
],
'mode' => [
'label' => 'Mode',
'type' => 'select',
'description' => 'Referral mode.',
'options' => [
'comission' => 'Comission',
'sign-up' => 'Sign-Up',
'both' => 'Both',
],
],
'percentage' => [
'label' => 'Percentage',
'type' => 'number',
'description' => 'If a referred user buys credits, the referral-user will get x% of the Credits the referred user bought.',
],
];
}
}

View file

@ -18,4 +18,35 @@ class ServerSettings extends Settings
{
return 'server';
}
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'allocation_limit' => [
'label' => 'Allocation Limit',
'type' => 'number',
'description' => 'The maximum amount of allocations to pull per node for automatic deployment, if more allocations are being used than this limit is set to, no new servers can be created.',
],
'creation_enabled' => [
'label' => 'Creation Enabled',
'type' => 'boolean',
'description' => 'Whether or not users can create servers.',
],
'enable_upgrade' => [
'label' => 'Enable Upgrade',
'type' => 'boolean',
'description' => 'Whether or not users can upgrade their servers.',
],
'charge_first_hour' => [
'label' => 'Charge First Hour',
'type' => 'boolean',
'description' => 'Whether or not the first hour of a server is charged.',
],
];
}
}

View file

@ -7,11 +7,38 @@ use Spatie\LaravelSettings\Settings;
class TicketSettings extends Settings
{
public bool $enabled;
public string $notify;
public static function group(): string
{
return 'ticket';
}
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'enabled' => [
'label' => 'Enabled',
'type' => 'boolean',
'description' => 'Enable or disable the ticket system.',
],
'notify' => [
'label' => 'Notify',
'type' => 'select',
'description' => 'Who will receive an E-Mail when a new Ticket is created.',
'options' => [
'admin' => 'Admins',
'moderator' => 'Moderators',
'all' => 'Admins and Moderators',
'none' => 'Nobody',
],
],
];
}
}

View file

@ -34,4 +34,75 @@ class UserSettings extends Settings
{
return 'user';
}
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|boolean|number|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'credits_reward_after_verify_discord' => [
'label' => 'Credits Reward After Verify Discord',
'type' => 'number',
'description' => 'The amount of credits a user gets after verifying their discord account.',
],
'credits_reward_after_verify_email' => [
'label' => 'Credits Reward After Verify Email',
'type' => 'number',
'description' => 'The amount of credits a user gets after verifying their email.',
],
'force_discord_verification' => [
'label' => 'Force Discord Verification',
'type' => 'bool',
'description' => 'Force users to verify their discord account.',
],
'force_email_verification' => [
'label' => 'Force Email Verification',
'type' => 'bool',
'description' => 'Force users to verify their email.',
],
'initial_credits' => [
'label' => 'Initial Credits',
'type' => 'number',
'description' => 'The amount of credits a user gets when they register.',
],
'initial_server_limit' => [
'label' => 'Initial Server Limit',
'type' => 'number',
'description' => 'The amount of servers a user can create when they register.',
],
'min_credits_to_make_server' => [
'label' => 'Min Credits To Make Server',
'type' => 'number',
'description' => 'The minimum amount of credits a user needs to create a server.',
],
'server_limit_after_irl_purchase' => [
'label' => 'Server Limit After IRL Purchase',
'type' => 'number',
'description' => 'The amount of servers a user can create after they purchase a server.',
],
'server_limit_after_verify_discord' => [
'label' => 'Server Limit After Verify Discord',
'type' => 'number',
'description' => 'The amount of servers a user can create after they verify their discord account.',
],
'server_limit_after_verify_email' => [
'label' => 'Server Limit After Verify Email',
'type' => 'number',
'description' => 'The amount of servers a user can create after they verify their email.',
],
'register_ip_check' => [
'label' => 'Register IP Check',
'type' => 'boolean',
'description' => 'Check if the IP a user is registering from is already in use.',
],
'creation_enabled' => [
'label' => 'Creation Enabled',
'type' => 'boolean',
'description' => 'Whether or not users can create servers.',
],
];
}
}

View file

@ -6,9 +6,7 @@ use Spatie\LaravelSettings\Settings;
class WebsiteSettings extends Settings
{
public bool $motd_enabled;
public string $motd_message;
public bool $show_imprint;
@ -17,15 +15,73 @@ class WebsiteSettings extends Settings
public bool $show_tos;
public bool $useful_links_enabled;
public bool $enable_login_logo;
public string $seo_title;
public string $seo_description;
public bool $motd_enabled;
public bool $enable_login_logo;
public string $motd_message;
public static function group(): string
{
return 'website';
}
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'motd_enabled' => [
'label' => 'Enable MOTD',
'type' => 'boolean',
'description' => 'Enable the MOTD (Message of the day) on the dashboard.',
],
'motd_message' => [
'label' => 'MOTD Message',
'type' => 'textarea',
'description' => 'The message of the day.',
],
'show_imprint' => [
'label' => 'Show Imprint',
'type' => 'boolean',
'description' => 'Show the imprint on the website.',
],
'show_privacy' => [
'label' => 'Show Privacy',
'type' => 'boolean',
'description' => 'Show the privacy on the website.',
],
'show_tos' => [
'label' => 'Show TOS',
'type' => 'boolean',
'description' => 'Show the TOS on the website.',
],
'useful_links_enabled' => [
'label' => 'Enable Useful Links',
'type' => 'boolean',
'description' => 'Enable the useful links on the dashboard.',
],
'seo_title' => [
'label' => 'SEO Title',
'type' => 'string',
'description' => 'The title of the website.',
],
'seo_description' => [
'label' => 'SEO Description',
'type' => 'string',
'description' => 'The description of the website.',
],
'enable_login_logo' => [
'label' => 'Enable Login Logo',
'type' => 'boolean',
'description' => 'Enable the logo on the login page.',
],
];
}
}

View file

@ -40,56 +40,89 @@
<div class="card-body">
<!-- Sidebar Menu -->
<div class="d-flex w-100">
<nav class="mt-1">
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="tablist"
data-accordion="false">
@foreach ($settings as $category => $options)
<li class="nav-item border-bottom-0">
<a href="#{{ $category }}" class="nav-link {{ $loop->first ? 'active' : '' }}"
data-toggle="pill" role="tab">
<i class="nav-icon fas fa-cog"></i>
<p>
{{ $category }}
</p>
</a>
</li>
@endforeach
</ul>
</nav>
<div class="col-2 p-0">
<nav class="mt-1">
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="tablist"
data-accordion="false">
@foreach ($settings as $category => $options)
<li class="nav-item border-bottom-0">
<a href="#{{ $category }}"
class="nav-link {{ $loop->first ? 'active' : '' }}" data-toggle="pill"
role="tab">
<i class="nav-icon fas fa-cog"></i>
<p>
{{ $category }}
</p>
</a>
</li>
@endforeach
</ul>
</nav>
</div>
<!-- /.sidebar-menu -->
<!-- Content in $settings -->
<div class="tab-content ml-3" style="width: 100%;">
@foreach ($settings as $category => $options)
<div container class="tab-pane fade container {{ $loop->first ? 'active show' : '' }}"
id="{{ $category }}" role="tabpanel">
@foreach ($options as $key => $value)
<div class="row">
<div class="col">
{{ $value['label'] }}
<div class="col-10 p-0">
<div class="tab-content ml-3" style="width: 100%;">
@foreach ($settings as $category => $options)
<div container class="tab-pane fade container {{ $loop->first ? 'active show' : '' }}"
id="{{ $category }}" role="tabpanel">
@foreach ($options as $key => $value)
<div class="row">
<div class="col-4 d-flex align-items-center">
<label for="{{ $key }}">{{ $value['label'] }}</label>
</div>
<div class="col-8">
<div class="custom-control mb-3 d-flex align-items-center">
@if ($value['description'])
<i class="fas fa-info-circle mr-4" data-toggle="popover"
data-trigger="hover" data-placement="top" data-html="true"
data-content="{{ $value['description'] }}"></i>
@else
<i class="fas fa-info-circle mr-4 invisible"></i>
@endif
@if ($value['type'] == 'string')
<input type="text" class="form-control"
name="{{ $key }}" value="{{ $value['value'] }}">
@elseif ($value['type'] == 'boolean')
<input type="checkbox" name="{{ $key }}"
value="{{ $value['value'] }}">
@elseif ($value['type'] == 'number')
<input type="number" class="form-control"
name="{{ $key }}" value="{{ $value['value'] }}">
@elseif ($value['type'] == 'select')
<select id="{{ $key }}" class="custom-select w-100"
name="{{ $key }}">
@foreach ($value['options'] as $option)
<option value="{{ $option }}"
{{ $value['value'] == $option ? 'selected' : '' }}>
{{ __($option) }}
</option>
@endforeach
</select>
@elseif($value['type'] == 'multiselect')
<select class="custom-select w-100" name="{{ $key }}"
multiple>
@foreach ($value['options'] as $option)
<option value="{{ $option }}"
{{ $value['value'] == $option ? 'selected' : '' }}>
{{ __($option) }}
</option>
@endforeach
</select>
@elseif($value['type'] == 'textarea')
<textarea class="form-control w-100" name="{{ $key }}" rows="3">{{ $value['value'] }}</textarea>
@endif
</div>
</div>
</div>
<div class="col">
@if (gettype($value['value']) == 'string')
<input type="text" class="form-control" name="{{ $key }}"
value="{{ $value['value'] }}">
@elseif (gettype($value['value']) == 'boolean')
<input type="checkbox" class="form-control" name="{{ $key }}"
value="{{ $value['value'] }}">
@elseif (gettype($value['value']) == 'integer' || gettype($value['value']) == 'double')
<input type="number" class="form-control" name="{{ $key }}"
value="{{ $value['value'] }}">
@elseif (gettype($value['value']) == 'array')
<select class="form-control" name="{{ $key }}">
@foreach ($value['value'] as $option)
<option value="{{ $option }}">{{ $option }}
</option>
@endforeach
</select>
@endif
</div>
</div>
@endforeach
</div>
@endforeach
@endforeach
</div>
@endforeach
</div>
</div>
</div>
</div>
@ -97,6 +130,7 @@
</div>
<!-- END CUSTOM CONTENT -->
</section>
@ -114,5 +148,20 @@
window.location.hash = this.hash;
$('html,body').scrollTop(scrollmem);
});
document.addEventListener('DOMContentLoaded', (event) => {
$('.custom-select').select2();
})
tinymce.init({
selector: 'textarea',
promotion: false,
skin: "oxide-dark",
content_css: "dark",
branding: false,
height: 500,
width: '100%',
plugins: ['image', 'link'],
});
</script>
@endsection