mirror of
https://github.com/chartdb/chartdb.git
synced 2025-10-23 07:11:56 +00:00
add buckle dialog (#498)
This commit is contained in:
BIN
public/buckle-animated.gif
Normal file
BIN
public/buckle-animated.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 404 KiB |
BIN
public/buckle.png
Normal file
BIN
public/buckle.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
@@ -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,
|
||||
});
|
||||
|
@@ -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>
|
||||
);
|
||||
};
|
||||
|
@@ -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,
|
||||
});
|
||||
|
@@ -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}
|
||||
|
80
src/dialogs/buckle-dialog/buckle-dialog.tsx
Normal file
80
src/dialogs/buckle-dialog/buckle-dialog.tsx
Normal 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>
|
||||
);
|
||||
};
|
@@ -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 () => {
|
||||
|
Reference in New Issue
Block a user