Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/dashboard/src/repositories/coachmarks/MigrationCoachmark.tsx
2501 views
1
/**
2
* Copyright (c) 2024 Gitpod GmbH. All rights reserved.
3
* Licensed under the GNU Affero General Public License (AGPL).
4
* See License.AGPL.txt in the project root for license information.
5
*/
6
7
import { Button } from "@podkit/buttons/Button";
8
import { Popover, PopoverArrow, PopoverContent, PopoverTrigger } from "@podkit/popover/Popover";
9
import { Text } from "@podkit/typography/Text";
10
import { Truck } from "lucide-react";
11
import { PropsWithChildren, useCallback, useMemo, useState } from "react";
12
import { Link, useHistory } from "react-router-dom";
13
import { useUserLoader } from "../../hooks/use-user-loader";
14
import { useUpdateCurrentUserMutation } from "../../data/current-user/update-mutation";
15
import dayjs from "dayjs";
16
import { trackEvent } from "../../Analytics";
17
18
const COACHMARK_KEY = "projects_configuration_migration";
19
20
type Props = PropsWithChildren<{}>;
21
export const ConfigurationsMigrationCoachmark = ({ children }: Props) => {
22
const [isOpen, setIsOpen] = useState(true);
23
24
const history = useHistory();
25
26
const { user } = useUserLoader();
27
const { mutate: updateUser } = useUpdateCurrentUserMutation();
28
29
const dismiss = useCallback(() => {
30
updateUser(
31
{
32
additionalData: { profile: { coachmarksDismissals: { [COACHMARK_KEY]: dayjs().toISOString() } } },
33
},
34
{
35
onSettled: (_, error) => {
36
trackEvent("coachmark_dismissed", {
37
name: COACHMARK_KEY,
38
success: !(error instanceof Error),
39
});
40
},
41
},
42
);
43
}, [updateUser]);
44
45
const show = useMemo<boolean>(() => {
46
if (!isOpen || !user) {
47
return false;
48
}
49
50
// For the users signing up after our launch of configurations, don't show it
51
if (user.createdAt && user.createdAt.toDate() > new Date("2/21/2024")) {
52
return false;
53
}
54
55
// User already knows about the feature
56
if (history.location.pathname.startsWith("/repositories")) {
57
dismiss();
58
return false;
59
}
60
61
return !user.profile?.coachmarksDismissals[COACHMARK_KEY];
62
}, [dismiss, history.location.pathname, isOpen, user]);
63
64
const handleClose = useCallback(() => {
65
setIsOpen(false);
66
// do not store the dismissal if the popover is not shown
67
if (show) {
68
dismiss();
69
}
70
}, [dismiss, show]);
71
72
return (
73
<Popover open={show}>
74
<PopoverTrigger onClick={handleClose}>{children}</PopoverTrigger>
75
<PopoverContent align={"start"} className="border-pk-border-base relative flex flex-col">
76
<PopoverArrow asChild>
77
<div className="mb-[6px] ml-2 inline-block overflow-hidden rotate-180 relative">
78
<div className="h-3 w-5 origin-bottom-left rotate-45 transform border border-pk-border-base bg-pk-surface-primary before:absolute before:bottom-0 before:left-0 before:w-full before:h-[1px] before:bg-pk-surface-primary" />
79
</div>
80
</PopoverArrow>
81
82
<Text className="flex flex-row gap-2 text-lg font-bold items-center pt-3">
83
<Truck /> Projects have moved
84
</Text>
85
<Text className="text-pk-content-secondary text-base pb-4 pt-2">
86
Projects are now called “
87
<Link to={"/repositories"} className="gp-link">
88
Repository settings
89
</Link>
90
”. You can find them in your organization menu.
91
</Text>
92
<Button className="self-end" variant={"secondary"} onClick={handleClose}>
93
Dismiss
94
</Button>
95
</PopoverContent>
96
</Popover>
97
);
98
};
99
100