add buckle dialog (#498)

This commit is contained in:
Guy Ben-Aharon
2024-12-23 20:31:58 +02:00
committed by GitHub
parent c155013668
commit 91c6fb9249
8 changed files with 170 additions and 1 deletions

BIN
public/buckle-animated.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

BIN
public/buckle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -40,6 +40,10 @@ export interface DialogContext {
openStarUsDialog: () => void;
closeStarUsDialog: () => void;
// Buckle dialog
openBuckleDialog: () => void;
closeBuckleDialog: () => void;
// Export image dialog
openExportImageDialog: (
params: Omit<ExportImageDialogProps, 'dialog'>
@@ -80,4 +84,6 @@ export const dialogContext = createContext<DialogContext>({
closeExportDiagramDialog: emptyFn,
openImportDiagramDialog: emptyFn,
closeImportDiagramDialog: emptyFn,
openBuckleDialog: emptyFn,
closeBuckleDialog: emptyFn,
});

View File

@@ -17,6 +17,7 @@ import type { ExportImageDialogProps } from '@/dialogs/export-image-dialog/expor
import { ExportImageDialog } from '@/dialogs/export-image-dialog/export-image-dialog';
import { ExportDiagramDialog } from '@/dialogs/export-diagram-dialog/export-diagram-dialog';
import { ImportDiagramDialog } from '@/dialogs/import-diagram-dialog/import-diagram-dialog';
import { BuckleDialog } from '@/dialogs/buckle-dialog/buckle-dialog';
export const DialogProvider: React.FC<React.PropsWithChildren> = ({
children,
@@ -27,6 +28,7 @@ export const DialogProvider: React.FC<React.PropsWithChildren> = ({
const [openCreateRelationshipDialog, setOpenCreateRelationshipDialog] =
useState(false);
const [openStarUsDialog, setOpenStarUsDialog] = useState(false);
const [openBuckleDialog, setOpenBuckleDialog] = useState(false);
// Export image dialog
const [openExportImageDialog, setOpenExportImageDialog] = useState(false);
@@ -114,6 +116,8 @@ export const DialogProvider: React.FC<React.PropsWithChildren> = ({
closeTableSchemaDialog: () => setOpenTableSchemaDialog(false),
openStarUsDialog: () => setOpenStarUsDialog(true),
closeStarUsDialog: () => setOpenStarUsDialog(false),
closeBuckleDialog: () => setOpenBuckleDialog(false),
openBuckleDialog: () => setOpenBuckleDialog(true),
closeExportImageDialog: () => setOpenExportImageDialog(false),
openExportImageDialog: openExportImageDialogHandler,
openExportDiagramDialog: () => setOpenExportDiagramDialog(true),
@@ -149,6 +153,7 @@ export const DialogProvider: React.FC<React.PropsWithChildren> = ({
/>
<ExportDiagramDialog dialog={{ open: openExportDiagramDialog }} />
<ImportDiagramDialog dialog={{ open: openImportDiagramDialog }} />
<BuckleDialog dialog={{ open: openBuckleDialog }} />
</dialogContext.Provider>
);
};

View File

@@ -30,6 +30,12 @@ export interface LocalConfigContext {
starUsDialogLastOpen: number;
setStarUsDialogLastOpen: (lastOpen: number) => void;
buckleWaitlistOpened: boolean;
setBuckleWaitlistOpened: (githubRepoOpened: boolean) => void;
buckleDialogLastOpen: number;
setBuckleDialogLastOpen: (lastOpen: number) => void;
showDependenciesOnCanvas: boolean;
setShowDependenciesOnCanvas: (showDependenciesOnCanvas: boolean) => void;
}
@@ -56,6 +62,12 @@ export const LocalConfigContext = createContext<LocalConfigContext>({
starUsDialogLastOpen: 0,
setStarUsDialogLastOpen: emptyFn,
buckleWaitlistOpened: false,
setBuckleWaitlistOpened: emptyFn,
buckleDialogLastOpen: 0,
setBuckleDialogLastOpen: emptyFn,
showDependenciesOnCanvas: false,
setShowDependenciesOnCanvas: emptyFn,
});

View File

@@ -10,6 +10,8 @@ const showCardinalityKey = 'show_cardinality';
const hideMultiSchemaNotificationKey = 'hide_multi_schema_notification';
const githubRepoOpenedKey = 'github_repo_opened';
const starUsDialogLastOpenKey = 'star_us_dialog_last_open';
const buckleWaitlistOpenedKey = 'buckle_waitlist_opened';
const buckleDialogLastOpenKey = 'buckle_dialog_last_open';
const showDependenciesOnCanvasKey = 'show_dependencies_on_canvas';
export const LocalConfigProvider: React.FC<React.PropsWithChildren> = ({
@@ -48,6 +50,17 @@ export const LocalConfigProvider: React.FC<React.PropsWithChildren> = ({
parseInt(localStorage.getItem(starUsDialogLastOpenKey) || '0')
);
const [buckleWaitlistOpened, setBuckleWaitlistOpened] =
React.useState<boolean>(
(localStorage.getItem(buckleWaitlistOpenedKey) || 'false') ===
'true'
);
const [buckleDialogLastOpen, setBuckleDialogLastOpen] =
React.useState<number>(
parseInt(localStorage.getItem(buckleDialogLastOpenKey) || '0')
);
const [showDependenciesOnCanvas, setShowDependenciesOnCanvas] =
React.useState<boolean>(
(localStorage.getItem(showDependenciesOnCanvasKey) || 'false') ===
@@ -65,6 +78,20 @@ export const LocalConfigProvider: React.FC<React.PropsWithChildren> = ({
localStorage.setItem(githubRepoOpenedKey, githubRepoOpened.toString());
}, [githubRepoOpened]);
useEffect(() => {
localStorage.setItem(
buckleDialogLastOpenKey,
buckleDialogLastOpen.toString()
);
}, [buckleDialogLastOpen]);
useEffect(() => {
localStorage.setItem(
buckleWaitlistOpenedKey,
buckleWaitlistOpened.toString()
);
}, [buckleWaitlistOpened]);
useEffect(() => {
localStorage.setItem(
hideMultiSchemaNotificationKey,
@@ -114,6 +141,10 @@ export const LocalConfigProvider: React.FC<React.PropsWithChildren> = ({
setStarUsDialogLastOpen,
showDependenciesOnCanvas,
setShowDependenciesOnCanvas,
setBuckleDialogLastOpen,
buckleDialogLastOpen,
buckleWaitlistOpened,
setBuckleWaitlistOpened,
}}
>
{children}

View File

@@ -0,0 +1,80 @@
import React, { useCallback, useEffect } from 'react';
import { useDialog } from '@/hooks/use-dialog';
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/dialog/dialog';
import { Button } from '@/components/button/button';
import type { BaseDialogProps } from '../common/base-dialog-props';
import { useLocalConfig } from '@/hooks/use-local-config';
import { useTheme } from '@/hooks/use-theme';
export interface BuckleDialogProps extends BaseDialogProps {}
export const BuckleDialog: React.FC<BuckleDialogProps> = ({ dialog }) => {
const { setBuckleWaitlistOpened } = useLocalConfig();
const { effectiveTheme } = useTheme();
useEffect(() => {
if (!dialog.open) return;
}, [dialog.open]);
const { closeBuckleDialog } = useDialog();
const handleConfirm = useCallback(() => {
setBuckleWaitlistOpened(true);
window.open('https://waitlist.buckle.dev', '_blank');
}, [setBuckleWaitlistOpened]);
return (
<Dialog
{...dialog}
onOpenChange={(open) => {
if (!open) {
closeBuckleDialog();
}
}}
>
<DialogContent
className="flex flex-col"
showClose={false}
onInteractOutside={(e) => {
e.preventDefault();
}}
>
<DialogHeader>
<DialogTitle className="hidden" />
<DialogDescription className="hidden" />
</DialogHeader>
<div className="flex w-full flex-col items-center">
<img
src={
effectiveTheme === 'light'
? '/buckle-animated.gif'
: '/buckle.png'
}
className="h-16"
/>
<div className="mt-6 text-center text-base">
We've been working on something big -{' '}
<span className="font-semibold">Ready to explore?</span>
</div>
</div>
<DialogFooter className="flex gap-1 md:justify-between">
<DialogClose asChild>
<Button variant="secondary">Not now</Button>
</DialogClose>
<DialogClose asChild>
<Button onClick={handleConfirm}>
Try ChartDB v2.0!
</Button>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
);
};

View File

@@ -41,6 +41,10 @@ import { AlertProvider } from '@/context/alert-context/alert-provider';
const OPEN_STAR_US_AFTER_SECONDS = 30;
const SHOW_STAR_US_AGAIN_AFTER_DAYS = 1;
const OPEN_BUCKLE_AFTER_SECONDS = 60;
const SHOW_BUCKLE_AGAIN_AFTER_DAYS = 1;
const SHOW_BUCKLE_AGAIN_OPENED_AFTER_DAYS = 7;
export const EditorDesktopLayoutLazy = React.lazy(
() => import('./editor-desktop-layout')
);
@@ -60,7 +64,8 @@ const EditorPageComponent: React.FC = () => {
const { openSelectSchema, showSidePanel } = useLayout();
const { resetRedoStack, resetUndoStack } = useRedoUndoStack();
const { showLoader, hideLoader } = useFullScreenLoader();
const { openCreateDiagramDialog, openStarUsDialog } = useDialog();
const { openCreateDiagramDialog, openStarUsDialog, openBuckleDialog } =
useDialog();
const { diagramId } = useParams<{ diagramId: string }>();
const { config, updateConfig } = useConfig();
const navigate = useNavigate();
@@ -72,6 +77,9 @@ const EditorPageComponent: React.FC = () => {
starUsDialogLastOpen,
setStarUsDialogLastOpen,
githubRepoOpened,
setBuckleDialogLastOpen,
buckleDialogLastOpen,
buckleWaitlistOpened,
} = useLocalConfig();
const { toast } = useToast();
const { t } = useTranslation();
@@ -164,6 +172,33 @@ const EditorPageComponent: React.FC = () => {
starUsDialogLastOpen,
]);
useEffect(() => {
if (!currentDiagram?.id) {
return;
}
if (
new Date().getTime() - buckleDialogLastOpen >
1000 *
60 *
60 *
24 *
(buckleWaitlistOpened
? SHOW_BUCKLE_AGAIN_OPENED_AFTER_DAYS
: SHOW_BUCKLE_AGAIN_AFTER_DAYS)
) {
const lastOpen = new Date().getTime();
setBuckleDialogLastOpen(lastOpen);
setTimeout(openBuckleDialog, OPEN_BUCKLE_AFTER_SECONDS * 1000);
}
}, [
currentDiagram?.id,
buckleWaitlistOpened,
openBuckleDialog,
setBuckleDialogLastOpen,
buckleDialogLastOpen,
]);
const lastDiagramId = useRef<string>('');
const handleChangeSchema = useCallback(async () => {