Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/defguard_setup/src/handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ pub mod auto_wizard;
pub mod initial_wizard;
pub mod migration;
pub mod session_info;
pub mod version;
14 changes: 14 additions & 0 deletions crates/defguard_setup/src/handlers/version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use axum::{Extension, Json};
use semver::Version;
use serde::Serialize;

#[derive(Serialize)]
pub struct VersionResponse {
version: String,
}

pub async fn get_version(Extension(version): Extension<Version>) -> Json<VersionResponse> {
Json(VersionResponse {
version: version.to_string(),
})
}
6 changes: 2 additions & 4 deletions crates/defguard_setup/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ use defguard_core::{
grpc::GatewayEvent,
handle_404,
handlers::{
app_info::get_app_info,
auth::{
authenticate, email_mfa_code, email_mfa_enable, email_mfa_init, logout, mfa_disable,
mfa_enable, recovery_code, request_email_mfa_code, totp_code, totp_enable, totp_secret,
Expand All @@ -30,7 +29,6 @@ use defguard_core::{
resource_display::get_locations_display,
session_info::get_session_info,
settings::{get_settings, get_settings_essentials, patch_settings},
user::me,
wireguard::{count_networks, list_networks},
},
health_check,
Expand All @@ -52,6 +50,7 @@ use crate::handlers::{
finish_setup, get_migration_state, migration_set_external_url_settings,
migration_set_internal_url_settings, update_migration_state,
},
version::get_version,
};

/// FIXME: This is a workaround which enables us to reuse the same API handlers
Expand Down Expand Up @@ -104,8 +103,7 @@ pub fn build_migration_webapp(
"/api/v1",
Router::new()
.route("/health", get(health_check))
.route("/info", get(get_app_info))
.route("/me", get(me))
.route("/version", get(get_version))
.route("/session-info", get(get_session_info))
.route("/settings_essentials", get(get_settings_essentials))
.route("/settings", get(get_settings).patch(patch_settings))
Expand Down
2 changes: 2 additions & 0 deletions crates/defguard_setup/src/setup_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ use crate::handlers::{
setup_login, setup_session, upload_ca,
},
session_info::get_session_info,
version::get_version,
};

pub fn build_setup_webapp(
Expand All @@ -54,6 +55,7 @@ pub fn build_setup_webapp(
"/api/v1",
Router::<()>::new()
.route("/health", get(health_check))
.route("/version", get(get_version))
.route("/settings_essentials", get(get_settings_essentials))
.route("/session-info", get(get_session_info))
.route("/network/display", get(get_locations_display))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ export const AutoAdoptionSetupPage = () => {
subtitle={m.initial_setup_auto_adoption_wizard_subtitle()}
title={m.initial_setup_auto_adoption_wizard_title()}
steps={stepsConfig}
videoGuidePlacementKey="autoAdoptionWizard"
isOnWelcomePage={!isAutoAdoptionFlowStarted}
welcomePageConfig={{
title: m.initial_setup_auto_adoption_welcome_title(),
Expand Down
1 change: 1 addition & 0 deletions web/src/pages/SetupPage/initial/SetupPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export const SetupPage = () => {
title={m.initial_setup_wizard_title()}
steps={stepsConfig}
id="setup-wizard"
videoGuidePlacementKey="initialSetupWizard"
isOnWelcomePage={isOnWelcomePage}
welcomePageConfig={{
title: m.initial_setup_welcome_title(),
Expand Down
14 changes: 1 addition & 13 deletions web/src/routes/_wizard/migration/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,14 @@ import { MigrationWizardPage } from '../../../pages/MigrationWizardPage/Migratio
import { useMigrationWizardStore } from '../../../pages/MigrationWizardPage/store/useMigrationWizardStore';
import { ActiveWizard } from '../../../shared/api/types';
import { isPresent } from '../../../shared/defguard-ui/utils/isPresent';
import { AppInfoProvider } from '../../../shared/providers/AppInfoProvider';
import { AppUserProvider } from '../../../shared/providers/AppUserProvider';
import {
getMigrationStateQueryOptions,
getSessionInfoQueryOptions,
getSettingsQueryOptions,
} from '../../../shared/query';

const MigrationWizardRoute = () => {
return (
<AppUserProvider>
<AppInfoProvider>
<MigrationWizardPage />
</AppInfoProvider>
</AppUserProvider>
);
};

export const Route = createFileRoute('/_wizard/migration/')({
component: MigrationWizardRoute,
component: MigrationWizardPage,
pendingComponent: AppLoaderPage,
beforeLoad: async ({ context }) => {
const sessionInfo = (await context.queryClient.fetchQuery(getSessionInfoQueryOptions))
Expand Down
3 changes: 2 additions & 1 deletion web/src/shared/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ import type {
UserProfileResponse,
ValidateDeviceIpsRequest,
ValidateIpAssignmentRequest,
VersionResponse,
WebauthnLoginStartResponse,
WebauthnRegisterFinishRequest,
WebauthnRegisterStartResponse,
Expand Down Expand Up @@ -191,6 +192,7 @@ const api = {
},
app: {
info: () => client.get<ApplicationInfo>('/info'),
version: () => client.get<VersionResponse>('/version'),
updates: () => client.get<UpdateInfo | null>('/updates'),
},
user: {
Expand Down Expand Up @@ -565,7 +567,6 @@ const api = {
getSessionInfo: () => client.get<SessionInfo>(`/session-info`),
getActivityLog: (data?: ActivityLogRequestParams) =>
fetchPage<ActivityLogEvent>(`/activity_log`, data),
info: () => client.get<ApplicationInfo>('/info'),
getLicenseInfo: () => client.get<LicenseInfoResponse>(`/enterprise_info`),
support: {
getSupportData: () => client.get<object>('/support/configuration'),
Expand Down
4 changes: 4 additions & 0 deletions web/src/shared/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,10 @@ export interface ApplicationInfo {
ldap_info: LdapInfo;
}

export interface VersionResponse {
version: string;
}

export interface UpdateInfo {
version: string;
release_date: string;
Expand Down
2 changes: 1 addition & 1 deletion web/src/shared/components/wizard/WizardPage/WizardPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const WizardPage = ({
...containerProps
}: Props) => {
const activeStep = steps[activeStepId];
const videoGuide = useWizardVideoGuidePlacement(videoGuidePlacementKey);
const videoGuide = useWizardVideoGuidePlacement(videoGuidePlacementKey, activeStepId);

const visibleSteps = useMemo(
() =>
Expand Down
107 changes: 67 additions & 40 deletions web/src/shared/components/wizard/WizardVideoGuide/WizardVideoGuide.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,55 +18,82 @@ type Props = {

export const WizardVideoGuide = ({ videoGuide }: Props) => {
const [isVideoOpen, setIsVideoOpen] = useState(false);
const video = videoGuide.video;
const hasDocs = Boolean(videoGuide.docs?.length);

if (!video && !hasDocs) {
return null;
}

return (
<>
<div id="wizard-video-support">
<SizedBox height={ThemeSpacing.Xl5} />

<div className="support-header">
<Helper size={16}>{m.migration_wizard_support_video_guide_helper()}</Helper>
<AppText font={TextStyle.TBodySm500} color={ThemeVariable.FgFaded}>
{m.migration_wizard_support_video_guide()}
</AppText>
</div>
<SizedBox height={ThemeSpacing.Md} />
<button type="button" className="video-card" onClick={() => setIsVideoOpen(true)}>
<Thumbnail
url={`https://img.youtube.com/vi/${videoGuide.youtubeVideoId}/hqdefault.jpg`}
title={videoGuide.title}
/>
<div className="video-info">
<AppText
className="video-title"
font={TextStyle.TBodySm400}
color={ThemeVariable.FgFaded}
{video && (
<>
<div className="support-header">
<Helper size={16}>{m.migration_wizard_support_video_guide_helper()}</Helper>
<AppText font={TextStyle.TBodySm500} color={ThemeVariable.FgFaded}>
{m.migration_wizard_support_video_guide()}
</AppText>
</div>
<SizedBox height={ThemeSpacing.Md} />
<button
type="button"
className="video-card"
onClick={() => setIsVideoOpen(true)}
>
{videoGuide.title}
</AppText>
</div>
</button>
<Divider spacing={ThemeSpacing.Xl2} />
<div className="support-header">
<Icon icon="file" size={16} staticColor={ThemeVariable.FgMuted} />
<AppText font={TextStyle.TBodySm500} color={ThemeVariable.FgFaded}>
{m.migration_wizard_support_related_documentation()}
</AppText>
</div>
<SizedBox height={ThemeSpacing.Md} />
<div className="doc-card">
<ExternalLink href={videoGuide.docsUrl} target="_blank" rel="noreferrer">
{videoGuide.docsTitle}
</ExternalLink>
</div>
<Thumbnail
url={`https://img.youtube.com/vi/${video?.youtubeVideoId}/hqdefault.jpg`}
title={video?.title ?? ''}
/>
<div className="video-info">
<AppText
className="video-title"
font={TextStyle.TBodySm400}
color={ThemeVariable.FgFaded}
>
{video?.title}
</AppText>
</div>
</button>
</>
)}

{video && hasDocs && <Divider spacing={ThemeSpacing.Xl2} />}

{hasDocs && (
<>
<div className="support-header">
<Icon icon="file" size={16} staticColor={ThemeVariable.FgMuted} />
<AppText font={TextStyle.TBodySm500} color={ThemeVariable.FgFaded}>
{m.migration_wizard_support_related_documentation()}
</AppText>
</div>
<SizedBox height={ThemeSpacing.Md} />
<div className="doc-card">
{videoGuide.docs?.map((doc) => (
<div className="doc-link-row" key={`${doc.docsTitle}-${doc.docsUrl}`}>
<ExternalLink href={doc.docsUrl} target="_blank" rel="noreferrer">
{doc.docsTitle}
</ExternalLink>
</div>
))}
</div>
</>
)}
</div>
<SizedBox height={ThemeSpacing.Xl5} />

<VideoOverlay
video={videoGuide}
isOpen={isVideoOpen}
onClose={() => setIsVideoOpen(false)}
afterClose={() => setIsVideoOpen(false)}
/>
{video && (
<VideoOverlay
video={video}
isOpen={isVideoOpen}
onClose={() => setIsVideoOpen(false)}
afterClose={() => setIsVideoOpen(false)}
/>
)}
</>
);
};
7 changes: 7 additions & 0 deletions web/src/shared/components/wizard/WizardVideoGuide/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,20 @@
}

.doc-card {
display: flex;
flex-direction: column;
padding: var(--spacing-lg);
border: var(--border-1) solid var(--border-default);
border-radius: var(--radius-lg);
background-color: var(--bg-default);
gap: var(--spacing-md);

.external-link {
font: var(--t-body-sm-400);
}
}

.doc-link-row {
display: flex;
}
}
4 changes: 2 additions & 2 deletions web/src/shared/components/wizard/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { HTMLProps } from 'react';
export interface WizardPageConfig {
title: string;
subtitle: string;
activeStep: string | number;
activeStep: string;
steps: WizardPageStepsConfig;
videoGuidePlacementKey?: string;
relatedDocs?: WizardDocsLink[];
Expand All @@ -17,7 +17,7 @@ export interface WizardDocsLink {
}

export interface WizardPageStep {
id: number | string;
id: string;
order: number;
label: string;
description?: string;
Expand Down
9 changes: 9 additions & 0 deletions web/src/shared/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,15 @@ export const getSessionInfoQueryOptions = queryOptions({
refetchOnWindowFocus: false,
});

export const getVersionQueryOptions = queryOptions({
queryFn: api.app.version,
queryKey: ['version'],
select: (resp) => resp.data.version,
refetchOnMount: true,
refetchOnReconnect: true,
refetchOnWindowFocus: false,
});

export const getSettingsEssentialsQueryOptions = queryOptions({
queryFn: api.settings.getSettingsEssentials,
queryKey: ['settings_essentials'],
Expand Down
Loading
Loading