mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
feat(console): early bird gift (#3177)
This commit is contained in:
parent
794e270dc5
commit
e69790fd17
21 changed files with 271 additions and 57 deletions
14
packages/console/src/assets/images/gift.svg
Normal file
14
packages/console/src/assets/images/gift.svg
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0_331_72604)">
|
||||||
|
<path d="M20.3332 19.2223C20.3332 20.4446 19.3332 21.4446 18.1109 21.4446H5.88873C4.6665 21.4446 3.6665 20.4446 3.6665 19.2223V9.77789C3.6665 8.55566 4.6665 7.55566 5.88873 7.55566H18.1109C19.3332 7.55566 20.3332 8.55566 20.3332 9.77789V19.2223Z" fill="#FFB95A"/>
|
||||||
|
<path d="M22 8.11114C22 9.33336 21 10.3334 19.7778 10.3334H4.22222C3 10.3334 2 9.33336 2 8.11114C2 6.88892 3 5.88892 4.22222 5.88892H19.7778C21 5.88892 22 6.88892 22 8.11114Z" fill="#FFB95A"/>
|
||||||
|
<path d="M3.6665 10.3333H20.3332V11.4444H3.6665V10.3333Z" fill="#EB9918"/>
|
||||||
|
<path d="M12.5556 3.66675H11.4445C10.5239 3.66675 9.77783 4.41286 9.77783 5.33341V21.4445H14.2223V5.33341C14.2223 4.41341 13.4762 3.66675 12.5556 3.66675Z" fill="#DD3730"/>
|
||||||
|
<path d="M10.8891 5.88893C11.5002 5.88893 11.5908 5.60226 11.0897 5.25171L7.35522 2.63726C6.85411 2.28671 6.19689 2.43393 5.89356 2.96448L4.77356 4.92448C4.47022 5.45504 4.72245 5.88893 5.33356 5.88893H10.8891ZM13.1113 5.88893C12.5002 5.88893 12.4097 5.60226 12.9108 5.25171L16.6458 2.63726C17.1463 2.28671 17.8041 2.43393 18.1074 2.96448L19.2274 4.92393C19.5302 5.45504 19.278 5.88893 18.6669 5.88893H13.1113Z" fill="#DD3730"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_331_72604">
|
||||||
|
<rect width="20" height="20" fill="white" transform="translate(2 2)"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,16 @@
|
||||||
|
@use '@/scss/underscore' as _;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
margin-top: _.unit(-5);
|
||||||
|
|
||||||
|
.description {
|
||||||
|
font: var(--font-body-2);
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
margin-bottom: _.unit(6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import ReactModal from 'react-modal';
|
||||||
|
|
||||||
|
import ModalLayout from '@/components/ModalLayout';
|
||||||
|
import * as modalStyles from '@/scss/modal.module.scss';
|
||||||
|
|
||||||
|
import Reservation from '../../Reservation';
|
||||||
|
import * as styles from './index.module.scss';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isOpen: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const GiftModal = ({ isOpen, onClose }: Props) => {
|
||||||
|
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ReactModal
|
||||||
|
shouldCloseOnOverlayClick
|
||||||
|
isOpen={isOpen}
|
||||||
|
className={modalStyles.content}
|
||||||
|
overlayClassName={modalStyles.overlay}
|
||||||
|
onRequestClose={onClose}
|
||||||
|
>
|
||||||
|
<ModalLayout
|
||||||
|
isTitleWordWrapEnabled
|
||||||
|
title="cloud.gift.title"
|
||||||
|
className={styles.content}
|
||||||
|
onClose={onClose}
|
||||||
|
>
|
||||||
|
<div className={styles.description}>{t('cloud.gift.description')}</div>
|
||||||
|
<Reservation
|
||||||
|
title="cloud.gift.reserve_title"
|
||||||
|
description="cloud.gift.reserve_description"
|
||||||
|
reservationButtonTitle="cloud.gift.book_button"
|
||||||
|
/>
|
||||||
|
</ModalLayout>
|
||||||
|
</ReactModal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftModal;
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import Gift from '@/assets/images/gift.svg';
|
||||||
|
import IconButton from '@/components/IconButton';
|
||||||
|
|
||||||
|
import GiftModal from './GiftModal';
|
||||||
|
|
||||||
|
const EarlyBirdGift = () => {
|
||||||
|
const [isGiftOpen, setIsGiftOpen] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<IconButton
|
||||||
|
size="large"
|
||||||
|
onClick={() => {
|
||||||
|
setIsGiftOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Gift />
|
||||||
|
</IconButton>
|
||||||
|
<GiftModal
|
||||||
|
isOpen={isGiftOpen}
|
||||||
|
onClose={() => {
|
||||||
|
setIsGiftOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EarlyBirdGift;
|
|
@ -0,0 +1,31 @@
|
||||||
|
@use '@/scss/underscore' as _;
|
||||||
|
|
||||||
|
.reservation {
|
||||||
|
width: 100%;
|
||||||
|
padding: _.unit(3) _.unit(4);
|
||||||
|
border: 1px solid var(--color-divider);
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.reservationInfo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.reservationIcon {
|
||||||
|
margin-right: _.unit(4);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reservationTitle {
|
||||||
|
font: var(--font-title-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reservationDescription {
|
||||||
|
font: var(--font-body-2);
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
padding-right: _.unit(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
45
packages/console/src/cloud/components/Reservation/index.tsx
Normal file
45
packages/console/src/cloud/components/Reservation/index.tsx
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import type { AdminConsoleKey } from '@logto/phrases';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import Calendar from '@/assets/images/calendar.svg';
|
||||||
|
import { reservationLink } from '@/cloud/constants';
|
||||||
|
import Button from '@/components/Button';
|
||||||
|
import { buildUrl } from '@/utils/url';
|
||||||
|
|
||||||
|
import * as styles from './index.module.scss';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
title: AdminConsoleKey;
|
||||||
|
description: AdminConsoleKey;
|
||||||
|
reservationButtonTitle: AdminConsoleKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Reservation = ({ title, description, reservationButtonTitle }: Props) => {
|
||||||
|
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.reservation}>
|
||||||
|
<div className={styles.reservationInfo}>
|
||||||
|
<Calendar className={styles.reservationIcon} />
|
||||||
|
<div>
|
||||||
|
<div className={styles.reservationTitle}>{t(title)}</div>
|
||||||
|
<div className={styles.reservationDescription}>{t(description)}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
type="outline"
|
||||||
|
title={reservationButtonTitle}
|
||||||
|
onClick={() => {
|
||||||
|
const bookLink = buildUrl(reservationLink, {
|
||||||
|
// Note: month format is YYYY-MM
|
||||||
|
month: new Date().toISOString().slice(0, 7),
|
||||||
|
});
|
||||||
|
|
||||||
|
window.open(bookLink, '_blank');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Reservation;
|
1
packages/console/src/cloud/constants/index.ts
Normal file
1
packages/console/src/cloud/constants/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export const reservationLink = 'https://calendly.com/logto/30min';
|
|
@ -24,32 +24,3 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: _.unit(8) 0;
|
margin: _.unit(8) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reservation {
|
|
||||||
width: 100%;
|
|
||||||
padding: _.unit(3) _.unit(4);
|
|
||||||
border: 1px solid var(--color-divider);
|
|
||||||
border-radius: 8px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.reservationInfo {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.reservationIcon {
|
|
||||||
margin-right: _.unit(4);
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.reservationTitle {
|
|
||||||
font: var(--font-title-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.reservationDescription {
|
|
||||||
font: var(--font-body-2);
|
|
||||||
color: var(--color-text-secondary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,15 +4,14 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import AirPlay from '@/assets/images/air-play.svg';
|
import AirPlay from '@/assets/images/air-play.svg';
|
||||||
import Calendar from '@/assets/images/calendar.svg';
|
|
||||||
import GetStarted from '@/assets/images/get-started.svg';
|
import GetStarted from '@/assets/images/get-started.svg';
|
||||||
import ActionBar from '@/cloud/components/ActionBar';
|
import ActionBar from '@/cloud/components/ActionBar';
|
||||||
|
import Reservation from '@/cloud/components/Reservation';
|
||||||
import * as pageLayout from '@/cloud/scss/layout.module.scss';
|
import * as pageLayout from '@/cloud/scss/layout.module.scss';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import Divider from '@/components/Divider';
|
import Divider from '@/components/Divider';
|
||||||
import OverlayScrollbar from '@/components/OverlayScrollbar';
|
import OverlayScrollbar from '@/components/OverlayScrollbar';
|
||||||
import { AppEndpointsContext } from '@/containers/AppEndpointsProvider';
|
import { AppEndpointsContext } from '@/containers/AppEndpointsProvider';
|
||||||
import { buildUrl } from '@/utils/url';
|
|
||||||
|
|
||||||
import { CloudPage } from '../../types';
|
import { CloudPage } from '../../types';
|
||||||
import { getCloudPagePathname } from '../../utils';
|
import { getCloudPagePathname } from '../../utils';
|
||||||
|
@ -49,29 +48,11 @@ const Congrats = () => {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Divider className={styles.divider} />
|
<Divider className={styles.divider} />
|
||||||
<div className={styles.reservation}>
|
<Reservation
|
||||||
<div className={styles.reservationInfo}>
|
title="cloud.congrats.reserve_title"
|
||||||
<Calendar className={styles.reservationIcon} />
|
description="cloud.congrats.reserve_description"
|
||||||
<div>
|
reservationButtonTitle="cloud.congrats.book_button"
|
||||||
<div className={styles.reservationTitle}>{t('cloud.congrats.reserve_title')}</div>
|
/>
|
||||||
<div className={styles.reservationDescription}>
|
|
||||||
{t('cloud.congrats.reserve_description')}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
type="outline"
|
|
||||||
title="cloud.congrats.book_button"
|
|
||||||
onClick={() => {
|
|
||||||
const bookLink = buildUrl('https://calendly.com/logto/30min', {
|
|
||||||
// Note: month format is YYYY-MM
|
|
||||||
month: new Date().toISOString().slice(0, 7),
|
|
||||||
});
|
|
||||||
|
|
||||||
window.open(bookLink, '_blank');
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</OverlayScrollbar>
|
</OverlayScrollbar>
|
||||||
<ActionBar step={4}>
|
<ActionBar step={4}>
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.titleEllipsis {
|
||||||
@include _.text-ellipsis;
|
@include _.text-ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,18 +10,27 @@ type Props = {
|
||||||
title: AdminConsoleKey | ReactElement<typeof DangerousRaw>;
|
title: AdminConsoleKey | ReactElement<typeof DangerousRaw>;
|
||||||
subtitle?: AdminConsoleKey | ReactElement<typeof DangerousRaw>;
|
subtitle?: AdminConsoleKey | ReactElement<typeof DangerousRaw>;
|
||||||
size?: 'small' | 'medium' | 'large';
|
size?: 'small' | 'medium' | 'large';
|
||||||
|
isWordWrapEnabled?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Always use this component to render CardTitle, with built-in i18n support.
|
* Always use this component to render CardTitle, with built-in i18n support.
|
||||||
*/
|
*/
|
||||||
const CardTitle = ({ title, subtitle, size = 'large', className }: Props) => {
|
const CardTitle = ({
|
||||||
|
title,
|
||||||
|
subtitle,
|
||||||
|
size = 'large',
|
||||||
|
isWordWrapEnabled = false,
|
||||||
|
className,
|
||||||
|
}: Props) => {
|
||||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(styles.container, styles[size], className)}>
|
<div className={classNames(styles.container, styles[size], className)}>
|
||||||
<div className={styles.title}>{typeof title === 'string' ? t(title) : title}</div>
|
<div className={classNames(styles.title, !isWordWrapEnabled && styles.titleEllipsis)}>
|
||||||
|
{typeof title === 'string' ? t(title) : title}
|
||||||
|
</div>
|
||||||
{subtitle && (
|
{subtitle && (
|
||||||
<div className={styles.subtitle}>
|
<div className={styles.subtitle}>
|
||||||
{typeof subtitle === 'string' ? t(subtitle) : subtitle}
|
{typeof subtitle === 'string' ? t(subtitle) : subtitle}
|
||||||
|
|
|
@ -18,6 +18,7 @@ type Props = {
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
className?: string;
|
className?: string;
|
||||||
size?: 'medium' | 'large' | 'xlarge';
|
size?: 'medium' | 'large' | 'xlarge';
|
||||||
|
isTitleWordWrapEnabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ModalLayout = ({
|
const ModalLayout = ({
|
||||||
|
@ -28,11 +29,12 @@ const ModalLayout = ({
|
||||||
onClose,
|
onClose,
|
||||||
className,
|
className,
|
||||||
size = 'medium',
|
size = 'medium',
|
||||||
|
isTitleWordWrapEnabled = false,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
return (
|
return (
|
||||||
<Card className={classNames(styles.container, styles[size])}>
|
<Card className={classNames(styles.container, styles[size])}>
|
||||||
<div className={styles.header}>
|
<div className={styles.header}>
|
||||||
<CardTitle title={title} subtitle={subtitle} />
|
<CardTitle title={title} subtitle={subtitle} isWordWrapEnabled={isTitleWordWrapEnabled} />
|
||||||
{onClose && (
|
{onClose && (
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
|
@ -2,7 +2,9 @@ import classNames from 'classnames';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import Logo from '@/assets/images/logo.svg';
|
import Logo from '@/assets/images/logo.svg';
|
||||||
|
import EarlyBirdGift from '@/cloud/components/EarlyBirdGift';
|
||||||
import Spacer from '@/components/Spacer';
|
import Spacer from '@/components/Spacer';
|
||||||
|
import { isCloud } from '@/consts/cloud';
|
||||||
import GetStartedProgress from '@/pages/GetStarted/components/GetStartedProgress';
|
import GetStartedProgress from '@/pages/GetStarted/components/GetStartedProgress';
|
||||||
|
|
||||||
import UserInfo from '../UserInfo';
|
import UserInfo from '../UserInfo';
|
||||||
|
@ -22,6 +24,7 @@ const Topbar = ({ className }: Props) => {
|
||||||
<div className={styles.text}>{t('title')}</div>
|
<div className={styles.text}>{t('title')}</div>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<GetStartedProgress />
|
<GetStartedProgress />
|
||||||
|
{isCloud && <EarlyBirdGift />}
|
||||||
<UserInfo />
|
<UserInfo />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -59,6 +59,14 @@ const cloud = {
|
||||||
discord_link: 'discord channel', // UNTRANSLATED
|
discord_link: 'discord channel', // UNTRANSLATED
|
||||||
enter_admin_console: 'Enter Admin Console', // UNTRANSLATED
|
enter_admin_console: 'Enter Admin Console', // UNTRANSLATED
|
||||||
},
|
},
|
||||||
|
gift: {
|
||||||
|
title: 'Secure early credit for Logto SaaS join the front-runners now !', // UNTRANSLATED
|
||||||
|
description: 'Book a one-on-one session with our team for early credit and use case sharing.', // UNTRANSLATED
|
||||||
|
reserve_title: 'Reserve your time with Logto team', // UNTRANSLATED
|
||||||
|
reserve_description:
|
||||||
|
'You can also save the calendar link. We’re always available to assist you.', // UNTRANSLATED
|
||||||
|
book_button: 'Book', // UNTRANSLATED
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default cloud;
|
export default cloud;
|
||||||
|
|
|
@ -59,6 +59,14 @@ const cloud = {
|
||||||
discord_link: 'discord channel',
|
discord_link: 'discord channel',
|
||||||
enter_admin_console: 'Enter Admin Console',
|
enter_admin_console: 'Enter Admin Console',
|
||||||
},
|
},
|
||||||
|
gift: {
|
||||||
|
title: 'Secure early credit for Logto SaaS join the front-runners now !',
|
||||||
|
description: 'Book a one-on-one session with our team for early credit and use case sharing.',
|
||||||
|
reserve_title: 'Reserve your time with Logto team',
|
||||||
|
reserve_description:
|
||||||
|
'You can also save the calendar link. We’re always available to assist you.',
|
||||||
|
book_button: 'Book',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default cloud;
|
export default cloud;
|
||||||
|
|
|
@ -59,6 +59,14 @@ const cloud = {
|
||||||
discord_link: 'discord channel', // UNTRANSLATED
|
discord_link: 'discord channel', // UNTRANSLATED
|
||||||
enter_admin_console: 'Enter Admin Console', // UNTRANSLATED
|
enter_admin_console: 'Enter Admin Console', // UNTRANSLATED
|
||||||
},
|
},
|
||||||
|
gift: {
|
||||||
|
title: 'Secure early credit for Logto SaaS join the front-runners now !', // UNTRANSLATED
|
||||||
|
description: 'Book a one-on-one session with our team for early credit and use case sharing.', // UNTRANSLATED
|
||||||
|
reserve_title: 'Reserve your time with Logto team', // UNTRANSLATED
|
||||||
|
reserve_description:
|
||||||
|
'You can also save the calendar link. We’re always available to assist you.', // UNTRANSLATED
|
||||||
|
book_button: 'Book', // UNTRANSLATED
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default cloud;
|
export default cloud;
|
||||||
|
|
|
@ -59,6 +59,14 @@ const cloud = {
|
||||||
discord_link: 'discord channel', // UNTRANSLATED
|
discord_link: 'discord channel', // UNTRANSLATED
|
||||||
enter_admin_console: 'Enter Admin Console', // UNTRANSLATED
|
enter_admin_console: 'Enter Admin Console', // UNTRANSLATED
|
||||||
},
|
},
|
||||||
|
gift: {
|
||||||
|
title: 'Secure early credit for Logto SaaS join the front-runners now !', // UNTRANSLATED
|
||||||
|
description: 'Book a one-on-one session with our team for early credit and use case sharing.', // UNTRANSLATED
|
||||||
|
reserve_title: 'Reserve your time with Logto team', // UNTRANSLATED
|
||||||
|
reserve_description:
|
||||||
|
'You can also save the calendar link. We’re always available to assist you.', // UNTRANSLATED
|
||||||
|
book_button: 'Book', // UNTRANSLATED
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default cloud;
|
export default cloud;
|
||||||
|
|
|
@ -59,6 +59,14 @@ const cloud = {
|
||||||
discord_link: 'discord channel', // UNTRANSLATED
|
discord_link: 'discord channel', // UNTRANSLATED
|
||||||
enter_admin_console: 'Enter Admin Console', // UNTRANSLATED
|
enter_admin_console: 'Enter Admin Console', // UNTRANSLATED
|
||||||
},
|
},
|
||||||
|
gift: {
|
||||||
|
title: 'Secure early credit for Logto SaaS join the front-runners now !', // UNTRANSLATED
|
||||||
|
description: 'Book a one-on-one session with our team for early credit and use case sharing.', // UNTRANSLATED
|
||||||
|
reserve_title: 'Reserve your time with Logto team', // UNTRANSLATED
|
||||||
|
reserve_description:
|
||||||
|
'You can also save the calendar link. We’re always available to assist you.', // UNTRANSLATED
|
||||||
|
book_button: 'Book', // UNTRANSLATED
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default cloud;
|
export default cloud;
|
||||||
|
|
|
@ -59,6 +59,14 @@ const cloud = {
|
||||||
discord_link: 'discord channel', // UNTRANSLATED
|
discord_link: 'discord channel', // UNTRANSLATED
|
||||||
enter_admin_console: 'Enter Admin Console', // UNTRANSLATED
|
enter_admin_console: 'Enter Admin Console', // UNTRANSLATED
|
||||||
},
|
},
|
||||||
|
gift: {
|
||||||
|
title: 'Secure early credit for Logto SaaS join the front-runners now !', // UNTRANSLATED
|
||||||
|
description: 'Book a one-on-one session with our team for early credit and use case sharing.', // UNTRANSLATED
|
||||||
|
reserve_title: 'Reserve your time with Logto team', // UNTRANSLATED
|
||||||
|
reserve_description:
|
||||||
|
'You can also save the calendar link. We’re always available to assist you.', // UNTRANSLATED
|
||||||
|
book_button: 'Book', // UNTRANSLATED
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default cloud;
|
export default cloud;
|
||||||
|
|
|
@ -59,6 +59,14 @@ const cloud = {
|
||||||
discord_link: 'discord channel', // UNTRANSLATED
|
discord_link: 'discord channel', // UNTRANSLATED
|
||||||
enter_admin_console: 'Enter Admin Console', // UNTRANSLATED
|
enter_admin_console: 'Enter Admin Console', // UNTRANSLATED
|
||||||
},
|
},
|
||||||
|
gift: {
|
||||||
|
title: 'Secure early credit for Logto SaaS join the front-runners now !', // UNTRANSLATED
|
||||||
|
description: 'Book a one-on-one session with our team for early credit and use case sharing.', // UNTRANSLATED
|
||||||
|
reserve_title: 'Reserve your time with Logto team', // UNTRANSLATED
|
||||||
|
reserve_description:
|
||||||
|
'You can also save the calendar link. We’re always available to assist you.', // UNTRANSLATED
|
||||||
|
book_button: 'Book', // UNTRANSLATED
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default cloud;
|
export default cloud;
|
||||||
|
|
|
@ -59,6 +59,14 @@ const cloud = {
|
||||||
discord_link: 'discord channel', // UNTRANSLATED
|
discord_link: 'discord channel', // UNTRANSLATED
|
||||||
enter_admin_console: 'Enter Admin Console', // UNTRANSLATED
|
enter_admin_console: 'Enter Admin Console', // UNTRANSLATED
|
||||||
},
|
},
|
||||||
|
gift: {
|
||||||
|
title: 'Secure early credit for Logto SaaS join the front-runners now !', // UNTRANSLATED
|
||||||
|
description: 'Book a one-on-one session with our team for early credit and use case sharing.', // UNTRANSLATED
|
||||||
|
reserve_title: 'Reserve your time with Logto team', // UNTRANSLATED
|
||||||
|
reserve_description:
|
||||||
|
'You can also save the calendar link. We’re always available to assist you.', // UNTRANSLATED
|
||||||
|
book_button: 'Book', // UNTRANSLATED
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default cloud;
|
export default cloud;
|
||||||
|
|
Loading…
Reference in a new issue