diff --git a/packages/ui/src/toast/index.tsx b/packages/ui/src/toast/index.tsx index f380505326..ce2d05ef78 100644 --- a/packages/ui/src/toast/index.tsx +++ b/packages/ui/src/toast/index.tsx @@ -25,13 +25,16 @@ type SetToastProps = type: Exclude; title: string; message?: string; + actionItems?: React.ReactNode; }; type PromiseToastCallback = (data: ToastData) => string; +type ActionItemsPromiseToastCallback = (data: ToastData) => JSX.Element; type PromiseToastData = { title: string; message?: PromiseToastCallback; + actionItems?: ActionItemsPromiseToastCallback; }; type PromiseToastOptions = { @@ -54,7 +57,7 @@ type ToastProps = { export const Toast = (props: ToastProps) => { const { theme } = props; - return ; + return ; }; export const setToast = (props: SetToastProps) => { @@ -66,29 +69,27 @@ export const setToast = (props: SetToastProps) => { borderColorClassName, }: ToastContentProps) => props.type === TOAST_TYPE.LOADING ? ( -
{ - e.stopPropagation(); - e.preventDefault(); - }} - className={cn( - "w-[350px] h-[67.3px] rounded-lg border shadow-sm p-2", - backgroundColorClassName, - borderColorClassName - )} - > -
- {icon &&
{icon}
} -
-
{props.title ?? "Loading..."}
-
- toast.dismiss(toastId)} - /> +
+
{ + e.stopPropagation(); + e.preventDefault(); + }} + className={cn("w-full rounded-lg border shadow-sm p-2", backgroundColorClassName, borderColorClassName)} + > +
+ {icon &&
{icon}
} +
+
{props.title ?? "Loading..."}
+
+ toast.dismiss(toastId)} + /> +
@@ -100,7 +101,7 @@ export const setToast = (props: SetToastProps) => { e.preventDefault(); }} className={cn( - "relative flex flex-col w-[350px] rounded-lg border shadow-sm p-2", + "relative group flex flex-col w-[350px] rounded-lg border shadow-sm p-2", backgroundColorClassName, borderColorClassName )} @@ -112,12 +113,15 @@ export const setToast = (props: SetToastProps) => { height={14} onClick={() => toast.dismiss(toastId)} /> -
- {icon &&
{icon}
} -
-
{props.title}
- {props.message &&
{props.message}
} +
+
+ {icon &&
{icon}
} +
+
{props.title}
+ {props.message &&
{props.message}
} +
+ {props.actionItems &&
{props.actionItems}
}
); @@ -128,7 +132,7 @@ export const setToast = (props: SetToastProps) => { (toastId) => renderToastContent({ toastId, - icon: , + icon: , textColorClassName: "text-toast-text-success", backgroundColorClassName: "bg-toast-background-success", borderColorClassName: "border-toast-border-success", @@ -140,7 +144,7 @@ export const setToast = (props: SetToastProps) => { (toastId) => renderToastContent({ toastId, - icon: , + icon: , textColorClassName: "text-toast-text-error", backgroundColorClassName: "bg-toast-background-error", borderColorClassName: "border-toast-border-error", @@ -152,7 +156,7 @@ export const setToast = (props: SetToastProps) => { (toastId) => renderToastContent({ toastId, - icon: , + icon: , textColorClassName: "text-toast-text-warning", backgroundColorClassName: "bg-toast-background-warning", borderColorClassName: "border-toast-border-warning", @@ -197,6 +201,7 @@ export const setPromiseToast = ( id: tId, title: options.success.title, message: options.success.message?.(data), + actionItems: options.success.actionItems?.(data), }); }) .catch((data: ToastData) => { @@ -205,6 +210,7 @@ export const setPromiseToast = ( id: tId, title: options.error.title, message: options.error.message?.(data), + actionItems: options.error.actionItems?.(data), }); }); }; diff --git a/web/app/[workspaceSlug]/(projects)/profile/[userId]/activity/page.tsx b/web/app/[workspaceSlug]/(projects)/profile/[userId]/activity/page.tsx index 8b5ba07e0c..cae273fd4c 100644 --- a/web/app/[workspaceSlug]/(projects)/profile/[userId]/activity/page.tsx +++ b/web/app/[workspaceSlug]/(projects)/profile/[userId]/activity/page.tsx @@ -6,6 +6,7 @@ import { useParams } from "next/navigation"; // ui import { Button } from "@plane/ui"; // components +import { PageHead } from "@/components/core"; import { DownloadActivityButton, WorkspaceActivityListPage } from "@/components/profile"; // constants import { EUserWorkspaceRoles } from "@/constants/workspace"; @@ -50,22 +51,25 @@ const ProfileActivityPage = observer(() => { currentUser?.id === userId && !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER; return ( -
-
-

Recent activity

- {canDownloadActivity && } + <> + +
+
+

Recent activity

+ {canDownloadActivity && } +
+
+ {activityPages} + {pageCount < totalPages && resultsCount !== 0 && ( +
+ +
+ )} +
-
- {activityPages} - {pageCount < totalPages && resultsCount !== 0 && ( -
- -
- )} -
-
+ ); }); diff --git a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/cycles/layout.tsx b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/cycles/layout.tsx index ced92a6ac8..5da3018b3f 100644 --- a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/cycles/layout.tsx +++ b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/cycles/layout.tsx @@ -7,7 +7,7 @@ import { ProjectArchivesHeader } from "../header"; export default function ProjectArchiveCyclesLayout({ children }: { children: React.ReactNode }) { return ( <> - } /> + } /> {children} ); diff --git a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/header.tsx b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/header.tsx index 8d7e934060..5f6db17a8a 100644 --- a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/header.tsx +++ b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/header.tsx @@ -2,7 +2,7 @@ import { FC } from "react"; import { observer } from "mobx-react"; -import { useParams, usePathname } from "next/navigation"; +import { useParams } from "next/navigation"; // ui import { ArchiveIcon, Breadcrumbs, Tooltip } from "@plane/ui"; // components @@ -15,12 +15,15 @@ import { useIssues, useProject } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; import { usePlatformOS } from "@/hooks/use-platform-os"; -export const ProjectArchivesHeader: FC = observer(() => { +type TProps = { + activeTab: 'issues' | 'cycles' | 'modules'; +} + +export const ProjectArchivesHeader: FC = observer((props: TProps) => { + const { activeTab } = props; // router const router = useAppRouter(); const { workspaceSlug, projectId } = useParams(); - const pathname = usePathname(); - const activeTab = pathname.split("/").pop(); // store hooks const { issuesFilter: { issueFilters }, diff --git a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(list)/layout.tsx b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(list)/layout.tsx index d12a5e01dd..eb2df313da 100644 --- a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(list)/layout.tsx +++ b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/issues/(list)/layout.tsx @@ -7,7 +7,7 @@ import { ProjectArchivesHeader } from "../../header"; export default function ProjectArchiveIssuesLayout({ children }: { children: React.ReactNode }) { return ( <> - } /> + } /> {children} ); diff --git a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/modules/layout.tsx b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/modules/layout.tsx index 333bcf74d6..c1e48db7c0 100644 --- a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/modules/layout.tsx +++ b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/archives/modules/layout.tsx @@ -7,7 +7,7 @@ import { ProjectArchivesHeader } from "../header"; export default function ProjectArchiveModulesLayout({ children }: { children: React.ReactNode }) { return ( <> - } /> + } /> {children} ); diff --git a/web/app/onboarding/page.tsx b/web/app/onboarding/page.tsx index 090b2059ef..9e318e521e 100644 --- a/web/app/onboarding/page.tsx +++ b/web/app/onboarding/page.tsx @@ -14,7 +14,7 @@ import { USER_WORKSPACES_LIST } from "@/constants/fetch-keys"; // helpers import { EPageTypes } from "@/helpers/authentication.helper"; // hooks -import { useUser, useWorkspace, useUserProfile, useEventTracker } from "@/hooks/store"; +import { useUser, useWorkspace, useUserProfile, useEventTracker, useUserSettings } from "@/hooks/store"; import { useAppRouter } from "@/hooks/use-app-router"; // wrappers import { AuthenticationWrapper } from "@/lib/wrappers"; @@ -39,6 +39,7 @@ const OnboardingPage = observer(() => { const { captureEvent } = useEventTracker(); const { isLoading: userLoader, data: user, updateCurrentUser } = useUser(); const { data: profile, updateUserOnBoard, updateUserProfile } = useUserProfile(); + const { data: currentUserSettings } = useUserSettings(); const { workspaces, fetchWorkspaces } = useWorkspace(); // computed values @@ -65,6 +66,27 @@ const OnboardingPage = observer(() => { await updateUserProfile(payload); }; + const getWorkspaceRedirectionUrl = (): string => { + let redirectionRoute = "/profile"; + + // validate the last and fallback workspace_slug + const currentWorkspaceSlug = + currentUserSettings?.workspace?.last_workspace_slug || + currentUserSettings?.workspace?.fallback_workspace_slug || + undefined; + + if (currentWorkspaceSlug) { + const isCurrentWorkspaceValid = Object.values(workspaces || {}).findIndex( + (workspace) => workspace.slug === currentWorkspaceSlug + ); + if (isCurrentWorkspaceValid >= 0) { + redirectionRoute = `/${currentWorkspaceSlug}`; + } + } + + return redirectionRoute; + }; + // complete onboarding const finishOnboarding = async () => { if (!user || !workspaces) return; @@ -95,7 +117,7 @@ const OnboardingPage = observer(() => { console.log("Failed to update onboarding status"); }); - router.replace(`/${firstWorkspace?.slug}`); + router.replace(`${getWorkspaceRedirectionUrl()}`); }; useEffect(() => { diff --git a/web/app/profile/appearance/page.tsx b/web/app/profile/appearance/page.tsx index 4a4c85d2f1..e3a2840d58 100644 --- a/web/app/profile/appearance/page.tsx +++ b/web/app/profile/appearance/page.tsx @@ -49,7 +49,7 @@ const ProfileAppearancePage = observer(() => { return ( <> - + {userProfile ? ( diff --git a/web/app/profile/notifications/page.tsx b/web/app/profile/notifications/page.tsx index f6bb1e4e51..b39563378b 100644 --- a/web/app/profile/notifications/page.tsx +++ b/web/app/profile/notifications/page.tsx @@ -23,7 +23,7 @@ export default function ProfileNotificationPage() { return ( <> - + { */}
-
+

First name* diff --git a/web/app/profile/security/page.tsx b/web/app/profile/security/page.tsx index 503c099f6e..e1de5ef1f1 100644 --- a/web/app/profile/security/page.tsx +++ b/web/app/profile/security/page.tsx @@ -130,7 +130,7 @@ const SecurityPage = observer(() => { return ( <> - +
diff --git a/web/core/components/estimates/root.tsx b/web/core/components/estimates/root.tsx index 4cecd94789..d50183a8ae 100644 --- a/web/core/components/estimates/root.tsx +++ b/web/core/components/estimates/root.tsx @@ -82,7 +82,11 @@ export const EstimateRoot: FC = observer((props) => {

Estimates have gone through a change, these are the estimates you had in your older versions which were not in use. Read more about them  - + here.

diff --git a/web/core/components/issues/create-issue-toast-action-items.tsx b/web/core/components/issues/create-issue-toast-action-items.tsx new file mode 100644 index 0000000000..0fe76fb9b6 --- /dev/null +++ b/web/core/components/issues/create-issue-toast-action-items.tsx @@ -0,0 +1,70 @@ +"use client"; +import React, { FC, useState } from "react"; +import { observer } from "mobx-react"; +// helpers +import { copyUrlToClipboard } from "@/helpers/string.helper"; +// hooks +import { useIssueDetail } from "@/hooks/store"; + +type TCreateIssueToastActionItems = { + workspaceSlug: string; + projectId: string; + issueId: string; +}; + +export const CreateIssueToastActionItems: FC = observer((props) => { + const { workspaceSlug, projectId, issueId } = props; + // state + const [copied, setCopied] = useState(false); + // store hooks + const { + issue: { getIssueById }, + } = useIssueDetail(); + + // derived values + const issue = getIssueById(issueId); + + if (!issue) return null; + + const issueLink = `${workspaceSlug}/projects/${projectId}/issues/${issueId}`; + + const copyToClipboard = async (e: React.MouseEvent) => { + try { + await copyUrlToClipboard(issueLink); + setCopied(true); + setTimeout(() => setCopied(false), 3000); + } catch (error) { + setCopied(false); + } + e.preventDefault(); + e.stopPropagation(); + }; + + return ( +
+ + View issue + + + {copied ? ( + <> + Copied! + + ) : ( + <> + + + )} +
+ ); +}); diff --git a/web/core/components/issues/index.ts b/web/core/components/issues/index.ts index 454d851109..8b8180a131 100644 --- a/web/core/components/issues/index.ts +++ b/web/core/components/issues/index.ts @@ -9,6 +9,7 @@ export * from "./parent-issues-list-modal"; export * from "./label"; export * from "./confirm-issue-discard"; export * from "./issue-update-status"; +export * from "./create-issue-toast-action-items"; // issue details export * from "./issue-detail"; diff --git a/web/core/components/issues/issue-layouts/calendar/quick-add-issue-form.tsx b/web/core/components/issues/issue-layouts/calendar/quick-add-issue-form.tsx index b40a7050a0..6ee3e19e33 100644 --- a/web/core/components/issues/issue-layouts/calendar/quick-add-issue-form.tsx +++ b/web/core/components/issues/issue-layouts/calendar/quick-add-issue-form.tsx @@ -12,6 +12,7 @@ import { ISearchIssueResponse, TIssue } from "@plane/types"; import { TOAST_TYPE, setPromiseToast, setToast, CustomMenu } from "@plane/ui"; // components import { ExistingIssuesListModal } from "@/components/core"; +import { CreateIssueToastActionItems } from "@/components/issues"; // constants import { ISSUE_CREATED } from "@/constants/event-tracker"; // helpers @@ -135,6 +136,13 @@ export const CalendarQuickAddIssueForm: React.FC = observer((props) => { success: { title: "Success!", message: () => "Issue created successfully.", + actionItems: (data) => ( + + ), }, error: { title: "Error!", diff --git a/web/core/components/issues/issue-layouts/gantt/quick-add-issue-form.tsx b/web/core/components/issues/issue-layouts/gantt/quick-add-issue-form.tsx index 9cb02b677a..f5996af691 100644 --- a/web/core/components/issues/issue-layouts/gantt/quick-add-issue-form.tsx +++ b/web/core/components/issues/issue-layouts/gantt/quick-add-issue-form.tsx @@ -8,6 +8,7 @@ import { PlusIcon } from "lucide-react"; import { IProject, TIssue } from "@plane/types"; // hooks import { setPromiseToast } from "@plane/ui"; +import { CreateIssueToastActionItems } from "@/components/issues"; import { ISSUE_CREATED } from "@/constants/event-tracker"; import { cn } from "@/helpers/common.helper"; import { renderFormattedPayloadDate } from "@/helpers/date-time.helper"; @@ -113,6 +114,13 @@ export const GanttQuickAddIssueForm: React.FC = observe success: { title: "Success!", message: () => "Issue created successfully.", + actionItems: (data) => ( + + ), }, error: { title: "Error!", diff --git a/web/core/components/issues/issue-layouts/kanban/quick-add-issue-form.tsx b/web/core/components/issues/issue-layouts/kanban/quick-add-issue-form.tsx index f0914fcddb..263ccc99c8 100644 --- a/web/core/components/issues/issue-layouts/kanban/quick-add-issue-form.tsx +++ b/web/core/components/issues/issue-layouts/kanban/quick-add-issue-form.tsx @@ -8,6 +8,7 @@ import { PlusIcon } from "lucide-react"; import { TIssue } from "@plane/types"; // hooks import { setPromiseToast } from "@plane/ui"; +import { CreateIssueToastActionItems } from "@/components/issues"; import { ISSUE_CREATED } from "@/constants/event-tracker"; import { createIssuePayload } from "@/helpers/issue.helper"; import { useEventTracker, useProject } from "@/hooks/store"; @@ -102,6 +103,13 @@ export const KanBanQuickAddIssueForm: React.FC = obser success: { title: "Success!", message: () => "Issue created successfully.", + actionItems: (data) => ( + + ), }, error: { title: "Error!", diff --git a/web/core/components/issues/issue-layouts/list/quick-add-issue-form.tsx b/web/core/components/issues/issue-layouts/list/quick-add-issue-form.tsx index 5bc85837aa..0025f2dfc1 100644 --- a/web/core/components/issues/issue-layouts/list/quick-add-issue-form.tsx +++ b/web/core/components/issues/issue-layouts/list/quick-add-issue-form.tsx @@ -8,6 +8,7 @@ import { PlusIcon } from "lucide-react"; import { TIssue, IProject } from "@plane/types"; // hooks import { setPromiseToast } from "@plane/ui"; +import { CreateIssueToastActionItems } from "@/components/issues"; import { ISSUE_CREATED } from "@/constants/event-tracker"; import { createIssuePayload } from "@/helpers/issue.helper"; import { useEventTracker, useProject } from "@/hooks/store"; @@ -104,6 +105,13 @@ export const ListQuickAddIssueForm: FC = observer((props success: { title: "Success!", message: () => "Issue created successfully.", + actionItems: (data) => ( + + ), }, error: { title: "Error!", diff --git a/web/core/components/issues/issue-layouts/quick-action-dropdowns/draft-issue.tsx b/web/core/components/issues/issue-layouts/quick-action-dropdowns/draft-issue.tsx index a3108aa8e2..70fb245889 100644 --- a/web/core/components/issues/issue-layouts/quick-action-dropdowns/draft-issue.tsx +++ b/web/core/components/issues/issue-layouts/quick-action-dropdowns/draft-issue.tsx @@ -81,6 +81,11 @@ export const DraftIssueQuickActions: React.FC = observer((pro }, ]; + // check if any of the menu items should render + const shouldRenderQuickAction = MENU_ITEMS.some((item) => item.shouldRender); + + if (!shouldRenderQuickAction) return <>; + return ( <> = observer((props) => success: { title: "Success!", message: () => "Issue created successfully.", + actionItems: (data) => ( + + ), }, error: { title: "Error!", diff --git a/web/core/components/issues/issue-modal/modal.tsx b/web/core/components/issues/issue-modal/modal.tsx index 5877069ef1..2ff03df666 100644 --- a/web/core/components/issues/issue-modal/modal.tsx +++ b/web/core/components/issues/issue-modal/modal.tsx @@ -7,6 +7,7 @@ import { useParams, usePathname } from "next/navigation"; import type { TIssue } from "@plane/types"; // ui import { EModalPosition, EModalWidth, ModalCore, TOAST_TYPE, setToast } from "@plane/ui"; +import { CreateIssueToastActionItems } from "@/components/issues"; // constants import { ISSUE_CREATED, ISSUE_UPDATED } from "@/constants/event-tracker"; import { EIssuesStoreType } from "@/constants/issue"; @@ -189,6 +190,13 @@ export const CreateUpdateIssueModal: React.FC = observer((prop type: TOAST_TYPE.SUCCESS, title: "Success!", message: `${is_draft_issue ? "Draft issue" : "Issue"} created successfully.`, + actionItems: !is_draft_issue && ( + + ), }); captureIssueEvent({ eventName: ISSUE_CREATED, diff --git a/web/core/components/notifications/notification-card.tsx b/web/core/components/notifications/notification-card.tsx index 7c4a8313ec..9b540d1185 100644 --- a/web/core/components/notifications/notification-card.tsx +++ b/web/core/components/notifications/notification-card.tsx @@ -8,7 +8,6 @@ import { ArchiveRestore, Clock, MessageSquare, MoreVertical, User2 } from "lucid import { Menu } from "@headlessui/react"; // type import type { IUserNotification, NotificationType } from "@plane/types"; -// ui import { ArchiveIcon, CustomMenu, Tooltip, TOAST_TYPE, setToast } from "@plane/ui"; // constants import { @@ -20,6 +19,7 @@ import { import { snoozeOptions } from "@/constants/notification"; // helper import { calculateTimeAgo, renderFormattedTime, renderFormattedDate, getDate } from "@/helpers/date-time.helper"; +import { sanitizeCommentForNotification } from "@/helpers/notification.helper"; import { replaceUnderscoreIfSnakeCase, truncateText, stripAndTruncateHTML } from "@/helpers/string.helper"; // hooks import { useEventTracker } from "@/hooks/store"; @@ -206,11 +206,7 @@ export const NotificationCard: React.FC = (props) => { ) ) : ( - {`"`} - {notification.data.issue_activity.new_value.length > 55 - ? notification?.data?.issue_activity?.issue_comment?.slice(0, 50) + "..." - : notification.data.issue_activity.issue_comment} - {`"`} + {sanitizeCommentForNotification(notification.data.issue_activity.new_value ?? undefined)} ) ) : ( diff --git a/web/core/components/onboarding/create-workspace.tsx b/web/core/components/onboarding/create-workspace.tsx index 2be98aca88..b8c708abcf 100644 --- a/web/core/components/onboarding/create-workspace.tsx +++ b/web/core/components/onboarding/create-workspace.tsx @@ -1,6 +1,7 @@ "use client"; import { useState } from "react"; +import { observer } from "mobx-react"; import { Controller, useForm } from "react-hook-form"; // types import { IUser, IWorkspace, TOnboardingSteps } from "@plane/types"; @@ -10,7 +11,7 @@ import { Button, CustomSelect, Input, Spinner, TOAST_TYPE, setToast } from "@pla import { E_ONBOARDING, WORKSPACE_CREATED } from "@/constants/event-tracker"; import { ORGANIZATION_SIZE, RESTRICTED_URLS } from "@/constants/workspace"; // hooks -import { useEventTracker, useUserProfile, useWorkspace } from "@/hooks/store"; +import { useEventTracker, useUserProfile, useUserSettings, useWorkspace } from "@/hooks/store"; // services import { WorkspaceService } from "@/services/workspace.service"; @@ -24,15 +25,15 @@ type Props = { // services const workspaceService = new WorkspaceService(); -export const CreateWorkspace: React.FC = (props) => { +export const CreateWorkspace: React.FC = observer((props) => { const { stepChange, user, invitedWorkspaces, handleCurrentViewChange } = props; // states const [slugError, setSlugError] = useState(false); const [invalidSlug, setInvalidSlug] = useState(false); // store hooks const { updateUserProfile } = useUserProfile(); - - const { createWorkspace, fetchWorkspaces, workspaces } = useWorkspace(); + const { fetchCurrentUserSettings } = useUserSettings(); + const { createWorkspace, fetchWorkspaces } = useWorkspace(); const { captureWorkspaceEvent } = useEventTracker(); // form info const { @@ -59,7 +60,7 @@ export const CreateWorkspace: React.FC = (props) => { setSlugError(false); await createWorkspace(formData) - .then(async (res) => { + .then(async (workspaceResponse) => { setToast({ type: TOAST_TYPE.SUCCESS, title: "Success!", @@ -68,14 +69,14 @@ export const CreateWorkspace: React.FC = (props) => { captureWorkspaceEvent({ eventName: WORKSPACE_CREATED, payload: { - ...res, + ...workspaceResponse, state: "SUCCESS", first_time: true, element: E_ONBOARDING, }, }); await fetchWorkspaces(); - await completeStep(); + await completeStep(workspaceResponse.id); }) .catch(() => { captureWorkspaceEvent({ @@ -103,11 +104,8 @@ export const CreateWorkspace: React.FC = (props) => { ); }; - const completeStep = async () => { - if (!user || !workspaces) return; - - const firstWorkspace = Object.values(workspaces ?? {})?.[0]; - + const completeStep = async (workspaceId: string) => { + if (!user) return; const payload: Partial = { workspace_create: true, workspace_join: true, @@ -115,8 +113,9 @@ export const CreateWorkspace: React.FC = (props) => { await stepChange(payload); await updateUserProfile({ - last_workspace_id: firstWorkspace?.id, + last_workspace_id: workspaceId, }); + await fetchCurrentUserSettings(); }; const isButtonDisabled = !isValid || invalidSlug || isSubmitting; @@ -286,4 +285,4 @@ export const CreateWorkspace: React.FC = (props) => {

); -}; +}); diff --git a/web/helpers/notification.helper.ts b/web/helpers/notification.helper.ts new file mode 100644 index 0000000000..fbc77d21bf --- /dev/null +++ b/web/helpers/notification.helper.ts @@ -0,0 +1,8 @@ +import { stripAndTruncateHTML } from "./string.helper"; + +export const sanitizeCommentForNotification = (mentionContent: string | undefined) => + mentionContent + ? stripAndTruncateHTML( + mentionContent.replace(/]*\blabel="([^"]*)"[^>]*><\/mention-component>/g, "$1") + ) + : mentionContent;