(0)
+
+ const nextPage = useCallback(() => {
+ setCurrentPage(cur => clamp(cur + 1))
+ sendMB('table-generator-promotion-next-page')
+ }, [])
+
+ const page = PROMOTION_PAGES[clamp(currentPage)]
+ const PageComponent = page.body
+ const pageTitle = page.title
+ const isAtLastPage = currentPage >= PROMOTION_PAGES.length - 1
+
+ const hideBecauseOfGrammarly =
+ grammarlyExtensionPresent() && NOW_TIME < GRAMMARLY_CUTOFF_TIME
+
+ if (
+ !timeoutExpired ||
+ !ref ||
+ typeof ref === 'function' ||
+ !ref.current ||
+ hideBecauseOfGrammarly
+ ) {
+ return null
+ }
+
+ return (
+
+
+ {pageTitle}
+
+
+ }
+ className="dark-themed"
+ >
+
+
+
+
+
+
+ )
+ })
+)
+
+const PromotionBody: FC = function PromotionBody({ children }) {
+ useEffect(() => {
+ sendMB('table-generator-promotion-prompt')
+ }, [])
+ return {children}
+}
+
+const Footer = memo<{
+ isAtLastPage: boolean
+ onComplete: () => void
+ onNext: () => void
+}>(function Footer({ isAtLastPage, onComplete, onNext }) {
+ return (
+
+ {!isAtLastPage ? (
+
+ ) : (
+
+ )}
+
+ )
+})
+
+const TablePromotionPage: FC = memo(function TablePromotionPage() {
+ return (
+ <>
+
+ You can now insert tables with just a few clicks and edit them without
+ code in Visual Editor. And there’s more…
+
+
+ >
+ )
+})
+
+const PastingPromotionPage: FC = memo(function PastingPromotionPage() {
+ return (
+ <>
+
+ You can also paste tables (and formatted text!) straight into{' '}
+ Visual Editor without losing the formatting.
+
+
+ >
+ )
+})
+
+const PROMOTION_PAGES: { title: string; body: FC }[] = [
+ {
+ title: 'Big news! Insert tables from the toolbar',
+ body: TablePromotionPage,
+ },
+ {
+ title: 'Paste a table straight into Visual Editor',
+ body: PastingPromotionPage,
+ },
+]
+
+const clamp = (num: number) =>
+ Math.min(Math.max(num, 0), PROMOTION_PAGES.length - 1)
+
+interface VideoProps extends React.VideoHTMLAttributes {
+ src: string
+}
+const Video = memo(function Video({ src, ...props }: VideoProps) {
+ return (
+
+ )
+})
diff --git a/services/web/frontend/js/shared/context/user-context.js b/services/web/frontend/js/shared/context/user-context.js
index 1c4207a4bd..8c2ba0c256 100644
--- a/services/web/frontend/js/shared/context/user-context.js
+++ b/services/web/frontend/js/shared/context/user-context.js
@@ -16,6 +16,7 @@ UserContext.Provider.propTypes = {
alphaProgram: PropTypes.boolean,
betaProgram: PropTypes.boolean,
labsProgram: PropTypes.boolean,
+ signUpDate: PropTypes.string,
features: PropTypes.shape({
dropbox: PropTypes.boolean,
github: PropTypes.boolean,
diff --git a/services/web/frontend/stories/source-editor/source-editor.stories.tsx b/services/web/frontend/stories/source-editor/source-editor.stories.tsx
index ad71f54158..1ce56d0a30 100644
--- a/services/web/frontend/stories/source-editor/source-editor.stories.tsx
+++ b/services/web/frontend/stories/source-editor/source-editor.stories.tsx
@@ -102,6 +102,9 @@ export const Visual = (args: any, { globals: { theme } }: any) => {
'paste-html': 'enabled',
'table-generator': 'enabled',
},
+ 'ol-completedTutorials': {
+ 'table-generator-promotion': '2023-09-01T00:00:00.000Z',
+ },
})
return
diff --git a/services/web/test/frontend/features/source-editor/components/codemirror-editor-table-generator.spec.tsx b/services/web/test/frontend/features/source-editor/components/codemirror-editor-table-generator.spec.tsx
index 361a08d0e7..cf25fcf9d7 100644
--- a/services/web/test/frontend/features/source-editor/components/codemirror-editor-table-generator.spec.tsx
+++ b/services/web/test/frontend/features/source-editor/components/codemirror-editor-table-generator.spec.tsx
@@ -114,6 +114,9 @@ describe(' Table editor', function () {
window.metaAttributesCache.set('ol-splitTestVariants', {
'table-generator': 'enabled',
})
+ window.metaAttributesCache.set('ol-completedTutorials', {
+ 'table-generator-promotion': '2023-09-01T00:00:00.000Z',
+ })
})
describe('Table rendering', function () {
diff --git a/services/web/types/user.ts b/services/web/types/user.ts
index 137d7a5abd..9478fba88e 100644
--- a/services/web/types/user.ts
+++ b/services/web/types/user.ts
@@ -2,6 +2,7 @@ export type User = {
id: string
email: string
allowedFreeTrial?: boolean
+ signUpDate?: string // date string
features?: {
collaborators?: number
compileGroup?: 'standard' | 'priority'