From c4559a6f0326b66c49704ecad3f6f5eed02562eb Mon Sep 17 00:00:00 2001 From: Alexe Vlad Date: Thu, 21 Sep 2023 06:44:02 +0000 Subject: [PATCH 01/13] fix: solved routing handler for admin settings --- .../components/admin/settings/GeneralSettings.tsx | 13 +++++++++++-- .../components/admin/settings/SettingsContainer.tsx | 10 +++++----- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/resources/scripts/components/admin/settings/GeneralSettings.tsx b/resources/scripts/components/admin/settings/GeneralSettings.tsx index eb4ece2c8c..8104c5a689 100644 --- a/resources/scripts/components/admin/settings/GeneralSettings.tsx +++ b/resources/scripts/components/admin/settings/GeneralSettings.tsx @@ -3,14 +3,24 @@ import tw from 'twin.macro'; import AdminBox from '@/components/admin/AdminBox'; import Field, { FieldRow } from '@/components/elements/Field'; +import { useStoreState } from 'easy-peasy'; +import { ApplicationStore } from '@/state'; export default () => { + const { name: appName } = useStoreState((state: ApplicationStore) => state.settings.data!); + const submit = () => { // }; return ( - +
@@ -18,7 +28,6 @@ export default () => { - { - } /> - } /> - Security

} /> - Features

} /> - Advanced

} /> + } /> + } /> + Security

} /> + Features

} /> + Advanced

} />
); From 088af0d5f4f100a95ffab3821eaaf4939aa05272 Mon Sep 17 00:00:00 2001 From: Alexe Vlad Date: Thu, 21 Sep 2023 08:30:35 +0000 Subject: [PATCH 02/13] feat(settings-ui): Added security container & added default recaptcha & 2fa --- .../admin/settings/GeneralSettings.tsx | 15 +++- .../admin/settings/SecuritySettings.tsx | 79 +++++++++++++++++++ .../admin/settings/SettingsContainer.tsx | 3 +- 3 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 resources/scripts/components/admin/settings/SecuritySettings.tsx diff --git a/resources/scripts/components/admin/settings/GeneralSettings.tsx b/resources/scripts/components/admin/settings/GeneralSettings.tsx index 8104c5a689..4c419d7633 100644 --- a/resources/scripts/components/admin/settings/GeneralSettings.tsx +++ b/resources/scripts/components/admin/settings/GeneralSettings.tsx @@ -5,9 +5,10 @@ import AdminBox from '@/components/admin/AdminBox'; import Field, { FieldRow } from '@/components/elements/Field'; import { useStoreState } from 'easy-peasy'; import { ApplicationStore } from '@/state'; +import SelectField from '@/components/elements/SelectField'; export default () => { - const { name: appName } = useStoreState((state: ApplicationStore) => state.settings.data!); + const { name: appName, locale: language } = useStoreState((state: ApplicationStore) => state.settings.data!); const submit = () => { // @@ -18,6 +19,7 @@ export default () => { onSubmit={submit} initialValues={{ appName, + language, googleAnalytics: '', }} > @@ -39,6 +41,17 @@ export default () => { />
+ + + + +
diff --git a/resources/scripts/components/admin/settings/SecuritySettings.tsx b/resources/scripts/components/admin/settings/SecuritySettings.tsx new file mode 100644 index 0000000000..0f6831bc6e --- /dev/null +++ b/resources/scripts/components/admin/settings/SecuritySettings.tsx @@ -0,0 +1,79 @@ +import { Form, Formik } from 'formik'; +import tw from 'twin.macro'; + +import AdminBox from '@/components/admin/AdminBox'; +import Field, { FieldRow } from '@/components/elements/Field'; +import { useStoreState } from 'easy-peasy'; +import { ApplicationStore } from '@/state'; +import SelectField from '@/components/elements/SelectField'; + +export default () => { + const { recaptcha } = useStoreState((state: ApplicationStore) => state.settings.data!); + const { enabled: recaptchaStatus, siteKey } = recaptcha; + + const submit = () => { + // + }; + + return ( + +
+
+ + + + + + + + + + + + + + + +
+
+
+ ); +}; diff --git a/resources/scripts/components/admin/settings/SettingsContainer.tsx b/resources/scripts/components/admin/settings/SettingsContainer.tsx index 6b10ab7de8..bce6cf13b9 100644 --- a/resources/scripts/components/admin/settings/SettingsContainer.tsx +++ b/resources/scripts/components/admin/settings/SettingsContainer.tsx @@ -7,6 +7,7 @@ import MailSettings from '@/components/admin/settings/MailSettings'; import FlashMessageRender from '@/components/FlashMessageRender'; import { SubNavigation, SubNavigationLink } from '@/components/admin/SubNavigation'; import GeneralSettings from '@/components/admin/settings/GeneralSettings'; +import SecuritySettings from './SecuritySettings'; export default () => { return ( @@ -43,7 +44,7 @@ export default () => { } /> } /> - Security

} /> + } /> Features

} /> Advanced

} />
From 240e1e314212116169545efaca6c9bb8dc5d17f8 Mon Sep 17 00:00:00 2001 From: Alexe Vlad Date: Thu, 21 Sep 2023 09:14:01 +0000 Subject: [PATCH 03/13] feat(settings-ui): added controller for settings --- .../Api/Application/SettingsController.php | 49 +++++++++++++++++++ .../admin/settings/SettingsContainer.tsx | 2 +- routes/api-application.php | 4 +- 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 app/Http/Controllers/Api/Application/SettingsController.php diff --git a/app/Http/Controllers/Api/Application/SettingsController.php b/app/Http/Controllers/Api/Application/SettingsController.php new file mode 100644 index 0000000000..f5b49607e8 --- /dev/null +++ b/app/Http/Controllers/Api/Application/SettingsController.php @@ -0,0 +1,49 @@ + [ + 'app_name' => config('app.name'), + 'languages' => $this->getAvailableLanguages(true), + ], + 'mail' => [ + 'host' => config('mail.mailers.smtp.host'), + 'port' => config('mail.mailers.smtp.port'), + 'encryption' => config('mail.mailers.smtp.encryption'), + 'username' => config('mail.mailers.smtp.username'), + 'password' => config('mail.mailers.smtp.password'), + 'from_address' => config('mail.from.address'), + 'from_name' => config('mail.from.name') + ], + 'security' => [ + 'recaptcha' => [ + 'enabled' => config('recaptcha.enabled'), + 'site_key' => config('recaptcha.website_key'), + 'secret_key' => config('recaptcha.secret_key'), + ], + '2fa_enabled' => config('pterodactyl.auth.2fa_required'), + ], + ]); + } +} diff --git a/resources/scripts/components/admin/settings/SettingsContainer.tsx b/resources/scripts/components/admin/settings/SettingsContainer.tsx index bce6cf13b9..34b4ca55b0 100644 --- a/resources/scripts/components/admin/settings/SettingsContainer.tsx +++ b/resources/scripts/components/admin/settings/SettingsContainer.tsx @@ -7,7 +7,7 @@ import MailSettings from '@/components/admin/settings/MailSettings'; import FlashMessageRender from '@/components/FlashMessageRender'; import { SubNavigation, SubNavigationLink } from '@/components/admin/SubNavigation'; import GeneralSettings from '@/components/admin/settings/GeneralSettings'; -import SecuritySettings from './SecuritySettings'; +import SecuritySettings from '@/components/admin/settings/SecuritySettings'; export default () => { return ( diff --git a/routes/api-application.php b/routes/api-application.php index 717739dda7..96f785b7c9 100644 --- a/routes/api-application.php +++ b/routes/api-application.php @@ -4,7 +4,9 @@ use Pterodactyl\Http\Controllers\Api\Application; Route::get('/version', [Application\VersionController::class, '__invoke']); - +Route::group(['prefix' => '/settings'], function () { + Route::get('/', [Application\SettingsController::class, '__invoke']); +}); /* |-------------------------------------------------------------------------- | Database Controller Routes From f71a62668c4a5cf6241b6559028b0cd27f1758da Mon Sep 17 00:00:00 2001 From: Alexe Vlad Date: Thu, 21 Sep 2023 19:13:39 +0000 Subject: [PATCH 04/13] fix: remove Google Analytics --- .../components/admin/settings/GeneralSettings.tsx | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/resources/scripts/components/admin/settings/GeneralSettings.tsx b/resources/scripts/components/admin/settings/GeneralSettings.tsx index 4c419d7633..c030f710bf 100644 --- a/resources/scripts/components/admin/settings/GeneralSettings.tsx +++ b/resources/scripts/components/admin/settings/GeneralSettings.tsx @@ -30,17 +30,6 @@ export default () => { - - - - - Date: Fri, 22 Sep 2023 07:02:14 +0000 Subject: [PATCH 05/13] ui(admin): added advanced settings, settings service/transformer & fixed styling --- .../Api/Application/SettingsController.php | 34 ++------ app/Models/Setting.php | 5 ++ app/Services/Helpers/SettingsService.php | 40 +++++++++ .../Api/Application/SettingsTransformer.php | 47 +++++++++++ .../admin/settings/AdvancedSettings.tsx | 82 +++++++++++++++++++ .../admin/settings/SettingsContainer.tsx | 3 +- .../scripts/components/elements/Input.tsx | 2 +- 7 files changed, 182 insertions(+), 31 deletions(-) create mode 100644 app/Services/Helpers/SettingsService.php create mode 100644 app/Transformers/Api/Application/SettingsTransformer.php create mode 100644 resources/scripts/components/admin/settings/AdvancedSettings.tsx diff --git a/app/Http/Controllers/Api/Application/SettingsController.php b/app/Http/Controllers/Api/Application/SettingsController.php index f5b49607e8..29dcdcd4e6 100644 --- a/app/Http/Controllers/Api/Application/SettingsController.php +++ b/app/Http/Controllers/Api/Application/SettingsController.php @@ -2,16 +2,15 @@ namespace Pterodactyl\Http\Controllers\Api\Application; -use Illuminate\Http\JsonResponse; -use Pterodactyl\Traits\Helpers\AvailableLanguages; +use Pterodactyl\Services\Helpers\SettingsService; +use Pterodactyl\Transformers\Api\Application\SettingsTransformer; class SettingsController extends ApplicationApiController { - use AvailableLanguages; /** * VersionController constructor. */ - public function __construct() + public function __construct(private SettingsService $settingsService) { parent::__construct(); } @@ -19,31 +18,8 @@ public function __construct() /** * Returns version information. */ - public function __invoke(): JsonResponse + public function __invoke(): array { - // TODO: Make transformer, and add more information. - return new JsonResponse([ - 'general' => [ - 'app_name' => config('app.name'), - 'languages' => $this->getAvailableLanguages(true), - ], - 'mail' => [ - 'host' => config('mail.mailers.smtp.host'), - 'port' => config('mail.mailers.smtp.port'), - 'encryption' => config('mail.mailers.smtp.encryption'), - 'username' => config('mail.mailers.smtp.username'), - 'password' => config('mail.mailers.smtp.password'), - 'from_address' => config('mail.from.address'), - 'from_name' => config('mail.from.name') - ], - 'security' => [ - 'recaptcha' => [ - 'enabled' => config('recaptcha.enabled'), - 'site_key' => config('recaptcha.website_key'), - 'secret_key' => config('recaptcha.secret_key'), - ], - '2fa_enabled' => config('pterodactyl.auth.2fa_required'), - ], - ]); + return $this->fractal->item($this->settingsService->getCurrentSettings())->transformWith(SettingsTransformer::class)->toArray(); } } diff --git a/app/Models/Setting.php b/app/Models/Setting.php index b8812bc665..56e516c53e 100644 --- a/app/Models/Setting.php +++ b/app/Models/Setting.php @@ -11,6 +11,11 @@ */ class Setting extends Model { + /** + * The resource name for this model when it is transformed into an + * API representation using fractal. + */ + public const RESOURCE_NAME = 'settings'; /** * The table associated with the model. */ diff --git a/app/Services/Helpers/SettingsService.php b/app/Services/Helpers/SettingsService.php new file mode 100644 index 0000000000..3103aaa761 --- /dev/null +++ b/app/Services/Helpers/SettingsService.php @@ -0,0 +1,40 @@ + [ + 'name' => config('app.name'), + 'languages' => $this->getAvailableLanguages(true), + ], + 'mail' => [ + 'host' => config('mail.mailers.smtp.host'), + 'port' => config('mail.mailers.smtp.port'), + 'encryption' => config('mail.mailers.smtp.encryption'), + 'username' => config('mail.mailers.smtp.username'), + 'password' => config('mail.mailers.smtp.password'), + 'from_address' => config('mail.from.address'), + 'from_name' => config('mail.from.name') + ], + 'security' => [ + 'recaptcha' => [ + 'enabled' => config('recaptcha.enabled'), + 'site_key' => config('recaptcha.website_key'), + 'secret_key' => config('recaptcha.secret_key'), + ], + '2fa_enabled' => config('pterodactyl.auth.2fa_required'), + ], + ); + } +} diff --git a/app/Transformers/Api/Application/SettingsTransformer.php b/app/Transformers/Api/Application/SettingsTransformer.php new file mode 100644 index 0000000000..dda5399a89 --- /dev/null +++ b/app/Transformers/Api/Application/SettingsTransformer.php @@ -0,0 +1,47 @@ + [ + 'name' => $model['general']['name'], + 'languages' => $model['general']['languages'], + ], + 'mail' => [ + 'host' => $model['mail']['host'], + 'port' => $model['mail']['port'], + 'from_address' => $model['mail']['from_address'], + 'from_name' => $model['mail']['from_name'], + 'encryption' => $model['mail']['encryption'], + 'username' => $model['mail']['username'], + 'password' => $model['mail']['password'], + ], + 'security' => [ + 'recaptcha' => [ + 'enabled' => $model['security']['recaptcha']['enabled'], + 'site_key' => $model['security']['recaptcha']['site_key'], + 'secret_key' => $model['security']['recaptcha']['secret_key'], + ], + '2fa_enabled' => $model['security']['2fa_enabled'], + ], + ]; + } +} diff --git a/resources/scripts/components/admin/settings/AdvancedSettings.tsx b/resources/scripts/components/admin/settings/AdvancedSettings.tsx new file mode 100644 index 0000000000..002ff1de4d --- /dev/null +++ b/resources/scripts/components/admin/settings/AdvancedSettings.tsx @@ -0,0 +1,82 @@ +import { Form, Formik } from 'formik'; +import tw from 'twin.macro'; + +import AdminBox from '@/components/admin/AdminBox'; +import Field, { FieldRow } from '@/components/elements/Field'; +import SelectField from '@/components/elements/SelectField'; + +export default () => { + const submit = () => { + // + }; + + return ( + +
+
+ + + + + + + + + + + + + +
+
+
+ ); +}; diff --git a/resources/scripts/components/admin/settings/SettingsContainer.tsx b/resources/scripts/components/admin/settings/SettingsContainer.tsx index 34b4ca55b0..8bf6de1fcb 100644 --- a/resources/scripts/components/admin/settings/SettingsContainer.tsx +++ b/resources/scripts/components/admin/settings/SettingsContainer.tsx @@ -8,6 +8,7 @@ import FlashMessageRender from '@/components/FlashMessageRender'; import { SubNavigation, SubNavigationLink } from '@/components/admin/SubNavigation'; import GeneralSettings from '@/components/admin/settings/GeneralSettings'; import SecuritySettings from '@/components/admin/settings/SecuritySettings'; +import AdvancedSettings from './AdvancedSettings'; export default () => { return ( @@ -46,7 +47,7 @@ export default () => { } /> } /> Features

} /> - Advanced

} /> + } /> ); diff --git a/resources/scripts/components/elements/Input.tsx b/resources/scripts/components/elements/Input.tsx index 89e6bb88e0..8537e96c5b 100644 --- a/resources/scripts/components/elements/Input.tsx +++ b/resources/scripts/components/elements/Input.tsx @@ -45,7 +45,7 @@ const inputStyle = css` & + .input-help { ${tw`mt-1 text-xs`}; - ${props => (props.hasError ? tw`text-red-200` : tw`text-neutral-200`)}; + ${props => (props.hasError ? tw`text-red-200` : tw`text-neutral-400`)}; } &:required, From 2e2007e674829b0f95296717b646000dedb2d159 Mon Sep 17 00:00:00 2001 From: Alexe Vlad Date: Fri, 22 Sep 2023 14:53:27 +0000 Subject: [PATCH 06/13] ui(admin): glueing backend and frontend --- resources/scripts/api/admin/settings.ts | 48 +++++++++++++++++++ .../api/definitions/admin/transformers.ts | 26 ++++++++++ .../admin/settings/GeneralSettings.tsx | 8 +++- .../admin/settings/MailSettings.tsx | 7 ++- .../admin/settings/SecuritySettings.tsx | 7 ++- .../admin/settings/SettingsContainer.tsx | 17 ++++++- 6 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 resources/scripts/api/admin/settings.ts diff --git a/resources/scripts/api/admin/settings.ts b/resources/scripts/api/admin/settings.ts new file mode 100644 index 0000000000..c13c831435 --- /dev/null +++ b/resources/scripts/api/admin/settings.ts @@ -0,0 +1,48 @@ +import { Model } from '@/api/admin/index'; +import http from '@/api/http'; +import Transformers from '../definitions/admin/transformers'; +import useSWR from 'swr'; + +export interface Settings extends Model { + general: GeneralSettings; + mail: MailSettings; + security: SecuritySettings; +} + +export interface GeneralSettings { + name: string; + languages: Language[]; +} + +type Language = { + [key: string]: string; +}; + +export type LanguageKey = 'en'; + +export interface MailSettings { + host: string; + port: number; + username: string; + password: string; + encryption: string; + fromAddress: string; + fromName: string; +} + +export interface SecuritySettings { + recaptcha: { + enabled: boolean; + siteKey: string; + secretKey: string; + }; + '2faEnabled': boolean; +} + +export const getSettings = () => { + return useSWR('settings', async () => { + const { data } = await http.get(`/api/application/settings`); + + return Transformers.toSettings(data); + }); +}; diff --git a/resources/scripts/api/definitions/admin/transformers.ts b/resources/scripts/api/definitions/admin/transformers.ts index d298341e83..31a345d2d1 100644 --- a/resources/scripts/api/definitions/admin/transformers.ts +++ b/resources/scripts/api/definitions/admin/transformers.ts @@ -6,6 +6,7 @@ import * as Models from '@definitions/admin/models'; import { Location } from '@/api/admin/location'; import { Egg, EggVariable } from '@/api/admin/egg'; import { Nest } from '@/api/admin/nest'; +import { Settings } from '@/api/admin/settings'; const isList = (data: FractalResponseList | FractalResponseData): data is FractalResponseList => data.object === 'list'; @@ -225,4 +226,29 @@ export default class Transformers { eggs: transform(attributes.relationships?.eggs as FractalResponseList, this.toEgg), }, }); + + static toSettings = ({ attributes }: FractalResponseData): Settings => ({ + general: { + name: attributes.general.name, + languages: attributes.general.languages, + }, + mail: { + host: attributes.mail.host, + port: attributes.mail.port, + username: attributes.mail.username, + password: attributes.mail.password, + encryption: attributes.mail.encryption, + fromAddress: attributes.mail.from_address, + fromName: attributes.mail.from_name, + }, + security: { + recaptcha: { + enabled: attributes.security.recaptcha.enabled, + siteKey: attributes.security.recaptcha.site_key, + secretKey: attributes.security.recaptcha.secret_key, + }, + '2faEnabled': attributes.security['2fa_enabled'], + }, + relationships: {}, + }); } diff --git a/resources/scripts/components/admin/settings/GeneralSettings.tsx b/resources/scripts/components/admin/settings/GeneralSettings.tsx index c030f710bf..ca980f489b 100644 --- a/resources/scripts/components/admin/settings/GeneralSettings.tsx +++ b/resources/scripts/components/admin/settings/GeneralSettings.tsx @@ -6,8 +6,13 @@ import Field, { FieldRow } from '@/components/elements/Field'; import { useStoreState } from 'easy-peasy'; import { ApplicationStore } from '@/state'; import SelectField from '@/components/elements/SelectField'; +import { GeneralSettings } from '@/api/admin/settings'; -export default () => { +interface Props { + data?: GeneralSettings; +} + +export default ({ data }: Props) => { const { name: appName, locale: language } = useStoreState((state: ApplicationStore) => state.settings.data!); const submit = () => { @@ -20,7 +25,6 @@ export default () => { initialValues={{ appName, language, - googleAnalytics: '', }} >
diff --git a/resources/scripts/components/admin/settings/MailSettings.tsx b/resources/scripts/components/admin/settings/MailSettings.tsx index 1e63eecc2c..4e83a7c2e7 100644 --- a/resources/scripts/components/admin/settings/MailSettings.tsx +++ b/resources/scripts/components/admin/settings/MailSettings.tsx @@ -6,8 +6,13 @@ import Button from '@/components/elements/Button'; import Field, { FieldRow } from '@/components/elements/Field'; import Label from '@/components/elements/Label'; import Select from '@/components/elements/Select'; +import { MailSettings } from '@/api/admin/settings'; -export default () => { +interface Props { + data?: MailSettings; +} + +export default ({ data }: Props) => { const submit = () => { // }; diff --git a/resources/scripts/components/admin/settings/SecuritySettings.tsx b/resources/scripts/components/admin/settings/SecuritySettings.tsx index 0f6831bc6e..cc376830f3 100644 --- a/resources/scripts/components/admin/settings/SecuritySettings.tsx +++ b/resources/scripts/components/admin/settings/SecuritySettings.tsx @@ -6,8 +6,13 @@ import Field, { FieldRow } from '@/components/elements/Field'; import { useStoreState } from 'easy-peasy'; import { ApplicationStore } from '@/state'; import SelectField from '@/components/elements/SelectField'; +import { SecuritySettings } from '@/api/admin/settings'; -export default () => { +interface Props { + data?: SecuritySettings; +} + +export default ({ data }: Props) => { const { recaptcha } = useStoreState((state: ApplicationStore) => state.settings.data!); const { enabled: recaptchaStatus, siteKey } = recaptcha; diff --git a/resources/scripts/components/admin/settings/SettingsContainer.tsx b/resources/scripts/components/admin/settings/SettingsContainer.tsx index 8bf6de1fcb..b120ce33f9 100644 --- a/resources/scripts/components/admin/settings/SettingsContainer.tsx +++ b/resources/scripts/components/admin/settings/SettingsContainer.tsx @@ -9,8 +9,23 @@ import { SubNavigation, SubNavigationLink } from '@/components/admin/SubNavigati import GeneralSettings from '@/components/admin/settings/GeneralSettings'; import SecuritySettings from '@/components/admin/settings/SecuritySettings'; import AdvancedSettings from './AdvancedSettings'; +import { getSettings } from '@/api/admin/settings'; +import { useEffect } from 'react'; +import useFlash from '@/plugins/useFlash'; export default () => { + const { clearFlashes, clearAndAddHttpError } = useFlash(); + const { data, error } = getSettings(); + + useEffect(() => { + if (!error) { + clearFlashes('admin:settings'); + return; + } + + clearAndAddHttpError({ key: 'admin:settings', error }); + }, [error]); + return (
@@ -46,7 +61,7 @@ export default () => { } /> } /> } /> - Features

} /> + {/* Features

} /> */} } /> From d2a35119f4466850a66a011f40e594b39701eec3 Mon Sep 17 00:00:00 2001 From: Alexe Vlad Date: Thu, 28 Sep 2023 07:26:22 +0000 Subject: [PATCH 07/13] fix: created store for settings page --- resources/scripts/api/admin/settings.ts | 21 ++++-- .../admin/settings/GeneralSettings.tsx | 18 ++--- .../admin/settings/MailSettings.tsx | 54 +++++++++------ .../admin/settings/SecuritySettings.tsx | 27 ++++---- ...ttingsContainer.tsx => SettingsRouter.tsx} | 67 +++++++++++++++---- resources/scripts/routers/AdminRouter.tsx | 4 +- 6 files changed, 130 insertions(+), 61 deletions(-) rename resources/scripts/components/admin/settings/{SettingsContainer.tsx => SettingsRouter.tsx} (59%) diff --git a/resources/scripts/api/admin/settings.ts b/resources/scripts/api/admin/settings.ts index c13c831435..b12a8070da 100644 --- a/resources/scripts/api/admin/settings.ts +++ b/resources/scripts/api/admin/settings.ts @@ -1,7 +1,6 @@ import { Model } from '@/api/admin/index'; import http from '@/api/http'; import Transformers from '../definitions/admin/transformers'; -import useSWR from 'swr'; export interface Settings extends Model { general: GeneralSettings; @@ -14,9 +13,9 @@ export interface GeneralSettings { languages: Language[]; } -type Language = { +interface Language { [key: string]: string; -}; +} export type LanguageKey = 'en'; @@ -39,10 +38,18 @@ export interface SecuritySettings { '2faEnabled': boolean; } -export const getSettings = () => { - return useSWR('settings', async () => { - const { data } = await http.get(`/api/application/settings`); +// export const getSettings = () => { +// return useSWR('settings', async () => { +// const { data } = await http.get(`/api/application/settings`); + +// return Transformers.toSettings(data); +// }); +// }; - return Transformers.toSettings(data); +export const getSettings = (): Promise => { + return new Promise((resolve, reject) => { + http.get('/api/application/settings') + .then(({ data }) => resolve(Transformers.toSettings(data))) + .catch(reject); }); }; diff --git a/resources/scripts/components/admin/settings/GeneralSettings.tsx b/resources/scripts/components/admin/settings/GeneralSettings.tsx index ca980f489b..997e51095b 100644 --- a/resources/scripts/components/admin/settings/GeneralSettings.tsx +++ b/resources/scripts/components/admin/settings/GeneralSettings.tsx @@ -6,14 +6,11 @@ import Field, { FieldRow } from '@/components/elements/Field'; import { useStoreState } from 'easy-peasy'; import { ApplicationStore } from '@/state'; import SelectField from '@/components/elements/SelectField'; -import { GeneralSettings } from '@/api/admin/settings'; +import { Context } from './SettingsRouter'; -interface Props { - data?: GeneralSettings; -} - -export default ({ data }: Props) => { - const { name: appName, locale: language } = useStoreState((state: ApplicationStore) => state.settings.data!); +export default () => { + const { name: appName, languages } = Context.useStoreState(state => state.settings!.general); + const { locale: language } = useStoreState((state: ApplicationStore) => state.settings.data!); const submit = () => { // @@ -41,7 +38,12 @@ export default ({ data }: Props) => { name={'language'} label={'Default language'} description={''} - options={[{ value: 'en', label: 'English' }]} + options={Object.keys(languages).map(key => { + return { + value: key, + label: languages[key as any] as unknown as string, + }; + })} /> diff --git a/resources/scripts/components/admin/settings/MailSettings.tsx b/resources/scripts/components/admin/settings/MailSettings.tsx index 4e83a7c2e7..cb3b40be2c 100644 --- a/resources/scripts/components/admin/settings/MailSettings.tsx +++ b/resources/scripts/components/admin/settings/MailSettings.tsx @@ -1,33 +1,44 @@ -import { Form, Formik } from 'formik'; +import { Form, Formik, FormikHelpers } from 'formik'; import tw from 'twin.macro'; import AdminBox from '@/components/admin/AdminBox'; import Button from '@/components/elements/Button'; import Field, { FieldRow } from '@/components/elements/Field'; import Label from '@/components/elements/Label'; -import Select from '@/components/elements/Select'; -import { MailSettings } from '@/api/admin/settings'; +import { Context } from './SettingsRouter'; +import SelectField from '@/components/elements/SelectField'; -interface Props { - data?: MailSettings; +interface Values { + smtpHost: string; + smtpPort: number; + smtpEncryption: string; + username: string; + password: string; + mailFrom: string; + mailFromName: string; } -export default ({ data }: Props) => { - const submit = () => { - // +export default () => { + const { host, port, encryption, username, password, fromAddress, fromName } = Context.useStoreState( + state => state.settings!.mail, + ); + + const submit = (values: Values, { setSubmitting }: FormikHelpers) => { + console.log(values); + setSubmitting(false); }; return ( {({ isSubmitting, isValid }) => ( @@ -50,11 +61,14 @@ export default ({ data }: Props) => { />
- +
diff --git a/resources/scripts/components/admin/settings/SecuritySettings.tsx b/resources/scripts/components/admin/settings/SecuritySettings.tsx index cc376830f3..64a941482f 100644 --- a/resources/scripts/components/admin/settings/SecuritySettings.tsx +++ b/resources/scripts/components/admin/settings/SecuritySettings.tsx @@ -1,23 +1,25 @@ -import { Form, Formik } from 'formik'; +import { Form, Formik, FormikHelpers } from 'formik'; import tw from 'twin.macro'; import AdminBox from '@/components/admin/AdminBox'; import Field, { FieldRow } from '@/components/elements/Field'; -import { useStoreState } from 'easy-peasy'; -import { ApplicationStore } from '@/state'; import SelectField from '@/components/elements/SelectField'; -import { SecuritySettings } from '@/api/admin/settings'; +import { Context } from './SettingsRouter'; -interface Props { - data?: SecuritySettings; +interface Values { + recaptchaStatus: string; + siteKey: string; + secretKey: string; + sfaRequired: string; } -export default ({ data }: Props) => { - const { recaptcha } = useStoreState((state: ApplicationStore) => state.settings.data!); - const { enabled: recaptchaStatus, siteKey } = recaptcha; +export default () => { + const security = Context.useStoreState(state => state.settings!.security); + const { enabled: recaptchaStatus, siteKey, secretKey } = security.recaptcha; - const submit = () => { - // + const submit = (values: Values, { setSubmitting }: FormikHelpers) => { + console.log(values); + setSubmitting(false); }; return ( @@ -26,7 +28,8 @@ export default ({ data }: Props) => { initialValues={{ recaptchaStatus: `${recaptchaStatus}`, siteKey, - sfaRequired: '0', + secretKey, + sfaRequired: `${security['2faEnabled']}` ?? '0', }} > diff --git a/resources/scripts/components/admin/settings/SettingsContainer.tsx b/resources/scripts/components/admin/settings/SettingsRouter.tsx similarity index 59% rename from resources/scripts/components/admin/settings/SettingsContainer.tsx rename to resources/scripts/components/admin/settings/SettingsRouter.tsx index b120ce33f9..22b82bd658 100644 --- a/resources/scripts/components/admin/settings/SettingsContainer.tsx +++ b/resources/scripts/components/admin/settings/SettingsRouter.tsx @@ -9,22 +9,57 @@ import { SubNavigation, SubNavigationLink } from '@/components/admin/SubNavigati import GeneralSettings from '@/components/admin/settings/GeneralSettings'; import SecuritySettings from '@/components/admin/settings/SecuritySettings'; import AdvancedSettings from './AdvancedSettings'; -import { getSettings } from '@/api/admin/settings'; -import { useEffect } from 'react'; -import useFlash from '@/plugins/useFlash'; +import { Settings, getSettings } from '@/api/admin/settings'; +import { useEffect, useState } from 'react'; +import { Action, Actions, action, createContextStore, useStoreActions } from 'easy-peasy'; +import { ApplicationStore } from '@/state'; +import Spinner from '@/components/elements/Spinner'; -export default () => { - const { clearFlashes, clearAndAddHttpError } = useFlash(); - const { data, error } = getSettings(); +interface ctx { + settings: Settings | undefined; + setSettings: Action; +} + +export const Context = createContextStore({ + settings: undefined, + + setSettings: action((state, payload) => { + state.settings = payload; + }), +}); + +const SettingsRouter = () => { + const { clearFlashes, clearAndAddHttpError } = useStoreActions( + (actions: Actions) => actions.flashes, + ); + const [loading, setLoading] = useState(true); + + const settings = Context.useStoreState(state => state.settings); + const setSettings = Context.useStoreActions(actions => actions.setSettings); useEffect(() => { - if (!error) { - clearFlashes('admin:settings'); - return; - } + clearFlashes('settings'); + + getSettings() + .then(settings => setSettings(settings)) + .catch(error => { + console.error(error); + clearAndAddHttpError({ key: 'settings', error }); + }) + .then(() => setLoading(false)); + }, []); - clearAndAddHttpError({ key: 'admin:settings', error }); - }, [error]); + if (loading || settings === undefined) { + return ( + + + +
+ +
+
+ ); + } return ( @@ -67,3 +102,11 @@ export default () => { ); }; + +export default () => { + return ( + + + + ); +}; diff --git a/resources/scripts/routers/AdminRouter.tsx b/resources/scripts/routers/AdminRouter.tsx index 4f918a06e4..e7285af8c7 100644 --- a/resources/scripts/routers/AdminRouter.tsx +++ b/resources/scripts/routers/AdminRouter.tsx @@ -18,7 +18,6 @@ import tw from 'twin.macro'; import CollapsedIcon from '@/assets/images/pterodactyl.svg'; import OverviewContainer from '@/components/admin/overview/OverviewContainer'; -import SettingsContainer from '@/components/admin/settings/SettingsContainer'; import DatabasesContainer from '@/components/admin/databases/DatabasesContainer'; import NewDatabaseContainer from '@/components/admin/databases/NewDatabaseContainer'; import DatabaseEditContainer from '@/components/admin/databases/DatabaseEditContainer'; @@ -46,6 +45,7 @@ import type { ApplicationStore } from '@/state'; import Sidebar from '@/components/admin/Sidebar'; // import useUserPersistedState from '@/plugins/useUserPersistedState'; import UsersContainer from '@/components/admin/users/UsersContainer'; +import SettingsRouter from '@/components/admin/settings/SettingsRouter'; function AdminRouter() { const email = useStoreState((state: ApplicationStore) => state.user.data!.email); @@ -145,7 +145,7 @@ function AdminRouter() {
} /> - } /> + } /> } /> } /> } /> From 8056d0a583c9cf500cfcca324152f6a6527fed55 Mon Sep 17 00:00:00 2001 From: Scai <59282365+alexevladgabriel@users.noreply.github.com> Date: Fri, 22 Dec 2023 17:28:47 +0200 Subject: [PATCH 08/13] fix buttons --- .../admin/databases/DatabaseDeleteButton.tsx | 2 +- .../admin/databases/DatabaseEditContainer.tsx | 2 +- .../admin/databases/DatabasesContainer.tsx | 2 +- .../admin/locations/LocationDeleteButton.tsx | 2 +- .../admin/locations/LocationEditContainer.tsx | 2 +- .../admin/locations/NewLocationButton.tsx | 2 +- .../admin/mounts/MountDeleteButton.tsx | 2 +- .../components/admin/mounts/MountForm.tsx | 2 +- .../admin/mounts/MountsContainer.tsx | 2 +- .../admin/nests/ImportEggButton.tsx | 2 +- .../admin/nests/NestDeleteButton.tsx | 2 +- .../admin/nests/NestEditContainer.tsx | 2 +- .../admin/nests/NewEggContainer.tsx | 2 +- .../components/admin/nests/NewNestButton.tsx | 2 +- .../admin/nests/eggs/EggDeleteButton.tsx | 2 +- .../admin/nests/eggs/EggExportButton.tsx | 2 +- .../admin/nests/eggs/EggInstallContainer.tsx | 2 +- .../admin/nests/eggs/EggSettingsContainer.tsx | 2 +- .../nests/eggs/EggVariablesContainer.tsx | 2 +- .../admin/nests/eggs/NewVariableButton.tsx | 2 +- .../admin/servers/ServerDeleteButton.tsx | 2 +- .../admin/servers/ServerSettingsContainer.tsx | 2 +- .../admin/settings/GeneralSettings.tsx | 27 +++++++++++++++---- .../server/files/FileEditContainer.tsx | 2 +- .../components/server/files/FileNameModal.tsx | 2 +- .../server/files/MassActionsBar.tsx | 2 +- 26 files changed, 47 insertions(+), 30 deletions(-) diff --git a/resources/scripts/components/admin/databases/DatabaseDeleteButton.tsx b/resources/scripts/components/admin/databases/DatabaseDeleteButton.tsx index 4c594d261b..b29f224a8f 100644 --- a/resources/scripts/components/admin/databases/DatabaseDeleteButton.tsx +++ b/resources/scripts/components/admin/databases/DatabaseDeleteButton.tsx @@ -4,7 +4,7 @@ import { useState } from 'react'; import tw from 'twin.macro'; import deleteDatabase from '@/api/admin/databases/deleteDatabase'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import { Shape } from '@/components/elements/button/types'; import ConfirmationModal from '@/components/elements/ConfirmationModal'; import type { ApplicationStore } from '@/state'; diff --git a/resources/scripts/components/admin/databases/DatabaseEditContainer.tsx b/resources/scripts/components/admin/databases/DatabaseEditContainer.tsx index dc4f74a324..4d4abcd241 100644 --- a/resources/scripts/components/admin/databases/DatabaseEditContainer.tsx +++ b/resources/scripts/components/admin/databases/DatabaseEditContainer.tsx @@ -14,7 +14,7 @@ import AdminContentBlock from '@/components/admin/AdminContentBlock'; import Spinner from '@/components/elements/Spinner'; import FlashMessageRender from '@/components/FlashMessageRender'; import AdminBox from '@/components/admin/AdminBox'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import Field from '@/components/elements/Field'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; import DatabaseDeleteButton from '@/components/admin/databases/DatabaseDeleteButton'; diff --git a/resources/scripts/components/admin/databases/DatabasesContainer.tsx b/resources/scripts/components/admin/databases/DatabasesContainer.tsx index e36555071f..1deda0c152 100644 --- a/resources/scripts/components/admin/databases/DatabasesContainer.tsx +++ b/resources/scripts/components/admin/databases/DatabasesContainer.tsx @@ -20,7 +20,7 @@ import AdminTable, { TableRow, useTableHooks, } from '@/components/admin/AdminTable'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import { Size } from '@/components/elements/button/types'; import CopyOnClick from '@/components/elements/CopyOnClick'; diff --git a/resources/scripts/components/admin/locations/LocationDeleteButton.tsx b/resources/scripts/components/admin/locations/LocationDeleteButton.tsx index 99aa7d1e24..1a24b05576 100644 --- a/resources/scripts/components/admin/locations/LocationDeleteButton.tsx +++ b/resources/scripts/components/admin/locations/LocationDeleteButton.tsx @@ -4,7 +4,7 @@ import { useState } from 'react'; import tw from 'twin.macro'; import deleteLocation from '@/api/admin/locations/deleteLocation'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import { Shape } from '@/components/elements/button/types'; import ConfirmationModal from '@/components/elements/ConfirmationModal'; import type { ApplicationStore } from '@/state'; diff --git a/resources/scripts/components/admin/locations/LocationEditContainer.tsx b/resources/scripts/components/admin/locations/LocationEditContainer.tsx index 261dec534a..f3a4cf2738 100644 --- a/resources/scripts/components/admin/locations/LocationEditContainer.tsx +++ b/resources/scripts/components/admin/locations/LocationEditContainer.tsx @@ -13,7 +13,7 @@ import updateLocation from '@/api/admin/locations/updateLocation'; import AdminBox from '@/components/admin/AdminBox'; import AdminContentBlock from '@/components/admin/AdminContentBlock'; import LocationDeleteButton from '@/components/admin/locations/LocationDeleteButton'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import Field from '@/components/elements/Field'; import Spinner from '@/components/elements/Spinner'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; diff --git a/resources/scripts/components/admin/locations/NewLocationButton.tsx b/resources/scripts/components/admin/locations/NewLocationButton.tsx index 0b5d0ff889..664f4521ac 100644 --- a/resources/scripts/components/admin/locations/NewLocationButton.tsx +++ b/resources/scripts/components/admin/locations/NewLocationButton.tsx @@ -6,7 +6,7 @@ import { object, string } from 'yup'; import createLocation from '@/api/admin/locations/createLocation'; import getLocations from '@/api/admin/locations/getLocations'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import { Size, Variant } from '@/components/elements/button/types'; import Field from '@/components/elements/Field'; import Modal from '@/components/elements/Modal'; diff --git a/resources/scripts/components/admin/mounts/MountDeleteButton.tsx b/resources/scripts/components/admin/mounts/MountDeleteButton.tsx index 7d47c547f3..25e1f4f2ba 100644 --- a/resources/scripts/components/admin/mounts/MountDeleteButton.tsx +++ b/resources/scripts/components/admin/mounts/MountDeleteButton.tsx @@ -4,7 +4,7 @@ import { useState } from 'react'; import tw from 'twin.macro'; import deleteMount from '@/api/admin/mounts/deleteMount'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import ConfirmationModal from '@/components/elements/ConfirmationModal'; import type { ApplicationStore } from '@/state'; diff --git a/resources/scripts/components/admin/mounts/MountForm.tsx b/resources/scripts/components/admin/mounts/MountForm.tsx index 8a9d2bd999..049c916f2b 100644 --- a/resources/scripts/components/admin/mounts/MountForm.tsx +++ b/resources/scripts/components/admin/mounts/MountForm.tsx @@ -5,7 +5,7 @@ import tw from 'twin.macro'; import { boolean, object, string } from 'yup'; import AdminBox from '@/components/admin/AdminBox'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import Field from '@/components/elements/Field'; import Label from '@/components/elements/Label'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; diff --git a/resources/scripts/components/admin/mounts/MountsContainer.tsx b/resources/scripts/components/admin/mounts/MountsContainer.tsx index f9aa5fb052..a9033eba06 100644 --- a/resources/scripts/components/admin/mounts/MountsContainer.tsx +++ b/resources/scripts/components/admin/mounts/MountsContainer.tsx @@ -18,7 +18,7 @@ import AdminTable, { ContentWrapper, useTableHooks, } from '@/components/admin/AdminTable'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import { Size } from '@/components/elements/button/types'; import CopyOnClick from '@/components/elements/CopyOnClick'; import FlashMessageRender from '@/components/FlashMessageRender'; diff --git a/resources/scripts/components/admin/nests/ImportEggButton.tsx b/resources/scripts/components/admin/nests/ImportEggButton.tsx index 94bafd6fd2..04727926ed 100644 --- a/resources/scripts/components/admin/nests/ImportEggButton.tsx +++ b/resources/scripts/components/admin/nests/ImportEggButton.tsx @@ -7,7 +7,7 @@ import tw from 'twin.macro'; import getEggs from '@/api/admin/nests/getEggs'; import importEgg from '@/api/admin/nests/importEgg'; import useFlash from '@/plugins/useFlash'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import { Size, Variant } from '@/components/elements/button/types'; import { Editor } from '@/components/elements/editor'; import Modal from '@/components/elements/Modal'; diff --git a/resources/scripts/components/admin/nests/NestDeleteButton.tsx b/resources/scripts/components/admin/nests/NestDeleteButton.tsx index 48528a0106..0d55249c66 100644 --- a/resources/scripts/components/admin/nests/NestDeleteButton.tsx +++ b/resources/scripts/components/admin/nests/NestDeleteButton.tsx @@ -4,7 +4,7 @@ import { useState } from 'react'; import tw from 'twin.macro'; import deleteNest from '@/api/admin/nests/deleteNest'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import { Shape } from '@/components/elements/button/types'; import ConfirmationModal from '@/components/elements/ConfirmationModal'; import type { ApplicationStore } from '@/state'; diff --git a/resources/scripts/components/admin/nests/NestEditContainer.tsx b/resources/scripts/components/admin/nests/NestEditContainer.tsx index 924eabba93..c8b6441105 100644 --- a/resources/scripts/components/admin/nests/NestEditContainer.tsx +++ b/resources/scripts/components/admin/nests/NestEditContainer.tsx @@ -14,7 +14,7 @@ import FlashMessageRender from '@/components/FlashMessageRender'; import type { Nest } from '@/api/admin/nests/getNests'; import getNest from '@/api/admin/nests/getNest'; import updateNest from '@/api/admin/nests/updateNest'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import { Size } from '@/components/elements/button/types'; import Field from '@/components/elements/Field'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; diff --git a/resources/scripts/components/admin/nests/NewEggContainer.tsx b/resources/scripts/components/admin/nests/NewEggContainer.tsx index 9530d724b0..db3e0af975 100644 --- a/resources/scripts/components/admin/nests/NewEggContainer.tsx +++ b/resources/scripts/components/admin/nests/NewEggContainer.tsx @@ -15,7 +15,7 @@ import { EggProcessContainer, EggStartupContainer, } from '@/components/admin/nests/eggs/EggSettingsContainer'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import FlashMessageRender from '@/components/FlashMessageRender'; import useFlash from '@/plugins/useFlash'; diff --git a/resources/scripts/components/admin/nests/NewNestButton.tsx b/resources/scripts/components/admin/nests/NewNestButton.tsx index a8a4fbecb7..105bca8b3c 100644 --- a/resources/scripts/components/admin/nests/NewNestButton.tsx +++ b/resources/scripts/components/admin/nests/NewNestButton.tsx @@ -6,7 +6,7 @@ import { object, string } from 'yup'; import createNest from '@/api/admin/nests/createNest'; import getNests from '@/api/admin/nests/getNests'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import { Size, Variant } from '@/components/elements/button/types'; import Field from '@/components/elements/Field'; import FlashMessageRender from '@/components/FlashMessageRender'; diff --git a/resources/scripts/components/admin/nests/eggs/EggDeleteButton.tsx b/resources/scripts/components/admin/nests/eggs/EggDeleteButton.tsx index c14286f552..ac7ecca5a7 100644 --- a/resources/scripts/components/admin/nests/eggs/EggDeleteButton.tsx +++ b/resources/scripts/components/admin/nests/eggs/EggDeleteButton.tsx @@ -4,7 +4,7 @@ import { useState } from 'react'; import tw from 'twin.macro'; import deleteEgg from '@/api/admin/eggs/deleteEgg'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import { Shape } from '@/components/elements/button/types'; import ConfirmationModal from '@/components/elements/ConfirmationModal'; import type { ApplicationStore } from '@/state'; diff --git a/resources/scripts/components/admin/nests/eggs/EggExportButton.tsx b/resources/scripts/components/admin/nests/eggs/EggExportButton.tsx index e3605e99cd..1f87ec82e3 100644 --- a/resources/scripts/components/admin/nests/eggs/EggExportButton.tsx +++ b/resources/scripts/components/admin/nests/eggs/EggExportButton.tsx @@ -6,7 +6,7 @@ import tw from 'twin.macro'; import { exportEgg } from '@/api/admin/egg'; import FlashMessageRender from '@/components/FlashMessageRender'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import { Variant } from '@/components/elements/button/types'; import { Editor } from '@/components/elements/editor'; import Modal from '@/components/elements/Modal'; diff --git a/resources/scripts/components/admin/nests/eggs/EggInstallContainer.tsx b/resources/scripts/components/admin/nests/eggs/EggInstallContainer.tsx index c566d2451f..6151b0fce2 100644 --- a/resources/scripts/components/admin/nests/eggs/EggInstallContainer.tsx +++ b/resources/scripts/components/admin/nests/eggs/EggInstallContainer.tsx @@ -8,7 +8,7 @@ import tw from 'twin.macro'; import { useEggFromRoute } from '@/api/admin/egg'; import updateEgg from '@/api/admin/eggs/updateEgg'; import AdminBox from '@/components/admin/AdminBox'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import { Editor } from '@/components/elements/editor'; import Field from '@/components/elements/Field'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; diff --git a/resources/scripts/components/admin/nests/eggs/EggSettingsContainer.tsx b/resources/scripts/components/admin/nests/eggs/EggSettingsContainer.tsx index 4642c68da3..52bc5f8d2a 100644 --- a/resources/scripts/components/admin/nests/eggs/EggSettingsContainer.tsx +++ b/resources/scripts/components/admin/nests/eggs/EggSettingsContainer.tsx @@ -14,7 +14,7 @@ import updateEgg from '@/api/admin/eggs/updateEgg'; import AdminBox from '@/components/admin/AdminBox'; import EggDeleteButton from '@/components/admin/nests/eggs/EggDeleteButton'; import EggExportButton from '@/components/admin/nests/eggs/EggExportButton'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import { Editor } from '@/components/elements/editor'; import Field, { TextareaField } from '@/components/elements/Field'; import Input from '@/components/elements/Input'; diff --git a/resources/scripts/components/admin/nests/eggs/EggVariablesContainer.tsx b/resources/scripts/components/admin/nests/eggs/EggVariablesContainer.tsx index 5b3b4e4388..f0366af825 100644 --- a/resources/scripts/components/admin/nests/eggs/EggVariablesContainer.tsx +++ b/resources/scripts/components/admin/nests/eggs/EggVariablesContainer.tsx @@ -13,7 +13,7 @@ import type { EggVariable } from '@/api/admin/egg'; import { useEggFromRoute } from '@/api/admin/egg'; import NewVariableButton from '@/components/admin/nests/eggs/NewVariableButton'; import AdminBox from '@/components/admin/AdminBox'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import Checkbox from '@/components/elements/Checkbox'; import Field, { FieldRow, TextareaField } from '@/components/elements/Field'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; diff --git a/resources/scripts/components/admin/nests/eggs/NewVariableButton.tsx b/resources/scripts/components/admin/nests/eggs/NewVariableButton.tsx index 753c221ae8..ffb6e04f6a 100644 --- a/resources/scripts/components/admin/nests/eggs/NewVariableButton.tsx +++ b/resources/scripts/components/admin/nests/eggs/NewVariableButton.tsx @@ -9,7 +9,7 @@ import { useEggFromRoute } from '@/api/admin/egg'; import { EggVariableForm, validationSchema } from '@/components/admin/nests/eggs/EggVariablesContainer'; import Modal from '@/components/elements/Modal'; import FlashMessageRender from '@/components/FlashMessageRender'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import useFlash from '@/plugins/useFlash'; import { Variant } from '@/components/elements/button/types'; diff --git a/resources/scripts/components/admin/servers/ServerDeleteButton.tsx b/resources/scripts/components/admin/servers/ServerDeleteButton.tsx index 02f1910e7e..6e7ad6349b 100644 --- a/resources/scripts/components/admin/servers/ServerDeleteButton.tsx +++ b/resources/scripts/components/admin/servers/ServerDeleteButton.tsx @@ -4,7 +4,7 @@ import { useStoreActions } from 'easy-peasy'; import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import ConfirmationModal from '@/components/elements/ConfirmationModal'; import deleteServer from '@/api/admin/servers/deleteServer'; import { useServerFromRoute } from '@/api/admin/server'; diff --git a/resources/scripts/components/admin/servers/ServerSettingsContainer.tsx b/resources/scripts/components/admin/servers/ServerSettingsContainer.tsx index 523004a4df..80ab5957e0 100644 --- a/resources/scripts/components/admin/servers/ServerSettingsContainer.tsx +++ b/resources/scripts/components/admin/servers/ServerSettingsContainer.tsx @@ -12,7 +12,7 @@ import BaseSettingsBox from '@/components/admin/servers/settings/BaseSettingsBox import FeatureLimitsBox from '@/components/admin/servers/settings/FeatureLimitsBox'; import NetworkingBox from '@/components/admin/servers/settings/NetworkingBox'; import ServerResourceBox from '@/components/admin/servers/settings/ServerResourceBox'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; export default () => { const { data: server } = useServerFromRoute(); diff --git a/resources/scripts/components/admin/settings/GeneralSettings.tsx b/resources/scripts/components/admin/settings/GeneralSettings.tsx index 997e51095b..cf6b200075 100644 --- a/resources/scripts/components/admin/settings/GeneralSettings.tsx +++ b/resources/scripts/components/admin/settings/GeneralSettings.tsx @@ -7,15 +7,26 @@ import { useStoreState } from 'easy-peasy'; import { ApplicationStore } from '@/state'; import SelectField from '@/components/elements/SelectField'; import { Context } from './SettingsRouter'; +import { debounce } from 'debounce'; -export default () => { +type Values = { + appName: string; + language: string; +}; + +export default function GeneralSettings() { const { name: appName, languages } = Context.useStoreState(state => state.settings!.general); const { locale: language } = useStoreState((state: ApplicationStore) => state.settings.data!); - const submit = () => { + const submit = (values: Values) => { // + console.log(values); }; + const setVariableValue = debounce((value: string) => { + console.log(value); + }, 500); + return ( {
- + setVariableValue(e.currentTarget.value)} + id={'appName'} + name={'appName'} + type={'text'} + label={'App Name'} + description={''} + /> @@ -37,7 +55,6 @@ export default () => { id={'language'} name={'language'} label={'Default language'} - description={''} options={Object.keys(languages).map(key => { return { value: key, @@ -51,4 +68,4 @@ export default () => { ); -}; +} diff --git a/resources/scripts/components/server/files/FileEditContainer.tsx b/resources/scripts/components/server/files/FileEditContainer.tsx index d35c733ff7..246cfa876a 100644 --- a/resources/scripts/components/server/files/FileEditContainer.tsx +++ b/resources/scripts/components/server/files/FileEditContainer.tsx @@ -9,7 +9,7 @@ import { httpErrorToHuman } from '@/api/http'; import getFileContents from '@/api/server/files/getFileContents'; import saveFileContents from '@/api/server/files/saveFileContents'; import FlashMessageRender from '@/components/FlashMessageRender'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import Can from '@/components/elements/Can'; import Select from '@/components/elements/Select'; import PageContentBlock from '@/components/elements/PageContentBlock'; diff --git a/resources/scripts/components/server/files/FileNameModal.tsx b/resources/scripts/components/server/files/FileNameModal.tsx index cd868d9758..1096c227b4 100644 --- a/resources/scripts/components/server/files/FileNameModal.tsx +++ b/resources/scripts/components/server/files/FileNameModal.tsx @@ -4,7 +4,7 @@ import { join } from 'pathe'; import tw from 'twin.macro'; import { object, string } from 'yup'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import Field from '@/components/elements/Field'; import type { RequiredModalProps } from '@/components/elements/Modal'; import Modal from '@/components/elements/Modal'; diff --git a/resources/scripts/components/server/files/MassActionsBar.tsx b/resources/scripts/components/server/files/MassActionsBar.tsx index fb8710036f..59dae50823 100644 --- a/resources/scripts/components/server/files/MassActionsBar.tsx +++ b/resources/scripts/components/server/files/MassActionsBar.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'; import compressFiles from '@/api/server/files/compressFiles'; import deleteFiles from '@/api/server/files/deleteFiles'; -import { Button } from '@/components/elements/button'; +import { Button } from '@/components/elements/button/index'; import { Dialog } from '@/components/elements/dialog'; import Portal from '@/components/elements/Portal'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; From 39dbbcfc1fb79ebb53cb5f34c1279531995f023d Mon Sep 17 00:00:00 2001 From: Scai <59282365+alexevladgabriel@users.noreply.github.com> Date: Sun, 31 Dec 2023 15:56:23 +0200 Subject: [PATCH 09/13] work on settings ui --- .../Api/Application/SettingsController.php | 42 +++++++++++-- .../Settings/UpdateSettingsRequest.php | 27 ++++++++ app/Http/ViewComposers/AssetComposer.php | 8 ++- app/Services/Helpers/SettingsService.php | 21 ++++--- .../Api/Application/SettingsTransformer.php | 1 + resources/scripts/api/admin/settings.ts | 19 +++--- .../api/definitions/admin/transformers.ts | 1 + .../admin/settings/AdvancedSettings.tsx | 8 +++ .../admin/settings/GeneralSettings.tsx | 62 ++++++++++++------- .../admin/settings/MailSettings.tsx | 15 +++-- .../admin/settings/SecuritySettings.tsx | 8 +++ .../admin/settings/SettingsRouter.tsx | 4 +- resources/scripts/state/settings.ts | 2 +- routes/api-application.php | 3 +- 14 files changed, 170 insertions(+), 51 deletions(-) create mode 100644 app/Http/Requests/Api/Application/Settings/UpdateSettingsRequest.php diff --git a/app/Http/Controllers/Api/Application/SettingsController.php b/app/Http/Controllers/Api/Application/SettingsController.php index 29dcdcd4e6..0413459335 100644 --- a/app/Http/Controllers/Api/Application/SettingsController.php +++ b/app/Http/Controllers/Api/Application/SettingsController.php @@ -2,24 +2,58 @@ namespace Pterodactyl\Http\Controllers\Api\Application; +use Illuminate\Http\Response; +use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface; +use Pterodactyl\Exceptions\Model\DataValidationException; +use Pterodactyl\Exceptions\Repository\RecordNotFoundException; +use Illuminate\Contracts\Console\Kernel; +use Pterodactyl\Http\Requests\Api\Application\Settings\UpdateSettingsRequest; use Pterodactyl\Services\Helpers\SettingsService; +use Pterodactyl\Traits\Helpers\AvailableLanguages; use Pterodactyl\Transformers\Api\Application\SettingsTransformer; class SettingsController extends ApplicationApiController { + use AvailableLanguages; + /** * VersionController constructor. + * + * @param Kernel $kernel + * @param SettingsService $settingsService + * @param SettingsRepositoryInterface $settingsRepository */ - public function __construct(private SettingsService $settingsService) - { + public function __construct( + private readonly Kernel $kernel, + private readonly SettingsService $settingsService, + private readonly SettingsRepositoryInterface $settingsRepository + ) { parent::__construct(); } /** - * Returns version information. + * Returns current settings of panel. */ - public function __invoke(): array + public function index(): array { return $this->fractal->item($this->settingsService->getCurrentSettings())->transformWith(SettingsTransformer::class)->toArray(); } + + /** + * Handle settings update. + * + * @throws DataValidationException + * @throws RecordNotFoundException + */ + public function update(UpdateSettingsRequest $request): Response + { + $data = $request->validated(); + + foreach($data as $key => $value) { + $this->settingsRepository->set($key, $value); + } + + $this->kernel->call('queue:clear'); + return response()->noContent(); + } } diff --git a/app/Http/Requests/Api/Application/Settings/UpdateSettingsRequest.php b/app/Http/Requests/Api/Application/Settings/UpdateSettingsRequest.php new file mode 100644 index 0000000000..fa4a557c08 --- /dev/null +++ b/app/Http/Requests/Api/Application/Settings/UpdateSettingsRequest.php @@ -0,0 +1,27 @@ + 'sometimes|required|string|max:191', + 'language' => ['sometimes', 'required', 'string', Rule::in(array_keys($this->getAvailableLanguages()))], + 'smtpHost' => 'sometimes|required|string', + 'smtpPort' => 'sometimes|required|integer|between:1,65535', + 'smtpEncryption' => ['sometimes', 'present', Rule::in([null, 'tls', 'ssl'])], + 'username' => 'sometimes|nullable|string|max:191', + 'password' => 'sometimes|nullable|string|max:191', + 'mailFrom' => 'sometimes|required|string|email', + 'mailFromName' => 'sometimes|nullable|string|max:191', + ]; + } +} diff --git a/app/Http/ViewComposers/AssetComposer.php b/app/Http/ViewComposers/AssetComposer.php index 2bbb39d5ce..29a84cb445 100644 --- a/app/Http/ViewComposers/AssetComposer.php +++ b/app/Http/ViewComposers/AssetComposer.php @@ -3,17 +3,21 @@ namespace Pterodactyl\Http\ViewComposers; use Illuminate\View\View; +use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface; class AssetComposer { + public function __construct(private SettingsRepositoryInterface $repository) + { + } /** * Provide access to the asset service in the views. */ public function compose(View $view): void { $view->with('siteConfiguration', [ - 'name' => config('app.name') ?? 'Pterodactyl', - 'locale' => config('app.locale') ?? 'en', + 'name' => $this->repository->get('appName', config('app.name')), + 'locale' => $this->repository->get('language', config('app.locale')), 'recaptcha' => [ 'enabled' => config('recaptcha.enabled', false), 'siteKey' => config('recaptcha.website_key') ?? '', diff --git a/app/Services/Helpers/SettingsService.php b/app/Services/Helpers/SettingsService.php index 3103aaa761..80b6e815de 100644 --- a/app/Services/Helpers/SettingsService.php +++ b/app/Services/Helpers/SettingsService.php @@ -2,12 +2,16 @@ namespace Pterodactyl\Services\Helpers; +use Pterodactyl\Repositories\Eloquent\SettingsRepository; use Pterodactyl\Traits\Helpers\AvailableLanguages; +use Pterodactyl\Models\Setting; class SettingsService { use AvailableLanguages; + public function __construct(private SettingsRepository $repository) {} + /** * Return the current version of the panel that is being used. */ @@ -15,17 +19,18 @@ public function getCurrentSettings(): array { return array( 'general' => [ - 'name' => config('app.name'), + 'name' => $this->repository->get('appName', config('app.name')), + 'language' => $this->repository->get('language', config('app.locale')), 'languages' => $this->getAvailableLanguages(true), ], 'mail' => [ - 'host' => config('mail.mailers.smtp.host'), - 'port' => config('mail.mailers.smtp.port'), - 'encryption' => config('mail.mailers.smtp.encryption'), - 'username' => config('mail.mailers.smtp.username'), - 'password' => config('mail.mailers.smtp.password'), - 'from_address' => config('mail.from.address'), - 'from_name' => config('mail.from.name') + 'host' => $this->repository->get('smtpHost', config('mail.mailers.smtp.host')), + 'port' => $this->repository->get('smtpPort', config('mail.mailers.smtp.port')), + 'encryption' => $this->repository->get('smtpEncryption', config('mail.mailers.smtp.encryption')), + 'username' => $this->repository->get('smtpUsername', config('mail.mailers.smtp.username')), + 'password' => $this->repository->get('smtpPassword', config('mail.mailers.smtp.password')), + 'from_address' => $this->repository->get('smtpFromAddress', config('mail.from.address')), + 'from_name' => $this->repository->get('smtpFromName', config('mail.from.name')), ], 'security' => [ 'recaptcha' => [ diff --git a/app/Transformers/Api/Application/SettingsTransformer.php b/app/Transformers/Api/Application/SettingsTransformer.php index dda5399a89..4a9198854f 100644 --- a/app/Transformers/Api/Application/SettingsTransformer.php +++ b/app/Transformers/Api/Application/SettingsTransformer.php @@ -23,6 +23,7 @@ public function transform(array $model): array return [ 'general' => [ 'name' => $model['general']['name'], + 'language' => $model['general']['language'], 'languages' => $model['general']['languages'], ], 'mail' => [ diff --git a/resources/scripts/api/admin/settings.ts b/resources/scripts/api/admin/settings.ts index b12a8070da..2d19c5b2ab 100644 --- a/resources/scripts/api/admin/settings.ts +++ b/resources/scripts/api/admin/settings.ts @@ -2,7 +2,7 @@ import { Model } from '@/api/admin/index'; import http from '@/api/http'; import Transformers from '../definitions/admin/transformers'; -export interface Settings extends Model { +export interface Settings { general: GeneralSettings; mail: MailSettings; security: SecuritySettings; @@ -10,14 +10,11 @@ export interface Settings extends Model { export interface GeneralSettings { name: string; - languages: Language[]; + language: LanguageKey; + languages: Record; } -interface Language { - [key: string]: string; -} - -export type LanguageKey = 'en'; +export type LanguageKey = 'en' | 'es' | 'ro'; export interface MailSettings { host: string; @@ -53,3 +50,11 @@ export const getSettings = (): Promise => { .catch(reject); }); }; + +export const updateSetting = (values: Type): Promise => { + return new Promise((resolve, reject) => { + http.patch('/api/application/settings', { ...values }) + .then(() => resolve()) + .catch(reject); + }); +}; diff --git a/resources/scripts/api/definitions/admin/transformers.ts b/resources/scripts/api/definitions/admin/transformers.ts index 31a345d2d1..6cbd8e694e 100644 --- a/resources/scripts/api/definitions/admin/transformers.ts +++ b/resources/scripts/api/definitions/admin/transformers.ts @@ -230,6 +230,7 @@ export default class Transformers { static toSettings = ({ attributes }: FractalResponseData): Settings => ({ general: { name: attributes.general.name, + language: attributes.general.language, languages: attributes.general.languages, }, mail: { diff --git a/resources/scripts/components/admin/settings/AdvancedSettings.tsx b/resources/scripts/components/admin/settings/AdvancedSettings.tsx index 002ff1de4d..f8fd2c9d4b 100644 --- a/resources/scripts/components/admin/settings/AdvancedSettings.tsx +++ b/resources/scripts/components/admin/settings/AdvancedSettings.tsx @@ -4,6 +4,7 @@ import tw from 'twin.macro'; import AdminBox from '@/components/admin/AdminBox'; import Field, { FieldRow } from '@/components/elements/Field'; import SelectField from '@/components/elements/SelectField'; +import { Button } from '@/components/elements/button/index'; export default () => { const submit = () => { @@ -76,6 +77,13 @@ export default () => {
+
+
+ +
+
); diff --git a/resources/scripts/components/admin/settings/GeneralSettings.tsx b/resources/scripts/components/admin/settings/GeneralSettings.tsx index cf6b200075..85f5bb110d 100644 --- a/resources/scripts/components/admin/settings/GeneralSettings.tsx +++ b/resources/scripts/components/admin/settings/GeneralSettings.tsx @@ -3,11 +3,15 @@ import tw from 'twin.macro'; import AdminBox from '@/components/admin/AdminBox'; import Field, { FieldRow } from '@/components/elements/Field'; -import { useStoreState } from 'easy-peasy'; +import { Actions } from 'easy-peasy'; import { ApplicationStore } from '@/state'; import SelectField from '@/components/elements/SelectField'; import { Context } from './SettingsRouter'; -import { debounce } from 'debounce'; +import { Button } from '@/components/elements/button/index'; +import { useState } from 'react'; +import { LanguageKey, updateSetting } from '@/api/admin/settings'; +import { useStoreActions } from '@/state/hooks'; +import { SiteSettings } from '@/state/settings'; type Values = { appName: string; @@ -15,17 +19,31 @@ type Values = { }; export default function GeneralSettings() { - const { name: appName, languages } = Context.useStoreState(state => state.settings!.general); - const { locale: language } = useStoreState((state: ApplicationStore) => state.settings.data!); + const { name: appName, languages, language } = Context.useStoreState(state => state.settings!.general); + const setSettings = useStoreActions(actions => actions.settings!.setSettings); - const submit = (values: Values) => { - // - console.log(values); - }; + const { addFlash, clearFlashes, clearAndAddHttpError } = useStoreActions( + (actions: Actions) => actions.flashes, + ); - const setVariableValue = debounce((value: string) => { - console.log(value); - }, 500); + const [loading, setLoading] = useState(false); + + const submit = async (values: Values) => { + clearFlashes('admin:settings'); + setLoading(true); + + try { + await updateSetting(values); + setSettings({ name: values.appName, locale: values.language } as SiteSettings); + addFlash({ type: 'success', message: 'Successfully updated settings.', key: 'admin:settings' }); + setTimeout(() => clearFlashes('admin:settings'), 2000); + } catch (error) { + console.error(error); + clearAndAddHttpError({ key: 'admin:settings', error }); + } finally { + setLoading(false); + } + }; return ( - setVariableValue(e.currentTarget.value)} - id={'appName'} - name={'appName'} - type={'text'} - label={'App Name'} - description={''} - /> + @@ -55,16 +66,23 @@ export default function GeneralSettings() { id={'language'} name={'language'} label={'Default language'} - options={Object.keys(languages).map(key => { + options={Object.keys(languages).map(lang => { return { - value: key, - label: languages[key as any] as unknown as string, + value: lang, + label: languages[lang as LanguageKey], }; })} />
+
+
+ +
+
); diff --git a/resources/scripts/components/admin/settings/MailSettings.tsx b/resources/scripts/components/admin/settings/MailSettings.tsx index cb3b40be2c..1ecdd47de7 100644 --- a/resources/scripts/components/admin/settings/MailSettings.tsx +++ b/resources/scripts/components/admin/settings/MailSettings.tsx @@ -2,11 +2,12 @@ import { Form, Formik, FormikHelpers } from 'formik'; import tw from 'twin.macro'; import AdminBox from '@/components/admin/AdminBox'; -import Button from '@/components/elements/Button'; +import { Button } from '@/components/elements/button/index'; import Field, { FieldRow } from '@/components/elements/Field'; import Label from '@/components/elements/Label'; import { Context } from './SettingsRouter'; import SelectField from '@/components/elements/SelectField'; +import { updateSetting } from '@/api/admin/settings'; interface Values { smtpHost: string; @@ -23,9 +24,15 @@ export default () => { state => state.settings!.mail, ); - const submit = (values: Values, { setSubmitting }: FormikHelpers) => { + const submit = async (values: Values, { setSubmitting }: FormikHelpers) => { console.log(values); - setSubmitting(false); + try { + await updateSetting(values); + } catch (error) { + console.error(error); + } finally { + setSubmitting(false); + } }; return ( @@ -109,7 +116,7 @@ export default () => {
-
diff --git a/resources/scripts/components/admin/settings/SecuritySettings.tsx b/resources/scripts/components/admin/settings/SecuritySettings.tsx index 64a941482f..0c0dbe106d 100644 --- a/resources/scripts/components/admin/settings/SecuritySettings.tsx +++ b/resources/scripts/components/admin/settings/SecuritySettings.tsx @@ -5,6 +5,7 @@ import AdminBox from '@/components/admin/AdminBox'; import Field, { FieldRow } from '@/components/elements/Field'; import SelectField from '@/components/elements/SelectField'; import { Context } from './SettingsRouter'; +import { Button } from '@/components/elements/button/index'; interface Values { recaptchaStatus: string; @@ -81,6 +82,13 @@ export default () => {
+
+
+ +
+
); diff --git a/resources/scripts/components/admin/settings/SettingsRouter.tsx b/resources/scripts/components/admin/settings/SettingsRouter.tsx index 22b82bd658..6ea5aeb0b8 100644 --- a/resources/scripts/components/admin/settings/SettingsRouter.tsx +++ b/resources/scripts/components/admin/settings/SettingsRouter.tsx @@ -84,9 +84,9 @@ const SettingsRouter = () => { - + {/* - + */} diff --git a/resources/scripts/state/settings.ts b/resources/scripts/state/settings.ts index 20dbbdc6e0..3233be8f0c 100644 --- a/resources/scripts/state/settings.ts +++ b/resources/scripts/state/settings.ts @@ -6,7 +6,7 @@ export interface SiteSettings { recaptcha: { enabled: boolean; siteKey: string; - }; + } | null; } export interface SettingsStore { diff --git a/routes/api-application.php b/routes/api-application.php index 96f785b7c9..59b0062f5d 100644 --- a/routes/api-application.php +++ b/routes/api-application.php @@ -5,7 +5,8 @@ Route::get('/version', [Application\VersionController::class, '__invoke']); Route::group(['prefix' => '/settings'], function () { - Route::get('/', [Application\SettingsController::class, '__invoke']); + Route::get('/', [Application\SettingsController::class, 'index']); + Route::patch('/', [Application\SettingsController::class, 'update']); }); /* |-------------------------------------------------------------------------- From f2521d1f9a192855e526b1d823a144d4eb228dc4 Mon Sep 17 00:00:00 2001 From: Scai <59282365+alexevladgabriel@users.noreply.github.com> Date: Sun, 31 Dec 2023 15:57:34 +0200 Subject: [PATCH 10/13] fix: gravatar url --- app/Models/User.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Models/User.php b/app/Models/User.php index 3446bf8071..58934b76b0 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -222,7 +222,7 @@ public function setUsernameAttribute(string $value) public function avatarUrl(): Attribute { return Attribute::make( - get: fn () => 'https://www.gravatar.com/avatar/' . $this->md5 . '.jpg', + get: fn () => 'https://www.gravatar.com/avatar/' . $this->md5, ); } @@ -236,7 +236,7 @@ public function adminRoleName(): Attribute public function md5(): Attribute { return Attribute::make( - get: fn () => md5(strtolower($this->email)), + get: fn () => md5(strtolower(trim($this->email))), ); } From 8609ccc0e7d9c5ed83b951455179ff5aeaf904a9 Mon Sep 17 00:00:00 2001 From: Scai <59282365+alexevladgabriel@users.noreply.github.com> Date: Sun, 31 Dec 2023 17:01:21 +0200 Subject: [PATCH 11/13] add handlers for mail & security --- .../RequireTwoFactorAuthentication.php | 5 +- .../Settings/UpdateSettingsRequest.php | 17 +++- app/Http/ViewComposers/AssetComposer.php | 4 +- app/Services/Helpers/SettingsService.php | 14 ++-- .../admin/settings/GeneralSettings.tsx | 81 ++++++++++--------- .../admin/settings/MailSettings.tsx | 45 +++++++---- .../admin/settings/SecuritySettings.tsx | 65 ++++++++++----- 7 files changed, 142 insertions(+), 89 deletions(-) diff --git a/app/Http/Middleware/RequireTwoFactorAuthentication.php b/app/Http/Middleware/RequireTwoFactorAuthentication.php index a6110edb16..bd0a73e46e 100644 --- a/app/Http/Middleware/RequireTwoFactorAuthentication.php +++ b/app/Http/Middleware/RequireTwoFactorAuthentication.php @@ -4,6 +4,7 @@ use Illuminate\Support\Str; use Illuminate\Http\Request; +use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface; use Pterodactyl\Models\User; use Pterodactyl\Exceptions\Http\TwoFactorAuthRequiredException; @@ -18,6 +19,8 @@ class RequireTwoFactorAuthentication */ protected string $redirectRoute = '/account'; + public function __construct(private readonly SettingsRepositoryInterface $settings) {} + /** * Check the user state on the incoming request to determine if they should be allowed to * proceed or not. This checks if the Panel is configured to require 2FA on an account in @@ -42,7 +45,7 @@ public function handle(Request $request, \Closure $next): mixed return $next($request); } - $level = (int) config('pterodactyl.auth.2fa_required'); + $level = (int) $this->settings->get('sfaEnabled', config('pterodactyl.auth.2fa_required')); // If this setting is not configured, or the user is already using 2FA then we can just // send them right through, nothing else needs to be checked. // diff --git a/app/Http/Requests/Api/Application/Settings/UpdateSettingsRequest.php b/app/Http/Requests/Api/Application/Settings/UpdateSettingsRequest.php index fa4a557c08..2b9961d57d 100644 --- a/app/Http/Requests/Api/Application/Settings/UpdateSettingsRequest.php +++ b/app/Http/Requests/Api/Application/Settings/UpdateSettingsRequest.php @@ -13,15 +13,24 @@ class UpdateSettingsRequest extends ApplicationApiRequest public function rules(): array { return [ + // General 'appName' => 'sometimes|required|string|max:191', 'language' => ['sometimes', 'required', 'string', Rule::in(array_keys($this->getAvailableLanguages()))], + + // Mail 'smtpHost' => 'sometimes|required|string', 'smtpPort' => 'sometimes|required|integer|between:1,65535', 'smtpEncryption' => ['sometimes', 'present', Rule::in([null, 'tls', 'ssl'])], - 'username' => 'sometimes|nullable|string|max:191', - 'password' => 'sometimes|nullable|string|max:191', - 'mailFrom' => 'sometimes|required|string|email', - 'mailFromName' => 'sometimes|nullable|string|max:191', + 'smtpUsername' => 'sometimes|nullable|string|max:191', + 'smtpPassword' => 'sometimes|nullable|string|max:191', + 'smtpMailFrom' => 'sometimes|required|string|email', + 'smtpMailFromName' => 'sometimes|nullable|string|max:191', + + // Security + 'recaptchaEnabled' => 'sometimes|required|boolean', + 'recaptchaSiteKey' => 'sometimes|required_if:recaptchaEnabled,true|string|max:191', + 'recaptchaSecretKey' => 'sometimes|required_if:recaptchaEnabled,true|string|max:191', + 'sfaEnabled' => 'sometimes|required|boolean', ]; } } diff --git a/app/Http/ViewComposers/AssetComposer.php b/app/Http/ViewComposers/AssetComposer.php index 29a84cb445..91e7489151 100644 --- a/app/Http/ViewComposers/AssetComposer.php +++ b/app/Http/ViewComposers/AssetComposer.php @@ -19,8 +19,8 @@ public function compose(View $view): void 'name' => $this->repository->get('appName', config('app.name')), 'locale' => $this->repository->get('language', config('app.locale')), 'recaptcha' => [ - 'enabled' => config('recaptcha.enabled', false), - 'siteKey' => config('recaptcha.website_key') ?? '', + 'enabled' => (bool)$this->repository->get('recaptchaEnabled', config('recaptcha.enabled', false)), + 'siteKey' => $this->repository->get('recaptchaSiteKey',config('recaptcha.website_key') ?? ''), ], ]); } diff --git a/app/Services/Helpers/SettingsService.php b/app/Services/Helpers/SettingsService.php index 80b6e815de..6fb38edf2f 100644 --- a/app/Services/Helpers/SettingsService.php +++ b/app/Services/Helpers/SettingsService.php @@ -10,7 +10,7 @@ class SettingsService { use AvailableLanguages; - public function __construct(private SettingsRepository $repository) {} + public function __construct(private readonly SettingsRepository $repository) {} /** * Return the current version of the panel that is being used. @@ -29,16 +29,16 @@ public function getCurrentSettings(): array 'encryption' => $this->repository->get('smtpEncryption', config('mail.mailers.smtp.encryption')), 'username' => $this->repository->get('smtpUsername', config('mail.mailers.smtp.username')), 'password' => $this->repository->get('smtpPassword', config('mail.mailers.smtp.password')), - 'from_address' => $this->repository->get('smtpFromAddress', config('mail.from.address')), - 'from_name' => $this->repository->get('smtpFromName', config('mail.from.name')), + 'from_address' => $this->repository->get('smtpMailFrom', config('mail.from.address')), + 'from_name' => $this->repository->get('smtpMailFromName', config('mail.from.name')), ], 'security' => [ 'recaptcha' => [ - 'enabled' => config('recaptcha.enabled'), - 'site_key' => config('recaptcha.website_key'), - 'secret_key' => config('recaptcha.secret_key'), + 'enabled' => $this->repository->get('recaptchaEnabled' , config('recaptcha.enabled')), + 'site_key' => $this->repository->get('recaptchaSiteKey', config('recaptcha.website_key')), + 'secret_key' => $this->repository->get('recaptchaSecretKey', config('recaptcha.secret_key')), ], - '2fa_enabled' => config('pterodactyl.auth.2fa_required'), + '2fa_enabled' => $this->repository->get('sfaEnabled', config('pterodactyl.auth.2fa_required')), ], ); } diff --git a/resources/scripts/components/admin/settings/GeneralSettings.tsx b/resources/scripts/components/admin/settings/GeneralSettings.tsx index 85f5bb110d..7c02153953 100644 --- a/resources/scripts/components/admin/settings/GeneralSettings.tsx +++ b/resources/scripts/components/admin/settings/GeneralSettings.tsx @@ -1,4 +1,4 @@ -import { Form, Formik } from 'formik'; +import { Form, Formik, FormikHelpers } from 'formik'; import tw from 'twin.macro'; import AdminBox from '@/components/admin/AdminBox'; @@ -8,14 +8,13 @@ import { ApplicationStore } from '@/state'; import SelectField from '@/components/elements/SelectField'; import { Context } from './SettingsRouter'; import { Button } from '@/components/elements/button/index'; -import { useState } from 'react'; import { LanguageKey, updateSetting } from '@/api/admin/settings'; import { useStoreActions } from '@/state/hooks'; import { SiteSettings } from '@/state/settings'; type Values = { appName: string; - language: string; + language: LanguageKey; }; export default function GeneralSettings() { @@ -26,11 +25,9 @@ export default function GeneralSettings() { (actions: Actions) => actions.flashes, ); - const [loading, setLoading] = useState(false); - - const submit = async (values: Values) => { + const submit = async (values: Values, { setSubmitting }: FormikHelpers) => { clearFlashes('admin:settings'); - setLoading(true); + setSubmitting(true); try { await updateSetting(values); @@ -41,7 +38,7 @@ export default function GeneralSettings() { console.error(error); clearAndAddHttpError({ key: 'admin:settings', error }); } finally { - setLoading(false); + setSubmitting(false); } }; @@ -53,37 +50,45 @@ export default function GeneralSettings() { language, }} > -
-
- - - - - - - - { - return { - value: lang, - label: languages[lang as LanguageKey], - }; - })} - /> - - -
-
-
- + {({ isSubmitting, isValid }) => ( + +
+ + + + + + + + { + return { + value: lang, + label: languages[lang as LanguageKey], + }; + })} + /> + + +
+
+
+ +
-
- + + )} ); } diff --git a/resources/scripts/components/admin/settings/MailSettings.tsx b/resources/scripts/components/admin/settings/MailSettings.tsx index 1ecdd47de7..3389d16f9f 100644 --- a/resources/scripts/components/admin/settings/MailSettings.tsx +++ b/resources/scripts/components/admin/settings/MailSettings.tsx @@ -8,15 +8,17 @@ import Label from '@/components/elements/Label'; import { Context } from './SettingsRouter'; import SelectField from '@/components/elements/SelectField'; import { updateSetting } from '@/api/admin/settings'; +import { Actions, useStoreActions } from 'easy-peasy'; +import { ApplicationStore } from '@/state'; interface Values { smtpHost: string; smtpPort: number; smtpEncryption: string; - username: string; - password: string; - mailFrom: string; - mailFromName: string; + smtpUsername: string; + smtpPassword: string; + smtpMailFrom: string; + smtpMailFromName: string; } export default () => { @@ -24,12 +26,21 @@ export default () => { state => state.settings!.mail, ); + const { addFlash, clearFlashes, clearAndAddHttpError } = useStoreActions( + (actions: Actions) => actions.flashes, + ); + const submit = async (values: Values, { setSubmitting }: FormikHelpers) => { - console.log(values); + clearFlashes('admin:settings'); + setSubmitting(true); + try { await updateSetting(values); + addFlash({ type: 'success', message: 'Successfully updated settings.', key: 'admin:settings' }); + setTimeout(() => clearFlashes('admin:settings'), 2000); } catch (error) { console.error(error); + clearAndAddHttpError({ key: 'admin:settings', error }); } finally { setSubmitting(false); } @@ -42,10 +53,10 @@ export default () => { smtpHost: host ?? 'smtp.example.com', smtpPort: port ?? 587, smtpEncryption: encryption ?? 'tls', - username: username ?? '', - password: password ?? '', - mailFrom: fromAddress ?? 'no-reply@example.com', - mailFromName: fromName ?? 'Pterodactyl Panel', + smtpUsername: username ?? '', + smtpPassword: password ?? '', + smtpMailFrom: fromAddress ?? 'no-reply@example.com', + smtpMailFromName: fromName ?? 'Pterodactyl Panel', }} > {({ isSubmitting, isValid }) => ( @@ -81,15 +92,15 @@ export default () => { { { const security = Context.useStoreState(state => state.settings!.security); const { enabled: recaptchaStatus, siteKey, secretKey } = security.recaptcha; - const submit = (values: Values, { setSubmitting }: FormikHelpers) => { - console.log(values); - setSubmitting(false); + const { addFlash, clearFlashes, clearAndAddHttpError } = useStoreActions( + (actions: Actions) => actions.flashes, + ); + + const submit = async (values: Values, { setSubmitting }: FormikHelpers) => { + clearFlashes('admin:settings'); + setSubmitting(true); + + try { + console.log(values); + await updateSetting(values); + addFlash({ type: 'success', message: 'Successfully updated settings.', key: 'admin:settings' }); + setTimeout(() => clearFlashes('admin:settings'), 2000); + } catch (error) { + console.error(error); + clearAndAddHttpError({ key: 'admin:settings', error }); + } finally { + setSubmitting(false); + } }; return (
@@ -38,24 +57,30 @@ export default () => { - + { Date: Mon, 1 Jan 2024 16:38:26 +0200 Subject: [PATCH 12/13] fix request security --- .../Requests/Api/Application/Settings/UpdateSettingsRequest.php | 2 +- .../scripts/components/admin/settings/SecuritySettings.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Requests/Api/Application/Settings/UpdateSettingsRequest.php b/app/Http/Requests/Api/Application/Settings/UpdateSettingsRequest.php index 2b9961d57d..6136e96cd6 100644 --- a/app/Http/Requests/Api/Application/Settings/UpdateSettingsRequest.php +++ b/app/Http/Requests/Api/Application/Settings/UpdateSettingsRequest.php @@ -30,7 +30,7 @@ public function rules(): array 'recaptchaEnabled' => 'sometimes|required|boolean', 'recaptchaSiteKey' => 'sometimes|required_if:recaptchaEnabled,true|string|max:191', 'recaptchaSecretKey' => 'sometimes|required_if:recaptchaEnabled,true|string|max:191', - 'sfaEnabled' => 'sometimes|required|boolean', + 'sfaEnabled' => 'sometimes|required|integer|between:0,2', ]; } } diff --git a/resources/scripts/components/admin/settings/SecuritySettings.tsx b/resources/scripts/components/admin/settings/SecuritySettings.tsx index a1f42f5aca..b4f577ccca 100644 --- a/resources/scripts/components/admin/settings/SecuritySettings.tsx +++ b/resources/scripts/components/admin/settings/SecuritySettings.tsx @@ -46,7 +46,7 @@ export default () => { Date: Sat, 13 Jan 2024 19:26:56 +0200 Subject: [PATCH 13/13] revert relative paths --- .../scripts/components/admin/databases/DatabaseDeleteButton.tsx | 2 +- .../components/admin/databases/DatabaseEditContainer.tsx | 2 +- .../scripts/components/admin/databases/DatabasesContainer.tsx | 2 +- .../scripts/components/admin/locations/LocationDeleteButton.tsx | 2 +- .../components/admin/locations/LocationEditContainer.tsx | 2 +- .../scripts/components/admin/locations/NewLocationButton.tsx | 2 +- resources/scripts/components/admin/mounts/MountDeleteButton.tsx | 2 +- resources/scripts/components/admin/mounts/MountForm.tsx | 2 +- resources/scripts/components/admin/mounts/MountsContainer.tsx | 2 +- resources/scripts/components/admin/nests/ImportEggButton.tsx | 2 +- resources/scripts/components/admin/nests/NestDeleteButton.tsx | 2 +- resources/scripts/components/admin/nests/NestEditContainer.tsx | 2 +- resources/scripts/components/admin/nests/NewEggContainer.tsx | 2 +- resources/scripts/components/admin/nests/NewNestButton.tsx | 2 +- .../scripts/components/admin/nests/eggs/EggDeleteButton.tsx | 2 +- .../scripts/components/admin/nests/eggs/EggExportButton.tsx | 2 +- .../scripts/components/admin/nests/eggs/EggInstallContainer.tsx | 2 +- .../components/admin/nests/eggs/EggSettingsContainer.tsx | 2 +- .../components/admin/nests/eggs/EggVariablesContainer.tsx | 2 +- .../scripts/components/admin/nests/eggs/NewVariableButton.tsx | 2 +- .../scripts/components/admin/servers/ServerDeleteButton.tsx | 2 +- .../components/admin/servers/ServerSettingsContainer.tsx | 2 +- .../scripts/components/admin/settings/AdvancedSettings.tsx | 2 +- resources/scripts/components/admin/settings/GeneralSettings.tsx | 2 +- resources/scripts/components/admin/settings/MailSettings.tsx | 2 +- .../scripts/components/admin/settings/SecuritySettings.tsx | 2 +- resources/scripts/components/admin/settings/SettingsRouter.tsx | 2 +- resources/scripts/components/admin/users/UsersContainer.tsx | 2 +- .../components/dashboard/forms/ConfigureTwoFactorForm.tsx | 2 +- .../scripts/components/dashboard/forms/DisableTOTPDialog.tsx | 2 +- .../scripts/components/dashboard/forms/RecoveryTokensDialog.tsx | 2 +- .../scripts/components/dashboard/forms/SetupTOTPDialog.tsx | 2 +- .../components/dashboard/forms/UpdateEmailAddressForm.tsx | 2 +- .../scripts/components/dashboard/forms/UpdatePasswordForm.tsx | 2 +- .../components/elements/activity/ActivityLogMetaButton.tsx | 2 +- .../scripts/components/elements/dialog/ConfirmationDialog.tsx | 2 +- resources/scripts/components/elements/dialog/Dialog.tsx | 2 +- .../scripts/components/elements/table/PaginationFooter.tsx | 2 +- resources/scripts/components/server/console/PowerButtons.tsx | 2 +- resources/scripts/components/server/files/FileEditContainer.tsx | 2 +- .../scripts/components/server/files/FileManagerContainer.tsx | 2 +- resources/scripts/components/server/files/FileManagerStatus.tsx | 2 +- resources/scripts/components/server/files/FileNameModal.tsx | 2 +- resources/scripts/components/server/files/MassActionsBar.tsx | 2 +- .../scripts/components/server/files/NewDirectoryButton.tsx | 2 +- resources/scripts/components/server/files/UploadButton.tsx | 2 +- resources/scripts/components/server/network/AllocationRow.tsx | 2 +- .../components/server/network/DeleteAllocationButton.tsx | 2 +- .../components/server/schedules/DeleteScheduleButton.tsx | 2 +- .../scripts/components/server/schedules/EditScheduleModal.tsx | 2 +- resources/scripts/components/server/schedules/NewTaskButton.tsx | 2 +- .../scripts/components/server/schedules/RunScheduleButton.tsx | 2 +- .../scripts/components/server/schedules/ScheduleContainer.tsx | 2 +- .../components/server/schedules/ScheduleEditContainer.tsx | 2 +- .../scripts/components/server/schedules/TaskDetailsModal.tsx | 2 +- .../scripts/components/server/settings/ReinstallServerBox.tsx | 2 +- .../scripts/components/server/settings/RenameServerBox.tsx | 2 +- .../scripts/components/server/settings/SettingsContainer.tsx | 2 +- resources/scripts/components/server/users/AddSubuserButton.tsx | 2 +- 59 files changed, 59 insertions(+), 59 deletions(-) diff --git a/resources/scripts/components/admin/databases/DatabaseDeleteButton.tsx b/resources/scripts/components/admin/databases/DatabaseDeleteButton.tsx index b29f224a8f..4c594d261b 100644 --- a/resources/scripts/components/admin/databases/DatabaseDeleteButton.tsx +++ b/resources/scripts/components/admin/databases/DatabaseDeleteButton.tsx @@ -4,7 +4,7 @@ import { useState } from 'react'; import tw from 'twin.macro'; import deleteDatabase from '@/api/admin/databases/deleteDatabase'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Shape } from '@/components/elements/button/types'; import ConfirmationModal from '@/components/elements/ConfirmationModal'; import type { ApplicationStore } from '@/state'; diff --git a/resources/scripts/components/admin/databases/DatabaseEditContainer.tsx b/resources/scripts/components/admin/databases/DatabaseEditContainer.tsx index 4d4abcd241..dc4f74a324 100644 --- a/resources/scripts/components/admin/databases/DatabaseEditContainer.tsx +++ b/resources/scripts/components/admin/databases/DatabaseEditContainer.tsx @@ -14,7 +14,7 @@ import AdminContentBlock from '@/components/admin/AdminContentBlock'; import Spinner from '@/components/elements/Spinner'; import FlashMessageRender from '@/components/FlashMessageRender'; import AdminBox from '@/components/admin/AdminBox'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import Field from '@/components/elements/Field'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; import DatabaseDeleteButton from '@/components/admin/databases/DatabaseDeleteButton'; diff --git a/resources/scripts/components/admin/databases/DatabasesContainer.tsx b/resources/scripts/components/admin/databases/DatabasesContainer.tsx index 1deda0c152..e36555071f 100644 --- a/resources/scripts/components/admin/databases/DatabasesContainer.tsx +++ b/resources/scripts/components/admin/databases/DatabasesContainer.tsx @@ -20,7 +20,7 @@ import AdminTable, { TableRow, useTableHooks, } from '@/components/admin/AdminTable'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Size } from '@/components/elements/button/types'; import CopyOnClick from '@/components/elements/CopyOnClick'; diff --git a/resources/scripts/components/admin/locations/LocationDeleteButton.tsx b/resources/scripts/components/admin/locations/LocationDeleteButton.tsx index 1a24b05576..99aa7d1e24 100644 --- a/resources/scripts/components/admin/locations/LocationDeleteButton.tsx +++ b/resources/scripts/components/admin/locations/LocationDeleteButton.tsx @@ -4,7 +4,7 @@ import { useState } from 'react'; import tw from 'twin.macro'; import deleteLocation from '@/api/admin/locations/deleteLocation'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Shape } from '@/components/elements/button/types'; import ConfirmationModal from '@/components/elements/ConfirmationModal'; import type { ApplicationStore } from '@/state'; diff --git a/resources/scripts/components/admin/locations/LocationEditContainer.tsx b/resources/scripts/components/admin/locations/LocationEditContainer.tsx index f3a4cf2738..261dec534a 100644 --- a/resources/scripts/components/admin/locations/LocationEditContainer.tsx +++ b/resources/scripts/components/admin/locations/LocationEditContainer.tsx @@ -13,7 +13,7 @@ import updateLocation from '@/api/admin/locations/updateLocation'; import AdminBox from '@/components/admin/AdminBox'; import AdminContentBlock from '@/components/admin/AdminContentBlock'; import LocationDeleteButton from '@/components/admin/locations/LocationDeleteButton'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import Field from '@/components/elements/Field'; import Spinner from '@/components/elements/Spinner'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; diff --git a/resources/scripts/components/admin/locations/NewLocationButton.tsx b/resources/scripts/components/admin/locations/NewLocationButton.tsx index 664f4521ac..0b5d0ff889 100644 --- a/resources/scripts/components/admin/locations/NewLocationButton.tsx +++ b/resources/scripts/components/admin/locations/NewLocationButton.tsx @@ -6,7 +6,7 @@ import { object, string } from 'yup'; import createLocation from '@/api/admin/locations/createLocation'; import getLocations from '@/api/admin/locations/getLocations'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Size, Variant } from '@/components/elements/button/types'; import Field from '@/components/elements/Field'; import Modal from '@/components/elements/Modal'; diff --git a/resources/scripts/components/admin/mounts/MountDeleteButton.tsx b/resources/scripts/components/admin/mounts/MountDeleteButton.tsx index 25e1f4f2ba..7d47c547f3 100644 --- a/resources/scripts/components/admin/mounts/MountDeleteButton.tsx +++ b/resources/scripts/components/admin/mounts/MountDeleteButton.tsx @@ -4,7 +4,7 @@ import { useState } from 'react'; import tw from 'twin.macro'; import deleteMount from '@/api/admin/mounts/deleteMount'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import ConfirmationModal from '@/components/elements/ConfirmationModal'; import type { ApplicationStore } from '@/state'; diff --git a/resources/scripts/components/admin/mounts/MountForm.tsx b/resources/scripts/components/admin/mounts/MountForm.tsx index 049c916f2b..8a9d2bd999 100644 --- a/resources/scripts/components/admin/mounts/MountForm.tsx +++ b/resources/scripts/components/admin/mounts/MountForm.tsx @@ -5,7 +5,7 @@ import tw from 'twin.macro'; import { boolean, object, string } from 'yup'; import AdminBox from '@/components/admin/AdminBox'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import Field from '@/components/elements/Field'; import Label from '@/components/elements/Label'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; diff --git a/resources/scripts/components/admin/mounts/MountsContainer.tsx b/resources/scripts/components/admin/mounts/MountsContainer.tsx index a9033eba06..f9aa5fb052 100644 --- a/resources/scripts/components/admin/mounts/MountsContainer.tsx +++ b/resources/scripts/components/admin/mounts/MountsContainer.tsx @@ -18,7 +18,7 @@ import AdminTable, { ContentWrapper, useTableHooks, } from '@/components/admin/AdminTable'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Size } from '@/components/elements/button/types'; import CopyOnClick from '@/components/elements/CopyOnClick'; import FlashMessageRender from '@/components/FlashMessageRender'; diff --git a/resources/scripts/components/admin/nests/ImportEggButton.tsx b/resources/scripts/components/admin/nests/ImportEggButton.tsx index 04727926ed..94bafd6fd2 100644 --- a/resources/scripts/components/admin/nests/ImportEggButton.tsx +++ b/resources/scripts/components/admin/nests/ImportEggButton.tsx @@ -7,7 +7,7 @@ import tw from 'twin.macro'; import getEggs from '@/api/admin/nests/getEggs'; import importEgg from '@/api/admin/nests/importEgg'; import useFlash from '@/plugins/useFlash'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Size, Variant } from '@/components/elements/button/types'; import { Editor } from '@/components/elements/editor'; import Modal from '@/components/elements/Modal'; diff --git a/resources/scripts/components/admin/nests/NestDeleteButton.tsx b/resources/scripts/components/admin/nests/NestDeleteButton.tsx index 0d55249c66..48528a0106 100644 --- a/resources/scripts/components/admin/nests/NestDeleteButton.tsx +++ b/resources/scripts/components/admin/nests/NestDeleteButton.tsx @@ -4,7 +4,7 @@ import { useState } from 'react'; import tw from 'twin.macro'; import deleteNest from '@/api/admin/nests/deleteNest'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Shape } from '@/components/elements/button/types'; import ConfirmationModal from '@/components/elements/ConfirmationModal'; import type { ApplicationStore } from '@/state'; diff --git a/resources/scripts/components/admin/nests/NestEditContainer.tsx b/resources/scripts/components/admin/nests/NestEditContainer.tsx index c8b6441105..924eabba93 100644 --- a/resources/scripts/components/admin/nests/NestEditContainer.tsx +++ b/resources/scripts/components/admin/nests/NestEditContainer.tsx @@ -14,7 +14,7 @@ import FlashMessageRender from '@/components/FlashMessageRender'; import type { Nest } from '@/api/admin/nests/getNests'; import getNest from '@/api/admin/nests/getNest'; import updateNest from '@/api/admin/nests/updateNest'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Size } from '@/components/elements/button/types'; import Field from '@/components/elements/Field'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; diff --git a/resources/scripts/components/admin/nests/NewEggContainer.tsx b/resources/scripts/components/admin/nests/NewEggContainer.tsx index db3e0af975..9530d724b0 100644 --- a/resources/scripts/components/admin/nests/NewEggContainer.tsx +++ b/resources/scripts/components/admin/nests/NewEggContainer.tsx @@ -15,7 +15,7 @@ import { EggProcessContainer, EggStartupContainer, } from '@/components/admin/nests/eggs/EggSettingsContainer'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import FlashMessageRender from '@/components/FlashMessageRender'; import useFlash from '@/plugins/useFlash'; diff --git a/resources/scripts/components/admin/nests/NewNestButton.tsx b/resources/scripts/components/admin/nests/NewNestButton.tsx index 105bca8b3c..a8a4fbecb7 100644 --- a/resources/scripts/components/admin/nests/NewNestButton.tsx +++ b/resources/scripts/components/admin/nests/NewNestButton.tsx @@ -6,7 +6,7 @@ import { object, string } from 'yup'; import createNest from '@/api/admin/nests/createNest'; import getNests from '@/api/admin/nests/getNests'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Size, Variant } from '@/components/elements/button/types'; import Field from '@/components/elements/Field'; import FlashMessageRender from '@/components/FlashMessageRender'; diff --git a/resources/scripts/components/admin/nests/eggs/EggDeleteButton.tsx b/resources/scripts/components/admin/nests/eggs/EggDeleteButton.tsx index ac7ecca5a7..c14286f552 100644 --- a/resources/scripts/components/admin/nests/eggs/EggDeleteButton.tsx +++ b/resources/scripts/components/admin/nests/eggs/EggDeleteButton.tsx @@ -4,7 +4,7 @@ import { useState } from 'react'; import tw from 'twin.macro'; import deleteEgg from '@/api/admin/eggs/deleteEgg'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Shape } from '@/components/elements/button/types'; import ConfirmationModal from '@/components/elements/ConfirmationModal'; import type { ApplicationStore } from '@/state'; diff --git a/resources/scripts/components/admin/nests/eggs/EggExportButton.tsx b/resources/scripts/components/admin/nests/eggs/EggExportButton.tsx index 1f87ec82e3..e3605e99cd 100644 --- a/resources/scripts/components/admin/nests/eggs/EggExportButton.tsx +++ b/resources/scripts/components/admin/nests/eggs/EggExportButton.tsx @@ -6,7 +6,7 @@ import tw from 'twin.macro'; import { exportEgg } from '@/api/admin/egg'; import FlashMessageRender from '@/components/FlashMessageRender'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Variant } from '@/components/elements/button/types'; import { Editor } from '@/components/elements/editor'; import Modal from '@/components/elements/Modal'; diff --git a/resources/scripts/components/admin/nests/eggs/EggInstallContainer.tsx b/resources/scripts/components/admin/nests/eggs/EggInstallContainer.tsx index 6151b0fce2..c566d2451f 100644 --- a/resources/scripts/components/admin/nests/eggs/EggInstallContainer.tsx +++ b/resources/scripts/components/admin/nests/eggs/EggInstallContainer.tsx @@ -8,7 +8,7 @@ import tw from 'twin.macro'; import { useEggFromRoute } from '@/api/admin/egg'; import updateEgg from '@/api/admin/eggs/updateEgg'; import AdminBox from '@/components/admin/AdminBox'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Editor } from '@/components/elements/editor'; import Field from '@/components/elements/Field'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; diff --git a/resources/scripts/components/admin/nests/eggs/EggSettingsContainer.tsx b/resources/scripts/components/admin/nests/eggs/EggSettingsContainer.tsx index 52bc5f8d2a..4642c68da3 100644 --- a/resources/scripts/components/admin/nests/eggs/EggSettingsContainer.tsx +++ b/resources/scripts/components/admin/nests/eggs/EggSettingsContainer.tsx @@ -14,7 +14,7 @@ import updateEgg from '@/api/admin/eggs/updateEgg'; import AdminBox from '@/components/admin/AdminBox'; import EggDeleteButton from '@/components/admin/nests/eggs/EggDeleteButton'; import EggExportButton from '@/components/admin/nests/eggs/EggExportButton'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Editor } from '@/components/elements/editor'; import Field, { TextareaField } from '@/components/elements/Field'; import Input from '@/components/elements/Input'; diff --git a/resources/scripts/components/admin/nests/eggs/EggVariablesContainer.tsx b/resources/scripts/components/admin/nests/eggs/EggVariablesContainer.tsx index f0366af825..5b3b4e4388 100644 --- a/resources/scripts/components/admin/nests/eggs/EggVariablesContainer.tsx +++ b/resources/scripts/components/admin/nests/eggs/EggVariablesContainer.tsx @@ -13,7 +13,7 @@ import type { EggVariable } from '@/api/admin/egg'; import { useEggFromRoute } from '@/api/admin/egg'; import NewVariableButton from '@/components/admin/nests/eggs/NewVariableButton'; import AdminBox from '@/components/admin/AdminBox'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import Checkbox from '@/components/elements/Checkbox'; import Field, { FieldRow, TextareaField } from '@/components/elements/Field'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; diff --git a/resources/scripts/components/admin/nests/eggs/NewVariableButton.tsx b/resources/scripts/components/admin/nests/eggs/NewVariableButton.tsx index ffb6e04f6a..753c221ae8 100644 --- a/resources/scripts/components/admin/nests/eggs/NewVariableButton.tsx +++ b/resources/scripts/components/admin/nests/eggs/NewVariableButton.tsx @@ -9,7 +9,7 @@ import { useEggFromRoute } from '@/api/admin/egg'; import { EggVariableForm, validationSchema } from '@/components/admin/nests/eggs/EggVariablesContainer'; import Modal from '@/components/elements/Modal'; import FlashMessageRender from '@/components/FlashMessageRender'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import useFlash from '@/plugins/useFlash'; import { Variant } from '@/components/elements/button/types'; diff --git a/resources/scripts/components/admin/servers/ServerDeleteButton.tsx b/resources/scripts/components/admin/servers/ServerDeleteButton.tsx index 6e7ad6349b..02f1910e7e 100644 --- a/resources/scripts/components/admin/servers/ServerDeleteButton.tsx +++ b/resources/scripts/components/admin/servers/ServerDeleteButton.tsx @@ -4,7 +4,7 @@ import { useStoreActions } from 'easy-peasy'; import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import ConfirmationModal from '@/components/elements/ConfirmationModal'; import deleteServer from '@/api/admin/servers/deleteServer'; import { useServerFromRoute } from '@/api/admin/server'; diff --git a/resources/scripts/components/admin/servers/ServerSettingsContainer.tsx b/resources/scripts/components/admin/servers/ServerSettingsContainer.tsx index 80ab5957e0..523004a4df 100644 --- a/resources/scripts/components/admin/servers/ServerSettingsContainer.tsx +++ b/resources/scripts/components/admin/servers/ServerSettingsContainer.tsx @@ -12,7 +12,7 @@ import BaseSettingsBox from '@/components/admin/servers/settings/BaseSettingsBox import FeatureLimitsBox from '@/components/admin/servers/settings/FeatureLimitsBox'; import NetworkingBox from '@/components/admin/servers/settings/NetworkingBox'; import ServerResourceBox from '@/components/admin/servers/settings/ServerResourceBox'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; export default () => { const { data: server } = useServerFromRoute(); diff --git a/resources/scripts/components/admin/settings/AdvancedSettings.tsx b/resources/scripts/components/admin/settings/AdvancedSettings.tsx index f8fd2c9d4b..8089655e69 100644 --- a/resources/scripts/components/admin/settings/AdvancedSettings.tsx +++ b/resources/scripts/components/admin/settings/AdvancedSettings.tsx @@ -4,7 +4,7 @@ import tw from 'twin.macro'; import AdminBox from '@/components/admin/AdminBox'; import Field, { FieldRow } from '@/components/elements/Field'; import SelectField from '@/components/elements/SelectField'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; export default () => { const submit = () => { diff --git a/resources/scripts/components/admin/settings/GeneralSettings.tsx b/resources/scripts/components/admin/settings/GeneralSettings.tsx index 7c02153953..1d7fdf5ff1 100644 --- a/resources/scripts/components/admin/settings/GeneralSettings.tsx +++ b/resources/scripts/components/admin/settings/GeneralSettings.tsx @@ -7,7 +7,7 @@ import { Actions } from 'easy-peasy'; import { ApplicationStore } from '@/state'; import SelectField from '@/components/elements/SelectField'; import { Context } from './SettingsRouter'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { LanguageKey, updateSetting } from '@/api/admin/settings'; import { useStoreActions } from '@/state/hooks'; import { SiteSettings } from '@/state/settings'; diff --git a/resources/scripts/components/admin/settings/MailSettings.tsx b/resources/scripts/components/admin/settings/MailSettings.tsx index 3389d16f9f..8a85fc86d0 100644 --- a/resources/scripts/components/admin/settings/MailSettings.tsx +++ b/resources/scripts/components/admin/settings/MailSettings.tsx @@ -2,7 +2,7 @@ import { Form, Formik, FormikHelpers } from 'formik'; import tw from 'twin.macro'; import AdminBox from '@/components/admin/AdminBox'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import Field, { FieldRow } from '@/components/elements/Field'; import Label from '@/components/elements/Label'; import { Context } from './SettingsRouter'; diff --git a/resources/scripts/components/admin/settings/SecuritySettings.tsx b/resources/scripts/components/admin/settings/SecuritySettings.tsx index b4f577ccca..bed4b3c0a0 100644 --- a/resources/scripts/components/admin/settings/SecuritySettings.tsx +++ b/resources/scripts/components/admin/settings/SecuritySettings.tsx @@ -5,7 +5,7 @@ import AdminBox from '@/components/admin/AdminBox'; import Field, { FieldRow } from '@/components/elements/Field'; import SelectField from '@/components/elements/SelectField'; import { Context } from './SettingsRouter'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { ApplicationStore } from '@/state'; import { Actions, useStoreActions } from 'easy-peasy'; import { updateSetting } from '@/api/admin/settings'; diff --git a/resources/scripts/components/admin/settings/SettingsRouter.tsx b/resources/scripts/components/admin/settings/SettingsRouter.tsx index 6ea5aeb0b8..32313f1ccf 100644 --- a/resources/scripts/components/admin/settings/SettingsRouter.tsx +++ b/resources/scripts/components/admin/settings/SettingsRouter.tsx @@ -1,4 +1,4 @@ -import { AdjustmentsIcon, ChipIcon, CodeIcon, MailIcon, ShieldCheckIcon } from '@heroicons/react/outline'; +import { ChipIcon, CodeIcon, MailIcon, ShieldCheckIcon } from '@heroicons/react/outline'; import { Route, Routes } from 'react-router-dom'; import tw from 'twin.macro'; diff --git a/resources/scripts/components/admin/users/UsersContainer.tsx b/resources/scripts/components/admin/users/UsersContainer.tsx index 0cb3398f7d..791f49e2ee 100644 --- a/resources/scripts/components/admin/users/UsersContainer.tsx +++ b/resources/scripts/components/admin/users/UsersContainer.tsx @@ -5,7 +5,7 @@ import { NavLink } from 'react-router-dom'; import { useGetUsers } from '@/api/admin/users'; import type { UUID } from '@/api/definitions'; import { Transition } from '@/components/elements/transitions'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import Checkbox from '@/components/elements/inputs/Checkbox'; import InputField from '@/components/elements/inputs/InputField'; import UserTableRow from '@/components/admin/users/UserTableRow'; diff --git a/resources/scripts/components/dashboard/forms/ConfigureTwoFactorForm.tsx b/resources/scripts/components/dashboard/forms/ConfigureTwoFactorForm.tsx index 059d1474e4..14f6beeaaf 100644 --- a/resources/scripts/components/dashboard/forms/ConfigureTwoFactorForm.tsx +++ b/resources/scripts/components/dashboard/forms/ConfigureTwoFactorForm.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'; import { useStoreState } from 'easy-peasy'; import { ApplicationStore } from '@/state'; import tw from 'twin.macro'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import SetupTOTPDialog from '@/components/dashboard/forms/SetupTOTPDialog'; import RecoveryTokensDialog from '@/components/dashboard/forms/RecoveryTokensDialog'; import DisableTOTPDialog from '@/components/dashboard/forms/DisableTOTPDialog'; diff --git a/resources/scripts/components/dashboard/forms/DisableTOTPDialog.tsx b/resources/scripts/components/dashboard/forms/DisableTOTPDialog.tsx index fe5039b794..fe623759ab 100644 --- a/resources/scripts/components/dashboard/forms/DisableTOTPDialog.tsx +++ b/resources/scripts/components/dashboard/forms/DisableTOTPDialog.tsx @@ -2,7 +2,7 @@ import { useContext, useEffect, useState } from 'react'; import * as React from 'react'; import asDialog from '@/hoc/asDialog'; import { Dialog, DialogWrapperContext } from '@/components/elements/dialog'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Input } from '@/components/elements/inputs'; import Tooltip from '@/components/elements/tooltip/Tooltip'; import disableAccountTwoFactor from '@/api/account/disableAccountTwoFactor'; diff --git a/resources/scripts/components/dashboard/forms/RecoveryTokensDialog.tsx b/resources/scripts/components/dashboard/forms/RecoveryTokensDialog.tsx index c5b090450a..f18debfec3 100644 --- a/resources/scripts/components/dashboard/forms/RecoveryTokensDialog.tsx +++ b/resources/scripts/components/dashboard/forms/RecoveryTokensDialog.tsx @@ -1,5 +1,5 @@ import { Dialog, DialogProps } from '@/components/elements/dialog'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import CopyOnClick from '@/components/elements/CopyOnClick'; import { Alert } from '@/components/elements/alert'; diff --git a/resources/scripts/components/dashboard/forms/SetupTOTPDialog.tsx b/resources/scripts/components/dashboard/forms/SetupTOTPDialog.tsx index f117a222c7..73e55bbb9f 100644 --- a/resources/scripts/components/dashboard/forms/SetupTOTPDialog.tsx +++ b/resources/scripts/components/dashboard/forms/SetupTOTPDialog.tsx @@ -5,7 +5,7 @@ import getTwoFactorTokenData, { TwoFactorTokenData } from '@/api/account/getTwoF import { useFlashKey } from '@/plugins/useFlash'; import tw from 'twin.macro'; import QRCode from 'qrcode.react'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import Spinner from '@/components/elements/Spinner'; import { Input } from '@/components/elements/inputs'; import CopyOnClick from '@/components/elements/CopyOnClick'; diff --git a/resources/scripts/components/dashboard/forms/UpdateEmailAddressForm.tsx b/resources/scripts/components/dashboard/forms/UpdateEmailAddressForm.tsx index 56632e1f4f..d5d0f33adb 100644 --- a/resources/scripts/components/dashboard/forms/UpdateEmailAddressForm.tsx +++ b/resources/scripts/components/dashboard/forms/UpdateEmailAddressForm.tsx @@ -7,7 +7,7 @@ import Field from '@/components/elements/Field'; import { httpErrorToHuman } from '@/api/http'; import { ApplicationStore } from '@/state'; import tw from 'twin.macro'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; interface Values { email: string; diff --git a/resources/scripts/components/dashboard/forms/UpdatePasswordForm.tsx b/resources/scripts/components/dashboard/forms/UpdatePasswordForm.tsx index 34dcd64e68..cd673534d8 100644 --- a/resources/scripts/components/dashboard/forms/UpdatePasswordForm.tsx +++ b/resources/scripts/components/dashboard/forms/UpdatePasswordForm.tsx @@ -8,7 +8,7 @@ import updateAccountPassword from '@/api/account/updateAccountPassword'; import { httpErrorToHuman } from '@/api/http'; import { ApplicationStore } from '@/state'; import tw from 'twin.macro'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; interface Values { current: string; diff --git a/resources/scripts/components/elements/activity/ActivityLogMetaButton.tsx b/resources/scripts/components/elements/activity/ActivityLogMetaButton.tsx index 6665b772fe..04d7e94219 100644 --- a/resources/scripts/components/elements/activity/ActivityLogMetaButton.tsx +++ b/resources/scripts/components/elements/activity/ActivityLogMetaButton.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; import { ClipboardListIcon } from '@heroicons/react/outline'; import { Dialog } from '@/components/elements/dialog'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; export default ({ meta }: { meta: Record }) => { const [open, setOpen] = useState(false); diff --git a/resources/scripts/components/elements/dialog/ConfirmationDialog.tsx b/resources/scripts/components/elements/dialog/ConfirmationDialog.tsx index 3f2cd7217c..195733b7e8 100644 --- a/resources/scripts/components/elements/dialog/ConfirmationDialog.tsx +++ b/resources/scripts/components/elements/dialog/ConfirmationDialog.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { Dialog, RenderDialogProps } from './'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; type ConfirmationProps = Omit & { children: React.ReactNode; diff --git a/resources/scripts/components/elements/dialog/Dialog.tsx b/resources/scripts/components/elements/dialog/Dialog.tsx index 6612d1871e..26563988d1 100644 --- a/resources/scripts/components/elements/dialog/Dialog.tsx +++ b/resources/scripts/components/elements/dialog/Dialog.tsx @@ -1,7 +1,7 @@ import { useRef, useState } from 'react'; import * as React from 'react'; import { Dialog as HDialog } from '@headlessui/react'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { XIcon } from '@heroicons/react/solid'; import { AnimatePresence, motion } from 'framer-motion'; import { DialogContext, IconPosition, RenderDialogProps, styles } from './'; diff --git a/resources/scripts/components/elements/table/PaginationFooter.tsx b/resources/scripts/components/elements/table/PaginationFooter.tsx index 43b5c9d48b..9240899687 100644 --- a/resources/scripts/components/elements/table/PaginationFooter.tsx +++ b/resources/scripts/components/elements/table/PaginationFooter.tsx @@ -1,6 +1,6 @@ import { PaginationDataSet } from '@/api/http'; import classNames from 'classnames'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { ChevronDoubleLeftIcon, ChevronDoubleRightIcon } from '@heroicons/react/solid'; interface Props { diff --git a/resources/scripts/components/server/console/PowerButtons.tsx b/resources/scripts/components/server/console/PowerButtons.tsx index 446fada52e..5fde279bb8 100644 --- a/resources/scripts/components/server/console/PowerButtons.tsx +++ b/resources/scripts/components/server/console/PowerButtons.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; import * as React from 'react'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import Can from '@/components/elements/Can'; import { ServerContext } from '@/state/server'; import { PowerAction } from '@/components/server/console/ServerConsoleContainer'; diff --git a/resources/scripts/components/server/files/FileEditContainer.tsx b/resources/scripts/components/server/files/FileEditContainer.tsx index 246cfa876a..d35c733ff7 100644 --- a/resources/scripts/components/server/files/FileEditContainer.tsx +++ b/resources/scripts/components/server/files/FileEditContainer.tsx @@ -9,7 +9,7 @@ import { httpErrorToHuman } from '@/api/http'; import getFileContents from '@/api/server/files/getFileContents'; import saveFileContents from '@/api/server/files/saveFileContents'; import FlashMessageRender from '@/components/FlashMessageRender'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import Can from '@/components/elements/Can'; import Select from '@/components/elements/Select'; import PageContentBlock from '@/components/elements/PageContentBlock'; diff --git a/resources/scripts/components/server/files/FileManagerContainer.tsx b/resources/scripts/components/server/files/FileManagerContainer.tsx index aa97904de9..e2242fd14a 100644 --- a/resources/scripts/components/server/files/FileManagerContainer.tsx +++ b/resources/scripts/components/server/files/FileManagerContainer.tsx @@ -11,7 +11,7 @@ import NewDirectoryButton from '@/components/server/files/NewDirectoryButton'; import { NavLink, useLocation } from 'react-router-dom'; import Can from '@/components/elements/Can'; import { ServerError } from '@/components/elements/ScreenBlock'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { ServerContext } from '@/state/server'; import useFileManagerSwr from '@/plugins/useFileManagerSwr'; // import FileManagerStatus from '@/components/server/files/FileManagerStatus'; diff --git a/resources/scripts/components/server/files/FileManagerStatus.tsx b/resources/scripts/components/server/files/FileManagerStatus.tsx index 1b065d031c..efb4fce66b 100644 --- a/resources/scripts/components/server/files/FileManagerStatus.tsx +++ b/resources/scripts/components/server/files/FileManagerStatus.tsx @@ -2,7 +2,7 @@ import { CloudUploadIcon, XIcon } from '@heroicons/react/solid'; import { useSignal } from '@preact/signals-react'; import { useContext, useEffect } from 'react'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Dialog, DialogWrapperContext } from '@/components/elements/dialog'; import Tooltip from '@/components/elements/tooltip/Tooltip'; import Code from '@/components/elements/Code'; diff --git a/resources/scripts/components/server/files/FileNameModal.tsx b/resources/scripts/components/server/files/FileNameModal.tsx index 1096c227b4..cd868d9758 100644 --- a/resources/scripts/components/server/files/FileNameModal.tsx +++ b/resources/scripts/components/server/files/FileNameModal.tsx @@ -4,7 +4,7 @@ import { join } from 'pathe'; import tw from 'twin.macro'; import { object, string } from 'yup'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import Field from '@/components/elements/Field'; import type { RequiredModalProps } from '@/components/elements/Modal'; import Modal from '@/components/elements/Modal'; diff --git a/resources/scripts/components/server/files/MassActionsBar.tsx b/resources/scripts/components/server/files/MassActionsBar.tsx index 59dae50823..fb8710036f 100644 --- a/resources/scripts/components/server/files/MassActionsBar.tsx +++ b/resources/scripts/components/server/files/MassActionsBar.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'; import compressFiles from '@/api/server/files/compressFiles'; import deleteFiles from '@/api/server/files/deleteFiles'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Dialog } from '@/components/elements/dialog'; import Portal from '@/components/elements/Portal'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; diff --git a/resources/scripts/components/server/files/NewDirectoryButton.tsx b/resources/scripts/components/server/files/NewDirectoryButton.tsx index f92c6f602d..3bf7fdc9a9 100644 --- a/resources/scripts/components/server/files/NewDirectoryButton.tsx +++ b/resources/scripts/components/server/files/NewDirectoryButton.tsx @@ -6,7 +6,7 @@ import { join } from 'pathe'; import { object, string } from 'yup'; import createDirectory from '@/api/server/files/createDirectory'; import tw from 'twin.macro'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { FileObject } from '@/api/server/files/loadDirectory'; import { useFlashKey } from '@/plugins/useFlash'; import useFileManagerSwr from '@/plugins/useFileManagerSwr'; diff --git a/resources/scripts/components/server/files/UploadButton.tsx b/resources/scripts/components/server/files/UploadButton.tsx index b3c6d94041..f21b16bf30 100644 --- a/resources/scripts/components/server/files/UploadButton.tsx +++ b/resources/scripts/components/server/files/UploadButton.tsx @@ -5,7 +5,7 @@ import { useEffect, useRef } from 'react'; import tw from 'twin.macro'; import getFileUploadUrl from '@/api/server/files/getFileUploadUrl'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { ModalMask } from '@/components/elements/Modal'; import Portal from '@/components/elements/Portal'; import FadeTransition from '@/components/elements/transitions/FadeTransition'; diff --git a/resources/scripts/components/server/network/AllocationRow.tsx b/resources/scripts/components/server/network/AllocationRow.tsx index 117910e90e..ac31d9def6 100644 --- a/resources/scripts/components/server/network/AllocationRow.tsx +++ b/resources/scripts/components/server/network/AllocationRow.tsx @@ -6,7 +6,7 @@ import { faNetworkWired } from '@fortawesome/free-solid-svg-icons'; import InputSpinner from '@/components/elements/InputSpinner'; import { Textarea } from '@/components/elements/Input'; import Can from '@/components/elements/Can'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import GreyRowBox from '@/components/elements/GreyRowBox'; import { Allocation } from '@/api/server/getServer'; import styled from 'styled-components'; diff --git a/resources/scripts/components/server/network/DeleteAllocationButton.tsx b/resources/scripts/components/server/network/DeleteAllocationButton.tsx index 5dd5b7c656..c112552d54 100644 --- a/resources/scripts/components/server/network/DeleteAllocationButton.tsx +++ b/resources/scripts/components/server/network/DeleteAllocationButton.tsx @@ -7,7 +7,7 @@ import deleteServerAllocation from '@/api/server/network/deleteServerAllocation' import getServerAllocations from '@/api/swr/getServerAllocations'; import { useFlashKey } from '@/plugins/useFlash'; import { Dialog } from '@/components/elements/dialog'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; interface Props { allocation: number; diff --git a/resources/scripts/components/server/schedules/DeleteScheduleButton.tsx b/resources/scripts/components/server/schedules/DeleteScheduleButton.tsx index d6b028556d..facada9e11 100644 --- a/resources/scripts/components/server/schedules/DeleteScheduleButton.tsx +++ b/resources/scripts/components/server/schedules/DeleteScheduleButton.tsx @@ -4,7 +4,7 @@ import { ServerContext } from '@/state/server'; import { Actions, useStoreActions } from 'easy-peasy'; import { ApplicationStore } from '@/state'; import { httpErrorToHuman } from '@/api/http'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Dialog } from '@/components/elements/dialog'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; diff --git a/resources/scripts/components/server/schedules/EditScheduleModal.tsx b/resources/scripts/components/server/schedules/EditScheduleModal.tsx index 8ab8536565..6a3e3b8b1e 100644 --- a/resources/scripts/components/server/schedules/EditScheduleModal.tsx +++ b/resources/scripts/components/server/schedules/EditScheduleModal.tsx @@ -9,7 +9,7 @@ import { httpErrorToHuman } from '@/api/http'; import FlashMessageRender from '@/components/FlashMessageRender'; import useFlash from '@/plugins/useFlash'; import tw from 'twin.macro'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import ModalContext from '@/context/ModalContext'; import asModal from '@/hoc/asModal'; import Switch from '@/components/elements/Switch'; diff --git a/resources/scripts/components/server/schedules/NewTaskButton.tsx b/resources/scripts/components/server/schedules/NewTaskButton.tsx index 186b0a2ff5..a732f46121 100644 --- a/resources/scripts/components/server/schedules/NewTaskButton.tsx +++ b/resources/scripts/components/server/schedules/NewTaskButton.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; import { Schedule } from '@/api/server/schedules/getServerSchedules'; import TaskDetailsModal from '@/components/server/schedules/TaskDetailsModal'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; interface Props { schedule: Schedule; diff --git a/resources/scripts/components/server/schedules/RunScheduleButton.tsx b/resources/scripts/components/server/schedules/RunScheduleButton.tsx index 7c1b4a69bc..be9d6c09fe 100644 --- a/resources/scripts/components/server/schedules/RunScheduleButton.tsx +++ b/resources/scripts/components/server/schedules/RunScheduleButton.tsx @@ -1,6 +1,6 @@ import { useCallback, useState } from 'react'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import triggerScheduleExecution from '@/api/server/schedules/triggerScheduleExecution'; import { ServerContext } from '@/state/server'; import useFlash from '@/plugins/useFlash'; diff --git a/resources/scripts/components/server/schedules/ScheduleContainer.tsx b/resources/scripts/components/server/schedules/ScheduleContainer.tsx index f644653e05..c8ba18fad2 100644 --- a/resources/scripts/components/server/schedules/ScheduleContainer.tsx +++ b/resources/scripts/components/server/schedules/ScheduleContainer.tsx @@ -10,7 +10,7 @@ import Can from '@/components/elements/Can'; import useFlash from '@/plugins/useFlash'; import tw from 'twin.macro'; import GreyRowBox from '@/components/elements/GreyRowBox'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import ServerContentBlock from '@/components/elements/ServerContentBlock'; import { Link } from 'react-router-dom'; diff --git a/resources/scripts/components/server/schedules/ScheduleEditContainer.tsx b/resources/scripts/components/server/schedules/ScheduleEditContainer.tsx index 840b3583e4..d7603f24a3 100644 --- a/resources/scripts/components/server/schedules/ScheduleEditContainer.tsx +++ b/resources/scripts/components/server/schedules/ScheduleEditContainer.tsx @@ -11,7 +11,7 @@ import useFlash from '@/plugins/useFlash'; import { ServerContext } from '@/state/server'; import PageContentBlock from '@/components/elements/PageContentBlock'; import tw from 'twin.macro'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import ScheduleTaskRow from '@/components/server/schedules/ScheduleTaskRow'; import isEqual from 'react-fast-compare'; import { format } from 'date-fns'; diff --git a/resources/scripts/components/server/schedules/TaskDetailsModal.tsx b/resources/scripts/components/server/schedules/TaskDetailsModal.tsx index a52e59a33b..e13e5fef41 100644 --- a/resources/scripts/components/server/schedules/TaskDetailsModal.tsx +++ b/resources/scripts/components/server/schedules/TaskDetailsModal.tsx @@ -12,7 +12,7 @@ import FormikFieldWrapper from '@/components/elements/FormikFieldWrapper'; import tw from 'twin.macro'; import Label from '@/components/elements/Label'; import { Textarea } from '@/components/elements/Input'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import Select from '@/components/elements/Select'; import ModalContext from '@/context/ModalContext'; import asModal from '@/hoc/asModal'; diff --git a/resources/scripts/components/server/settings/ReinstallServerBox.tsx b/resources/scripts/components/server/settings/ReinstallServerBox.tsx index 0a5a157232..5bf2073e42 100644 --- a/resources/scripts/components/server/settings/ReinstallServerBox.tsx +++ b/resources/scripts/components/server/settings/ReinstallServerBox.tsx @@ -6,7 +6,7 @@ import { Actions, useStoreActions } from 'easy-peasy'; import { ApplicationStore } from '@/state'; import { httpErrorToHuman } from '@/api/http'; import tw from 'twin.macro'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import { Dialog } from '@/components/elements/dialog'; export default () => { diff --git a/resources/scripts/components/server/settings/RenameServerBox.tsx b/resources/scripts/components/server/settings/RenameServerBox.tsx index 34d0508793..475b209c9f 100644 --- a/resources/scripts/components/server/settings/RenameServerBox.tsx +++ b/resources/scripts/components/server/settings/RenameServerBox.tsx @@ -8,7 +8,7 @@ import { object, string } from 'yup'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; import { ApplicationStore } from '@/state'; import { httpErrorToHuman } from '@/api/http'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; import tw from 'twin.macro'; import Label from '@/components/elements/Label'; import FormikFieldWrapper from '@/components/elements/FormikFieldWrapper'; diff --git a/resources/scripts/components/server/settings/SettingsContainer.tsx b/resources/scripts/components/server/settings/SettingsContainer.tsx index e86aa07d99..0277c1a136 100644 --- a/resources/scripts/components/server/settings/SettingsContainer.tsx +++ b/resources/scripts/components/server/settings/SettingsContainer.tsx @@ -12,7 +12,7 @@ import ServerContentBlock from '@/components/elements/ServerContentBlock'; import isEqual from 'react-fast-compare'; import CopyOnClick from '@/components/elements/CopyOnClick'; import { ip } from '@/lib/formatters'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; export default () => { const username = useStoreState(state => state.user.data!.username); diff --git a/resources/scripts/components/server/users/AddSubuserButton.tsx b/resources/scripts/components/server/users/AddSubuserButton.tsx index 42bfa6a4f7..561ef68c12 100644 --- a/resources/scripts/components/server/users/AddSubuserButton.tsx +++ b/resources/scripts/components/server/users/AddSubuserButton.tsx @@ -1,6 +1,6 @@ import { useState } from 'react'; import EditSubuserModal from '@/components/server/users/EditSubuserModal'; -import { Button } from '@/components/elements/button/index'; +import { Button } from '@/components/elements/button'; export default () => { const [visible, setVisible] = useState(false);