From 060bc3623971844ec68f4e3ce3c17986dcbb268c Mon Sep 17 00:00:00 2001 From: Aleksander <170264518+t-aleksander@users.noreply.github.com> Date: Mon, 16 Feb 2026 15:24:47 +0100 Subject: [PATCH 1/3] design fixes --- web/messages/en/common.json | 4 +- web/messages/en/initial_wizard.json | 202 +++++++++--------- web/src/pages/EdgeSetupPage/EdgeSetupPage.tsx | 15 +- .../EdgeSetupPage/useEdgeWizardStore.tsx | 10 +- .../GatewaySetupPage/GatewaySetupPage.tsx | 15 +- .../useGatewayWizardStore.tsx | 10 +- web/src/pages/SetupPage/SetupPage.tsx | 2 +- .../SetupPage/steps/SetupAdminUserStep.tsx | 2 +- .../steps/SetupCertificateAuthorityStep.tsx | 16 +- .../SetupCertificateAuthoritySummaryStep.tsx | 6 +- .../steps/SetupGeneralConfigStep.tsx | 2 +- .../wizard/WizardPage/WizardPage.tsx | 28 +-- .../components/wizard/WizardTop/WizardTop.tsx | 2 +- .../WizardWelcomePage/WizardWelcomePage.tsx | 55 +++-- .../wizard/WizardWelcomePage/style.scss | 145 ++++++++----- web/src/shared/components/wizard/types.ts | 3 +- 16 files changed, 300 insertions(+), 217 deletions(-) diff --git a/web/messages/en/common.json b/web/messages/en/common.json index 6c50778f35..2310dcb6fc 100644 --- a/web/messages/en/common.json +++ b/web/messages/en/common.json @@ -52,5 +52,7 @@ "search_users": "Find users", "select_users_all": "All users", "sucessfull_enrollment_email": "Enrollment email sent successfully", - "failed_to_start_enrollment": "Failed to start enrollment" + "failed_to_start_enrollment": "Failed to start enrollment", + "misc_recommended": "Recommended", + "footer_copyright": "Copyright © {year} Defguard Sp. z o.o." } diff --git a/web/messages/en/initial_wizard.json b/web/messages/en/initial_wizard.json index 9a1e6ca6e3..10306548f9 100644 --- a/web/messages/en/initial_wizard.json +++ b/web/messages/en/initial_wizard.json @@ -1,109 +1,113 @@ { - "$schema": "https://inlang.com/schema/inlang-message-format", - "initial_setup_wizard_title": "Initial Setup Wizard", - "initial_setup_wizard_subtitle": "This wizard will guide you through the initial configuration of your Defguard instance.", - "initial_setup_welcome_title": "Welcome to Defguard initial configuration wizard.", - "initial_setup_welcome_subtitle": "This wizard walks you through the steps to configure your VPN connection with a simple and intuitive setup process.", - "initial_setup_welcome_button_configure": "Configure Defguard", + "$schema": "https://inlang.com/schema/inlang-message-format", + "initial_setup_wizard_title": "Initial Setup Wizard", + "initial_setup_wizard_subtitle": "This wizard will guide you through the initial configuration of your Defguard instance.", + "initial_setup_welcome_title": "Welcome to Defguard initial configuration wizard.", + "initial_setup_welcome_subtitle": "This wizard walks you through the steps to configure your VPN connection with a simple and intuitive setup process.", + "initial_setup_welcome_button_configure": "Configure Defguard", "initial_setup_login_subtitle": "Please enter your admin credentials to continue the setup wizard.", - "initial_setup_step_admin_user_label": "Create Admin User", - "initial_setup_step_admin_user_description": "Manage core details and connection parameters for your VPN location.", - "initial_setup_step_general_config_label": "General Configuration", - "initial_setup_step_general_config_description": "Manage core details and connection parameters for your VPN location.", - "initial_setup_step_certificate_authority_label": "Certificate Authority", - "initial_setup_step_certificate_authority_description": "Securing component communication", - "initial_setup_step_certificate_authority_summary_label": "Certificate Authority Summary", - "initial_setup_step_certificate_authority_summary_description": "Securing component communication", - "initial_setup_step_edge_component_label": "Edge Component", - "initial_setup_step_edge_component_description": "Set up your VPN proxy quickly and ensure secure, optimized traffic flow for your users.", - "initial_setup_step_edge_adoption_label": "Edge Component Adoption", - "initial_setup_step_edge_adoption_description": "Review the system’s checks and see if any issues need attention before deployment.", - "initial_setup_step_confirmation_label": "Confirmation", - "initial_setup_step_confirmation_description": "Your configuration was successful. You’re all set.", + "initial_setup_step_admin_user_label": "Create Admin User", + "initial_setup_step_admin_user_description": "Manage core details and connection parameters for your VPN location.", + "initial_setup_step_general_config_label": "General Configuration", + "initial_setup_step_general_config_description": "Manage core details and connection parameters for your VPN location.", + "initial_setup_step_certificate_authority_label": "Certificate Authority", + "initial_setup_step_certificate_authority_description": "Securing component communication", + "initial_setup_step_certificate_authority_summary_label": "Certificate Authority Summary", + "initial_setup_step_certificate_authority_summary_description": "Securing component communication", + "initial_setup_step_edge_component_label": "Edge Component", + "initial_setup_step_edge_component_description": "Set up your VPN proxy quickly and ensure secure, optimized traffic flow for your users.", + "initial_setup_step_edge_adoption_label": "Edge Component Adoption", + "initial_setup_step_edge_adoption_description": "Review the system’s checks and see if any issues need attention before deployment.", + "initial_setup_step_confirmation_label": "Confirmation", + "initial_setup_step_confirmation_description": "Your configuration was successful. You’re all set.", - "initial_setup_admin_user_password_rule_required_label": "Field is required", - "initial_setup_admin_user_password_rule_required_message": "Password is required", - "initial_setup_admin_user_password_rule_min_label": "Minimum length of 8", - "initial_setup_admin_user_password_rule_min_message": "Password must be at least 8 characters", - "initial_setup_admin_user_password_rule_number_label": "At least one number required", - "initial_setup_admin_user_password_rule_number_message": "Password must contain at least one number", - "initial_setup_admin_user_password_rule_special_label": "At least one special character", - "initial_setup_admin_user_password_rule_special_message": "Password must contain at least one special character", - "initial_setup_admin_user_password_rule_lower_label": "At least one lowercase character", - "initial_setup_admin_user_password_rule_lower_message": "Password must contain at least one lowercase letter", - "initial_setup_admin_user_password_rule_upper_label": "At least one uppercase character", - "initial_setup_admin_user_password_rule_upper_message": "Password must contain at least one uppercase letter", - "initial_setup_admin_user_error_first_name_required": "First name is required", - "initial_setup_admin_user_error_last_name_required": "Last name is required", - "initial_setup_admin_user_error_username_min": "Username must be at least 3 characters", - "initial_setup_admin_user_error_email_invalid": "Invalid email address", - "initial_setup_admin_user_error_email_required": "Email is required", - "initial_setup_admin_user_label_first_name": "First Name", - "initial_setup_admin_user_label_last_name": "Last Name", - "initial_setup_admin_user_label_username": "Username", - "initial_setup_admin_user_label_email": "Email", - "initial_setup_admin_user_label_password": "Password", - "initial_setup_admin_user_error_create_failed": "Failed to create admin user. Please try again.", - "initial_setup_admin_user_password_checklist_title": "Your password must include:", + "initial_setup_admin_user_password_rule_required_label": "Field is required", + "initial_setup_admin_user_password_rule_required_message": "Password is required", + "initial_setup_admin_user_password_rule_min_label": "Minimum length of 8", + "initial_setup_admin_user_password_rule_min_message": "Password must be at least 8 characters", + "initial_setup_admin_user_password_rule_number_label": "At least one number required", + "initial_setup_admin_user_password_rule_number_message": "Password must contain at least one number", + "initial_setup_admin_user_password_rule_special_label": "At least one special character", + "initial_setup_admin_user_password_rule_special_message": "Password must contain at least one special character", + "initial_setup_admin_user_password_rule_lower_label": "At least one lowercase character", + "initial_setup_admin_user_password_rule_lower_message": "Password must contain at least one lowercase letter", + "initial_setup_admin_user_password_rule_upper_label": "At least one uppercase character", + "initial_setup_admin_user_password_rule_upper_message": "Password must contain at least one uppercase letter", + "initial_setup_admin_user_error_first_name_required": "First name is required", + "initial_setup_admin_user_error_last_name_required": "Last name is required", + "initial_setup_admin_user_error_username_min": "Username must be at least 3 characters", + "initial_setup_admin_user_error_email_invalid": "Invalid email address", + "initial_setup_admin_user_error_email_required": "Email is required", + "initial_setup_admin_user_label_first_name": "First Name", + "initial_setup_admin_user_label_last_name": "Last Name", + "initial_setup_admin_user_label_username": "Username", + "initial_setup_admin_user_label_email": "Email", + "initial_setup_admin_user_label_password": "Password", + "initial_setup_admin_user_error_create_failed": "Failed to create admin user. Please try again.", + "initial_setup_admin_user_password_checklist_title": "Your password must include:", - "initial_setup_general_config_error_invalid_url": "Invalid URL", - "initial_setup_general_config_error_defguard_url_required": "Defguard URL is required", - "initial_setup_general_config_error_admin_group_required": "Default admin group name is required", - "initial_setup_general_config_error_auth_period_min": "Authentication period must be at least 1 day", - "initial_setup_general_config_error_mfa_timeout_min": "MFA code timeout must be at least 60 seconds", - "initial_setup_general_config_label_defguard_url": "Defguard URL", - "initial_setup_general_config_label_admin_group": "Default Admin Group Name", - "initial_setup_general_config_label_auth_period": "Default Authentication Period (days)", - "initial_setup_general_config_label_mfa_timeout": "Default MFA Code Timeout (seconds)", - "initial_setup_general_config_label_public_proxy_url": "Public Edge component URL", - "initial_setup_general_config_error_save_failed": "Failed to create admin user. Please try again.", - "initial_setup_general_config_error_public_proxy_url_invalid": "Public Proxy URL must be a valid URL", - "initial_setup_general_config_error_public_proxy_url_required": "Public Proxy URL is required", + "initial_setup_general_config_error_invalid_url": "Invalid URL", + "initial_setup_general_config_error_defguard_url_required": "Defguard URL is required", + "initial_setup_general_config_error_admin_group_required": "Default admin group name is required", + "initial_setup_general_config_error_auth_period_min": "Authentication period must be at least 1 day", + "initial_setup_general_config_error_mfa_timeout_min": "MFA code timeout must be at least 60 seconds", + "initial_setup_general_config_label_defguard_url": "Defguard URL", + "initial_setup_general_config_label_admin_group": "Default Admin Group Name", + "initial_setup_general_config_label_auth_period": "Default Authentication Period (days)", + "initial_setup_general_config_label_mfa_timeout": "Default MFA Code Timeout (seconds)", + "initial_setup_general_config_label_public_proxy_url": "Public Edge component URL", + "initial_setup_general_config_error_save_failed": "Failed to create admin user. Please try again.", + "initial_setup_general_config_error_public_proxy_url_invalid": "Public Proxy URL must be a valid URL", + "initial_setup_general_config_error_public_proxy_url_required": "Public Proxy URL is required", - "initial_setup_ca_validity_one_year": "1 year", - "initial_setup_ca_validity_years": "{years} years", - "initial_setup_ca_error_common_name_required": "Common name is required", - "initial_setup_ca_error_email_invalid": "Invalid email address", - "initial_setup_ca_error_email_required": "Email is required", - "initial_setup_ca_error_validity_min": "Validity period must be at least 1 year", - "initial_setup_ca_error_cert_required": "Certificate file is required", - "initial_setup_ca_error_create_failed": "Failed to create CA. Please review the information and try again.", - "initial_setup_ca_error_upload_failed": "Failed to upload CA. Please ensure the certificate file is valid and try again.", - "initial_setup_ca_option_create_title": "Certificate Authority Setup", - "initial_setup_ca_option_create_description": "By choosing this option, Defguard will create its own certificate authority and automatically configure all components to use its certificates — no manual setup required.", - "initial_setup_ca_label_common_name": "Common Name", - "initial_setup_ca_placeholder_common_name": "Defguard Certificate Authority", - "initial_setup_ca_label_email": "Email", - "initial_setup_ca_placeholder_email": "email@example.com", - "initial_setup_ca_label_validity": "Validity Period", - "initial_setup_ca_option_use_own_title": "Use your own certificate authority", - "initial_setup_ca_option_use_own_description": "Upload your certificate authority certificate and Defguard will use it to issue and configure certificates for components.", + "initial_setup_ca_validity_one_year": "1 year", + "initial_setup_ca_validity_years": "{years} years", + "initial_setup_ca_error_common_name_required": "Common name is required", + "initial_setup_ca_error_email_invalid": "Invalid email address", + "initial_setup_ca_error_email_required": "Email is required", + "initial_setup_ca_error_validity_min": "Validity period must be at least 1 year", + "initial_setup_ca_error_cert_required": "Certificate file is required", + "initial_setup_ca_error_create_failed": "Failed to create CA. Please review the information and try again.", + "initial_setup_ca_error_upload_failed": "Failed to upload CA. Please ensure the certificate file is valid and try again.", + "initial_setup_ca_option_create_title": "Create a certificate authority & configure all Defguard components", + "initial_setup_ca_option_create_description": "By choosing this option, Defguard will create its own certificate authority and automatically configure all components to use its certificates — no manual setup required.", + "initial_setup_ca_label_common_name": "Common Name", + "initial_setup_ca_placeholder_common_name": "Defguard Certificate Authority", + "initial_setup_ca_label_email": "Email", + "initial_setup_ca_placeholder_email": "email@example.com", + "initial_setup_ca_label_validity": "Validity Period", + "initial_setup_ca_option_use_own_title": "Use your own certificate authority", + "initial_setup_ca_option_use_own_description": "Upload your certificate authority certificate and Defguard will use it to issue and configure certificates for components.", - "initial_setup_ca_generated_title": "Certificate Authority Generated", - "initial_setup_ca_generated_subtitle": "The system created all required certificate files, including the root certificate and private key. You can download these files and continue with the configuration.", - "initial_setup_ca_download_button": "Download CA certificate", - "initial_setup_ca_validated_title": "Certificate Authority Validated", - "initial_setup_ca_validated_subtitle": "Your uploaded Certificate Authority has been successfully validated. All required files were checked and confirmed as correct and ready for use. You can download the validated CA files if needed for your setup.", - "initial_setup_ca_info_title": "Information extracted from uploaded file", - "initial_setup_ca_info_label_common_name": "Common Name", - "initial_setup_ca_info_label_validity": "Validity", - "initial_setup_ca_validity_unknown": "—", - "initial_setup_ca_validity_less_than_year": "Less than a year", + "initial_setup_ca_generated_title": "Certificate Authority Generated", + "initial_setup_ca_generated_subtitle": "The system created all required certificate files, including the root certificate and private key. You can download these files and continue with the configuration.", + "initial_setup_ca_download_button": "Download CA certificate", + "initial_setup_ca_validated_title": "Certificate Authority Validated", + "initial_setup_ca_validated_subtitle": "Your uploaded Certificate Authority has been successfully validated. All required files were checked and confirmed as correct and ready for use. You can download the validated CA files if needed for your setup.", + "initial_setup_ca_info_title": "Information extracted from uploaded file", + "initial_setup_ca_info_label_common_name": "Common Name", + "initial_setup_ca_info_label_validity": "Validity", + "initial_setup_ca_validity_unknown": "—", + "initial_setup_ca_validity_less_than_year": "Less than a year", - "initial_setup_confirmation_error_finish_failed": "Failed to finish setup. Please try again.", - "initial_setup_confirmation_header": "General system settings are complete.", - "initial_setup_confirmation_lead": "You've completed the first stage of the setup. Defguard is almost ready to go.", - "initial_setup_confirmation_title": "In order to fully deploy Defguard you need:", - "initial_setup_confirmation_action_title": "Create first location.", - "initial_setup_confirmation_action_subtitle": "To organize users, manage access, track users activity and device monitoring.", - "initial_setup_confirmation_action_time": "Around 3 minutes", - "initial_setup_confirmation_footer": "Once you create your first location, the only step left will be to connect a gateway — and the system will be fully ready to use. This usually takes about n 10–15 minutes, depending on the complexity of your VPN configuration.", - "initial_setup_confirmation_cancel": "I'll do this later", - "initial_setup_confirmation_submit": "Create location now", + "initial_setup_confirmation_error_finish_failed": "Failed to finish setup. Please try again.", + "initial_setup_confirmation_header": "General system settings are complete.", + "initial_setup_confirmation_lead": "You've completed the first stage of the setup. Defguard is almost ready to go.", + "initial_setup_confirmation_title": "In order to fully deploy Defguard you need:", + "initial_setup_confirmation_action_title": "Create first location.", + "initial_setup_confirmation_action_subtitle": "To organize users, manage access, track users activity and device monitoring.", + "initial_setup_confirmation_action_time": "Around 3 minutes", + "initial_setup_confirmation_footer": "Once you create your first location, the only step left will be to connect a gateway — and the system will be fully ready to use. This usually takes about n 10–15 minutes, depending on the complexity of your VPN configuration.", + "initial_setup_confirmation_cancel": "I'll do this later", + "initial_setup_confirmation_submit": "Create location now", - "initial_setup_controls_back": "Back", - "initial_setup_controls_continue": "Continue", - "initial_setup_controls_next": "Next", - "initial_setup_controls_finish": "Finish" + "initial_setup_controls_back": "Back", + "initial_setup_controls_continue": "Continue", + "initial_setup_controls_finish": "Finish", + + "initial_setup_wizard_welcome_docs_description": "Before installation, we recommend reading our documentation to understand the system architecture and core components.", + "initial_setup_wizard_welcome_docs_alt": "Documentation", + "initial_setup_wizard_welcome_docs_link": "Read documentation", + "initial_setup_wizard_footer_support_text": "For help, contact our support team at" } diff --git a/web/src/pages/EdgeSetupPage/EdgeSetupPage.tsx b/web/src/pages/EdgeSetupPage/EdgeSetupPage.tsx index 4b76693f54..78e6b3c74d 100644 --- a/web/src/pages/EdgeSetupPage/EdgeSetupPage.tsx +++ b/web/src/pages/EdgeSetupPage/EdgeSetupPage.tsx @@ -20,8 +20,8 @@ import { useEdgeWizardStore } from './useEdgeWizardStore'; export const EdgeSetupPage = () => { const activeStep = useEdgeWizardStore((s) => s.activeStep); - const showWelcome = useEdgeWizardStore((s) => s.showWelcome); - const setShowWelcome = useEdgeWizardStore((s) => s.setShowWelcome); + const isOnWelcomePage = useEdgeWizardStore((s) => s.isOnWelcomePage); + const setisOnWelcomePage = useEdgeWizardStore((s) => s.setisOnWelcomePage); const navigate = useNavigate(); const stepsConfig = useMemo( @@ -70,7 +70,7 @@ export const EdgeSetupPage = () => { setShowWelcome(false)} + onClick={() => setisOnWelcomePage(false)} /> @@ -91,7 +91,7 @@ export const EdgeSetupPage = () => { title={m.edge_setup_page_title()} steps={stepsConfig} id="setup-wizard" - showWelcome={showWelcome} + isOnWelcomePage={isOnWelcomePage} welcomePageConfig={{ title: m.edge_setup_welcome_title(), subtitle: m.edge_setup_welcome_subtitle(), @@ -99,6 +99,13 @@ export const EdgeSetupPage = () => { docsLink: 'https://docs.defguard.net/edge-component/deployment', docsText: m.edge_setup_welcome_docs_text(), media: , + onClose: () => { + navigate({ to: '/vpn-overview', replace: true }).then(() => { + setTimeout(() => { + useEdgeWizardStore.getState().reset(); + }, 100); + }); + }, }} > {stepsComponents[activeStep]} diff --git a/web/src/pages/EdgeSetupPage/useEdgeWizardStore.tsx b/web/src/pages/EdgeSetupPage/useEdgeWizardStore.tsx index 44b5f09b05..5c3ffd901e 100644 --- a/web/src/pages/EdgeSetupPage/useEdgeWizardStore.tsx +++ b/web/src/pages/EdgeSetupPage/useEdgeWizardStore.tsx @@ -5,7 +5,7 @@ import { type EdgeAdoptionState, EdgeSetupStep, type EdgeSetupStepValue } from ' type StoreValues = { activeStep: EdgeSetupStepValue; - showWelcome: boolean; + isOnWelcomePage: boolean; common_name: string; ip_or_domain: string; grpc_port: number; @@ -16,7 +16,7 @@ type StoreMethods = { reset: () => void; start: (values?: Partial) => void; setActiveStep: (step: EdgeSetupStepValue) => void; - setShowWelcome: (show: boolean) => void; + setisOnWelcomePage: (show: boolean) => void; resetEdgeAdoptionState: () => void; setEdgeAdoptionState: (state: EdgeAdoptionState) => void; }; @@ -32,7 +32,7 @@ const edgeAdoptionStateDefaults: EdgeAdoptionState = { const defaults: StoreValues = { activeStep: EdgeSetupStep.EdgeComponent, - showWelcome: true, + isOnWelcomePage: true, common_name: '', ip_or_domain: '', grpc_port: 50051, @@ -51,7 +51,7 @@ export const useEdgeWizardStore = create()( }); }, setActiveStep: (step) => set({ activeStep: step }), - setShowWelcome: (show) => set({ showWelcome: show }), + setisOnWelcomePage: (show) => set({ isOnWelcomePage: show }), resetEdgeAdoptionState: () => set(() => ({ edgeAdoptionState: { ...edgeAdoptionStateDefaults }, @@ -69,7 +69,7 @@ export const useEdgeWizardStore = create()( 'reset', 'start', 'setActiveStep', - 'setShowWelcome', + 'setisOnWelcomePage', 'resetEdgeAdoptionState', 'setEdgeAdoptionState', ]), diff --git a/web/src/pages/GatewaySetupPage/GatewaySetupPage.tsx b/web/src/pages/GatewaySetupPage/GatewaySetupPage.tsx index 9478c5f9b1..cd1c07bf5b 100644 --- a/web/src/pages/GatewaySetupPage/GatewaySetupPage.tsx +++ b/web/src/pages/GatewaySetupPage/GatewaySetupPage.tsx @@ -17,8 +17,8 @@ import { useGatewayWizardStore } from './useGatewayWizardStore'; export const GatewaySetupPage = () => { const activeStep = useGatewayWizardStore((s) => s.activeStep); - const showWelcome = useGatewayWizardStore((s) => s.showWelcome); - const setShowWelcome = useGatewayWizardStore((s) => s.setShowWelcome); + const isOnWelcomePage = useGatewayWizardStore((s) => s.isOnWelcomePage); + const setisOnWelcomePage = useGatewayWizardStore((s) => s.setisOnWelcomePage); const navigate = useNavigate(); const stepsConfig = useMemo( @@ -61,7 +61,7 @@ export const GatewaySetupPage = () => { setShowWelcome(false)} + onClick={() => setisOnWelcomePage(false)} /> @@ -82,7 +82,7 @@ export const GatewaySetupPage = () => { title={m.gateway_setup_page_title()} steps={stepsConfig} id="setup-wizard" - showWelcome={showWelcome} + isOnWelcomePage={isOnWelcomePage} welcomePageConfig={{ title: m.gateway_setup_welcome_title(), subtitle: m.gateway_setup_welcome_subtitle(), @@ -90,6 +90,13 @@ export const GatewaySetupPage = () => { docsLink: 'https://docs.defguard.net/edge-component/deployment', docsText: m.gateway_setup_welcome_docs_text(), media: , + onClose: () => { + navigate({ to: '/locations', replace: true }).then(() => { + setTimeout(() => { + useGatewayWizardStore.getState().reset(); + }, 100); + }); + }, }} > {stepsComponents[activeStep]} diff --git a/web/src/pages/GatewaySetupPage/useGatewayWizardStore.tsx b/web/src/pages/GatewaySetupPage/useGatewayWizardStore.tsx index 792b62d59c..c884077696 100644 --- a/web/src/pages/GatewaySetupPage/useGatewayWizardStore.tsx +++ b/web/src/pages/GatewaySetupPage/useGatewayWizardStore.tsx @@ -15,7 +15,7 @@ type GatewayAdoptionState = { type StoreValues = { activeStep: GatewaySetupStepValue; - showWelcome: boolean; + isOnWelcomePage: boolean; common_name: string; ip_or_domain: string; grpc_port: number; @@ -27,7 +27,7 @@ type StoreMethods = { reset: () => void; start: (values?: Partial) => void; setActiveStep: (step: GatewaySetupStepValue) => void; - setShowWelcome: (show: boolean) => void; + setisOnWelcomePage: (show: boolean) => void; resetGatewayAdoptionState: () => void; setGatewayAdoptionState: (state: GatewayAdoptionState) => void; }; @@ -43,7 +43,7 @@ const gatewayAdoptionStateDefaults: GatewayAdoptionState = { const defaults: StoreValues = { activeStep: GatewaySetupStep.GatewayComponent, - showWelcome: true, + isOnWelcomePage: true, common_name: '', ip_or_domain: '', grpc_port: 50066, @@ -63,7 +63,7 @@ export const useGatewayWizardStore = create()( }); }, setActiveStep: (step) => set({ activeStep: step }), - setShowWelcome: (show) => set({ showWelcome: show }), + setisOnWelcomePage: (show) => set({ isOnWelcomePage: show }), resetGatewayAdoptionState: () => set(() => ({ gatewayAdoptionState: { ...gatewayAdoptionStateDefaults }, @@ -81,7 +81,7 @@ export const useGatewayWizardStore = create()( 'reset', 'start', 'setActiveStep', - 'setShowWelcome', + 'setisOnWelcomePage', 'resetEdgeAdoptionState', 'setEdgeAdoptionState', ]), diff --git a/web/src/pages/SetupPage/SetupPage.tsx b/web/src/pages/SetupPage/SetupPage.tsx index 36b0d5787c..fb87f5bb8a 100644 --- a/web/src/pages/SetupPage/SetupPage.tsx +++ b/web/src/pages/SetupPage/SetupPage.tsx @@ -117,7 +117,7 @@ export const SetupPage = () => { title={m.initial_setup_wizard_title()} steps={stepsConfig} id="setup-wizard" - showWelcome={isOnWelcomePage} + isOnWelcomePage={isOnWelcomePage} welcomePageConfig={{ title: m.initial_setup_welcome_title(), subtitle: m.initial_setup_welcome_subtitle(), diff --git a/web/src/pages/SetupPage/steps/SetupAdminUserStep.tsx b/web/src/pages/SetupPage/steps/SetupAdminUserStep.tsx index 6cc9475710..0a163f4b29 100644 --- a/web/src/pages/SetupPage/steps/SetupAdminUserStep.tsx +++ b/web/src/pages/SetupPage/steps/SetupAdminUserStep.tsx @@ -229,7 +229,7 @@ export const SetupAdminUserStep = () => { [] = [ { key: 2, label: m.initial_setup_ca_validity_years({ years: 2 }), value: 2 }, { key: 3, label: m.initial_setup_ca_validity_years({ years: 3 }), value: 3 }, { key: 5, label: m.initial_setup_ca_validity_years({ years: 5 }), value: 5 }, - { key: 10, label: m.initial_setup_ca_validity_years({ years: 10 }), value: 10 }, + { + key: 10, + label: m.initial_setup_ca_validity_years({ years: 10 }), + value: 10, + }, ]; type CreateCAFormFields = CreateCAStoreValues; @@ -250,9 +255,12 @@ export const SetupCertificateAuthorityStep = () => { value={caOption === CAOption.Create} onClick={() => setCAOption(CAOption.Create)} content={m.initial_setup_ca_option_create_description()} + badge={{ + text: m.misc_recommended(), + variant: BadgeVariant.Success, + }} > - {caOption === CAOption.Create && } @@ -270,13 +278,13 @@ export const SetupCertificateAuthorityStep = () => { { {m.initial_setup_ca_info_label_common_name()} {commonName} - {m.initial_setup_ca_info_label_validity()} @@ -115,7 +114,10 @@ export const SetupCertificateAuthoritySummaryStep = () => { onClick: handleBack, variant: 'outlined', }} - submitProps={{ text: m.initial_setup_controls_next(), onClick: handleNext }} + submitProps={{ + text: m.initial_setup_controls_continue(), + onClick: handleNext, + }} /> ); diff --git a/web/src/pages/SetupPage/steps/SetupGeneralConfigStep.tsx b/web/src/pages/SetupPage/steps/SetupGeneralConfigStep.tsx index 99aa415dc4..dbfed75228 100644 --- a/web/src/pages/SetupPage/steps/SetupGeneralConfigStep.tsx +++ b/web/src/pages/SetupPage/steps/SetupGeneralConfigStep.tsx @@ -167,7 +167,7 @@ export const SetupGeneralConfigStep = () => { { const activeStep = steps[activeStepId]; @@ -60,14 +60,14 @@ export const WizardPage = ({ return ( - - - - - {welcomePageConfig && showWelcome ? ( - - ) : ( - <> + {isPresent(welcomePageConfig) && isOnWelcomePage ? ( + + ) : ( + <> + + + + {title} @@ -85,11 +85,11 @@ export const WizardPage = ({ {children} - > - )} - - - + + + + > + )} ); }; diff --git a/web/src/shared/components/wizard/WizardTop/WizardTop.tsx b/web/src/shared/components/wizard/WizardTop/WizardTop.tsx index 3696618f11..77b0320de8 100644 --- a/web/src/shared/components/wizard/WizardTop/WizardTop.tsx +++ b/web/src/shared/components/wizard/WizardTop/WizardTop.tsx @@ -9,7 +9,7 @@ type Props = { export const WizardTop = ({ onClick }: Props) => { return ( - + {isPresent(onClick) && } diff --git a/web/src/shared/components/wizard/WizardWelcomePage/WizardWelcomePage.tsx b/web/src/shared/components/wizard/WizardWelcomePage/WizardWelcomePage.tsx index d701461e65..8f3a3df01f 100644 --- a/web/src/shared/components/wizard/WizardWelcomePage/WizardWelcomePage.tsx +++ b/web/src/shared/components/wizard/WizardWelcomePage/WizardWelcomePage.tsx @@ -1,9 +1,12 @@ import './style.scss'; +import dayjs from 'dayjs'; +import { m } from '../../../../paraglide/messages'; import { AppText } from '../../../defguard-ui/components/AppText/AppText'; import { ExternalLink } from '../../../defguard-ui/components/ExternalLink/ExternalLink'; import { SizedBox } from '../../../defguard-ui/components/SizedBox/SizedBox'; import { TextStyle, ThemeSpacing, ThemeVariable } from '../../../defguard-ui/types'; import type { WizardWelcomePageConfig } from '../types'; +import { WizardTop } from '../WizardTop/WizardTop'; import fileIcon from './assets/file_icon.png'; type Props = WizardWelcomePageConfig; @@ -14,32 +17,48 @@ export const WizardWelcomePage = ({ content, media, docsLink = 'https://docs.defguard.net/', - docsText = 'Before installation, we recommend reading our documentation to understand the system architecture and core components.', + docsText = m.initial_setup_wizard_welcome_docs_description(), + onClose, }: Props) => { return ( - - - {title} - - - {subtitle} - - {content} - - - - + + + + + + {title} + + + {subtitle} + + {content} - - {docsText} - - {`Read documentation`} + + + + + + {docsText} + + + {m.initial_setup_wizard_welcome_docs_link()} + + + {media} + + + {m.footer_copyright({ year: dayjs().year() })} + + {m.initial_setup_wizard_footer_support_text()}{' '} + + support@defguard.net + + - {media} ); }; diff --git a/web/src/shared/components/wizard/WizardWelcomePage/style.scss b/web/src/shared/components/wizard/WizardWelcomePage/style.scss index ca839562ee..34b46bf26c 100644 --- a/web/src/shared/components/wizard/WizardWelcomePage/style.scss +++ b/web/src/shared/components/wizard/WizardWelcomePage/style.scss @@ -1,81 +1,114 @@ /* stylelint-disable no-descending-specificity */ .wizard-welcome-page { display: grid; - grid-template-columns: 667fr 443fr; - border-radius: var(--radius-xxl); - background-color: var(--bg-default); - box-shadow: var(--menu-shadow); - overflow: hidden; - width: 100%; - max-width: 1110px; - - .main-track { - box-sizing: border-box; - padding: var(--spacing-4xl); - display: flex; - flex-direction: column; - justify-content: space-between; + grid-template-rows: auto auto auto 1fr auto; + justify-items: center; + min-height: 100vh; - .top-content { - h1 { - font: var(--t-title-h3); - color: var(--fg-default); - } - } + & > .wizard-top:not(.closeable) { + margin-top: 28px; + border-bottom: 0; } - .media-track { - height: 100%; - width: 100%; - max-width: 100%; - position: relative; + background-color: var(--bg-muted); + + & > .content { + display: grid; + grid-template-columns: 667fr 443fr; + border-radius: var(--radius-xxl); + background-color: var(--bg-default); + box-shadow: var(--menu-shadow); overflow: hidden; - display: flex; - align-items: center; - justify-content: center; + width: 100%; + max-width: 1110px; - img { - width: 100%; - height: 100%; - object-fit: cover; - } + .main-track { + box-sizing: border-box; + padding: var(--spacing-4xl); + display: flex; + flex-direction: column; + justify-content: space-between; - video { - width: 100%; - min-height: 657px; - min-width: 443px; - object-fit: cover; + .top-content { + h1 { + font: var(--t-title-h3); + color: var(--fg-default); + } + } } - } - #docs-card { - display: grid; - grid-template-columns: 54px 1fr; - background-color: transparent; - border: var(--border-1) solid var(--border-disabled); - border-radius: var(--radius-lg); - padding: var(--spacing-md); - column-gap: var(--spacing-2xl); - - .image-track { + .media-track { + height: 100%; width: 100%; max-width: 100%; + position: relative; overflow: hidden; + display: flex; + align-items: center; + justify-content: center; img { width: 100%; + height: 100%; + object-fit: cover; + } + + video { + width: 100%; + min-height: 657px; + min-width: 443px; + object-fit: cover; } } - .content { - display: flex; - flex-flow: column; - row-gap: var(--spacing-sm); + #docs-card { + display: grid; + grid-template-columns: 54px 1fr; + background-color: transparent; + border: var(--border-1) solid var(--border-disabled); + border-radius: var(--radius-lg); + padding: var(--spacing-md); + column-gap: var(--spacing-2xl); + + .image-track { + width: 100%; + max-width: 100%; + overflow: hidden; + + img { + width: 100%; + } + } + + .content { + display: flex; + flex-flow: column; + row-gap: var(--spacing-sm); - p { - font: var(--t-body-sm-400); - color: var(--fg-muted); + p { + font: var(--t-body-sm-400); + color: var(--fg-muted); + } } } } + + & > .footer { + grid-row: 5; + margin-bottom: 24px; + display: flex; + justify-content: space-between; + max-width: 1110px; + width: 100%; + + & > p, + a { + color: var(--fg-muted); + font: var(--t-body-xs-400); + } + + .mail { + color: var(--fg-action); + } + } } diff --git a/web/src/shared/components/wizard/types.ts b/web/src/shared/components/wizard/types.ts index ab7ea791b9..bb9d6a5e6c 100644 --- a/web/src/shared/components/wizard/types.ts +++ b/web/src/shared/components/wizard/types.ts @@ -5,7 +5,7 @@ export interface WizardPageConfig { steps: WizardPageStepsConfig; relatedDocs?: WizardDocsLink[]; welcomePageConfig?: WizardWelcomePageConfig; - showWelcome?: boolean; + isOnWelcomePage?: boolean; } export interface WizardDocsLink { @@ -28,6 +28,7 @@ export interface WizardWelcomePageConfig { media: React.ReactNode; docsLink?: string; docsText?: string; + onClose?: () => void; } export type WizardPageStepsConfig = Record; From fc491d6c8e28112dedf6d21ee516b5c5402d7278 Mon Sep 17 00:00:00 2001 From: Aleksander <170264518+t-aleksander@users.noreply.github.com> Date: Mon, 16 Feb 2026 15:28:26 +0100 Subject: [PATCH 2/3] update defguard ui --- web/src/shared/defguard-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/shared/defguard-ui b/web/src/shared/defguard-ui index 410b8fa3cc..d141d65123 160000 --- a/web/src/shared/defguard-ui +++ b/web/src/shared/defguard-ui @@ -1 +1 @@ -Subproject commit 410b8fa3cc154d82282dad8dbb3ef2cb9d99f064 +Subproject commit d141d651230573556ec18d57bdbbd9228fd8dd76 From 07a7204e389f01945eb4fcbdcaa97496b3b158a3 Mon Sep 17 00:00:00 2001 From: Aleksander <170264518+t-aleksander@users.noreply.github.com> Date: Mon, 16 Feb 2026 16:25:41 +0100 Subject: [PATCH 3/3] update ui --- web/src/shared/defguard-ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/shared/defguard-ui b/web/src/shared/defguard-ui index d141d65123..aa169c5e3e 160000 --- a/web/src/shared/defguard-ui +++ b/web/src/shared/defguard-ui @@ -1 +1 @@ -Subproject commit d141d651230573556ec18d57bdbbd9228fd8dd76 +Subproject commit aa169c5e3e4e09d2cc518d931de084e2b2a8b41f
{title}
{docsText}
{m.footer_copyright({ year: dayjs().year() })}
+ {m.initial_setup_wizard_footer_support_text()}{' '} + + support@defguard.net + +