mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-04-16 23:08:38 +02:00
reduce bloat, change translations and change onboarding download for desktop file to show a selector button to allow you to select different OS version, if we guessed wrong
This commit is contained in:
@@ -5062,7 +5062,7 @@
|
||||
},
|
||||
"welcomeSlide": {
|
||||
"title": "Welcome to Stirling",
|
||||
"body": "Stirling PDF is now ready for teams of all sizes.<br />This update includes a new layout, powerful new admin capabilities, and our most requested feature - <strong>Edit Text</strong>."
|
||||
"body": "Stirling PDF is now ready for teams of all sizes. This update includes a new layout, powerful new admin capabilities, and our most requested feature - <strong>Edit Text</strong>."
|
||||
},
|
||||
"allTools": "This is the <strong>Tools</strong> panel, where you can browse and select from all available PDF tools.",
|
||||
"selectCropTool": "Let's select the <strong>Crop</strong> tool to demonstrate how to use one of the tools.",
|
||||
@@ -5096,6 +5096,17 @@
|
||||
"overLimitBody": "Our licensing permits up to <strong>{{freeTierLimit}}</strong> users for free per server. You have <strong>{{overLimitUserCopy}}</strong> Stirling users. To continue uninterrupted, upgrade to the Stirling Server plan - <strong>unlimited seats</strong>, PDF text editing, and full admin control for $99/server/mo.",
|
||||
"freeBody": "Our <strong>Open-Core</strong> licensing permits up to <strong>{{freeTierLimit}}</strong> users for free per server. To scale uninterrupted and get early access to our new <strong>PDF text editing tool</strong>, we recommend the Stirling Server plan - full editing and <strong>unlimited seats</strong> for $99/server/mo."
|
||||
},
|
||||
"desktopInstall": {
|
||||
"title": "Download",
|
||||
"titleWithOs": "Download for {{osLabel}}",
|
||||
"body": "Stirling works best as a desktop app. You can use it offline, access documents faster, and make edits locally on your computer."
|
||||
},
|
||||
"planOverview": {
|
||||
"adminTitle": "Admin Overview",
|
||||
"userTitle": "Plan Overview",
|
||||
"adminBody": "As an admin, you can manage users, configure settings, and monitor server health. The first <strong>{{freeTierLimit}}</strong> people on your server get to use Stirling free of charge.",
|
||||
"userBody": "Invite teammates, assign roles, and keep your documents organized in one secure workspace. Enable login mode whenever you're ready to grow beyond solo use."
|
||||
},
|
||||
"securityCheck": {
|
||||
"message": "The application has undergone significant changes recently. Your server admin's attention may be required. Please confirm your role to continue."
|
||||
}
|
||||
|
||||
@@ -4872,7 +4872,7 @@
|
||||
},
|
||||
"welcomeSlide": {
|
||||
"title": "Welcome to Stirling",
|
||||
"body": "Stirling PDF is now ready for teams of all sizes.<br />This update includes a new layout, powerful new admin capabilities, and our most requested feature - <strong>Edit Text</strong>."
|
||||
"body": "Stirling PDF is now ready for teams of all sizes. This update includes a new layout, powerful new admin capabilities, and our most requested feature - <strong>Edit Text</strong>."
|
||||
},
|
||||
"allTools": "This is the <strong>Tools</strong> panel, where you can browse and select from all available PDF tools.",
|
||||
"selectCropTool": "Let's select the <strong>Crop</strong> tool to demonstrate how to use one of the tools.",
|
||||
@@ -4906,6 +4906,17 @@
|
||||
"overLimitBody": "Our licensing permits up to <strong>{{freeTierLimit}}</strong> users for free per server. You have <strong>{{overLimitUserCopy}}</strong> Stirling users. To continue uninterrupted, upgrade to the Stirling Server plan - <strong>unlimited seats</strong>, PDF text editing, and full admin control for $99/server/mo.",
|
||||
"freeBody": "Our <strong>Open-Core</strong> licensing permits up to <strong>{{freeTierLimit}}</strong> users for free per server. To scale uninterrupted and get early access to our new <strong>PDF text editing tool</strong>, we recommend the Stirling Server plan - full editing and <strong>unlimited seats</strong> for $99/server/mo."
|
||||
},
|
||||
"desktopInstall": {
|
||||
"title": "Download",
|
||||
"titleWithOs": "Download for {{osLabel}}",
|
||||
"body": "Stirling works best as a desktop app. You can use it offline, access documents faster, and make edits locally on your computer."
|
||||
},
|
||||
"planOverview": {
|
||||
"adminTitle": "Admin Overview",
|
||||
"userTitle": "Plan Overview",
|
||||
"adminBody": "As an admin, you can manage users, configure settings, and monitor server health. The first <strong>{{freeTierLimit}}</strong> people on your server get to use Stirling free of charge.",
|
||||
"userBody": "Invite teammates, assign roles, and keep your documents organized in one secure workspace. Enable login mode whenever you're ready to grow beyond solo use."
|
||||
},
|
||||
"securityCheck": {
|
||||
"message": "The application has undergone significant changes recently. Your server admin's attention may be required. Please confirm your role to continue."
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { Button, Group, ActionIcon } from '@mantine/core';
|
||||
import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
|
||||
import { ButtonDefinition, type FlowState } from '@app/components/onboarding/onboardingFlowConfig';
|
||||
import type { LicenseNotice } from '@app/components/onboarding/slides/types';
|
||||
import type { LicenseNotice } from '@app/types/types';
|
||||
import type { ButtonAction } from '@app/components/onboarding/onboardingFlowConfig';
|
||||
|
||||
interface RenderButtonsProps {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { LicenseNotice } from '@app/components/onboarding/slides/types';
|
||||
import type { LicenseNotice } from '@app/types/types';
|
||||
|
||||
export interface InitialOnboardingModalProps {
|
||||
opened: boolean;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState, useRef } from 'react';
|
||||
import { usePreferences } from '@app/contexts/PreferencesContext';
|
||||
import { useOnboarding } from '@app/contexts/OnboardingContext';
|
||||
import { useOs } from '@app/hooks/useOs';
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
type FlowState,
|
||||
type SlideId,
|
||||
} from '@app/components/onboarding/onboardingFlowConfig';
|
||||
import type { LicenseNotice } from '@app/components/onboarding/slides/types';
|
||||
import type { LicenseNotice } from '@app/types/types';
|
||||
import { resolveFlow } from './flowResolver';
|
||||
import { useServerExperience } from '@app/hooks/useServerExperience';
|
||||
import { DEFAULT_STATE, type InitialOnboardingModalProps, type OnboardingState } from './types';
|
||||
@@ -45,6 +45,7 @@ export function useInitialOnboardingState({
|
||||
} = useServerExperience();
|
||||
const osType = useOs();
|
||||
const navigate = useNavigate();
|
||||
const selectedDownloadUrlRef = useRef<string>('');
|
||||
|
||||
const [state, setState] = useState<OnboardingState>(DEFAULT_STATE);
|
||||
|
||||
@@ -105,7 +106,7 @@ export function useInitialOnboardingState({
|
||||
case 'windows':
|
||||
return { label: 'Windows', url: 'https://files.stirlingpdf.com/win-installer.exe' };
|
||||
case 'mac-apple':
|
||||
return { label: 'Mac', url: 'https://files.stirlingpdf.com/mac-installer.dmg' };
|
||||
return { label: 'Mac (Apple Silicon)', url: 'https://files.stirlingpdf.com/mac-installer.dmg' };
|
||||
case 'mac-intel':
|
||||
return { label: 'Mac (Intel)', url: 'https://files.stirlingpdf.com/mac-x86_64-installer.dmg' };
|
||||
case 'linux-x64':
|
||||
@@ -116,6 +117,16 @@ export function useInitialOnboardingState({
|
||||
}
|
||||
}, [osType]);
|
||||
|
||||
const osOptions = useMemo(() => {
|
||||
const options = [
|
||||
{ label: 'Windows', url: 'https://files.stirlingpdf.com/win-installer.exe', value: 'windows' },
|
||||
{ label: 'Mac (Apple Silicon)', url: 'https://files.stirlingpdf.com/mac-installer.dmg', value: 'mac-apple' },
|
||||
{ label: 'Mac (Intel)', url: 'https://files.stirlingpdf.com/mac-x86_64-installer.dmg', value: 'mac-intel' },
|
||||
{ label: 'Linux', url: 'https://docs.stirlingpdf.com/Installation/Unix%20Installation/', value: 'linux' },
|
||||
];
|
||||
return options.filter(opt => opt.url);
|
||||
}, []);
|
||||
|
||||
const { ids: flowSlideIds, type: flowType } = resolveFlow(
|
||||
effectiveEnableLogin,
|
||||
effectiveIsAdmin,
|
||||
@@ -182,9 +193,22 @@ export function useInitialOnboardingState({
|
||||
onLicenseNoticeUpdate?.(licenseNotice);
|
||||
}, [licenseNotice, onLicenseNoticeUpdate]);
|
||||
|
||||
// Initialize ref with default URL
|
||||
useEffect(() => {
|
||||
if (!selectedDownloadUrlRef.current && os.url) {
|
||||
selectedDownloadUrlRef.current = os.url;
|
||||
}
|
||||
}, [os.url]);
|
||||
|
||||
const handleDownloadUrlChange = useCallback((url: string) => {
|
||||
selectedDownloadUrlRef.current = url;
|
||||
}, []);
|
||||
|
||||
const currentSlide = slideDefinition.createSlide({
|
||||
osLabel: os.label,
|
||||
osUrl: os.url,
|
||||
osOptions,
|
||||
onDownloadUrlChange: handleDownloadUrlChange,
|
||||
selectedRole: state.selectedRole,
|
||||
onRoleSelect: handleRoleSelect,
|
||||
licenseNotice,
|
||||
@@ -243,7 +267,7 @@ export function useInitialOnboardingState({
|
||||
closeAndMarkSeen();
|
||||
return;
|
||||
case 'download-selected': {
|
||||
const downloadUrl = os.url || currentSlide.downloadUrl;
|
||||
const downloadUrl = selectedDownloadUrlRef.current || os.url || currentSlide.downloadUrl;
|
||||
if (downloadUrl) {
|
||||
window.open(downloadUrl, '_blank', 'noopener');
|
||||
}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import apiClient from '@app/services/apiClient';
|
||||
|
||||
interface UseLicenseInfoOptions {
|
||||
opened: boolean;
|
||||
shouldFetch: boolean;
|
||||
}
|
||||
|
||||
export function useLicenseInfo({ opened, shouldFetch }: UseLicenseInfoOptions) {
|
||||
const [licenseUserCount, setLicenseUserCount] = useState<number | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!opened) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!shouldFetch) {
|
||||
setLicenseUserCount(null);
|
||||
return;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
|
||||
const fetchLicenseInfo = async () => {
|
||||
try {
|
||||
const response = await apiClient.get<{ totalUsers?: number }>(
|
||||
'/api/v1/proprietary/ui-data/admin-settings',
|
||||
{
|
||||
suppressErrorToast: true,
|
||||
} as any,
|
||||
);
|
||||
|
||||
if (!cancelled) {
|
||||
const totalUsers = response.data?.totalUsers;
|
||||
setLicenseUserCount(typeof totalUsers === 'number' ? totalUsers : null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[onboarding] failed to fetch license information', error);
|
||||
if (!cancelled) {
|
||||
setLicenseUserCount(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fetchLicenseInfo();
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [opened, shouldFetch]);
|
||||
|
||||
return licenseUserCount;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Modal, Button, Group, Stack } from '@mantine/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import AnimatedSlideBackground from '@app/components/onboarding/slides/AnimatedSlideBackground';
|
||||
import ServerLicenseSlide from '@app/components/onboarding/slides/ServerLicenseSlide';
|
||||
import { LicenseNotice } from '@app/components/onboarding/slides/types';
|
||||
import { LicenseNotice } from '@app/types/types';
|
||||
import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '@app/styles/zIndex';
|
||||
import styles from '@app/components/onboarding/InitialOnboardingModal/InitialOnboardingModal.module.css';
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useAppConfig } from '@app/contexts/AppConfigContext';
|
||||
import { useCookieConsentContext } from '@app/contexts/CookieConsentContext';
|
||||
import { useOnboarding } from '@app/contexts/OnboardingContext';
|
||||
import { useAuth } from '@app/auth/UseSession';
|
||||
import type { LicenseNotice } from '@app/components/onboarding/slides/types';
|
||||
import type { LicenseNotice } from '@app/types/types';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import {
|
||||
ONBOARDING_SESSION_BLOCK_KEY,
|
||||
|
||||
@@ -3,7 +3,7 @@ import DesktopInstallSlide from '@app/components/onboarding/slides/DesktopInstal
|
||||
import SecurityCheckSlide from '@app/components/onboarding/slides/SecurityCheckSlide';
|
||||
import PlanOverviewSlide from '@app/components/onboarding/slides/PlanOverviewSlide';
|
||||
import ServerLicenseSlide from '@app/components/onboarding/slides/ServerLicenseSlide';
|
||||
import { SlideConfig, LicenseNotice } from '@app/components/onboarding/slides/types';
|
||||
import { SlideConfig, LicenseNotice } from '@app/types/types';
|
||||
|
||||
export type SlideId =
|
||||
| 'welcome'
|
||||
@@ -31,9 +31,17 @@ export interface FlowState {
|
||||
selectedRole: 'admin' | 'user' | null;
|
||||
}
|
||||
|
||||
export interface OSOption {
|
||||
label: string;
|
||||
url: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface SlideFactoryParams {
|
||||
osLabel: string;
|
||||
osUrl: string;
|
||||
osOptions?: OSOption[];
|
||||
onDownloadUrlChange?: (url: string) => void;
|
||||
selectedRole: 'admin' | 'user' | null;
|
||||
onRoleSelect: (role: 'admin' | 'user' | null) => void;
|
||||
licenseNotice?: LicenseNotice;
|
||||
@@ -79,7 +87,7 @@ export const SLIDE_DEFINITIONS: Record<SlideId, SlideDefinition> = {
|
||||
},
|
||||
'desktop-install': {
|
||||
id: 'desktop-install',
|
||||
createSlide: ({ osLabel, osUrl }) => DesktopInstallSlide({ osLabel, osUrl }),
|
||||
createSlide: ({ osLabel, osUrl, osOptions, onDownloadUrlChange }) => DesktopInstallSlide({ osLabel, osUrl, osOptions, onDownloadUrlChange }),
|
||||
hero: { type: 'dual-icon' },
|
||||
buttons: [
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import styles from './AnimatedSlideBackground.module.css';
|
||||
import { AnimatedSlideBackgroundProps } from './types';
|
||||
import { AnimatedSlideBackgroundProps } from '../../../types/types';
|
||||
|
||||
type CircleStyles = React.CSSProperties & {
|
||||
'--circle-move-x'?: string;
|
||||
|
||||
@@ -1,21 +1,34 @@
|
||||
import React from 'react';
|
||||
import { SlideConfig } from './types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SlideConfig } from '../../../types/types';
|
||||
import { UNIFIED_CIRCLE_CONFIG } from './unifiedBackgroundConfig';
|
||||
import { DesktopInstallTitle, type OSOption } from './DesktopInstallTitle';
|
||||
|
||||
export type { OSOption };
|
||||
|
||||
interface DesktopInstallSlideProps {
|
||||
osLabel: string;
|
||||
osUrl: string;
|
||||
osOptions?: OSOption[];
|
||||
onDownloadUrlChange?: (url: string) => void;
|
||||
}
|
||||
|
||||
export default function DesktopInstallSlide({ osLabel, osUrl }: DesktopInstallSlideProps): SlideConfig {
|
||||
const title = osLabel ? `Download for ${osLabel}` : 'Download';
|
||||
export default function DesktopInstallSlide({ osLabel, osUrl, osOptions = [], onDownloadUrlChange }: DesktopInstallSlideProps): SlideConfig {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return {
|
||||
key: 'desktop-install',
|
||||
title,
|
||||
title: (
|
||||
<DesktopInstallTitle
|
||||
osLabel={osLabel}
|
||||
osUrl={osUrl}
|
||||
osOptions={osOptions || []}
|
||||
onDownloadUrlChange={onDownloadUrlChange}
|
||||
/>
|
||||
),
|
||||
body: (
|
||||
<span>
|
||||
Stirling works best as a desktop app. You can use it offline, access documents faster, and make edits locally on your computer.
|
||||
{t('onboarding.desktopInstall.body', 'Stirling works best as a desktop app. You can use it offline, access documents faster, and make edits locally on your computer.')}
|
||||
</span>
|
||||
),
|
||||
downloadUrl: osUrl,
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Menu, ActionIcon } from '@mantine/core';
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
|
||||
export interface OSOption {
|
||||
label: string;
|
||||
url: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface DesktopInstallTitleProps {
|
||||
osLabel: string;
|
||||
osUrl: string;
|
||||
osOptions: OSOption[];
|
||||
onDownloadUrlChange?: (url: string) => void;
|
||||
}
|
||||
|
||||
export const DesktopInstallTitle: React.FC<DesktopInstallTitleProps> = ({
|
||||
osLabel,
|
||||
osUrl,
|
||||
osOptions,
|
||||
onDownloadUrlChange
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [selectedOsUrl, setSelectedOsUrl] = React.useState<string>(osUrl);
|
||||
|
||||
React.useEffect(() => {
|
||||
setSelectedOsUrl(osUrl);
|
||||
}, [osUrl]);
|
||||
|
||||
const handleOsSelect = React.useCallback((option: OSOption) => {
|
||||
setSelectedOsUrl(option.url);
|
||||
onDownloadUrlChange?.(option.url);
|
||||
}, [onDownloadUrlChange]);
|
||||
|
||||
const currentOsOption = osOptions.find(opt => opt.url === selectedOsUrl) ||
|
||||
(osOptions.length > 0 ? osOptions[0] : { label: osLabel, url: osUrl });
|
||||
|
||||
const displayLabel = currentOsOption.label || osLabel;
|
||||
const title = displayLabel
|
||||
? t('onboarding.desktopInstall.titleWithOs', 'Download for {{osLabel}}', { osLabel: displayLabel })
|
||||
: t('onboarding.desktopInstall.title', 'Download');
|
||||
|
||||
// If only one option or no options, don't show dropdown
|
||||
if (osOptions.length <= 1) {
|
||||
return <div style={{ textAlign: 'center', width: '100%' }}>{title}</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '0.5rem', width: '100%' }}>
|
||||
<span style={{ whiteSpace: 'nowrap' }}>{title}</span>
|
||||
<Menu position="bottom" offset={5} zIndex={10000}>
|
||||
<Menu.Target>
|
||||
<ActionIcon
|
||||
variant="transparent"
|
||||
size="sm"
|
||||
style={{
|
||||
background: 'transparent',
|
||||
border: 'none',
|
||||
color: 'inherit',
|
||||
padding: 0
|
||||
}}
|
||||
>
|
||||
<ExpandMoreIcon fontSize="small" />
|
||||
</ActionIcon>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown>
|
||||
{osOptions.map((option) => {
|
||||
const isSelected = option.url === selectedOsUrl;
|
||||
return (
|
||||
<Menu.Item
|
||||
key={option.url}
|
||||
onClick={() => handleOsSelect(option)}
|
||||
style={{
|
||||
backgroundColor: isSelected
|
||||
? 'light-dark(var(--mantine-color-blue-1), var(--mantine-color-blue-8))'
|
||||
: 'transparent',
|
||||
color: isSelected
|
||||
? 'light-dark(var(--mantine-color-blue-9), var(--mantine-color-white))'
|
||||
: 'inherit',
|
||||
}}
|
||||
>
|
||||
{option.label}
|
||||
</Menu.Item>
|
||||
);
|
||||
})}
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { SlideConfig, LicenseNotice } from './types';
|
||||
import { useTranslation, Trans } from 'react-i18next';
|
||||
import { SlideConfig, LicenseNotice } from '../../../types/types';
|
||||
import { UNIFIED_CIRCLE_CONFIG } from './unifiedBackgroundConfig';
|
||||
|
||||
interface PlanOverviewSlideProps {
|
||||
@@ -10,21 +11,28 @@ interface PlanOverviewSlideProps {
|
||||
const DEFAULT_FREE_TIER_LIMIT = 5;
|
||||
|
||||
export default function PlanOverviewSlide({ isAdmin, licenseNotice }: PlanOverviewSlideProps): SlideConfig {
|
||||
const { t } = useTranslation();
|
||||
const freeTierLimit = licenseNotice?.freeTierLimit ?? DEFAULT_FREE_TIER_LIMIT;
|
||||
|
||||
const adminBody = (
|
||||
<span>
|
||||
As an admin, you can manage users, configure settings, and monitor server health. The first{' '}
|
||||
<strong>{freeTierLimit}</strong> people on your server get to use Stirling free of charge.
|
||||
<Trans
|
||||
i18nKey="onboarding.planOverview.adminBody"
|
||||
components={{ strong: <strong /> }}
|
||||
values={{ freeTierLimit }}
|
||||
defaults="As an admin, you can manage users, configure settings, and monitor server health. The first <strong>{{freeTierLimit}}</strong> people on your server get to use Stirling free of charge."
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
|
||||
return {
|
||||
key: isAdmin ? 'admin-overview' : 'plan-overview',
|
||||
title: isAdmin ? 'Admin Overview' : 'Plan Overview',
|
||||
title: isAdmin
|
||||
? t('onboarding.planOverview.adminTitle', 'Admin Overview')
|
||||
: t('onboarding.planOverview.userTitle', 'Plan Overview'),
|
||||
body: isAdmin ? adminBody : (
|
||||
<span>
|
||||
Invite teammates, assign roles, and keep your documents organized in one secure workspace. Enable login mode whenever you're ready to grow beyond solo use.
|
||||
{t('onboarding.planOverview.userBody', 'Invite teammates, assign roles, and keep your documents organized in one secure workspace. Enable login mode whenever you\'re ready to grow beyond solo use.')}
|
||||
</span>
|
||||
),
|
||||
background: {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Select } from '@mantine/core';
|
||||
import styles from '../InitialOnboardingModal/InitialOnboardingModal.module.css';
|
||||
import { SlideConfig } from './types';
|
||||
import { SlideConfig } from '../../../types/types';
|
||||
import LocalIcon from '@app/components/shared/LocalIcon';
|
||||
import { UNIFIED_CIRCLE_CONFIG } from './unifiedBackgroundConfig';
|
||||
import i18n from '@app/i18n';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Trans } from 'react-i18next';
|
||||
import { SlideConfig, LicenseNotice } from './types';
|
||||
import { SlideConfig, LicenseNotice } from '../../../types/types';
|
||||
import { UNIFIED_CIRCLE_CONFIG } from './unifiedBackgroundConfig';
|
||||
import i18n from '@app/i18n';
|
||||
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import React from 'react';
|
||||
import { Trans } from 'react-i18next';
|
||||
import { SlideConfig } from './types';
|
||||
import { useTranslation, Trans } from 'react-i18next';
|
||||
import { SlideConfig } from '../../../types/types';
|
||||
import styles from '../InitialOnboardingModal/InitialOnboardingModal.module.css';
|
||||
import { UNIFIED_CIRCLE_CONFIG } from './unifiedBackgroundConfig';
|
||||
import i18n from '@app/i18n';
|
||||
|
||||
export default function WelcomeSlide(): SlideConfig {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return {
|
||||
key: 'welcome',
|
||||
title: (
|
||||
<span className={styles.welcomeTitleContainer}>
|
||||
{i18n.t('onboarding.welcomeSlide.title', 'Welcome to Stirling')}
|
||||
{t('onboarding.welcomeSlide.title', 'Welcome to Stirling')}
|
||||
<span className={styles.v2Badge}>
|
||||
V2
|
||||
</span>
|
||||
@@ -20,11 +21,8 @@ export default function WelcomeSlide(): SlideConfig {
|
||||
<span>
|
||||
<Trans
|
||||
i18nKey="onboarding.welcomeSlide.body"
|
||||
components={{
|
||||
strong: <strong />,
|
||||
br: <br />,
|
||||
}}
|
||||
defaults="Stirling PDF is now ready for teams of all sizes.<br />This update includes a new layout, powerful new admin capabilities, and our most requested feature - <strong>Edit Text</strong>."
|
||||
components={{ strong: <strong /> }}
|
||||
defaults="Stirling PDF is now ready for teams of all sizes. This update includes a new layout, powerful new admin capabilities, and our most requested feature - <strong>Edit Text</strong>."
|
||||
/>
|
||||
</span>
|
||||
),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AnimatedCircleConfig } from './types';
|
||||
import { AnimatedCircleConfig } from '../../../types/types';
|
||||
|
||||
/**
|
||||
* Unified circle background configuration used across all onboarding slides.
|
||||
|
||||
@@ -270,12 +270,7 @@ const QuickAccessBar = forwardRef<HTMLDivElement>((_, ref) => {
|
||||
<div
|
||||
key={buttonConfig.id}
|
||||
data-tour="help-button"
|
||||
onClick={() =>
|
||||
startTour('tools', {
|
||||
source: 'quick-access-help-button',
|
||||
metadata: { entry: 'direct' },
|
||||
})
|
||||
}
|
||||
onClick={() => startTour('tools')}
|
||||
>
|
||||
{renderNavButton(buttonConfig, index)}
|
||||
</div>
|
||||
@@ -292,12 +287,7 @@ const QuickAccessBar = forwardRef<HTMLDivElement>((_, ref) => {
|
||||
<Menu.Dropdown>
|
||||
<Menu.Item
|
||||
leftSection={<LocalIcon icon="view-carousel-rounded" width="1.25rem" height="1.25rem" />}
|
||||
onClick={() =>
|
||||
startTour('tools', {
|
||||
source: 'quick-access-help-menu',
|
||||
metadata: { entry: 'menu-tools' },
|
||||
})
|
||||
}
|
||||
onClick={() => startTour('tools')}
|
||||
>
|
||||
<div>
|
||||
<div style={{ fontWeight: 500 }}>
|
||||
@@ -310,12 +300,7 @@ const QuickAccessBar = forwardRef<HTMLDivElement>((_, ref) => {
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
leftSection={<LocalIcon icon="admin-panel-settings-rounded" width="1.25rem" height="1.25rem" />}
|
||||
onClick={() =>
|
||||
startTour('admin', {
|
||||
source: 'quick-access-help-menu',
|
||||
metadata: { entry: 'menu-admin' },
|
||||
})
|
||||
}
|
||||
onClick={() => startTour('admin')}
|
||||
>
|
||||
<div>
|
||||
<div style={{ fontWeight: 500 }}>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { LicenseNotice } from '@app/components/onboarding/slides/types';
|
||||
import type { LicenseNotice } from '@app/types/types';
|
||||
|
||||
export const ONBOARDING_SESSION_BLOCK_KEY = 'stirling-onboarding-session-active';
|
||||
export const ONBOARDING_SESSION_EVENT = 'stirling:onboarding-session-started';
|
||||
|
||||
Reference in New Issue
Block a user