From 3ef67acb920a28eefa4f93b3b660531753652d0c Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Fri, 24 May 2024 13:52:22 +0530 Subject: [PATCH 01/77] [WEB-1417] chore: fix size updating issue on create workspace form when multiple errors are shown. (#4575) --- web/components/onboarding/create-workspace.tsx | 4 ++-- web/components/workspace/create-workspace-form.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/web/components/onboarding/create-workspace.tsx b/web/components/onboarding/create-workspace.tsx index 57da9fc5a26..0dcf04387af 100644 --- a/web/components/onboarding/create-workspace.tsx +++ b/web/components/onboarding/create-workspace.tsx @@ -224,9 +224,9 @@ export const CreateWorkspace: React.FC = (props) => { )} />

You can only edit the slug of the URL

- {slugError && Workspace URL is already taken!} + {slugError &&

Workspace URL is already taken!

} {invalidSlug && ( - {`URL can only contain ( - ), ( _ ) & alphanumeric characters.`} +

{`URL can only contain ( - ), ( _ ) & alphanumeric characters.`}

)}
diff --git a/web/components/workspace/create-workspace-form.tsx b/web/components/workspace/create-workspace-form.tsx index 9ccaa813d22..d96bf093fd7 100644 --- a/web/components/workspace/create-workspace-form.tsx +++ b/web/components/workspace/create-workspace-form.tsx @@ -188,9 +188,9 @@ export const CreateWorkspaceForm: FC = observer((props) => { )} /> - {slugError && Workspace URL is already taken!} + {slugError &&

Workspace URL is already taken!

} {invalidSlug && ( - {`URL can only contain ( - ), ( _ ) & alphanumeric characters.`} +

{`URL can only contain ( - ), ( _ ) & alphanumeric characters.`}

)}
From f5d95ba3a155fe1af855d38b2a4bac85a111f6a0 Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Fri, 24 May 2024 13:52:37 +0530 Subject: [PATCH 02/77] chore: minor improvement in admin service provider field. (#4577) --- admin/components/common/copy-field.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/components/common/copy-field.tsx b/admin/components/common/copy-field.tsx index 47e1a3364e0..6322356b44d 100644 --- a/admin/components/common/copy-field.tsx +++ b/admin/components/common/copy-field.tsx @@ -24,7 +24,7 @@ export const CopyField: React.FC = (props) => { return (
-

{label}

+

{label}

-
{description}
+
{description}
); }; From 4bb4609833bc5f463644a3d35605ad92949f7e64 Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Fri, 24 May 2024 13:56:20 +0530 Subject: [PATCH 03/77] [WEB-1413] chore: update label creation toast error message. (#4572) --- web/components/labels/create-label-modal.tsx | 4 ++-- web/components/labels/create-update-label-inline.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/web/components/labels/create-label-modal.tsx b/web/components/labels/create-label-modal.tsx index 0de255c8ca7..18bed7a3aee 100644 --- a/web/components/labels/create-label-modal.tsx +++ b/web/components/labels/create-label-modal.tsx @@ -73,9 +73,9 @@ export const CreateLabelModal: React.FC = observer((props) => { }) .catch((error) => { setToast({ - title: "Oops!", + title: "Error!", type: TOAST_TYPE.ERROR, - message: error?.error ?? "Error while adding the label", + message: error?.detail ?? "Something went wrong. Please try again later.", }); reset(formData); }); diff --git a/web/components/labels/create-update-label-inline.tsx b/web/components/labels/create-update-label-inline.tsx index 2aa8851c90a..280ae55d924 100644 --- a/web/components/labels/create-update-label-inline.tsx +++ b/web/components/labels/create-update-label-inline.tsx @@ -63,9 +63,9 @@ export const CreateUpdateLabelInline = observer( }) .catch((error) => { setToast({ - title: "Oops!", + title: "Error!", type: TOAST_TYPE.ERROR, - message: error?.error ?? "Error while adding the label", + message: error?.detail ?? "Something went wrong. Please try again later.", }); reset(formData); }); From 571d35cd8b9ddd58534536c526e9bf30e93e8606 Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Fri, 24 May 2024 14:20:56 +0530 Subject: [PATCH 04/77] chore: fix breadcrumbs inconsistency. (#4574) --- web/components/headers/project-inbox.tsx | 2 +- web/components/headers/project-settings.tsx | 22 ++++++------- web/components/headers/workspace-settings.tsx | 22 +++++-------- .../[projectId]/settings/automations.tsx | 2 +- .../[projectId]/settings/estimates.tsx | 2 +- .../[projectId]/settings/features.tsx | 2 +- .../projects/[projectId]/settings/index.tsx | 2 +- .../projects/[projectId]/settings/labels.tsx | 2 +- .../projects/[projectId]/settings/members.tsx | 2 +- .../projects/[projectId]/settings/states.tsx | 2 +- .../[workspaceSlug]/settings/api-tokens.tsx | 2 +- .../[workspaceSlug]/settings/billing.tsx | 2 +- .../[workspaceSlug]/settings/exports.tsx | 2 +- .../[workspaceSlug]/settings/imports.tsx | 22 ++++++------- web/pages/[workspaceSlug]/settings/index.tsx | 2 +- .../[workspaceSlug]/settings/integrations.tsx | 32 +++++++++---------- .../[workspaceSlug]/settings/members.tsx | 2 +- .../settings/webhooks/[webhookId].tsx | 2 +- .../settings/webhooks/index.tsx | 2 +- 19 files changed, 60 insertions(+), 68 deletions(-) diff --git a/web/components/headers/project-inbox.tsx b/web/components/headers/project-inbox.tsx index d61e2492db3..082720358c8 100644 --- a/web/components/headers/project-inbox.tsx +++ b/web/components/headers/project-inbox.tsx @@ -46,7 +46,7 @@ export const ProjectInboxHeader: FC = observer(() => { } /> + } /> } /> diff --git a/web/components/headers/project-settings.tsx b/web/components/headers/project-settings.tsx index f25bfe8040f..36b9cd2472a 100644 --- a/web/components/headers/project-settings.tsx +++ b/web/components/headers/project-settings.tsx @@ -2,22 +2,17 @@ import { FC } from "react"; import { observer } from "mobx-react"; import { useRouter } from "next/router"; // ui +import { Settings } from "lucide-react"; import { Breadcrumbs, CustomMenu } from "@plane/ui"; -// helper +// components import { BreadcrumbLink } from "@/components/common"; import { ProjectLogo } from "@/components/project"; +// constants import { EUserProjectRoles, PROJECT_SETTINGS_LINKS } from "@/constants/project"; // hooks import { useProject, useUser } from "@/hooks/store"; -// constants -// components - -export interface IProjectSettingHeader { - title: string; -} -export const ProjectSettingHeader: FC = observer((props) => { - const { title } = props; +export const ProjectSettingHeader: FC = observer(() => { // router const router = useRouter(); const { workspaceSlug, projectId } = router.query; @@ -52,7 +47,12 @@ export const ProjectSettingHeader: FC = observer((props) } />
- } /> + } /> + } + />
@@ -62,7 +62,7 @@ export const ProjectSettingHeader: FC = observer((props) maxHeight="lg" customButton={ - {title} + Settings } placement="bottom-start" diff --git a/web/components/headers/workspace-settings.tsx b/web/components/headers/workspace-settings.tsx index c73d06547ce..2d3e9649e1e 100644 --- a/web/components/headers/workspace-settings.tsx +++ b/web/components/headers/workspace-settings.tsx @@ -1,21 +1,15 @@ import { FC } from "react"; -import { observer } from "mobx-react"; -import { useRouter } from "next/router"; +import { observer } from "mobx-react";; import { Settings } from "lucide-react"; // ui import { Breadcrumbs } from "@plane/ui"; // components import { BreadcrumbLink } from "@/components/common"; +// hooks +import { useWorkspace } from "@/hooks/store"; -export interface IWorkspaceSettingHeader { - title: string; -} - -export const WorkspaceSettingHeader: FC = observer((props) => { - const { title } = props; - const router = useRouter(); - - const { workspaceSlug } = router.query; +export const WorkspaceSettingHeader: FC = observer(() => { + const { currentWorkspace } = useWorkspace(); return (
@@ -26,13 +20,13 @@ export const WorkspaceSettingHeader: FC = observer((pro type="text" link={ } /> } /> - } /> + } />
diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx index 0dfc55d0236..060520fafb2 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx @@ -63,7 +63,7 @@ const AutomationSettingsPage: NextPageWithLayout = observer(() => { AutomationSettingsPage.getLayout = function getLayout(page: ReactElement) { return ( - } withProjectWrapper> + } withProjectWrapper> {page} ); diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/estimates.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/estimates.tsx index 5872ed32278..83bd4fd2599 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/estimates.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/estimates.tsx @@ -35,7 +35,7 @@ const EstimatesSettingsPage: NextPageWithLayout = observer(() => { EstimatesSettingsPage.getLayout = function getLayout(page: ReactElement) { return ( - } withProjectWrapper> + } withProjectWrapper> {page} ); diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx index a9bffc2e2a9..a55b58beb2f 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx @@ -54,7 +54,7 @@ const FeaturesSettingsPage: NextPageWithLayout = observer(() => { FeaturesSettingsPage.getLayout = function getLayout(page: ReactElement) { return ( - } withProjectWrapper> + } withProjectWrapper> {page} ); diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx index 9a9db7f515e..b07be48a5ed 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx @@ -93,7 +93,7 @@ const GeneralSettingsPage: NextPageWithLayout = observer(() => { GeneralSettingsPage.getLayout = function getLayout(page: ReactElement) { return ( - } withProjectWrapper> + } withProjectWrapper> {page} ); diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/labels.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/labels.tsx index cf13b6d257f..5c264430555 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/labels.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/labels.tsx @@ -45,7 +45,7 @@ const LabelsSettingsPage: NextPageWithLayout = observer(() => { LabelsSettingsPage.getLayout = function getLayout(page: ReactElement) { return ( - }> + }> {page} ); diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/members.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/members.tsx index dcc46ed2d54..6d60c0e7638 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/members.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/members.tsx @@ -31,7 +31,7 @@ const MembersSettingsPage: NextPageWithLayout = observer(() => { MembersSettingsPage.getLayout = function getLayout(page: ReactElement) { return ( - } withProjectWrapper> + } withProjectWrapper> {page} ); diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx index 19d1c03550a..3a696cf8e92 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx @@ -32,7 +32,7 @@ const StatesSettingsPage: NextPageWithLayout = observer(() => { StatesSettingsPage.getLayout = function getLayout(page: ReactElement) { return ( - }> + }> {page} ); diff --git a/web/pages/[workspaceSlug]/settings/api-tokens.tsx b/web/pages/[workspaceSlug]/settings/api-tokens.tsx index 87ef1621971..464c5e3736b 100644 --- a/web/pages/[workspaceSlug]/settings/api-tokens.tsx +++ b/web/pages/[workspaceSlug]/settings/api-tokens.tsx @@ -99,7 +99,7 @@ const ApiTokensPage: NextPageWithLayout = observer(() => { ApiTokensPage.getLayout = function getLayout(page: React.ReactElement) { return ( - }> + }> {page} ); diff --git a/web/pages/[workspaceSlug]/settings/billing.tsx b/web/pages/[workspaceSlug]/settings/billing.tsx index 4bfe4ac416c..583a78b17c8 100644 --- a/web/pages/[workspaceSlug]/settings/billing.tsx +++ b/web/pages/[workspaceSlug]/settings/billing.tsx @@ -59,7 +59,7 @@ const BillingSettingsPage: NextPageWithLayout = observer(() => { BillingSettingsPage.getLayout = function getLayout(page: React.ReactElement) { return ( - }> + }> {page} ); diff --git a/web/pages/[workspaceSlug]/settings/exports.tsx b/web/pages/[workspaceSlug]/settings/exports.tsx index 9f462e66564..730f34e4975 100644 --- a/web/pages/[workspaceSlug]/settings/exports.tsx +++ b/web/pages/[workspaceSlug]/settings/exports.tsx @@ -50,7 +50,7 @@ const ExportsPage: NextPageWithLayout = observer(() => { ExportsPage.getLayout = function getLayout(page: React.ReactElement) { return ( - }> + }> {page} ); diff --git a/web/pages/[workspaceSlug]/settings/imports.tsx b/web/pages/[workspaceSlug]/settings/imports.tsx index d1f6573b489..2eda7cce24d 100644 --- a/web/pages/[workspaceSlug]/settings/imports.tsx +++ b/web/pages/[workspaceSlug]/settings/imports.tsx @@ -1,17 +1,17 @@ import { observer } from "mobx-react"; +// components +import { PageHead } from "@/components/core"; +import { WorkspaceSettingHeader } from "@/components/headers"; +import IntegrationGuide from "@/components/integration/guide"; +// constants +import { EUserWorkspaceRoles } from "@/constants/workspace"; // hooks -import { PageHead } from "components/core"; -import { WorkspaceSettingHeader } from "components/headers"; -import IntegrationGuide from "components/integration/guide"; -import { EUserWorkspaceRoles } from "constants/workspace"; -import { useUser, useWorkspace } from "hooks/store"; +import { useUser, useWorkspace } from "@/hooks/store"; // layouts -import { AppLayout } from "layouts/app-layout"; -import { WorkspaceSettingLayout } from "layouts/settings-layout"; -// components +import { AppLayout } from "@/layouts/app-layout"; +import { WorkspaceSettingLayout } from "@/layouts/settings-layout"; // types -import { NextPageWithLayout } from "lib/types"; -// constants +import { NextPageWithLayout } from "@/lib/types"; const ImportsPage: NextPageWithLayout = observer(() => { // store hooks @@ -49,7 +49,7 @@ const ImportsPage: NextPageWithLayout = observer(() => { ImportsPage.getLayout = function getLayout(page: React.ReactElement) { return ( - }> + }> {page} ); diff --git a/web/pages/[workspaceSlug]/settings/index.tsx b/web/pages/[workspaceSlug]/settings/index.tsx index dcd8a710bc6..cbe92de6150 100644 --- a/web/pages/[workspaceSlug]/settings/index.tsx +++ b/web/pages/[workspaceSlug]/settings/index.tsx @@ -28,7 +28,7 @@ const WorkspaceSettingsPage: NextPageWithLayout = observer(() => { WorkspaceSettingsPage.getLayout = function getLayout(page: ReactElement) { return ( - }> + }> {page} ); diff --git a/web/pages/[workspaceSlug]/settings/integrations.tsx b/web/pages/[workspaceSlug]/settings/integrations.tsx index 9f06b92eec6..702ca58847a 100644 --- a/web/pages/[workspaceSlug]/settings/integrations.tsx +++ b/web/pages/[workspaceSlug]/settings/integrations.tsx @@ -2,25 +2,23 @@ import { ReactElement } from "react"; import { observer } from "mobx-react"; import { useRouter } from "next/router"; import useSWR from "swr"; +// components +import { PageHead } from "@/components/core"; +import { WorkspaceSettingHeader } from "@/components/headers"; +import { SingleIntegrationCard } from "@/components/integration"; +import { IntegrationAndImportExportBanner, IntegrationsSettingsLoader } from "@/components/ui"; +// constants +import { APP_INTEGRATIONS } from "@/constants/fetch-keys"; +import { EUserWorkspaceRoles } from "@/constants/workspace"; // hooks -// services +import { useUser, useWorkspace } from "@/hooks/store"; // layouts -// components -import { PageHead } from "components/core"; -import { WorkspaceSettingHeader } from "components/headers"; -import { SingleIntegrationCard } from "components/integration"; -// ui -import { IntegrationAndImportExportBanner, IntegrationsSettingsLoader } from "components/ui"; +import { AppLayout } from "@/layouts/app-layout"; +import { WorkspaceSettingLayout } from "@/layouts/settings-layout"; // types -// fetch-keys -import { APP_INTEGRATIONS } from "constants/fetch-keys"; -// constants -import { EUserWorkspaceRoles } from "constants/workspace"; -import { useUser, useWorkspace } from "hooks/store"; -import { AppLayout } from "layouts/app-layout"; -import { WorkspaceSettingLayout } from "layouts/settings-layout"; -import { NextPageWithLayout } from "lib/types"; -import { IntegrationService } from "services/integrations"; +import { NextPageWithLayout } from "@/lib/types"; +// services +import { IntegrationService } from "@/services/integrations"; const integrationService = new IntegrationService(); @@ -73,7 +71,7 @@ const WorkspaceIntegrationsPage: NextPageWithLayout = observer(() => { WorkspaceIntegrationsPage.getLayout = function getLayout(page: ReactElement) { return ( - }> + }> {page} ); diff --git a/web/pages/[workspaceSlug]/settings/members.tsx b/web/pages/[workspaceSlug]/settings/members.tsx index e64a3e66f95..e01528ddc12 100644 --- a/web/pages/[workspaceSlug]/settings/members.tsx +++ b/web/pages/[workspaceSlug]/settings/members.tsx @@ -122,7 +122,7 @@ const WorkspaceMembersSettingsPage: NextPageWithLayout = observer(() => { WorkspaceMembersSettingsPage.getLayout = function getLayout(page: ReactElement) { return ( - }> + }> {page} ); diff --git a/web/pages/[workspaceSlug]/settings/webhooks/[webhookId].tsx b/web/pages/[workspaceSlug]/settings/webhooks/[webhookId].tsx index c326588ac01..71a16ea8ba9 100644 --- a/web/pages/[workspaceSlug]/settings/webhooks/[webhookId].tsx +++ b/web/pages/[workspaceSlug]/settings/webhooks/[webhookId].tsx @@ -107,7 +107,7 @@ const WebhookDetailsPage: NextPageWithLayout = observer(() => { WebhookDetailsPage.getLayout = function getLayout(page: React.ReactElement) { return ( - }> + }> {page} ); diff --git a/web/pages/[workspaceSlug]/settings/webhooks/index.tsx b/web/pages/[workspaceSlug]/settings/webhooks/index.tsx index 05ac3a2b513..6046df7e150 100644 --- a/web/pages/[workspaceSlug]/settings/webhooks/index.tsx +++ b/web/pages/[workspaceSlug]/settings/webhooks/index.tsx @@ -102,7 +102,7 @@ const WebhooksListPage: NextPageWithLayout = observer(() => { WebhooksListPage.getLayout = function getLayout(page: React.ReactElement) { return ( - }> + }> {page} ); From 9f573d42990f480c0fb7e8c566def4d2743a751f Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Fri, 24 May 2024 14:33:30 +0530 Subject: [PATCH 05/77] [WEB-1415] fix: issue attachment count mutation (#4567) * fix: attachment count mutation * fix: attachment count update logic --- .../issue/issue-details/attachment.store.ts | 26 ++++++++++++++----- web/store/issue/issue-details/root.store.ts | 2 +- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/web/store/issue/issue-details/attachment.store.ts b/web/store/issue/issue-details/attachment.store.ts index ff537ebfbfa..ebb757e3b56 100644 --- a/web/store/issue/issue-details/attachment.store.ts +++ b/web/store/issue/issue-details/attachment.store.ts @@ -4,10 +4,11 @@ import set from "lodash/set"; import uniq from "lodash/uniq"; import update from "lodash/update"; import { action, computed, makeObservable, observable, runInAction } from "mobx"; -// services -import { IssueAttachmentService } from "@/services/issue"; // types import { TIssueAttachment, TIssueAttachmentMap, TIssueAttachmentIdMap } from "@plane/types"; +// services +import { IssueAttachmentService } from "@/services/issue"; +import { IIssueRootStore } from "../root.store"; import { IIssueDetail } from "./root.store"; export interface IIssueAttachmentStoreActions { @@ -43,11 +44,12 @@ export class IssueAttachmentStore implements IIssueAttachmentStore { attachments: TIssueAttachmentIdMap = {}; attachmentMap: TIssueAttachmentMap = {}; // root store + rootIssueStore: IIssueRootStore; rootIssueDetailStore: IIssueDetail; // services issueAttachmentService; - constructor(rootStore: IIssueDetail) { + constructor(rootStore: IIssueRootStore) { makeObservable(this, { // observables attachments: observable, @@ -61,7 +63,8 @@ export class IssueAttachmentStore implements IIssueAttachmentStore { removeAttachment: action, }); // root store - this.rootIssueDetailStore = rootStore; + this.rootIssueStore = rootStore; + this.rootIssueDetailStore = rootStore.issueDetail; // services this.issueAttachmentService = new IssueAttachmentService(); } @@ -87,9 +90,9 @@ export class IssueAttachmentStore implements IIssueAttachmentStore { // actions addAttachments = (issueId: string, attachments: TIssueAttachment[]) => { if (attachments && attachments.length > 0) { - const _attachmentIds = attachments.map((attachment) => attachment.id); + const newAttachmentIds = attachments.map((attachment) => attachment.id); runInAction(() => { - update(this.attachments, [issueId], (attachmentIds = []) => uniq(concat(attachmentIds, _attachmentIds))); + update(this.attachments, [issueId], (attachmentIds = []) => uniq(concat(attachmentIds, newAttachmentIds))); attachments.forEach((attachment) => set(this.attachmentMap, attachment.id, attachment)); }); } @@ -110,12 +113,17 @@ export class IssueAttachmentStore implements IIssueAttachmentStore { createAttachment = async (workspaceSlug: string, projectId: string, issueId: string, data: FormData) => { try { const response = await this.issueAttachmentService.uploadIssueAttachment(workspaceSlug, projectId, issueId, data); + const issueAttachmentsCount = this.getAttachmentsByIssueId(issueId)?.length ?? 0; - if (response && response.id) + if (response && response.id) { runInAction(() => { update(this.attachments, [issueId], (attachmentIds = []) => uniq(concat(attachmentIds, [response.id]))); set(this.attachmentMap, response.id, response); + this.rootIssueStore.issues.updateIssue(issueId, { + attachment_count: issueAttachmentsCount + 1, // increment attachment count + }); }); + } return response; } catch (error) { @@ -131,6 +139,7 @@ export class IssueAttachmentStore implements IIssueAttachmentStore { issueId, attachmentId ); + const issueAttachmentsCount = this.getAttachmentsByIssueId(issueId)?.length ?? 1; runInAction(() => { update(this.attachments, [issueId], (attachmentIds = []) => { @@ -138,6 +147,9 @@ export class IssueAttachmentStore implements IIssueAttachmentStore { return attachmentIds; }); delete this.attachmentMap[attachmentId]; + this.rootIssueStore.issues.updateIssue(issueId, { + attachment_count: issueAttachmentsCount - 1, // decrement attachment count + }); }); return response; diff --git a/web/store/issue/issue-details/root.store.ts b/web/store/issue/issue-details/root.store.ts index 9a851ccf0e2..f488422f16c 100644 --- a/web/store/issue/issue-details/root.store.ts +++ b/web/store/issue/issue-details/root.store.ts @@ -140,7 +140,7 @@ export class IssueDetail implements IIssueDetail { this.rootIssueStore = rootStore; this.issue = new IssueStore(this); this.reaction = new IssueReactionStore(this); - this.attachment = new IssueAttachmentStore(this); + this.attachment = new IssueAttachmentStore(rootStore); this.activity = new IssueActivityStore(this); this.comment = new IssueCommentStore(this); this.commentReaction = new IssueCommentReactionStore(this); From 7a47ce9d1d2cfc940e8e59df709e4db701cc3803 Mon Sep 17 00:00:00 2001 From: rahulramesha <71900764+rahulramesha@users.noreply.github.com> Date: Fri, 24 May 2024 15:59:41 +0530 Subject: [PATCH 06/77] [WEB-1398] fix: quick add issue flicker for cycle and module grouping (#4579) * utilize optimistic updates to fix quick add issue flicker * add comments --- web/store/issue/cycle/issue.store.ts | 20 ++++++++------- web/store/issue/module/issue.store.ts | 14 +++++----- web/store/issue/project-views/issue.store.ts | 25 ++++++++++-------- web/store/issue/project/issue.store.ts | 27 ++++++++++++-------- 4 files changed, 49 insertions(+), 37 deletions(-) diff --git a/web/store/issue/cycle/issue.store.ts b/web/store/issue/cycle/issue.store.ts index 3632d03f715..f537daca227 100644 --- a/web/store/issue/cycle/issue.store.ts +++ b/web/store/issue/cycle/issue.store.ts @@ -293,24 +293,26 @@ export class CycleIssues extends IssueHelperStore implements ICycleIssues { const response = await this.createIssue(workspaceSlug, projectId, data, cycleId); - if (data.module_ids && data.module_ids.length > 0) + const quickAddIssueIndex = this.issues[cycleId].findIndex((_issueId) => _issueId === data.id); + if (quickAddIssueIndex >= 0) { + runInAction(() => { + this.issues[cycleId].splice(quickAddIssueIndex, 1); + this.rootIssueStore.issues.removeIssue(data.id); + }); + } + + if (data.module_ids && data.module_ids.length > 0) { await this.rootStore.moduleIssues.changeModulesInIssue( workspaceSlug, projectId, response.id, data.module_ids, [] - ); + ) + } this.rootIssueStore.rootStore.cycle.fetchCycleDetails(workspaceSlug, projectId, cycleId); - const quickAddIssueIndex = this.issues[cycleId].findIndex((_issueId) => _issueId === data.id); - if (quickAddIssueIndex >= 0) - runInAction(() => { - this.issues[cycleId].splice(quickAddIssueIndex, 1); - this.rootIssueStore.issues.removeIssue(data.id); - }); - return response; } catch (error) { if (cycleId) this.fetchIssues(workspaceSlug, projectId, "mutation", cycleId); diff --git a/web/store/issue/module/issue.store.ts b/web/store/issue/module/issue.store.ts index 8a04d90b89f..24d27769d35 100644 --- a/web/store/issue/module/issue.store.ts +++ b/web/store/issue/module/issue.store.ts @@ -294,17 +294,19 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues { const response = await this.createIssue(workspaceSlug, projectId, data, moduleId); - if (data.cycle_id && data.cycle_id !== "") - await this.rootStore.cycleIssues.addIssueToCycle(workspaceSlug, projectId, data.cycle_id, [response.id]); - - this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId); - const quickAddIssueIndex = this.issues[moduleId].findIndex((_issueId) => _issueId === data.id); - if (quickAddIssueIndex >= 0) + if (quickAddIssueIndex >= 0) { runInAction(() => { this.issues[moduleId].splice(quickAddIssueIndex, 1); this.rootIssueStore.issues.removeIssue(data.id); }); + } + + if (data.cycle_id && data.cycle_id !== "") { + await this.rootStore.cycleIssues.addCycleToIssue(workspaceSlug, projectId, data.cycle_id, response.id) + } + + this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId); return response; } catch (error) { diff --git a/web/store/issue/project-views/issue.store.ts b/web/store/issue/project-views/issue.store.ts index ce2c126545b..f39bdd5a4a5 100644 --- a/web/store/issue/project-views/issue.store.ts +++ b/web/store/issue/project-views/issue.store.ts @@ -239,24 +239,27 @@ export class ProjectViewIssues extends IssueHelperStore implements IProjectViewI const response = await this.createIssue(workspaceSlug, projectId, data, viewId); - if (data.cycle_id && data.cycle_id !== "") - await this.rootStore.cycleIssues.addIssueToCycle(workspaceSlug, projectId, data.cycle_id, [response.id]); + const quickAddIssueIndex = this.issues[viewId].findIndex((_issueId) => _issueId === data.id); + if (quickAddIssueIndex >= 0) { + runInAction(() => { + this.issues[viewId].splice(quickAddIssueIndex, 1); + this.rootIssueStore.issues.removeIssue(data.id); + }); + } + + if (data.cycle_id && data.cycle_id !== "") { + await this.rootStore.cycleIssues.addCycleToIssue(workspaceSlug, projectId, data.cycle_id, response.id) + } - if (data.module_ids && data.module_ids.length > 0) + if (data.module_ids && data.module_ids.length > 0) { await this.rootStore.moduleIssues.changeModulesInIssue( workspaceSlug, projectId, response.id, data.module_ids, [] - ); - - const quickAddIssueIndex = this.issues[viewId].findIndex((_issueId) => _issueId === data.id); - if (quickAddIssueIndex >= 0) - runInAction(() => { - this.issues[viewId].splice(quickAddIssueIndex, 1); - this.rootIssueStore.issues.removeIssue(data.id); - }); + ) + } return response; } catch (error) { diff --git a/web/store/issue/project/issue.store.ts b/web/store/issue/project/issue.store.ts index 8591f494c93..1e1f9a515b2 100644 --- a/web/store/issue/project/issue.store.ts +++ b/web/store/issue/project/issue.store.ts @@ -243,24 +243,29 @@ export class ProjectIssues extends IssueHelperStore implements IProjectIssues { const response = await this.createIssue(workspaceSlug, projectId, data); - if (data.cycle_id && data.cycle_id !== "") - await this.rootStore.cycleIssues.addIssueToCycle(workspaceSlug, projectId, data.cycle_id, [response.id]); + const quickAddIssueIndex = this.issues[projectId].findIndex((_issueId) => _issueId === data.id); + + if (quickAddIssueIndex >= 0) { + runInAction(() => { + this.issues[projectId].splice(quickAddIssueIndex, 1); + this.rootStore.issues.removeIssue(data.id); + }); + } + + //TODO: error handling needs to be improved for rare cases + if (data.cycle_id && data.cycle_id !== "") { + await this.rootStore.cycleIssues.addCycleToIssue(workspaceSlug, projectId, data.cycle_id, response.id) + } - if (data.module_ids && data.module_ids.length > 0) + if (data.module_ids && data.module_ids.length > 0) { await this.rootStore.moduleIssues.changeModulesInIssue( workspaceSlug, projectId, response.id, data.module_ids, [] - ); - - const quickAddIssueIndex = this.issues[projectId].findIndex((_issueId) => _issueId === data.id); - if (quickAddIssueIndex >= 0) - runInAction(() => { - this.issues[projectId].splice(quickAddIssueIndex, 1); - this.rootStore.issues.removeIssue(data.id); - }); + ) + } return response; } catch (error) { this.fetchIssues(workspaceSlug, projectId, "mutation"); From 724f227842bc004a026cae8bf29f78341ac727ae Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Fri, 24 May 2024 16:59:49 +0530 Subject: [PATCH 07/77] [WEB-1404] chore: admin app improvements (#4580) * [WEB-1404] fix: redirection to web app and issue with telemetry checkbox in setup form. * chore: add scrollbar in admin app. * chore: fix `workspaces_exist` logic in instance api. --- admin/app/authentication/github/page.tsx | 6 +- admin/app/authentication/google/page.tsx | 6 +- admin/app/globals.css | 98 ++++++++++++++----- .../components/admin-sidebar/help-section.tsx | 2 +- .../components/admin-sidebar/sidebar-menu.tsx | 2 +- admin/components/instance/setup-form.tsx | 3 +- admin/components/new-user-popup.tsx | 7 +- apiserver/plane/license/api/views/instance.py | 2 +- 8 files changed, 86 insertions(+), 40 deletions(-) diff --git a/admin/app/authentication/github/page.tsx b/admin/app/authentication/github/page.tsx index b65b99205e2..8532910f7a2 100644 --- a/admin/app/authentication/github/page.tsx +++ b/admin/app/authentication/github/page.tsx @@ -64,8 +64,8 @@ const InstanceGithubAuthenticationPage = observer(() => { return ( <> -
-
+
+
{ withBorder={false} />
-
+
{formattedConfig ? ( ) : ( diff --git a/admin/app/authentication/google/page.tsx b/admin/app/authentication/google/page.tsx index 05117dbe336..fcdcd47ad0d 100644 --- a/admin/app/authentication/google/page.tsx +++ b/admin/app/authentication/google/page.tsx @@ -58,8 +58,8 @@ const InstanceGoogleAuthenticationPage = observer(() => { return ( <> -
-
+
+
+
{formattedConfig ? ( ) : ( diff --git a/admin/app/globals.css b/admin/app/globals.css index eefcb1b26d1..0a2218c219e 100644 --- a/admin/app/globals.css +++ b/admin/app/globals.css @@ -332,42 +332,90 @@ body { } /* scrollbar style */ -::-webkit-scrollbar { - display: none; +@-moz-document url-prefix() { + * { + scrollbar-width: none; + } + .vertical-scrollbar, + .horizontal-scrollbar { + scrollbar-width: initial; + scrollbar-color: rgba(96, 100, 108, 0.1) transparent; + } + .vertical-scrollbar:hover, + .horizontal-scrollbar:hover { + scrollbar-color: rgba(96, 100, 108, 0.25) transparent; + } + .vertical-scrollbar:active, + .horizontal-scrollbar:active { + scrollbar-color: rgba(96, 100, 108, 0.7) transparent; + } } -.horizontal-scroll-enable { - overflow-x: scroll; +.vertical-scrollbar { + overflow-y: auto; } - -.horizontal-scroll-enable::-webkit-scrollbar { +.horizontal-scrollbar { + overflow-x: auto; +} +.vertical-scrollbar::-webkit-scrollbar, +.horizontal-scrollbar::-webkit-scrollbar { display: block; - height: 7px; - width: 0; } - -.horizontal-scroll-enable::-webkit-scrollbar-track { - height: 7px; - background-color: rgba(var(--color-background-100)); +.vertical-scrollbar::-webkit-scrollbar-track, +.horizontal-scrollbar::-webkit-scrollbar-track { + background-color: transparent; + border-radius: 9999px; } - -.horizontal-scroll-enable::-webkit-scrollbar-thumb { - border-radius: 5px; - background-color: rgba(var(--color-scrollbar)); +.vertical-scrollbar::-webkit-scrollbar-thumb, +.horizontal-scrollbar::-webkit-scrollbar-thumb { + background-clip: padding-box; + background-color: rgba(96, 100, 108, 0.1); + border-radius: 9999px; } - -.vertical-scroll-enable::-webkit-scrollbar { - display: block; - width: 5px; +.vertical-scrollbar:hover::-webkit-scrollbar-thumb, +.horizontal-scrollbar:hover::-webkit-scrollbar-thumb { + background-color: rgba(96, 100, 108, 0.25); +} +.vertical-scrollbar::-webkit-scrollbar-thumb:hover, +.horizontal-scrollbar::-webkit-scrollbar-thumb:hover { + background-color: rgba(96, 100, 108, 0.5); +} +.vertical-scrollbar::-webkit-scrollbar-thumb:active, +.horizontal-scrollbar::-webkit-scrollbar-thumb:active { + background-color: rgba(96, 100, 108, 0.7); +} +.vertical-scrollbar::-webkit-scrollbar-corner, +.horizontal-scrollbar::-webkit-scrollbar-corner { + background-color: transparent; +} +.vertical-scrollbar-margin-top-md::-webkit-scrollbar-track { + margin-top: 44px; } -.vertical-scroll-enable::-webkit-scrollbar-track { - width: 5px; +/* scrollbar sm size */ +.scrollbar-sm::-webkit-scrollbar { + height: 12px; + width: 12px; } +.scrollbar-sm::-webkit-scrollbar-thumb { + border: 3px solid rgba(0, 0, 0, 0); +} +/* scrollbar md size */ +.scrollbar-md::-webkit-scrollbar { + height: 14px; + width: 14px; +} +.scrollbar-md::-webkit-scrollbar-thumb { + border: 3px solid rgba(0, 0, 0, 0); +} +/* scrollbar lg size */ -.vertical-scroll-enable::-webkit-scrollbar-thumb { - border-radius: 5px; - background-color: rgba(var(--color-background-90)); +.scrollbar-lg::-webkit-scrollbar { + height: 16px; + width: 16px; +} +.scrollbar-lg::-webkit-scrollbar-thumb { + border: 4px solid rgba(0, 0, 0, 0); } /* end scrollbar style */ diff --git a/admin/components/admin-sidebar/help-section.tsx b/admin/components/admin-sidebar/help-section.tsx index 371bb49d882..56ccbcd8446 100644 --- a/admin/components/admin-sidebar/help-section.tsx +++ b/admin/components/admin-sidebar/help-section.tsx @@ -38,7 +38,7 @@ export const HelpSection: FC = observer(() => { // refs const helpOptionsRef = useRef(null); - const redirectionLink = encodeURI(WEB_BASE_URL + "/create-workspace"); + const redirectionLink = encodeURI(WEB_BASE_URL + "/"); return (
{ }; return ( -
+
{INSTANCE_ADMIN_LINKS.map((item, index) => { const isActive = item.href === pathName || pathName.includes(item.href); return ( diff --git a/admin/components/instance/setup-form.tsx b/admin/components/instance/setup-form.tsx index 56d536c742c..77bf8e56228 100644 --- a/admin/components/instance/setup-form.tsx +++ b/admin/components/instance/setup-form.tsx @@ -158,6 +158,7 @@ export const InstanceSetupForm: FC = (props) => { onError={() => setIsSubmitting(false)} > +
@@ -319,8 +320,6 @@ export const InstanceSetupForm: FC = (props) => {
handleFormChange("is_telemetry_enabled", !formData.is_telemetry_enabled)} checked={formData.is_telemetry_enabled} /> diff --git a/admin/components/new-user-popup.tsx b/admin/components/new-user-popup.tsx index 73a405d4a8d..840de0c3ac1 100644 --- a/admin/components/new-user-popup.tsx +++ b/admin/components/new-user-popup.tsx @@ -7,9 +7,9 @@ import { useTheme as nextUseTheme } from "next-themes"; // ui import { Button, getButtonStyling } from "@plane/ui"; // helpers -import { resolveGeneralTheme } from "helpers/common.helper"; +import { WEB_BASE_URL, resolveGeneralTheme } from "helpers/common.helper"; // hooks -import { useInstance, useTheme } from "@/hooks/store"; +import { useTheme } from "@/hooks/store"; // icons import TakeoffIconLight from "/public/logos/takeoff-icon-light.svg"; import TakeoffIconDark from "/public/logos/takeoff-icon-dark.svg"; @@ -17,11 +17,10 @@ import TakeoffIconDark from "/public/logos/takeoff-icon-dark.svg"; export const NewUserPopup: React.FC = observer(() => { // hooks const { isNewUserPopup, toggleNewUserPopup } = useTheme(); - const { config } = useInstance(); // theme const { resolvedTheme } = nextUseTheme(); - const redirectionLink = `${config?.app_base_url ? `${config?.app_base_url}/create-workspace` : `/god-mode/`}`; + const redirectionLink = encodeURI(WEB_BASE_URL + "/create-workspace"); if (!isNewUserPopup) return <>; return ( diff --git a/apiserver/plane/license/api/views/instance.py b/apiserver/plane/license/api/views/instance.py index 525ab54ece7..1ec09fbb518 100644 --- a/apiserver/plane/license/api/views/instance.py +++ b/apiserver/plane/license/api/views/instance.py @@ -148,7 +148,7 @@ def get(self, request): data["app_base_url"] = settings.APP_BASE_URL instance_data = serializer.data - instance_data["workspaces_exist"] = Workspace.objects.count() > 1 + instance_data["workspaces_exist"] = Workspace.objects.count() >= 1 response_data = {"config": data, "instance": instance_data} return Response(response_data, status=status.HTTP_200_OK) From c7996544b4d0d50ec47ef8ddce65ebedd341f111 Mon Sep 17 00:00:00 2001 From: Nikhil <118773738+pablohashescobar@users.noreply.github.com> Date: Fri, 24 May 2024 18:43:37 +0530 Subject: [PATCH 08/77] fix: server error on email password disabled (#4584) --- apiserver/plane/authentication/adapter/error.py | 1 + .../plane/authentication/provider/credentials/email.py | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apiserver/plane/authentication/adapter/error.py b/apiserver/plane/authentication/adapter/error.py index 457a67f4fa2..7b12db9456a 100644 --- a/apiserver/plane/authentication/adapter/error.py +++ b/apiserver/plane/authentication/adapter/error.py @@ -17,6 +17,7 @@ "INVALID_EMAIL_SIGN_UP": 5045, "INVALID_EMAIL_MAGIC_SIGN_UP": 5050, "MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED": 5055, + "EMAIL_PASSWORD_AUTHENTICATION_DISABLED": 5056, # Sign In "USER_DOES_NOT_EXIST": 5060, "AUTHENTICATION_FAILED_SIGN_IN": 5065, diff --git a/apiserver/plane/authentication/provider/credentials/email.py b/apiserver/plane/authentication/provider/credentials/email.py index 7e4e619d8a2..4c776412858 100644 --- a/apiserver/plane/authentication/provider/credentials/email.py +++ b/apiserver/plane/authentication/provider/credentials/email.py @@ -41,8 +41,10 @@ def __init__( if ENABLE_EMAIL_PASSWORD == "0": raise AuthenticationException( - error_code=AUTHENTICATION_ERROR_CODES["ENABLE_EMAIL_PASSWORD"], - error_message="ENABLE_EMAIL_PASSWORD", + error_code=AUTHENTICATION_ERROR_CODES[ + "EMAIL_PASSWORD_AUTHENTICATION_DISABLED" + ], + error_message="EMAIL_PASSWORD_AUTHENTICATION_DISABLED", ) def set_user_data(self): From f0ece1c6b72e217479c81cb28b80bf0045243c2d Mon Sep 17 00:00:00 2001 From: rahulramesha <71900764+rahulramesha@users.noreply.github.com> Date: Fri, 24 May 2024 19:39:28 +0530 Subject: [PATCH 09/77] optionally chain sub issue count (#4585) --- web/components/issues/issue-layouts/list/block.tsx | 2 +- .../issues/issue-layouts/properties/all-properties.tsx | 2 +- .../issue-layouts/spreadsheet/columns/sub-issue-column.tsx | 2 +- web/components/issues/issue-layouts/spreadsheet/issue-row.tsx | 2 +- web/components/issues/sub-issues/issue-list-item.tsx | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/web/components/issues/issue-layouts/list/block.tsx b/web/components/issues/issue-layouts/list/block.tsx index 3cf82cd319b..4f5c7784d44 100644 --- a/web/components/issues/issue-layouts/list/block.tsx +++ b/web/components/issues/issue-layouts/list/block.tsx @@ -68,7 +68,7 @@ export const IssueBlock = observer((props: IssueBlockProps) => { setPeekIssue({ workspaceSlug, projectId: issue.project_id, issueId: issue.id, nestingLevel: nestingLevel }); const issue = issuesMap[issueId]; - const subIssuesCount = issue.sub_issues_count; + const subIssuesCount = issue?.sub_issues_count ?? 0; const { isMobile } = usePlatformOS(); diff --git a/web/components/issues/issue-layouts/properties/all-properties.tsx b/web/components/issues/issue-layouts/properties/all-properties.tsx index 79f2fca70bc..22f14833e3c 100644 --- a/web/components/issues/issue-layouts/properties/all-properties.tsx +++ b/web/components/issues/issue-layouts/properties/all-properties.tsx @@ -63,7 +63,7 @@ export const IssueProperties: React.FC = observer((props) => { const currentLayout = `${activeLayout} layout`; // derived values const stateDetails = getStateById(issue.state_id); - const subIssueCount = issue.sub_issues_count; + const subIssueCount = issue?.sub_issues_count ?? 0; const issueOperations = useMemo( () => ({ diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/sub-issue-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/sub-issue-column.tsx index c597bc698ab..8a6d26ac6c1 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/sub-issue-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/sub-issue-column.tsx @@ -19,7 +19,7 @@ export const SpreadsheetSubIssueColumn: React.FC = observer((props: Props // hooks const { workspaceSlug } = useAppRouter(); // derived values - const subIssueCount = issue.sub_issues_count; + const subIssueCount = issue?.sub_issues_count ?? 0; const redirectToIssueDetail = () => { router.push({ diff --git a/web/components/issues/issue-layouts/spreadsheet/issue-row.tsx b/web/components/issues/issue-layouts/spreadsheet/issue-row.tsx index 03854fcad54..eb33a13f35a 100644 --- a/web/components/issues/issue-layouts/spreadsheet/issue-row.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/issue-row.tsx @@ -203,7 +203,7 @@ const IssueRowDetails = observer((props: IssueRowDetailsProps) => { }; const disableUserActions = !canEditProperties(issueDetail.project_id); - const subIssuesCount = issueDetail.sub_issues_count; + const subIssuesCount = issueDetail?.sub_issues_count ?? 0; return ( <> diff --git a/web/components/issues/sub-issues/issue-list-item.tsx b/web/components/issues/sub-issues/issue-list-item.tsx index a3c3e9946dc..e0c57f4c45f 100644 --- a/web/components/issues/sub-issues/issue-list-item.tsx +++ b/web/components/issues/sub-issues/issue-list-item.tsx @@ -61,7 +61,7 @@ export const IssueListItem: React.FC = observer((props) => { undefined; const subIssueHelpers = subIssueHelpersByIssueId(parentIssueId); - const subIssueCount = issue?.sub_issues_count || 0; + const subIssueCount = issue?.sub_issues_count ?? 0; const handleIssuePeekOverview = (issue: TIssue) => workspaceSlug && From 55148ab3f7603f5fb5cab47c6c2f914aafce50b8 Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Fri, 24 May 2024 20:04:00 +0530 Subject: [PATCH 10/77] fix: redirection to `/god-mode`. (#4587) --- web/next.config.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/web/next.config.js b/web/next.config.js index 1cb49a40d76..574d16c17f1 100644 --- a/web/next.config.js +++ b/web/next.config.js @@ -69,6 +69,10 @@ const nextConfig = { const ADMIN_BASE_URL = process.env.NEXT_PUBLIC_ADMIN_BASE_URL || "" const ADMIN_BASE_PATH = process.env.NEXT_PUBLIC_ADMIN_BASE_PATH || "" const GOD_MODE_BASE_URL = ADMIN_BASE_URL + ADMIN_BASE_PATH + rewrites.push({ + source: "/god-mode", + destination: `${GOD_MODE_BASE_URL}/`, + }) rewrites.push({ source: "/god-mode/:path*", destination: `${GOD_MODE_BASE_URL}/:path*`, From 99e3097122131fed1a4723006964971623351f94 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Fri, 24 May 2024 20:12:40 +0530 Subject: [PATCH 11/77] fix: update theme post sign-in (#4586) --- web/helpers/theme.helper.ts | 3 +-- web/lib/wrappers/store-wrapper.tsx | 35 ++++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/web/helpers/theme.helper.ts b/web/helpers/theme.helper.ts index 6ebebc820fd..fd3bd07afa4 100644 --- a/web/helpers/theme.helper.ts +++ b/web/helpers/theme.helper.ts @@ -59,9 +59,8 @@ const calculateShades = (hexValue: string): TShades => { return shades as TShades; }; -export const applyTheme = (palette: string, isDarkPalette: boolean) => { +export const applyTheme = (palette: string, isDarkPalette: boolean, dom: HTMLElement | null) => { if (!palette) return; - const dom = document?.querySelector("[data-theme='custom']"); // palette: [bg, text, primary, sidebarBg, sidebarText] const values: string[] = palette.split(","); values.push(isDarkPalette ? "dark" : "light"); diff --git a/web/lib/wrappers/store-wrapper.tsx b/web/lib/wrappers/store-wrapper.tsx index ec5b79bfa01..e4e191d5a26 100644 --- a/web/lib/wrappers/store-wrapper.tsx +++ b/web/lib/wrappers/store-wrapper.tsx @@ -22,7 +22,7 @@ const StoreWrapper: FC = observer((props) => { const { sidebarCollapsed, toggleSidebar } = useAppTheme(); const { data: userProfile } = useUserProfile(); // states - const [dom, setDom] = useState(); + const [dom, setDom] = useState(null); /** * Sidebar collapsed fetching from local storage @@ -38,19 +38,40 @@ const StoreWrapper: FC = observer((props) => { * Setting up the theme of the user by fetching it from local storage */ useEffect(() => { + setTheme(userProfile?.theme?.theme || "system"); if (!userProfile?.theme?.theme) return; - if (window) setDom(() => window.document?.querySelector("[data-theme='custom']") || undefined); - setTheme(userProfile?.theme?.theme || "system"); - if (userProfile?.theme?.theme === "custom" && userProfile?.theme?.palette && dom) + if (userProfile?.theme?.theme === "custom" && userProfile?.theme?.palette) { applyTheme( userProfile?.theme?.palette !== ",,,," ? userProfile?.theme?.palette : "#0d101b,#c5c5c5,#3f76ff,#0d101b,#c5c5c5", - false + false, + dom ); - else unsetCustomCssVariables(); - }, [userProfile, userProfile?.theme?.theme, userProfile?.theme?.palette, setTheme, dom]); + } else unsetCustomCssVariables(); + }, [userProfile, userProfile?.theme, userProfile?.theme?.palette, setTheme, dom]); + + useEffect(() => { + if (dom) return; + + const observer = new MutationObserver((mutationsList, observer) => { + for (const mutation of mutationsList) { + if (mutation.type === "childList") { + const customThemeElement = window.document?.querySelector("[data-theme='custom']"); + if (customThemeElement) { + setDom(customThemeElement); + observer.disconnect(); + break; + } + } + } + }); + + observer.observe(document.body, { childList: true, subtree: true }); + + return () => observer.disconnect(); + }, [dom]); useEffect(() => { if (!router.query) return; From f76ca5643e11a270717fce633fbf77e278694518 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Fri, 24 May 2024 21:14:34 +0530 Subject: [PATCH 12/77] fix: issue store sub issue retrieve project id (#4588) --- web/store/issue/issue-details/issue.store.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/store/issue/issue-details/issue.store.ts b/web/store/issue/issue-details/issue.store.ts index 26408b485a1..361df2e2565 100644 --- a/web/store/issue/issue-details/issue.store.ts +++ b/web/store/issue/issue-details/issue.store.ts @@ -111,8 +111,8 @@ export class IssueStore implements IIssueStore { // store handlers from issue detail // parent - if (issue && issue?.parent && issue?.parent?.id) { - const parentIssue = await this.issueService.retrieve(workspaceSlug, projectId, issue?.parent?.id); + if (issue && issue?.parent && issue?.parent?.id && issue?.parent?.project_id) { + const parentIssue = await this.issueService.retrieve(workspaceSlug, issue.parent.project_id, issue?.parent?.id); this.rootIssueDetailStore.rootIssueStore.issues.addIssue([parentIssue]); } // assignees From dbba991dd3a1373b821f81a0bc10384882c16f31 Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Fri, 24 May 2024 21:15:24 +0530 Subject: [PATCH 13/77] chore: send test email error message update and scrollbar improvement. (#4589) --- admin/app/ai/page.tsx | 6 +++--- admin/app/authentication/page.tsx | 6 +++--- admin/app/email/page.tsx | 6 +++--- admin/app/email/test-email-modal.tsx | 2 +- admin/app/general/page.tsx | 6 +++--- admin/app/image/page.tsx | 6 +++--- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/admin/app/ai/page.tsx b/admin/app/ai/page.tsx index 0979bbabe6a..a54ce6d8c4f 100644 --- a/admin/app/ai/page.tsx +++ b/admin/app/ai/page.tsx @@ -19,14 +19,14 @@ const InstanceAIPage = observer(() => { return ( <> -
-
+
+
AI features for all your workspaces
Configure your AI API credentials so Plane AI features are turned on for all your workspaces.
-
+
{formattedConfig ? ( ) : ( diff --git a/admin/app/authentication/page.tsx b/admin/app/authentication/page.tsx index 25be147ca68..d1e6fb0ba18 100644 --- a/admin/app/authentication/page.tsx +++ b/admin/app/authentication/page.tsx @@ -119,14 +119,14 @@ const InstanceAuthenticationPage = observer(() => { return ( <> -
-
+
+
Manage authentication for your instance
Configure authentication modes for your team and restrict sign ups to be invite only.
-
+
{formattedConfig ? (
Authentication modes
diff --git a/admin/app/email/page.tsx b/admin/app/email/page.tsx index de776b17508..198020d4d61 100644 --- a/admin/app/email/page.tsx +++ b/admin/app/email/page.tsx @@ -19,8 +19,8 @@ const InstanceEmailPage = observer(() => { return ( <> -
-
+
+
Secure emails from your own instance
Plane can send useful emails to you and your users from your own instance without talking to the Internet. @@ -30,7 +30,7 @@ const InstanceEmailPage = observer(() => {
-
+
{formattedConfig ? ( ) : ( diff --git a/admin/app/email/test-email-modal.tsx b/admin/app/email/test-email-modal.tsx index 0feea412868..6d5cb8032d0 100644 --- a/admin/app/email/test-email-modal.tsx +++ b/admin/app/email/test-email-modal.tsx @@ -51,7 +51,7 @@ export const SendTestEmailModal: FC = (props) => { setSendEmailStep(ESendEmailSteps.SUCCESS); }) .catch((error) => { - setError(error?.message || "Failed to send email"); + setError(error?.error || "Failed to send email"); setSendEmailStep(ESendEmailSteps.FAILED); }) .finally(() => { diff --git a/admin/app/general/page.tsx b/admin/app/general/page.tsx index bab2a94fcfc..5aaea9f8e7c 100644 --- a/admin/app/general/page.tsx +++ b/admin/app/general/page.tsx @@ -10,15 +10,15 @@ function GeneralPage() { console.log("instance", instance); return ( <> -
-
+
+
General settings
Change the name of your instance and instance admin e-mail addresses. Enable or disable telemetry in your instance.
-
+
{instance && instanceAdmins && ( )} diff --git a/admin/app/image/page.tsx b/admin/app/image/page.tsx index 5c1b838bed3..ceaad61f244 100644 --- a/admin/app/image/page.tsx +++ b/admin/app/image/page.tsx @@ -19,14 +19,14 @@ const InstanceImagePage = observer(() => { return ( <> -
-
+
+
Third-party image libraries
Let your users search and choose images from third-party libraries
-
+
{formattedConfig ? ( ) : ( From 2b2f667868ceb1efbd38e3876743db205957a1af Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Mon, 27 May 2024 13:50:51 +0530 Subject: [PATCH 14/77] [WEB-1432] fix: redirection to parent issue detail page when it is from another project. (#4601) --- web/components/issues/issue-detail/parent-select.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/components/issues/issue-detail/parent-select.tsx b/web/components/issues/issue-detail/parent-select.tsx index d8399fc02be..402319af4c9 100644 --- a/web/components/issues/issue-detail/parent-select.tsx +++ b/web/components/issues/issue-detail/parent-select.tsx @@ -103,7 +103,7 @@ export const IssueParentSelect: React.FC = observer((props)
Date: Mon, 27 May 2024 15:02:03 +0530 Subject: [PATCH 15/77] fix: sentry config update for web app --- admin/next.config.js | 1 + space/next.config.js | 2 +- turbo.json | 10 +- web/instrumentation.ts | 9 + web/next.config.js | 40 +- web/package.json | 6 +- web/sentry.client.config.js | 18 - web/sentry.client.config.ts | 31 ++ web/sentry.edge.config.js | 18 - web/sentry.edge.config.ts | 17 + web/sentry.server.config.js | 18 - web/sentry.server.config.ts | 19 + yarn.lock | 974 +++++++++++++++++++++++++++++++++++- 13 files changed, 1081 insertions(+), 82 deletions(-) create mode 100644 web/instrumentation.ts delete mode 100644 web/sentry.client.config.js create mode 100644 web/sentry.client.config.ts delete mode 100644 web/sentry.edge.config.js create mode 100644 web/sentry.edge.config.ts delete mode 100644 web/sentry.server.config.js create mode 100644 web/sentry.server.config.ts diff --git a/admin/next.config.js b/admin/next.config.js index 07f6664af88..2109cec69fe 100644 --- a/admin/next.config.js +++ b/admin/next.config.js @@ -1,4 +1,5 @@ /** @type {import('next').NextConfig} */ + const nextConfig = { trailingSlash: true, reactStrictMode: false, diff --git a/space/next.config.js b/space/next.config.js index eb9dde88a32..c3e47cc9ded 100644 --- a/space/next.config.js +++ b/space/next.config.js @@ -28,7 +28,7 @@ const nextConfig = { }, }; -if (parseInt(process.env.NEXT_PUBLIC_ENABLE_SENTRY || "0", 10)) { +if (parseInt(process.env.SENTRY_MONITORING_ENABLED || "0", 10)) { module.exports = withSentryConfig( nextConfig, { silent: true, authToken: process.env.SENTRY_AUTH_TOKEN }, diff --git a/turbo.json b/turbo.json index c08733c85c4..d2d4758128b 100644 --- a/turbo.json +++ b/turbo.json @@ -8,9 +8,6 @@ "NEXT_PUBLIC_SPACE_BASE_URL", "NEXT_PUBLIC_SPACE_BASE_PATH", "NEXT_PUBLIC_WEB_BASE_URL", - "NEXT_PUBLIC_SENTRY_DSN", - "NEXT_PUBLIC_SENTRY_ENVIRONMENT", - "NEXT_PUBLIC_ENABLE_SENTRY", "NEXT_PUBLIC_TRACK_EVENTS", "NEXT_PUBLIC_PLAUSIBLE_DOMAIN", "NEXT_PUBLIC_CRISP_ID", @@ -21,7 +18,12 @@ "NEXT_PUBLIC_POSTHOG_HOST", "NEXT_PUBLIC_POSTHOG_DEBUG", "NEXT_PUBLIC_SUPPORT_EMAIL", - "SENTRY_AUTH_TOKEN" + "SENTRY_AUTH_TOKEN", + "SENTRY_ORG_ID", + "SENTRY_PROJECT_ID", + "SENTRY_ENVIRONMENT", + "SENTRY_MONITORING_ENABLED", + "SENTRY_DSN" ], "pipeline": { "build": { diff --git a/web/instrumentation.ts b/web/instrumentation.ts new file mode 100644 index 00000000000..7b89a972e15 --- /dev/null +++ b/web/instrumentation.ts @@ -0,0 +1,9 @@ +export async function register() { + if (process.env.NEXT_RUNTIME === 'nodejs') { + await import('./sentry.server.config'); + } + + if (process.env.NEXT_RUNTIME === 'edge') { + await import('./sentry.edge.config'); + } +} diff --git a/web/next.config.js b/web/next.config.js index 574d16c17f1..0482f507fa9 100644 --- a/web/next.config.js +++ b/web/next.config.js @@ -82,12 +82,40 @@ const nextConfig = { }, }; -if (parseInt(process.env.NEXT_PUBLIC_ENABLE_SENTRY || "0", 10)) { - module.exports = withSentryConfig( - nextConfig, - { silent: true, authToken: process.env.SENTRY_AUTH_TOKEN }, - { hideSourceMaps: true } - ); +const sentryConfig = { + // For all available options, see: + // https://github.com/getsentry/sentry-webpack-plugin#options + org: process.env.SENTRY_ORG_ID || "plane-hq", + project: process.env.SENTRY_PROJECT_ID || "plane-web", + authToken: process.env.SENTRY_AUTH_TOKEN, + // Only print logs for uploading source maps in CI + silent: true, + + // Upload a larger set of source maps for prettier stack traces (increases build time) + widenClientFileUpload: true, + + // Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers. + // This can increase your server load as well as your hosting bill. + // Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client- + // side errors will fail. + tunnelRoute: "/monitoring", + + // Hides source maps from generated client bundles + hideSourceMaps: true, + + // Automatically tree-shake Sentry logger statements to reduce bundle size + disableLogger: true, + + // Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.) + // See the following for more information: + // https://docs.sentry.io/product/crons/ + // https://vercel.com/docs/cron-jobs + automaticVercelMonitors: true, +} + + +if (parseInt(process.env.SENTRY_MONITORING_ENABLED || "0", 10)) { + module.exports = withSentryConfig(nextConfig, sentryConfig); } else { module.exports = nextConfig; } diff --git a/web/package.json b/web/package.json index 52542afc406..cca3ca2f6b9 100644 --- a/web/package.json +++ b/web/package.json @@ -25,14 +25,14 @@ "@nivo/line": "0.80.0", "@nivo/pie": "0.80.0", "@nivo/scatterplot": "0.80.0", + "@plane/constants": "*", "@plane/document-editor": "*", "@plane/lite-text-editor": "*", "@plane/rich-text-editor": "*", "@plane/types": "*", "@plane/ui": "*", - "@plane/constants": "*", "@popperjs/core": "^2.11.8", - "@sentry/nextjs": "^7.108.0", + "@sentry/nextjs": "^8", "axios": "^1.1.3", "clsx": "^2.0.0", "cmdk": "^1.0.0", @@ -83,4 +83,4 @@ "tsconfig": "*", "typescript": "4.7.4" } -} \ No newline at end of file +} diff --git a/web/sentry.client.config.js b/web/sentry.client.config.js deleted file mode 100644 index ca473045b45..00000000000 --- a/web/sentry.client.config.js +++ /dev/null @@ -1,18 +0,0 @@ -// This file configures the initialization of Sentry on the browser. -// The config you add here will be used whenever a page is visited. -// https://docs.sentry.io/platforms/javascript/guides/nextjs/ - -import * as Sentry from "@sentry/nextjs"; - -const SENTRY_DSN = process.env.NEXT_PUBLIC_SENTRY_DSN; - -Sentry.init({ - dsn: SENTRY_DSN, - environment: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT || "development", - // Adjust this value in production, or use tracesSampler for greater control - tracesSampleRate: 1.0, - // ... - // Note: if you want to override the automatic release value, do not set a - // `release` value here - use the environment variable `SENTRY_RELEASE`, so - // that it will also get attached to your source maps -}); diff --git a/web/sentry.client.config.ts b/web/sentry.client.config.ts new file mode 100644 index 00000000000..c4db9a644f5 --- /dev/null +++ b/web/sentry.client.config.ts @@ -0,0 +1,31 @@ +// This file configures the initialization of Sentry on the client. +// The config you add here will be used whenever a users loads a page in their browser. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: process.env.SENTRY_DSN || "", + environment: process.env.SENTRY_ENVIRONMENT || "development", + + // Adjust this value in production, or use tracesSampler for greater control + tracesSampleRate: 1, + + // Setting this option to true will print useful information to the console while you're setting up Sentry. + debug: false, + + replaysOnErrorSampleRate: 1.0, + + // This sets the sample rate to be 10%. You may want this to be 100% while + // in development and sample at a lower rate in production + replaysSessionSampleRate: 0.1, + + // You can remove this option if you're not planning to use the Sentry Session Replay feature: + integrations: [ + Sentry.replayIntegration({ + // Additional Replay configuration goes in here, for example: + maskAllText: true, + blockAllMedia: true, + }), + ], +}); diff --git a/web/sentry.edge.config.js b/web/sentry.edge.config.js deleted file mode 100644 index 8374ed4101e..00000000000 --- a/web/sentry.edge.config.js +++ /dev/null @@ -1,18 +0,0 @@ -// This file configures the initialization of Sentry on the server. -// The config you add here will be used whenever middleware or an Edge route handles a request. -// https://docs.sentry.io/platforms/javascript/guides/nextjs/ - -import * as Sentry from "@sentry/nextjs"; - -const SENTRY_DSN = process.env.NEXT_PUBLIC_SENTRY_DSN; - -Sentry.init({ - dsn: SENTRY_DSN, - environment: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT || "development", - // Adjust this value in production, or use tracesSampler for greater control - tracesSampleRate: 1.0, - // ... - // Note: if you want to override the automatic release value, do not set a - // `release` value here - use the environment variable `SENTRY_RELEASE`, so - // that it will also get attached to your source maps -}); diff --git a/web/sentry.edge.config.ts b/web/sentry.edge.config.ts new file mode 100644 index 00000000000..334a14a4340 --- /dev/null +++ b/web/sentry.edge.config.ts @@ -0,0 +1,17 @@ +// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on). +// The config you add here will be used whenever one of the edge features is loaded. +// Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: process.env.SENTRY_DSN || "", + environment: process.env.SENTRY_ENVIRONMENT || "development", + + // Adjust this value in production, or use tracesSampler for greater control + tracesSampleRate: 1, + + // Setting this option to true will print useful information to the console while you're setting up Sentry. + debug: false, +}); diff --git a/web/sentry.server.config.js b/web/sentry.server.config.js deleted file mode 100644 index d2acb07e154..00000000000 --- a/web/sentry.server.config.js +++ /dev/null @@ -1,18 +0,0 @@ -// This file configures the initialization of Sentry on the server. -// The config you add here will be used whenever the server handles a request. -// https://docs.sentry.io/platforms/javascript/guides/nextjs/ - -import * as Sentry from "@sentry/nextjs"; - -const SENTRY_DSN = process.env.NEXT_PUBLIC_SENTRY_DSN; - -Sentry.init({ - dsn: SENTRY_DSN, - environment: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT || "development", - // Adjust this value in production, or use tracesSampler for greater control - tracesSampleRate: 1.0, - // ... - // Note: if you want to override the automatic release value, do not set a - // `release` value here - use the environment variable `SENTRY_RELEASE`, so - // that it will also get attached to your source maps -}); diff --git a/web/sentry.server.config.ts b/web/sentry.server.config.ts new file mode 100644 index 00000000000..d2f094f6ab1 --- /dev/null +++ b/web/sentry.server.config.ts @@ -0,0 +1,19 @@ +// This file configures the initialization of Sentry on the server. +// The config you add here will be used whenever the server handles a request. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: process.env.SENTRY_DSN || "", + environment: process.env.SENTRY_ENVIRONMENT || "development", + + // Adjust this value in production, or use tracesSampler for greater control + tracesSampleRate: 1, + + // Setting this option to true will print useful information to the console while you're setting up Sentry. + debug: false, + + // Uncomment the line below to enable Spotlight (https://spotlightjs.com) + // spotlight: process.env.NODE_ENV === 'development', +}); diff --git a/yarn.lock b/yarn.lock index b1a7ba562ae..d28b8bf7d70 100644 --- a/yarn.lock +++ b/yarn.lock @@ -69,11 +69,24 @@ "@babel/highlight" "^7.24.2" picocolors "^1.0.0" +"@babel/code-frame@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.6.tgz#ab88da19344445c3d8889af2216606d3329f3ef2" + integrity sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA== + dependencies: + "@babel/highlight" "^7.24.6" + picocolors "^1.0.0" + "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.5", "@babel/compat-data@^7.24.4": version "7.24.4" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a" integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ== +"@babel/compat-data@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.6.tgz#b3600217688cabb26e25f8e467019e66d71b7ae2" + integrity sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ== + "@babel/core@^7.11.1", "@babel/core@^7.18.9", "@babel/core@^7.23.0", "@babel/core@^7.24.4": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.5.tgz#15ab5b98e101972d171aeef92ac70d8d6718f06a" @@ -95,6 +108,27 @@ json5 "^2.2.3" semver "^6.3.1" +"@babel/core@^7.18.5": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.6.tgz#8650e0e4b03589ebe886c4e4a60398db0a7ec787" + integrity sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.24.6" + "@babel/generator" "^7.24.6" + "@babel/helper-compilation-targets" "^7.24.6" + "@babel/helper-module-transforms" "^7.24.6" + "@babel/helpers" "^7.24.6" + "@babel/parser" "^7.24.6" + "@babel/template" "^7.24.6" + "@babel/traverse" "^7.24.6" + "@babel/types" "^7.24.6" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + "@babel/generator@^7.24.4", "@babel/generator@^7.24.5": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.5.tgz#e5afc068f932f05616b66713e28d0f04e99daeb3" @@ -105,6 +139,16 @@ "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" +"@babel/generator@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.6.tgz#dfac82a228582a9d30c959fe50ad28951d4737a7" + integrity sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg== + dependencies: + "@babel/types" "^7.24.6" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" @@ -130,6 +174,17 @@ lru-cache "^5.1.1" semver "^6.3.1" +"@babel/helper-compilation-targets@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz#4a51d681f7680043d38e212715e2a7b1ad29cb51" + integrity sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg== + dependencies: + "@babel/compat-data" "^7.24.6" + "@babel/helper-validator-option" "^7.24.6" + browserslist "^4.22.2" + lru-cache "^5.1.1" + semver "^6.3.1" + "@babel/helper-create-class-features-plugin@^7.24.1", "@babel/helper-create-class-features-plugin@^7.24.4", "@babel/helper-create-class-features-plugin@^7.24.5": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.5.tgz#7d19da92c7e0cd8d11c09af2ce1b8e7512a6e723" @@ -170,6 +225,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== +"@babel/helper-environment-visitor@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz#ac7ad5517821641550f6698dd5468f8cef78620d" + integrity sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g== + "@babel/helper-function-name@^7.23.0": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" @@ -178,6 +238,14 @@ "@babel/template" "^7.22.15" "@babel/types" "^7.23.0" +"@babel/helper-function-name@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz#cebdd063386fdb95d511d84b117e51fc68fec0c8" + integrity sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w== + dependencies: + "@babel/template" "^7.24.6" + "@babel/types" "^7.24.6" + "@babel/helper-hoist-variables@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" @@ -185,6 +253,13 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-hoist-variables@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz#8a7ece8c26756826b6ffcdd0e3cf65de275af7f9" + integrity sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA== + dependencies: + "@babel/types" "^7.24.6" + "@babel/helper-member-expression-to-functions@^7.23.0", "@babel/helper-member-expression-to-functions@^7.24.5": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.5.tgz#5981e131d5c7003c7d1fa1ad49e86c9b097ec475" @@ -199,6 +274,13 @@ dependencies: "@babel/types" "^7.24.0" +"@babel/helper-module-imports@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz#65e54ffceed6a268dc4ce11f0433b82cfff57852" + integrity sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g== + dependencies: + "@babel/types" "^7.24.6" + "@babel/helper-module-transforms@^7.23.3", "@babel/helper-module-transforms@^7.24.5": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz#ea6c5e33f7b262a0ae762fd5986355c45f54a545" @@ -210,6 +292,17 @@ "@babel/helper-split-export-declaration" "^7.24.5" "@babel/helper-validator-identifier" "^7.24.5" +"@babel/helper-module-transforms@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz#22346ed9df44ce84dee850d7433c5b73fab1fe4e" + integrity sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA== + dependencies: + "@babel/helper-environment-visitor" "^7.24.6" + "@babel/helper-module-imports" "^7.24.6" + "@babel/helper-simple-access" "^7.24.6" + "@babel/helper-split-export-declaration" "^7.24.6" + "@babel/helper-validator-identifier" "^7.24.6" + "@babel/helper-optimise-call-expression@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" @@ -247,6 +340,13 @@ dependencies: "@babel/types" "^7.24.5" +"@babel/helper-simple-access@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz#1d6e04d468bba4fc963b4906f6dac6286cfedff1" + integrity sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g== + dependencies: + "@babel/types" "^7.24.6" + "@babel/helper-skip-transparent-expression-wrappers@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" @@ -261,21 +361,43 @@ dependencies: "@babel/types" "^7.24.5" +"@babel/helper-split-export-declaration@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz#e830068f7ba8861c53b7421c284da30ae656d7a3" + integrity sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw== + dependencies: + "@babel/types" "^7.24.6" + "@babel/helper-string-parser@^7.24.1": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz#f99c36d3593db9540705d0739a1f10b5e20c696e" integrity sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ== +"@babel/helper-string-parser@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz#28583c28b15f2a3339cfafafeaad42f9a0e828df" + integrity sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q== + "@babel/helper-validator-identifier@^7.22.20", "@babel/helper-validator-identifier@^7.24.5": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz#918b1a7fa23056603506370089bd990d8720db62" integrity sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA== +"@babel/helper-validator-identifier@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz#08bb6612b11bdec78f3feed3db196da682454a5e" + integrity sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw== + "@babel/helper-validator-option@^7.23.5": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== +"@babel/helper-validator-option@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz#59d8e81c40b7d9109ab7e74457393442177f460a" + integrity sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ== + "@babel/helper-wrap-function@^7.22.20": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.24.5.tgz#335f934c0962e2c1ed1fb9d79e06a56115067c09" @@ -294,6 +416,14 @@ "@babel/traverse" "^7.24.5" "@babel/types" "^7.24.5" +"@babel/helpers@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.6.tgz#cd124245299e494bd4e00edda0e4ea3545c2c176" + integrity sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA== + dependencies: + "@babel/template" "^7.24.6" + "@babel/types" "^7.24.6" + "@babel/highlight@^7.24.2": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.5.tgz#bc0613f98e1dd0720e99b2a9ee3760194a704b6e" @@ -304,11 +434,26 @@ js-tokens "^4.0.0" picocolors "^1.0.0" +"@babel/highlight@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.6.tgz#6d610c1ebd2c6e061cade0153bf69b0590b7b3df" + integrity sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ== + dependencies: + "@babel/helper-validator-identifier" "^7.24.6" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + "@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.23.0", "@babel/parser@^7.24.0", "@babel/parser@^7.24.4", "@babel/parser@^7.24.5": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.5.tgz#4a4d5ab4315579e5398a82dcf636ca80c3392790" integrity sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg== +"@babel/parser@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.6.tgz#5e030f440c3c6c78d195528c3b688b101a365328" + integrity sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q== + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.5": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.5.tgz#4c3685eb9cd790bcad2843900fe0250c91ccf895" @@ -1047,6 +1192,15 @@ "@babel/parser" "^7.24.0" "@babel/types" "^7.24.0" +"@babel/template@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.6.tgz#048c347b2787a6072b24c723664c8d02b67a44f9" + integrity sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw== + dependencies: + "@babel/code-frame" "^7.24.6" + "@babel/parser" "^7.24.6" + "@babel/types" "^7.24.6" + "@babel/traverse@^7.18.9", "@babel/traverse@^7.24.1", "@babel/traverse@^7.24.5": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.5.tgz#972aa0bc45f16983bf64aa1f877b2dd0eea7e6f8" @@ -1063,6 +1217,22 @@ debug "^4.3.1" globals "^11.1.0" +"@babel/traverse@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.6.tgz#0941ec50cdeaeacad0911eb67ae227a4f8424edc" + integrity sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw== + dependencies: + "@babel/code-frame" "^7.24.6" + "@babel/generator" "^7.24.6" + "@babel/helper-environment-visitor" "^7.24.6" + "@babel/helper-function-name" "^7.24.6" + "@babel/helper-hoist-variables" "^7.24.6" + "@babel/helper-split-export-declaration" "^7.24.6" + "@babel/parser" "^7.24.6" + "@babel/types" "^7.24.6" + debug "^4.3.1" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.18.9", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.24.0", "@babel/types@^7.24.5", "@babel/types@^7.4.4": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.5.tgz#7661930afc638a5383eb0c4aee59b74f38db84d7" @@ -1072,6 +1242,15 @@ "@babel/helper-validator-identifier" "^7.24.5" to-fast-properties "^2.0.0" +"@babel/types@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.6.tgz#ba4e1f59870c10dc2fa95a274ac4feec23b21912" + integrity sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ== + dependencies: + "@babel/helper-string-parser" "^7.24.6" + "@babel/helper-validator-identifier" "^7.24.6" + to-fast-properties "^2.0.0" + "@base2/pretty-print-object@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz#371ba8be66d556812dc7fb169ebc3c08378f69d4" @@ -2050,6 +2229,225 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@opentelemetry/api-logs@0.51.1": + version "0.51.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.51.1.tgz#ded1874c04516c2b8cb24828eef3d6c3d1f75343" + integrity sha512-E3skn949Pk1z2XtXu/lxf6QAZpawuTM/IUEXcAzpiUkTd73Hmvw26FiN3cJuTmkpM5hZzHwkomVdtrh/n/zzwA== + dependencies: + "@opentelemetry/api" "^1.0.0" + +"@opentelemetry/api@^1.0.0", "@opentelemetry/api@^1.6.0", "@opentelemetry/api@^1.8", "@opentelemetry/api@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.8.0.tgz#5aa7abb48f23f693068ed2999ae627d2f7d902ec" + integrity sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w== + +"@opentelemetry/context-async-hooks@^1.23.0": + version "1.24.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-1.24.1.tgz#1db7116d78f60e993e0d337bd497885a53deba1a" + integrity sha512-R5r6DO4kgEOVBxFXhXjwospLQkv+sYxwCfjvoZBe7Zm6KKXAV9kDSJhi/D1BweowdZmO+sdbENLs374gER8hpQ== + +"@opentelemetry/core@1.24.1", "@opentelemetry/core@^1.1.0", "@opentelemetry/core@^1.24.1", "@opentelemetry/core@^1.8.0": + version "1.24.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.24.1.tgz#35ab9d2ac9ca938e0ffbdfa40c49c169ac8ba80d" + integrity sha512-wMSGfsdmibI88K9wB498zXY04yThPexo8jvwNNlm542HZB7XrrMRBbAyKJqG8qDRJwIBdBrPMi4V9ZPW/sqrcg== + dependencies: + "@opentelemetry/semantic-conventions" "1.24.1" + +"@opentelemetry/instrumentation-connect@0.36.0": + version "0.36.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.36.0.tgz#6a83722f0cb22a7f9b3bd8185f940308bbed0e50" + integrity sha512-k9++bmJZ9zDEs3u3DnKTn2l7QTiNFg3gPx7G9rW0TPnP+xZoBSBTrEcGYBaqflQlrFG23Q58+X1sM2ayWPv5Fg== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.51.0" + "@opentelemetry/semantic-conventions" "^1.0.0" + "@types/connect" "3.4.36" + +"@opentelemetry/instrumentation-express@0.39.0": + version "0.39.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-express/-/instrumentation-express-0.39.0.tgz#2e7452645431c24b7a878a7919ce6dbc215f9def" + integrity sha512-AG8U7z7D0JcBu/7dDcwb47UMEzj9/FMiJV2iQZqrsZnxR3FjB9J9oIH2iszJYci2eUdp2WbdvtpD9RV/zmME5A== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.51.0" + "@opentelemetry/semantic-conventions" "^1.22.0" + +"@opentelemetry/instrumentation-fastify@0.36.1": + version "0.36.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.36.1.tgz#e814f2fcce22bdc1fd96928ac45a8f9dd751bdd5" + integrity sha512-3Nfm43PI0I+3EX+1YbSy6xbDu276R1Dh1tqAk68yd4yirnIh52Kd5B+nJ8CgHA7o3UKakpBjj6vSzi5vNCzJIA== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.51.0" + "@opentelemetry/semantic-conventions" "^1.22.0" + +"@opentelemetry/instrumentation-graphql@0.40.0": + version "0.40.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.40.0.tgz#111e035070f40f5d73f2289df0f38e56a0fbc999" + integrity sha512-LVRdEHWACWOczv2imD+mhUrLMxsEjPPi32vIZJT57zygR5aUiA4em8X3aiGOCycgbMWkIu8xOSGSxdx3JmzN+w== + dependencies: + "@opentelemetry/instrumentation" "^0.51.0" + +"@opentelemetry/instrumentation-hapi@0.38.0": + version "0.38.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.38.0.tgz#2913263248c190638aaed921b1f272af0b830a2b" + integrity sha512-ZcOqEuwuutTDYIjhDIStix22ECblG/i9pHje23QGs4Q4YS4RMaZ5hKCoQJxW88Z4K7T53rQkdISmoXFKDV8xMg== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.51.0" + "@opentelemetry/semantic-conventions" "^1.0.0" + +"@opentelemetry/instrumentation-http@0.51.1": + version "0.51.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.51.1.tgz#c450f01af42e44cfd1302a527dc391f09e8364c0" + integrity sha512-6b3nZnFFEz/3xZ6w8bVxctPUWIPWiXuPQ725530JgxnN1cvYFd8CJ75PrHZNjynmzSSnqBkN3ef4R9N+RpMh8Q== + dependencies: + "@opentelemetry/core" "1.24.1" + "@opentelemetry/instrumentation" "0.51.1" + "@opentelemetry/semantic-conventions" "1.24.1" + semver "^7.5.2" + +"@opentelemetry/instrumentation-ioredis@0.40.0": + version "0.40.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.40.0.tgz#3a747dc44c6244d7f4c8cc98a6b75b9856241eaf" + integrity sha512-Jv/fH7KhpWe4KBirsiqeUJIYrsdR2iu2l4nWhfOlRvaZ+zYIiLEzTQR6QhBbyRoAbU4OuYJzjWusOmmpGBnwng== + dependencies: + "@opentelemetry/instrumentation" "^0.51.0" + "@opentelemetry/redis-common" "^0.36.2" + "@opentelemetry/semantic-conventions" "^1.0.0" + +"@opentelemetry/instrumentation-koa@0.40.0": + version "0.40.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.40.0.tgz#c83ea7bb63836776282629c889ba8b77113b528c" + integrity sha512-dJc3H/bKMcgUYcQpLF+1IbmUKus0e5Fnn/+ru/3voIRHwMADT3rFSUcGLWSczkg68BCgz0vFWGDTvPtcWIFr7A== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.51.0" + "@opentelemetry/semantic-conventions" "^1.22.0" + "@types/koa" "2.14.0" + "@types/koa__router" "12.0.3" + +"@opentelemetry/instrumentation-mongodb@0.43.0": + version "0.43.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.43.0.tgz#b1c53f18ec55058a817571ea9f0c85017ddd9bc6" + integrity sha512-bMKej7Y76QVUD3l55Q9YqizXybHUzF3pujsBFjqbZrRn2WYqtsDtTUlbCK7fvXNPwFInqZ2KhnTqd0gwo8MzaQ== + dependencies: + "@opentelemetry/instrumentation" "^0.51.0" + "@opentelemetry/sdk-metrics" "^1.9.1" + "@opentelemetry/semantic-conventions" "^1.22.0" + +"@opentelemetry/instrumentation-mongoose@0.38.1": + version "0.38.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.38.1.tgz#e2e56423431dfb57ebc10b9a93897f827f1750b0" + integrity sha512-zaeiasdnRjXe6VhYCBMdkmAVh1S5MmXC/0spet+yqoaViGnYst/DOxPvhwg3yT4Yag5crZNWsVXnA538UjP6Ow== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.51.0" + "@opentelemetry/semantic-conventions" "^1.22.0" + +"@opentelemetry/instrumentation-mysql2@0.38.1": + version "0.38.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.38.1.tgz#42093bba3c4424ebd5487a01a12e5526c8ea4da8" + integrity sha512-qkpHMgWSDTYVB1vlZ9sspf7l2wdS5DDq/rbIepDwX5BA0N0068JTQqh0CgAh34tdFqSCnWXIhcyOXC2TtRb0sg== + dependencies: + "@opentelemetry/instrumentation" "^0.51.0" + "@opentelemetry/semantic-conventions" "^1.22.0" + "@opentelemetry/sql-common" "^0.40.1" + +"@opentelemetry/instrumentation-mysql@0.38.1": + version "0.38.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.38.1.tgz#7b897f3b663bf7a245a5a0ff780f2198973a4e44" + integrity sha512-+iBAawUaTfX/HAlvySwozx0C2B6LBfNPXX1W8Z2On1Uva33AGkw2UjL9XgIg1Pj4eLZ9R4EoJ/aFz+Xj4E/7Fw== + dependencies: + "@opentelemetry/instrumentation" "^0.51.0" + "@opentelemetry/semantic-conventions" "^1.22.0" + "@types/mysql" "2.15.22" + +"@opentelemetry/instrumentation-nestjs-core@0.37.1": + version "0.37.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.37.1.tgz#c5ef8afe0275c61ecf158974e8c4b19a8dc01763" + integrity sha512-ebYQjHZEmGHWEALwwDGhSQVLBaurFnuLIkZD5igPXrt7ohfF4lc5/4al1LO+vKc0NHk8SJWStuRueT86ISA8Vg== + dependencies: + "@opentelemetry/instrumentation" "^0.51.0" + "@opentelemetry/semantic-conventions" "^1.0.0" + +"@opentelemetry/instrumentation-pg@0.41.0": + version "0.41.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.41.0.tgz#fd3540789f3f1b4bd051a348f85d61065f2cd8a1" + integrity sha512-BSlhpivzBD77meQNZY9fS4aKgydA8AJBzv2dqvxXFy/Hq64b7HURgw/ztbmwFeYwdF5raZZUifiiNSMLpOJoSA== + dependencies: + "@opentelemetry/instrumentation" "^0.51.0" + "@opentelemetry/semantic-conventions" "^1.22.0" + "@opentelemetry/sql-common" "^0.40.1" + "@types/pg" "8.6.1" + "@types/pg-pool" "2.0.4" + +"@opentelemetry/instrumentation@0.51.1", "@opentelemetry/instrumentation@^0.49 || ^0.50 || ^0.51", "@opentelemetry/instrumentation@^0.51.0", "@opentelemetry/instrumentation@^0.51.1": + version "0.51.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.51.1.tgz#46fb2291150ec6923e50b2f094b9407bc726ca9b" + integrity sha512-JIrvhpgqY6437QIqToyozrUG1h5UhwHkaGK/WAX+fkrpyPtc+RO5FkRtUd9BH0MibabHHvqsnBGKfKVijbmp8w== + dependencies: + "@opentelemetry/api-logs" "0.51.1" + "@types/shimmer" "^1.0.2" + import-in-the-middle "1.7.4" + require-in-the-middle "^7.1.1" + semver "^7.5.2" + shimmer "^1.2.1" + +"@opentelemetry/instrumentation@^0.43.0": + version "0.43.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.43.0.tgz#749521415df03396f969bf42341fcb4acd2e9c7b" + integrity sha512-S1uHE+sxaepgp+t8lvIDuRgyjJWisAb733198kwQTUc9ZtYQ2V2gmyCtR1x21ePGVLoMiX/NWY7WA290hwkjJQ== + dependencies: + "@types/shimmer" "^1.0.2" + import-in-the-middle "1.4.2" + require-in-the-middle "^7.1.1" + semver "^7.5.2" + shimmer "^1.2.1" + +"@opentelemetry/redis-common@^0.36.2": + version "0.36.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz#906ac8e4d804d4109f3ebd5c224ac988276fdc47" + integrity sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g== + +"@opentelemetry/resources@1.24.1", "@opentelemetry/resources@^1.23.0": + version "1.24.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.24.1.tgz#5e2cb84814824f3b1e1017e6caeeee8402e0ad6e" + integrity sha512-cyv0MwAaPF7O86x5hk3NNgenMObeejZFLJJDVuSeSMIsknlsj3oOZzRv3qSzlwYomXsICfBeFFlxwHQte5mGXQ== + dependencies: + "@opentelemetry/core" "1.24.1" + "@opentelemetry/semantic-conventions" "1.24.1" + +"@opentelemetry/sdk-metrics@^1.9.1": + version "1.24.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics/-/sdk-metrics-1.24.1.tgz#82ee3069b2ca9bb7c1e91272ff81536dc2e9bc8d" + integrity sha512-FrAqCbbGao9iKI+Mgh+OsC9+U2YMoXnlDHe06yH7dvavCKzE3S892dGtX54+WhSFVxHR/TMRVJiK/CV93GR0TQ== + dependencies: + "@opentelemetry/core" "1.24.1" + "@opentelemetry/resources" "1.24.1" + lodash.merge "^4.6.2" + +"@opentelemetry/sdk-trace-base@^1.22", "@opentelemetry/sdk-trace-base@^1.23.0": + version "1.24.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.24.1.tgz#dc2ab89126e75e442913fb5af98803fde67b2536" + integrity sha512-zz+N423IcySgjihl2NfjBf0qw1RWe11XIAWVrTNOSSI6dtSPJiVom2zipFB2AEEtJWpv0Iz6DY6+TjnyTV5pWg== + dependencies: + "@opentelemetry/core" "1.24.1" + "@opentelemetry/resources" "1.24.1" + "@opentelemetry/semantic-conventions" "1.24.1" + +"@opentelemetry/semantic-conventions@1.24.1", "@opentelemetry/semantic-conventions@^1.0.0", "@opentelemetry/semantic-conventions@^1.17.0", "@opentelemetry/semantic-conventions@^1.22.0", "@opentelemetry/semantic-conventions@^1.23.0": + version "1.24.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.1.tgz#d4bcebda1cb5146d47a2a53daaa7922f8e084dfb" + integrity sha512-VkliWlS4/+GHLLW7J/rVBA00uXus1SWvwFvcUDxDwmFxYfg/2VI6ekwdXS28cjI8Qz2ky2BzG8OUHo+WeYIWqw== + +"@opentelemetry/sql-common@^0.40.1": + version "0.40.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz#93fbc48d8017449f5b3c3274f2268a08af2b83b6" + integrity sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg== + dependencies: + "@opentelemetry/core" "^1.1.0" + "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" @@ -2065,6 +2463,15 @@ resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== +"@prisma/instrumentation@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-5.14.0.tgz#7a51429f644afce24eb154d518b1c65e37456160" + integrity sha512-DeybWvIZzu/mUsOYP9MVd6AyBj+MP7xIMrcuIn25MX8FiQX39QBnET5KhszTAip/ToctUuDwSJ46QkIoyo3RFA== + dependencies: + "@opentelemetry/api" "^1.8" + "@opentelemetry/instrumentation" "^0.49 || ^0.50 || ^0.51" + "@opentelemetry/sdk-trace-base" "^1.22" + "@radix-ui/primitive@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.1.tgz#e46f9958b35d10e9f6dc71c497305c22e3e55dbd" @@ -2423,6 +2830,15 @@ dependencies: "@daybrush/utils" "^1.4.0" +"@sentry-internal/browser-utils@8.4.0": + version "8.4.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-8.4.0.tgz#5b108878e93713757d75e7e8ae7780297d36ad17" + integrity sha512-Mfm3TK3KUlghhuKM3rjTeD4D5kAiB7iVNFoaDJIJBVKa67M9BvlNTnNJMDi7+9rV4RuLQYxXn0p5HEZJFYp3Zw== + dependencies: + "@sentry/core" "8.4.0" + "@sentry/types" "8.4.0" + "@sentry/utils" "8.4.0" + "@sentry-internal/feedback@7.116.0": version "7.116.0" resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-7.116.0.tgz#f1352b1a0d5fd7b7167775330ccf03bcc1b7892b" @@ -2432,6 +2848,15 @@ "@sentry/types" "7.116.0" "@sentry/utils" "7.116.0" +"@sentry-internal/feedback@8.4.0": + version "8.4.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-8.4.0.tgz#81067dadda249b354b72f5adba20374dea43fdf4" + integrity sha512-1/WshI2X9seZAQXrOiv6/LU08fbSSvJU0b1ZWMhn+onb/FWPomsL/UN0WufCYA65S5JZGdaWC8fUcJxWC8PATQ== + dependencies: + "@sentry/core" "8.4.0" + "@sentry/types" "8.4.0" + "@sentry/utils" "8.4.0" + "@sentry-internal/replay-canvas@7.116.0": version "7.116.0" resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-7.116.0.tgz#1cd4a85f99dd3cd61120e087232f5cbea21d5eb2" @@ -2442,6 +2867,26 @@ "@sentry/types" "7.116.0" "@sentry/utils" "7.116.0" +"@sentry-internal/replay-canvas@8.4.0": + version "8.4.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-8.4.0.tgz#cf5e903d8935ba6b60a5027d0055902987353920" + integrity sha512-g+U4IPQdODCg7fQQVNvH6ix05Tl1mOQXXRexgtp+tXdys4sHQSBUYraJYZy+mY3OGnLRgKFqELM0fnffJSpuyQ== + dependencies: + "@sentry-internal/replay" "8.4.0" + "@sentry/core" "8.4.0" + "@sentry/types" "8.4.0" + "@sentry/utils" "8.4.0" + +"@sentry-internal/replay@8.4.0": + version "8.4.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-8.4.0.tgz#8fc4a6bf1d5f480fcde2d56cd75042953e44efda" + integrity sha512-RSzQwCF/QTi5/5XAuj0VJImAhu4MheeHYvAbr/PuMSF4o1j89gBA7e3boA4u8633IqUeu5w3S5sb6jVrKaVifg== + dependencies: + "@sentry-internal/browser-utils" "8.4.0" + "@sentry/core" "8.4.0" + "@sentry/types" "8.4.0" + "@sentry/utils" "8.4.0" + "@sentry-internal/tracing@7.116.0": version "7.116.0" resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.116.0.tgz#af3e4e264c440aa5525b5877a10b9a0f870b40e3" @@ -2451,6 +2896,11 @@ "@sentry/types" "7.116.0" "@sentry/utils" "7.116.0" +"@sentry/babel-plugin-component-annotate@2.16.0": + version "2.16.0" + resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.16.0.tgz#c831713b85516fb3f9da2985836ddf444dc634e6" + integrity sha512-+uy1qPkA5MSNgJ0L9ur/vNTydfdHwHnBX2RQ+0thsvkqf90fU788YjkkXwUiBBNuqNyI69JiOW6frixAWy7oUg== + "@sentry/browser@7.116.0": version "7.116.0" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.116.0.tgz#950c1a9672bf886c556c2c7b9198b90189e3f0c2" @@ -2465,6 +2915,68 @@ "@sentry/types" "7.116.0" "@sentry/utils" "7.116.0" +"@sentry/browser@8.4.0": + version "8.4.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.4.0.tgz#f4aa381eab212432d71366884693a36c2e3a1675" + integrity sha512-hmXeIZBdN0A6yCuoMTcigGxLl42nbeb205fXtouwE7Maa0qM2HM+Ijq0sHzbhxR3zU0JXDtcJh1k6wtJOREJ3g== + dependencies: + "@sentry-internal/browser-utils" "8.4.0" + "@sentry-internal/feedback" "8.4.0" + "@sentry-internal/replay" "8.4.0" + "@sentry-internal/replay-canvas" "8.4.0" + "@sentry/core" "8.4.0" + "@sentry/types" "8.4.0" + "@sentry/utils" "8.4.0" + +"@sentry/bundler-plugin-core@2.16.0": + version "2.16.0" + resolved "https://registry.yarnpkg.com/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.16.0.tgz#0c33e7a054fb56e43bd160ac141f71dfebf6dda5" + integrity sha512-dhgIZsIR3L9KnE2OO5JJm6hPtStAjEPYKQsZzxRr69uVhd9xAvfXeXr0afKVNVEcIDksas6yMgHqwQ2wOXFIAg== + dependencies: + "@babel/core" "^7.18.5" + "@sentry/babel-plugin-component-annotate" "2.16.0" + "@sentry/cli" "^2.22.3" + dotenv "^16.3.1" + find-up "^5.0.0" + glob "^9.3.2" + magic-string "0.27.0" + unplugin "1.0.1" + +"@sentry/cli-darwin@2.31.2": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.31.2.tgz#faeb87d09d8b21b8b8dd2e2aa848b538f01ddd26" + integrity sha512-BHA/JJXj1dlnoZQdK4efRCtHRnbBfzbIZUKAze7oRR1RfNqERI84BVUQeKateD3jWSJXQfEuclIShc61KOpbKw== + +"@sentry/cli-linux-arm64@2.31.2": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.31.2.tgz#669c9c3f7f9130d26f5db732f793378863d58869" + integrity sha512-FLVKkJ/rWvPy/ka7OrUdRW63a/z8HYI1Gt8Pr6rWs50hb7YJja8lM8IO10tYmcFE/tODICsnHO9HTeUg2g2d1w== + +"@sentry/cli-linux-arm@2.31.2": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.31.2.tgz#3e36ed7db09e922f00221281252e58dfd8755ea5" + integrity sha512-W8k5mGYYZz/I/OxZH65YAK7dCkQAl+wbuoASGOQjUy5VDgqH0QJ8kGJufXvFPM+f3ZQGcKAnVsZ6tFqZXETBAw== + +"@sentry/cli-linux-i686@2.31.2": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.31.2.tgz#02b7da274369b78a5676c20bb26cc37caed5244b" + integrity sha512-A64QtzaPi3MYFpZ+Fwmi0mrSyXgeLJ0cWr4jdeTGrzNpeowSteKgd6tRKU+LVq0k5shKE7wdnHk+jXnoajulMA== + +"@sentry/cli-linux-x64@2.31.2": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.31.2.tgz#54f74a9e5925db9ddafebc0efd4056c5377be5fd" + integrity sha512-YL/r+15R4mOEiU3mzn7iFQOeFEUB6KxeKGTTrtpeOGynVUGIdq4nV5rHow5JDbIzOuBS3SpOmcIMluvo1NCh0g== + +"@sentry/cli-win32-i686@2.31.2": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.31.2.tgz#5dab845a824be0927566171aa05f015e887fe82d" + integrity sha512-Az/2bmW+TFI059RE0mSBIxTBcoShIclz7BDebmIoCkZ+retrwAzpmBnBCDAHow+Yi43utOow+3/4idGa2OxcLw== + +"@sentry/cli-win32-x64@2.31.2": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.31.2.tgz#e12fec0a54f6d9cced5235fbc68ba8f94165634b" + integrity sha512-XIzyRnJu539NhpFa+JYkotzVwv3NrZ/4GfHB/JWA2zReRvsk39jJG8D5HOmm0B9JA63QQT7Dt39RW8g3lkmb6w== + "@sentry/cli@^1.77.1": version "1.77.3" resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.77.3.tgz#c40b4d09b0878d6565d42a915855add99db4fec3" @@ -2477,6 +2989,25 @@ proxy-from-env "^1.1.0" which "^2.0.2" +"@sentry/cli@^2.22.3": + version "2.31.2" + resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.31.2.tgz#39df8e52966aa8db4f9c51f4bc77abd62b6a630e" + integrity sha512-2aKyUx6La2P+pplL8+2vO67qJ+c1C79KYWAyQBE0JIT5kvKK9JpwtdNoK1F0/2mRpwhhYPADCz3sVIRqmL8cQQ== + dependencies: + https-proxy-agent "^5.0.0" + node-fetch "^2.6.7" + progress "^2.0.3" + proxy-from-env "^1.1.0" + which "^2.0.2" + optionalDependencies: + "@sentry/cli-darwin" "2.31.2" + "@sentry/cli-linux-arm" "2.31.2" + "@sentry/cli-linux-arm64" "2.31.2" + "@sentry/cli-linux-i686" "2.31.2" + "@sentry/cli-linux-x64" "2.31.2" + "@sentry/cli-win32-i686" "2.31.2" + "@sentry/cli-win32-x64" "2.31.2" + "@sentry/core@7.116.0": version "7.116.0" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.116.0.tgz#7cff43134878a696b2b3b981ae384ec3db9ac8c3" @@ -2485,6 +3016,14 @@ "@sentry/types" "7.116.0" "@sentry/utils" "7.116.0" +"@sentry/core@8.4.0": + version "8.4.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.4.0.tgz#ab3f7202f3cae82daf4c3c408f50d2c6fb913620" + integrity sha512-0eACPlJvKloFIlcT1c/vjGnvqxLxpGyGuSsU7uonrkmBqIRwLYXWtR4PoHapysKtjPVoHAn9au50ut6ymC2V8Q== + dependencies: + "@sentry/types" "8.4.0" + "@sentry/utils" "8.4.0" + "@sentry/integrations@7.116.0": version "7.116.0" resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.116.0.tgz#b641342249da76cd2feb2fb5511424b66f967449" @@ -2514,6 +3053,26 @@ rollup "2.78.0" stacktrace-parser "^0.1.10" +"@sentry/nextjs@^8": + version "8.4.0" + resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-8.4.0.tgz#c1b80256f003bf0c63d6b5220b51adff9e6cab7e" + integrity sha512-g0C/vDrK3NeJhw/xXpUZCS/NuuTluSixlS3tZOd82AJVXGhepNlzm+RAbuMv2R9CVfvdHvZYDtZf7WxWDrhrrg== + dependencies: + "@opentelemetry/instrumentation-http" "0.51.1" + "@rollup/plugin-commonjs" "24.0.0" + "@sentry/core" "8.4.0" + "@sentry/node" "8.4.0" + "@sentry/opentelemetry" "8.4.0" + "@sentry/react" "8.4.0" + "@sentry/types" "8.4.0" + "@sentry/utils" "8.4.0" + "@sentry/vercel-edge" "8.4.0" + "@sentry/webpack-plugin" "2.16.0" + chalk "3.0.0" + resolve "1.22.8" + rollup "3.29.4" + stacktrace-parser "^0.1.10" + "@sentry/node@7.116.0": version "7.116.0" resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.116.0.tgz#199c304e203f35ca0e814fb7fc8a9b3f30b2c612" @@ -2525,6 +3084,49 @@ "@sentry/types" "7.116.0" "@sentry/utils" "7.116.0" +"@sentry/node@8.4.0": + version "8.4.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-8.4.0.tgz#342a92c0937aa149fb428928f9ea7e0c3e8d2158" + integrity sha512-k0uqG2F8BQWATIEghA1jQ0tBAr9mJsyS+ZiruXjbixy8kd7+ZM1CCiqeqqrYaanS0hI0mvtg9uxTQzBa1SMQsA== + dependencies: + "@opentelemetry/api" "^1.8.0" + "@opentelemetry/context-async-hooks" "^1.23.0" + "@opentelemetry/core" "^1.24.1" + "@opentelemetry/instrumentation" "^0.51.1" + "@opentelemetry/instrumentation-connect" "0.36.0" + "@opentelemetry/instrumentation-express" "0.39.0" + "@opentelemetry/instrumentation-fastify" "0.36.1" + "@opentelemetry/instrumentation-graphql" "0.40.0" + "@opentelemetry/instrumentation-hapi" "0.38.0" + "@opentelemetry/instrumentation-http" "0.51.1" + "@opentelemetry/instrumentation-ioredis" "0.40.0" + "@opentelemetry/instrumentation-koa" "0.40.0" + "@opentelemetry/instrumentation-mongodb" "0.43.0" + "@opentelemetry/instrumentation-mongoose" "0.38.1" + "@opentelemetry/instrumentation-mysql" "0.38.1" + "@opentelemetry/instrumentation-mysql2" "0.38.1" + "@opentelemetry/instrumentation-nestjs-core" "0.37.1" + "@opentelemetry/instrumentation-pg" "0.41.0" + "@opentelemetry/resources" "^1.23.0" + "@opentelemetry/sdk-trace-base" "^1.23.0" + "@opentelemetry/semantic-conventions" "^1.23.0" + "@prisma/instrumentation" "5.14.0" + "@sentry/core" "8.4.0" + "@sentry/opentelemetry" "8.4.0" + "@sentry/types" "8.4.0" + "@sentry/utils" "8.4.0" + optionalDependencies: + opentelemetry-instrumentation-fetch-node "1.2.0" + +"@sentry/opentelemetry@8.4.0": + version "8.4.0" + resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-8.4.0.tgz#0f7a0f197031bf387421f78487a3767e724828b3" + integrity sha512-1YXLuRHMhzPzoiD8Pzts5GlZY4V5GSXGn5aBmFlJ13vSrUK6C4qhPfZMboppntPihOxupCPg3XP76ZMj6+XuOg== + dependencies: + "@sentry/core" "8.4.0" + "@sentry/types" "8.4.0" + "@sentry/utils" "8.4.0" + "@sentry/react@7.116.0": version "7.116.0" resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.116.0.tgz#7157200c66675949b126feaa5de155fe83510dd8" @@ -2536,6 +3138,17 @@ "@sentry/utils" "7.116.0" hoist-non-react-statics "^3.3.2" +"@sentry/react@8.4.0": + version "8.4.0" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-8.4.0.tgz#95f4fed03709b231770a4f32d3c960c544b0dc3c" + integrity sha512-YnDN+szKFm1fQ9311nAulsRbboeMbqNmosMLA6PweBDEwD0HEJsovQT+ZJxXiOL220qsgWVJzk+aTPtf+oY4wA== + dependencies: + "@sentry/browser" "8.4.0" + "@sentry/core" "8.4.0" + "@sentry/types" "8.4.0" + "@sentry/utils" "8.4.0" + hoist-non-react-statics "^3.3.2" + "@sentry/replay@7.116.0": version "7.116.0" resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.116.0.tgz#cde921133c8927be92d60baf03c2b0aea73380f1" @@ -2551,6 +3164,11 @@ resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.116.0.tgz#0be3434e7e53c86db4993e668af1c3a65bfb7519" integrity sha512-QCCvG5QuQrwgKzV11lolNQPP2k67Q6HHD9vllZ/C4dkxkjoIym8Gy+1OgAN3wjsR0f/kG9o5iZyglgNpUVRapQ== +"@sentry/types@8.4.0": + version "8.4.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-8.4.0.tgz#42500005a198ff8c247490434ed55e0a9f975ad1" + integrity sha512-mHUaaYEQCNukzYsTLp4rP2NNO17vUf+oSGS6qmhrsGqmGNICKw2CIwJlPPGeAkq9Y4tiUOye2m5OT1xsOtxLIw== + "@sentry/utils@7.116.0": version "7.116.0" resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.116.0.tgz#f32463ab10f76f464274233a9df202e5357d17ff" @@ -2558,6 +3176,13 @@ dependencies: "@sentry/types" "7.116.0" +"@sentry/utils@8.4.0": + version "8.4.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-8.4.0.tgz#1b816e65d8dbf055c5e1554361aaf9a8a8a94102" + integrity sha512-oDF0RVWW0AyEnsP1x4McHUvQSAxJgx3G6wM9Sb4wc1F8rwsHnCtGHc+WRZ5Gd2AXC5EGkfbg5919+1ku/L4Dww== + dependencies: + "@sentry/types" "8.4.0" + "@sentry/vercel-edge@7.116.0": version "7.116.0" resolved "https://registry.yarnpkg.com/@sentry/vercel-edge/-/vercel-edge-7.116.0.tgz#09be1df26e381f0cd9580eb43737d58f6f74d1e7" @@ -2569,6 +3194,15 @@ "@sentry/types" "7.116.0" "@sentry/utils" "7.116.0" +"@sentry/vercel-edge@8.4.0": + version "8.4.0" + resolved "https://registry.yarnpkg.com/@sentry/vercel-edge/-/vercel-edge-8.4.0.tgz#64905348220a90fb9f1a747aea26e84735518ae0" + integrity sha512-iT/lZYYHziAQH0OdSCjqA1WJ1gkwAiE/Aosn3h+ddktqoU7DG/bknzwD+QSt4EQjTn3GvuXFj/JonEfbA1wlow== + dependencies: + "@sentry/core" "8.4.0" + "@sentry/types" "8.4.0" + "@sentry/utils" "8.4.0" + "@sentry/webpack-plugin@1.21.0": version "1.21.0" resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.21.0.tgz#bbe7cb293751f80246a4a56f9a7dd6de00f14b58" @@ -2577,6 +3211,15 @@ "@sentry/cli" "^1.77.1" webpack-sources "^2.0.0 || ^3.0.0" +"@sentry/webpack-plugin@2.16.0": + version "2.16.0" + resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-2.16.0.tgz#4764577edb10c9575a8b4ce03135493f995f56b9" + integrity sha512-BeKLmtK4OD9V3j92fm/lm6yp+++s2U5Uf17HwNFGt39PEOq+wUDISsx0dhXA5Qls2Bg3WhguDK71blCaVefMeg== + dependencies: + "@sentry/bundler-plugin-core" "2.16.0" + unplugin "1.0.1" + uuid "^9.0.0" + "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -3665,6 +4308,13 @@ resolved "https://registry.yarnpkg.com/@tiptap/suggestion/-/suggestion-2.4.0.tgz#1926cde5f197d116baf7794f55bd971245540e5c" integrity sha512-6dCkjbL8vIzcLWtS6RCBx0jlYPKf2Beuyq5nNLrDDZZuyJow5qJAY0eGu6Xomp9z0WDK/BYOxT4hHNoGMDkoAg== +"@types/accepts@*": + version "1.3.7" + resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.7.tgz#3b98b1889d2b2386604c2bbbe62e4fb51e95b265" + integrity sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ== + dependencies: + "@types/node" "*" + "@types/aria-query@^5.0.1": version "5.0.4" resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" @@ -3718,6 +4368,28 @@ dependencies: "@types/node" "*" +"@types/connect@3.4.36": + version "3.4.36" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.36.tgz#e511558c15a39cb29bd5357eebb57bd1459cd1ab" + integrity sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w== + dependencies: + "@types/node" "*" + +"@types/content-disposition@*": + version "0.5.8" + resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.8.tgz#6742a5971f490dc41e59d277eee71361fea0b537" + integrity sha512-QVSSvno3dE0MgO76pJhmv4Qyi/j0Yk9pBp0Y7TJ2Tlj+KCgJWY6qX7nnxCOLkZ3VYRSIk1WTxCvwUSdx6CCLdg== + +"@types/cookies@*": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@types/cookies/-/cookies-0.9.0.tgz#a2290cfb325f75f0f28720939bee854d4142aee2" + integrity sha512-40Zk8qR147RABiQ7NQnBzWzDcjKzNrntB5BAmeGCb2p/MIyOE+4BVvc17wumsUqUw00bJYqoXFHYygQnEFh4/Q== + dependencies: + "@types/connect" "*" + "@types/express" "*" + "@types/keygrip" "*" + "@types/node" "*" + "@types/cross-spawn@^6.0.2": version "6.0.6" resolved "https://registry.yarnpkg.com/@types/cross-spawn/-/cross-spawn-6.0.6.tgz#0163d0b79a6f85409e0decb8dcca17147f81fd22" @@ -3820,7 +4492,7 @@ "@types/range-parser" "*" "@types/send" "*" -"@types/express@^4.7.0": +"@types/express@*", "@types/express@^4.7.0": version "4.17.21" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== @@ -3865,6 +4537,11 @@ resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== +"@types/http-assert@*": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@types/http-assert/-/http-assert-1.5.5.tgz#dfb1063eb7c240ee3d3fe213dac5671cfb6a8dbf" + integrity sha512-4+tE/lwdAahgZT1g30Jkdm9PzFRde0xwxBNUyRsCitRvCQB90iuA2uJYdUnhnANRcqGXaWOGY4FEoxeElNAK2g== + "@types/http-errors@*": version "2.0.4" resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" @@ -3885,6 +4562,53 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/keygrip@*": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.6.tgz#1749535181a2a9b02ac04a797550a8787345b740" + integrity sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ== + +"@types/koa-compose@*": + version "3.2.8" + resolved "https://registry.yarnpkg.com/@types/koa-compose/-/koa-compose-3.2.8.tgz#dec48de1f6b3d87f87320097686a915f1e954b57" + integrity sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA== + dependencies: + "@types/koa" "*" + +"@types/koa@*": + version "2.15.0" + resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.15.0.tgz#eca43d76f527c803b491731f95df575636e7b6f2" + integrity sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g== + dependencies: + "@types/accepts" "*" + "@types/content-disposition" "*" + "@types/cookies" "*" + "@types/http-assert" "*" + "@types/http-errors" "*" + "@types/keygrip" "*" + "@types/koa-compose" "*" + "@types/node" "*" + +"@types/koa@2.14.0": + version "2.14.0" + resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.14.0.tgz#8939e8c3b695defc12f2ef9f38064509e564be18" + integrity sha512-DTDUyznHGNHAl+wd1n0z1jxNajduyTh8R53xoewuerdBzGo6Ogj6F2299BFtrexJw4NtgjsI5SMPCmV9gZwGXA== + dependencies: + "@types/accepts" "*" + "@types/content-disposition" "*" + "@types/cookies" "*" + "@types/http-assert" "*" + "@types/http-errors" "*" + "@types/keygrip" "*" + "@types/koa-compose" "*" + "@types/node" "*" + +"@types/koa__router@12.0.3": + version "12.0.3" + resolved "https://registry.yarnpkg.com/@types/koa__router/-/koa__router-12.0.3.tgz#3fb74ea1991cadd6c6712b6106657aa6e64afca4" + integrity sha512-5YUJVv6NwM1z7m6FuYpKfNLTZ932Z6EF6xy2BbtpJSyn13DKNQEkXVffFVSnJHxvwwWh2SAeumpjAYUELqgjyw== + dependencies: + "@types/koa" "*" + "@types/linkify-it@^3": version "3.0.5" resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-3.0.5.tgz#1e78a3ac2428e6d7e6c05c1665c242023a4601d8" @@ -3935,6 +4659,13 @@ resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433" integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== +"@types/mysql@2.15.22": + version "2.15.22" + resolved "https://registry.yarnpkg.com/@types/mysql/-/mysql-2.15.22.tgz#8705edb9872bf4aa9dbc004cd494e00334e5cdb4" + integrity sha512-wK1pzsJVVAjYCSZWQoWHziQZbNggXFDUEIGf54g4ZM/ERuP86uGdWeKZWMYlqTPMZfHJJvLPyogXGvCOg87yLQ== + dependencies: + "@types/node" "*" + "@types/node@*", "@types/node@^20.5.2": version "20.12.12" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.12.tgz#7cbecdf902085cec634fdb362172dfe12b8f2050" @@ -3984,6 +4715,31 @@ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== +"@types/pg-pool@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/pg-pool/-/pg-pool-2.0.4.tgz#b5c60f678094ff3acf3442628a7f708928fcf263" + integrity sha512-qZAvkv1K3QbmHHFYSNRYPkRjOWRLBYrL4B9c+wG0GSVGBw0NtJwPcgx/DSddeDJvRGMHCEQ4VMEVfuJ/0gZ3XQ== + dependencies: + "@types/pg" "*" + +"@types/pg@*": + version "8.11.6" + resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.11.6.tgz#a2d0fb0a14b53951a17df5197401569fb9c0c54b" + integrity sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ== + dependencies: + "@types/node" "*" + pg-protocol "*" + pg-types "^4.0.1" + +"@types/pg@8.6.1": + version "8.6.1" + resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.6.1.tgz#099450b8dc977e8197a44f5229cedef95c8747f9" + integrity sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w== + dependencies: + "@types/node" "*" + pg-protocol "*" + pg-types "^2.2.0" + "@types/pretty-hrtime@^1.0.0": version "1.0.3" resolved "https://registry.yarnpkg.com/@types/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#ee1bd8c9f7a01b3445786aad0ef23aba5f511a44" @@ -4026,7 +4782,7 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@18.2.48", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^18.2.42", "@types/react@^18.2.48": +"@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^18.2.42", "@types/react@^18.2.48": version "18.2.48" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.48.tgz#11df5664642d0bd879c1f58bc1d37205b064e8f1" integrity sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w== @@ -4081,6 +4837,11 @@ "@types/node" "*" "@types/send" "*" +"@types/shimmer@^1.0.2": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.5.tgz#491d8984d4510e550bfeb02d518791d7f59d2b88" + integrity sha512-9Hp0ObzwwO57DpLFF0InUjUm/II8GmKAvzbefxQTihCb7KI6yc9yzf0nLc4mVdby5N4DRCgQM2wCup9KTieeww== + "@types/trusted-types@*", "@types/trusted-types@^2.0.2": version "2.0.7" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" @@ -4532,6 +5293,11 @@ acorn-import-assertions@^1.9.0: resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== + acorn-jsx@^5.3.1, acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -4547,7 +5313,7 @@ acorn@^7.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.11.3, acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0: +acorn@^8.11.3, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: version "8.11.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== @@ -5353,7 +6119,7 @@ citty@^0.1.6: dependencies: consola "^3.2.3" -cjs-module-lexer@^1.2.3: +cjs-module-lexer@^1.2.2, cjs-module-lexer@^1.2.3: version "1.3.1" resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz#c485341ae8fd999ca4ee5af2d7a1c9ae01e0099c" integrity sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q== @@ -7601,6 +8367,16 @@ glob@^8.0.3: minimatch "^5.0.1" once "^1.3.0" +glob@^9.3.2: + version "9.3.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21" + integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q== + dependencies: + fs.realpath "^1.0.0" + minimatch "^8.0.2" + minipass "^4.2.4" + path-scurry "^1.6.1" + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -7927,6 +8703,26 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" +import-in-the-middle@1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz#2a266676e3495e72c04bbaa5ec14756ba168391b" + integrity sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw== + dependencies: + acorn "^8.8.2" + acorn-import-assertions "^1.9.0" + cjs-module-lexer "^1.2.2" + module-details-from-path "^1.0.3" + +import-in-the-middle@1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.7.4.tgz#508da6e91cfa84f210dcdb6c0a91ab0c9e8b3ebc" + integrity sha512-Lk+qzWmiQuRPPulGQeK5qq0v32k2bHnWrRPFgqyvhw7Kkov5L6MOLOIU3pcWeujc9W4q54Cp3Q2WV16eQkc7Bg== + dependencies: + acorn "^8.8.2" + acorn-import-attributes "^1.9.5" + cjs-module-lexer "^1.2.2" + module-details-from-path "^1.0.3" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -8835,6 +9631,13 @@ lz-string@^1.5.0: resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== +magic-string@0.27.0, magic-string@^0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3" + integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.13" + magic-string@^0.25.0, magic-string@^0.25.7: version "0.25.9" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" @@ -8842,13 +9645,6 @@ magic-string@^0.25.0, magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.8" -magic-string@^0.27.0: - version "0.27.0" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3" - integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA== - dependencies: - "@jridgewell/sourcemap-codec" "^1.4.13" - magic-string@^0.30.5: version "0.30.10" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.10.tgz#123d9c41a0cb5640c892b041d4cfb3bd0aa4b39e" @@ -9268,6 +10064,13 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" +minimatch@^8.0.2: + version "8.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-8.0.4.tgz#847c1b25c014d4e9a7f68aaf63dedd668a626229" + integrity sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA== + dependencies: + brace-expansion "^2.0.1" + minimatch@^9.0.1, minimatch@^9.0.4: version "9.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" @@ -9287,6 +10090,11 @@ minipass@^3.0.0: dependencies: yallist "^4.0.0" +minipass@^4.2.4: + version "4.2.8" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a" + integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== + minipass@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" @@ -9346,6 +10154,11 @@ mobx@^6.10.0, mobx@^6.12.0: resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.12.3.tgz#b6a0fde4268116be602d50bffb32f1b90a8fb077" integrity sha512-c8NKkO4R2lShkSXZ2Ongj1ycjugjzFFo/UswHBnS62y07DMcTc9Rvo03/3nRyszIvwPNljlkd4S828zIBv/piw== +module-details-from-path@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" + integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== + mri@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" @@ -9645,6 +10458,11 @@ objectorarray@^1.0.5: resolved "https://registry.yarnpkg.com/objectorarray/-/objectorarray-1.0.5.tgz#2c05248bbefabd8f43ad13b41085951aac5e68a5" integrity sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg== +obuf@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + ohash@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/ohash/-/ohash-1.1.3.tgz#f12c3c50bfe7271ce3fd1097d42568122ccdcf07" @@ -9692,6 +10510,15 @@ open@^8.0.4, open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" +opentelemetry-instrumentation-fetch-node@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/opentelemetry-instrumentation-fetch-node/-/opentelemetry-instrumentation-fetch-node-1.2.0.tgz#5beaad33b622f7021c61733af864fb505cd35626" + integrity sha512-aiSt/4ubOTyb1N5C2ZbGrBvaJOXIZhZvpRPYuUVxQJe27wJZqf/o65iPrqgLcgfeOLaQ8cS2Q+762jrYvniTrA== + dependencies: + "@opentelemetry/api" "^1.6.0" + "@opentelemetry/instrumentation" "^0.43.0" + "@opentelemetry/semantic-conventions" "^1.17.0" + optionator@^0.9.3: version "0.9.4" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" @@ -9874,7 +10701,7 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.10.1, path-scurry@^1.11.0: +path-scurry@^1.10.1, path-scurry@^1.11.0, path-scurry@^1.6.1: version "1.11.1" resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== @@ -9916,6 +10743,45 @@ peek-stream@^1.1.0: duplexify "^3.5.0" through2 "^2.0.3" +pg-int8@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" + integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== + +pg-numeric@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pg-numeric/-/pg-numeric-1.0.2.tgz#816d9a44026086ae8ae74839acd6a09b0636aa3a" + integrity sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw== + +pg-protocol@*: + version "1.6.1" + resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.1.tgz#21333e6d83b01faaebfe7a33a7ad6bfd9ed38cb3" + integrity sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg== + +pg-types@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" + integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== + dependencies: + pg-int8 "1.0.1" + postgres-array "~2.0.0" + postgres-bytea "~1.0.0" + postgres-date "~1.0.4" + postgres-interval "^1.1.0" + +pg-types@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-4.0.2.tgz#399209a57c326f162461faa870145bb0f918b76d" + integrity sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng== + dependencies: + pg-int8 "1.0.1" + pg-numeric "1.0.2" + postgres-array "~3.0.1" + postgres-bytea "~3.0.0" + postgres-date "~2.1.0" + postgres-interval "^3.0.0" + postgres-range "^1.1.1" + picocolors@^1.0.0, picocolors@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" @@ -10141,6 +11007,55 @@ postcss@^8.4.23, postcss@^8.4.29, postcss@^8.4.33, postcss@^8.4.38: picocolors "^1.0.0" source-map-js "^1.2.0" +postgres-array@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" + integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== + +postgres-array@~3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-3.0.2.tgz#68d6182cb0f7f152a7e60dc6a6889ed74b0a5f98" + integrity sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog== + +postgres-bytea@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w== + +postgres-bytea@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-3.0.0.tgz#9048dc461ac7ba70a6a42d109221619ecd1cb089" + integrity sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw== + dependencies: + obuf "~1.1.2" + +postgres-date@~1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8" + integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q== + +postgres-date@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-2.1.0.tgz#b85d3c1fb6fb3c6c8db1e9942a13a3bf625189d0" + integrity sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA== + +postgres-interval@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" + integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== + dependencies: + xtend "^4.0.0" + +postgres-interval@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-3.0.0.tgz#baf7a8b3ebab19b7f38f07566c7aab0962f0c86a" + integrity sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw== + +postgres-range@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/postgres-range/-/postgres-range-1.1.4.tgz#a59c5f9520909bcec5e63e8cf913a92e4c952863" + integrity sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w== + posthog-js@^1.131.3: version "1.132.2" resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.132.2.tgz#6d776fbba0db699517a04eaaf5278da4914a4efd" @@ -11021,6 +11936,15 @@ require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +require-in-the-middle@^7.1.1: + version "7.3.0" + resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.3.0.tgz#ce64a1083647dc07b3273b348357efac8a9945c9" + integrity sha512-nQFEv9gRw6SJAwWD2LrL0NmQvAcO7FBwJbwmr2ttPAacfy0xuiOjE5zt+zM4xDyuyvUaxBi/9gb2SoCyNEVJcw== + dependencies: + debug "^4.1.1" + module-details-from-path "^1.0.3" + resolve "^1.22.1" + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -11118,6 +12042,13 @@ rollup@2.78.0: optionalDependencies: fsevents "~2.3.2" +rollup@3.29.4: + version "3.29.4" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981" + integrity sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw== + optionalDependencies: + fsevents "~2.3.2" + rollup@^2.43.1, rollup@^2.74.1: version "2.79.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7" @@ -11271,7 +12202,7 @@ semver@^6.0.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.5, semver@^7.3.7, semver@^7.5.4, semver@^7.6.0: +semver@^7.3.5, semver@^7.3.7, semver@^7.5.2, semver@^7.5.4, semver@^7.6.0: version "7.6.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== @@ -11388,6 +12319,11 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +shimmer@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" + integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== + side-channel@^1.0.4, side-channel@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" @@ -12578,6 +13514,16 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +unplugin@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-1.0.1.tgz#83b528b981cdcea1cad422a12cd02e695195ef3f" + integrity sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA== + dependencies: + acorn "^8.8.1" + chokidar "^3.5.3" + webpack-sources "^3.2.3" + webpack-virtual-modules "^0.5.0" + unplugin@^1.3.1: version "1.10.1" resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-1.10.1.tgz#8ceda065dc71bc67d923dea0920f05c67f2cd68c" @@ -13147,7 +14093,7 @@ ws@^8.2.3: resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.0.tgz#d145d18eca2ed25aaf791a183903f7be5e295fea" integrity sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow== -xtend@~4.0.1: +xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== From aaf3484ee52e8e39998bb6595ea6917d9a40104c Mon Sep 17 00:00:00 2001 From: sriram veeraghanta Date: Mon, 27 May 2024 15:21:41 +0530 Subject: [PATCH 16/77] fix: sentry config update for space app --- space/.gitignore | 3 + space/instrumentation.ts | 9 + space/next.config.js | 44 +++- space/package.json | 2 +- space/sentry.client.config.js | 18 -- space/sentry.client.config.ts | 31 +++ space/sentry.edge.config.js | 18 -- space/sentry.edge.config.ts | 17 ++ ...rver.config.js => sentry.server.config.ts} | 17 +- turbo.json | 6 +- web/sentry.client.config.ts | 4 +- web/sentry.edge.config.ts | 4 +- web/sentry.server.config.ts | 4 +- yarn.lock | 189 +----------------- 14 files changed, 119 insertions(+), 247 deletions(-) create mode 100644 space/instrumentation.ts delete mode 100644 space/sentry.client.config.js create mode 100644 space/sentry.client.config.ts delete mode 100644 space/sentry.edge.config.js create mode 100644 space/sentry.edge.config.ts rename space/{sentry.server.config.js => sentry.server.config.ts} (56%) diff --git a/space/.gitignore b/space/.gitignore index a2a963ee7e0..a64f113f12d 100644 --- a/space/.gitignore +++ b/space/.gitignore @@ -37,3 +37,6 @@ next-env.d.ts # env .env + +# Sentry Config File +.env.sentry-build-plugin diff --git a/space/instrumentation.ts b/space/instrumentation.ts new file mode 100644 index 00000000000..7b89a972e15 --- /dev/null +++ b/space/instrumentation.ts @@ -0,0 +1,9 @@ +export async function register() { + if (process.env.NEXT_RUNTIME === 'nodejs') { + await import('./sentry.server.config'); + } + + if (process.env.NEXT_RUNTIME === 'edge') { + await import('./sentry.edge.config'); + } +} diff --git a/space/next.config.js b/space/next.config.js index c3e47cc9ded..d18ce805f4d 100644 --- a/space/next.config.js +++ b/space/next.config.js @@ -28,12 +28,46 @@ const nextConfig = { }, }; + +const sentryConfig = { + // For all available options, see: + // https://github.com/getsentry/sentry-webpack-plugin#options + + org: process.env.SENTRY_ORG_ID || "plane-hq", + project: process.env.SENTRY_PROJECT_ID || "plane-space", + authToken: process.env.SENTRY_AUTH_TOKEN, + // Only print logs for uploading source maps in CI + silent: true, + + // For all available options, see: + // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/ + + // Upload a larger set of source maps for prettier stack traces (increases build time) + widenClientFileUpload: true, + + // Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers. + // This can increase your server load as well as your hosting bill. + // Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client- + // side errors will fail. + tunnelRoute: "/monitoring", + + // Hides source maps from generated client bundles + hideSourceMaps: true, + + // Automatically tree-shake Sentry logger statements to reduce bundle size + disableLogger: true, + + // Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.) + // See the following for more information: + // https://docs.sentry.io/product/crons/ + // https://vercel.com/docs/cron-jobs + automaticVercelMonitors: true, +} + + if (parseInt(process.env.SENTRY_MONITORING_ENABLED || "0", 10)) { - module.exports = withSentryConfig( - nextConfig, - { silent: true, authToken: process.env.SENTRY_AUTH_TOKEN }, - { hideSourceMaps: true } - ); + module.exports = withSentryConfig(nextConfig, sentryConfig); } else { module.exports = nextConfig; } + diff --git a/space/package.json b/space/package.json index a084c143b9c..7ba146f27e6 100644 --- a/space/package.json +++ b/space/package.json @@ -23,7 +23,7 @@ "@plane/rich-text-editor": "*", "@plane/types": "*", "@plane/ui": "*", - "@sentry/nextjs": "^7.108.0", + "@sentry/nextjs": "^8", "axios": "^1.3.4", "clsx": "^2.0.0", "dompurify": "^3.0.11", diff --git a/space/sentry.client.config.js b/space/sentry.client.config.js deleted file mode 100644 index ca473045b45..00000000000 --- a/space/sentry.client.config.js +++ /dev/null @@ -1,18 +0,0 @@ -// This file configures the initialization of Sentry on the browser. -// The config you add here will be used whenever a page is visited. -// https://docs.sentry.io/platforms/javascript/guides/nextjs/ - -import * as Sentry from "@sentry/nextjs"; - -const SENTRY_DSN = process.env.NEXT_PUBLIC_SENTRY_DSN; - -Sentry.init({ - dsn: SENTRY_DSN, - environment: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT || "development", - // Adjust this value in production, or use tracesSampler for greater control - tracesSampleRate: 1.0, - // ... - // Note: if you want to override the automatic release value, do not set a - // `release` value here - use the environment variable `SENTRY_RELEASE`, so - // that it will also get attached to your source maps -}); diff --git a/space/sentry.client.config.ts b/space/sentry.client.config.ts new file mode 100644 index 00000000000..c8103062290 --- /dev/null +++ b/space/sentry.client.config.ts @@ -0,0 +1,31 @@ +// This file configures the initialization of Sentry on the client. +// The config you add here will be used whenever a users loads a page in their browser. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, + environment: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT || "development", + + // Adjust this value in production, or use tracesSampler for greater control + tracesSampleRate: 1, + + // Setting this option to true will print useful information to the console while you're setting up Sentry. + debug: false, + + replaysOnErrorSampleRate: 1.0, + + // This sets the sample rate to be 10%. You may want this to be 100% while + // in development and sample at a lower rate in production + replaysSessionSampleRate: 0.1, + + // You can remove this option if you're not planning to use the Sentry Session Replay feature: + integrations: [ + Sentry.replayIntegration({ + // Additional Replay configuration goes in here, for example: + maskAllText: true, + blockAllMedia: true, + }), + ], +}); diff --git a/space/sentry.edge.config.js b/space/sentry.edge.config.js deleted file mode 100644 index 8374ed4101e..00000000000 --- a/space/sentry.edge.config.js +++ /dev/null @@ -1,18 +0,0 @@ -// This file configures the initialization of Sentry on the server. -// The config you add here will be used whenever middleware or an Edge route handles a request. -// https://docs.sentry.io/platforms/javascript/guides/nextjs/ - -import * as Sentry from "@sentry/nextjs"; - -const SENTRY_DSN = process.env.NEXT_PUBLIC_SENTRY_DSN; - -Sentry.init({ - dsn: SENTRY_DSN, - environment: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT || "development", - // Adjust this value in production, or use tracesSampler for greater control - tracesSampleRate: 1.0, - // ... - // Note: if you want to override the automatic release value, do not set a - // `release` value here - use the environment variable `SENTRY_RELEASE`, so - // that it will also get attached to your source maps -}); diff --git a/space/sentry.edge.config.ts b/space/sentry.edge.config.ts new file mode 100644 index 00000000000..2dbc6e93afb --- /dev/null +++ b/space/sentry.edge.config.ts @@ -0,0 +1,17 @@ +// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on). +// The config you add here will be used whenever one of the edge features is loaded. +// Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, + environment: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT || "development", + + // Adjust this value in production, or use tracesSampler for greater control + tracesSampleRate: 1, + + // Setting this option to true will print useful information to the console while you're setting up Sentry. + debug: false, +}); diff --git a/space/sentry.server.config.js b/space/sentry.server.config.ts similarity index 56% rename from space/sentry.server.config.js rename to space/sentry.server.config.ts index d2acb07e154..e578f1530c0 100644 --- a/space/sentry.server.config.js +++ b/space/sentry.server.config.ts @@ -4,15 +4,16 @@ import * as Sentry from "@sentry/nextjs"; -const SENTRY_DSN = process.env.NEXT_PUBLIC_SENTRY_DSN; - Sentry.init({ - dsn: SENTRY_DSN, + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, environment: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT || "development", + // Adjust this value in production, or use tracesSampler for greater control - tracesSampleRate: 1.0, - // ... - // Note: if you want to override the automatic release value, do not set a - // `release` value here - use the environment variable `SENTRY_RELEASE`, so - // that it will also get attached to your source maps + tracesSampleRate: 1, + + // Setting this option to true will print useful information to the console while you're setting up Sentry. + debug: false, + + // Uncomment the line below to enable Spotlight (https://spotlightjs.com) + // spotlight: process.env.NODE_ENV === 'development', }); diff --git a/turbo.json b/turbo.json index d2d4758128b..4fb34d29d89 100644 --- a/turbo.json +++ b/turbo.json @@ -21,9 +21,9 @@ "SENTRY_AUTH_TOKEN", "SENTRY_ORG_ID", "SENTRY_PROJECT_ID", - "SENTRY_ENVIRONMENT", - "SENTRY_MONITORING_ENABLED", - "SENTRY_DSN" + "NEXT_PUBLIC_SENTRY_ENVIRONMENT", + "NEXT_PUBLIC_SENTRY_DSN", + "SENTRY_MONITORING_ENABLED" ], "pipeline": { "build": { diff --git a/web/sentry.client.config.ts b/web/sentry.client.config.ts index c4db9a644f5..c8103062290 100644 --- a/web/sentry.client.config.ts +++ b/web/sentry.client.config.ts @@ -5,8 +5,8 @@ import * as Sentry from "@sentry/nextjs"; Sentry.init({ - dsn: process.env.SENTRY_DSN || "", - environment: process.env.SENTRY_ENVIRONMENT || "development", + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, + environment: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT || "development", // Adjust this value in production, or use tracesSampler for greater control tracesSampleRate: 1, diff --git a/web/sentry.edge.config.ts b/web/sentry.edge.config.ts index 334a14a4340..2dbc6e93afb 100644 --- a/web/sentry.edge.config.ts +++ b/web/sentry.edge.config.ts @@ -6,8 +6,8 @@ import * as Sentry from "@sentry/nextjs"; Sentry.init({ - dsn: process.env.SENTRY_DSN || "", - environment: process.env.SENTRY_ENVIRONMENT || "development", + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, + environment: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT || "development", // Adjust this value in production, or use tracesSampler for greater control tracesSampleRate: 1, diff --git a/web/sentry.server.config.ts b/web/sentry.server.config.ts index d2f094f6ab1..e578f1530c0 100644 --- a/web/sentry.server.config.ts +++ b/web/sentry.server.config.ts @@ -5,8 +5,8 @@ import * as Sentry from "@sentry/nextjs"; Sentry.init({ - dsn: process.env.SENTRY_DSN || "", - environment: process.env.SENTRY_ENVIRONMENT || "development", + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, + environment: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT || "development", // Adjust this value in production, or use tracesSampler for greater control tracesSampleRate: 1, diff --git a/yarn.lock b/yarn.lock index d28b8bf7d70..d5f20fa8f56 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2839,15 +2839,6 @@ "@sentry/types" "8.4.0" "@sentry/utils" "8.4.0" -"@sentry-internal/feedback@7.116.0": - version "7.116.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-7.116.0.tgz#f1352b1a0d5fd7b7167775330ccf03bcc1b7892b" - integrity sha512-tmfO+RTCrhIWMs3yg8X0axhbjWRZLsldSfoXBgfjNCk/XwkYiVGp7WnYVbb+IO+01mHCsis9uaYOBggLgFRB5Q== - dependencies: - "@sentry/core" "7.116.0" - "@sentry/types" "7.116.0" - "@sentry/utils" "7.116.0" - "@sentry-internal/feedback@8.4.0": version "8.4.0" resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-8.4.0.tgz#81067dadda249b354b72f5adba20374dea43fdf4" @@ -2857,16 +2848,6 @@ "@sentry/types" "8.4.0" "@sentry/utils" "8.4.0" -"@sentry-internal/replay-canvas@7.116.0": - version "7.116.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-7.116.0.tgz#1cd4a85f99dd3cd61120e087232f5cbea21d5eb2" - integrity sha512-Sy0ydY7A97JY/IFTIj8U25kHqR5rL9oBk3HFE5EK9Phw56irVhHzEwLWae0jlFeCQEWoBYqpPgO5vXsaYzrWvw== - dependencies: - "@sentry/core" "7.116.0" - "@sentry/replay" "7.116.0" - "@sentry/types" "7.116.0" - "@sentry/utils" "7.116.0" - "@sentry-internal/replay-canvas@8.4.0": version "8.4.0" resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-8.4.0.tgz#cf5e903d8935ba6b60a5027d0055902987353920" @@ -2887,34 +2868,11 @@ "@sentry/types" "8.4.0" "@sentry/utils" "8.4.0" -"@sentry-internal/tracing@7.116.0": - version "7.116.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.116.0.tgz#af3e4e264c440aa5525b5877a10b9a0f870b40e3" - integrity sha512-y5ppEmoOlfr77c/HqsEXR72092qmGYS4QE5gSz5UZFn9CiinEwGfEorcg2xIrrCuU7Ry/ZU2VLz9q3xd04drRA== - dependencies: - "@sentry/core" "7.116.0" - "@sentry/types" "7.116.0" - "@sentry/utils" "7.116.0" - "@sentry/babel-plugin-component-annotate@2.16.0": version "2.16.0" resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.16.0.tgz#c831713b85516fb3f9da2985836ddf444dc634e6" integrity sha512-+uy1qPkA5MSNgJ0L9ur/vNTydfdHwHnBX2RQ+0thsvkqf90fU788YjkkXwUiBBNuqNyI69JiOW6frixAWy7oUg== -"@sentry/browser@7.116.0": - version "7.116.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.116.0.tgz#950c1a9672bf886c556c2c7b9198b90189e3f0c2" - integrity sha512-2aosATT5qE+QLKgTmyF9t5Emsluy1MBczYNuPmLhDxGNfB+MA86S8u7Hb0CpxdwjS0nt14gmbiOtJHoeAF3uTw== - dependencies: - "@sentry-internal/feedback" "7.116.0" - "@sentry-internal/replay-canvas" "7.116.0" - "@sentry-internal/tracing" "7.116.0" - "@sentry/core" "7.116.0" - "@sentry/integrations" "7.116.0" - "@sentry/replay" "7.116.0" - "@sentry/types" "7.116.0" - "@sentry/utils" "7.116.0" - "@sentry/browser@8.4.0": version "8.4.0" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.4.0.tgz#f4aa381eab212432d71366884693a36c2e3a1675" @@ -2977,18 +2935,6 @@ resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.31.2.tgz#e12fec0a54f6d9cced5235fbc68ba8f94165634b" integrity sha512-XIzyRnJu539NhpFa+JYkotzVwv3NrZ/4GfHB/JWA2zReRvsk39jJG8D5HOmm0B9JA63QQT7Dt39RW8g3lkmb6w== -"@sentry/cli@^1.77.1": - version "1.77.3" - resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.77.3.tgz#c40b4d09b0878d6565d42a915855add99db4fec3" - integrity sha512-c3eDqcDRmy4TFz2bFU5Y6QatlpoBPPa8cxBooaS4aMQpnIdLYPF1xhyyiW0LQlDUNc3rRjNF7oN5qKoaRoMTQQ== - dependencies: - https-proxy-agent "^5.0.0" - mkdirp "^0.5.5" - node-fetch "^2.6.7" - progress "^2.0.3" - proxy-from-env "^1.1.0" - which "^2.0.2" - "@sentry/cli@^2.22.3": version "2.31.2" resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.31.2.tgz#39df8e52966aa8db4f9c51f4bc77abd62b6a630e" @@ -3008,14 +2954,6 @@ "@sentry/cli-win32-i686" "2.31.2" "@sentry/cli-win32-x64" "2.31.2" -"@sentry/core@7.116.0": - version "7.116.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.116.0.tgz#7cff43134878a696b2b3b981ae384ec3db9ac8c3" - integrity sha512-J6Wmjjx+o7RwST0weTU1KaKUAlzbc8MGkJV1rcHM9xjNTWTva+nrcCM3vFBagnk2Gm/zhwv3h0PvWEqVyp3U1Q== - dependencies: - "@sentry/types" "7.116.0" - "@sentry/utils" "7.116.0" - "@sentry/core@8.4.0": version "8.4.0" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.4.0.tgz#ab3f7202f3cae82daf4c3c408f50d2c6fb913620" @@ -3024,35 +2962,6 @@ "@sentry/types" "8.4.0" "@sentry/utils" "8.4.0" -"@sentry/integrations@7.116.0": - version "7.116.0" - resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.116.0.tgz#b641342249da76cd2feb2fb5511424b66f967449" - integrity sha512-UZb60gaF+7veh1Yv79RiGvgGYOnU6xA97H+hI6tKgc1uT20YpItO4X56Vhp0lvyEyUGFZzBRRH1jpMDPNGPkqw== - dependencies: - "@sentry/core" "7.116.0" - "@sentry/types" "7.116.0" - "@sentry/utils" "7.116.0" - localforage "^1.8.1" - -"@sentry/nextjs@^7.108.0": - version "7.116.0" - resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-7.116.0.tgz#56225d3d279e0180c65aa20f29e2b497fde544de" - integrity sha512-FhPokzfjejc1a66cy/eyfMVhZk0r2ogvN0+1ezu7l4k78voS1NW+MyDxqHdgNmDoGdLnqw7Zc2CNursREwq7KQ== - dependencies: - "@rollup/plugin-commonjs" "24.0.0" - "@sentry/core" "7.116.0" - "@sentry/integrations" "7.116.0" - "@sentry/node" "7.116.0" - "@sentry/react" "7.116.0" - "@sentry/types" "7.116.0" - "@sentry/utils" "7.116.0" - "@sentry/vercel-edge" "7.116.0" - "@sentry/webpack-plugin" "1.21.0" - chalk "3.0.0" - resolve "1.22.8" - rollup "2.78.0" - stacktrace-parser "^0.1.10" - "@sentry/nextjs@^8": version "8.4.0" resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-8.4.0.tgz#c1b80256f003bf0c63d6b5220b51adff9e6cab7e" @@ -3073,17 +2982,6 @@ rollup "3.29.4" stacktrace-parser "^0.1.10" -"@sentry/node@7.116.0": - version "7.116.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.116.0.tgz#199c304e203f35ca0e814fb7fc8a9b3f30b2c612" - integrity sha512-HB/4TrJWbnu6swNzkid+MlwzLwY/D/klGt3R0aatgrgWPo2jJm6bSl4LUT39Cr2eg5I1gsREQtXE2mAlC6gm8w== - dependencies: - "@sentry-internal/tracing" "7.116.0" - "@sentry/core" "7.116.0" - "@sentry/integrations" "7.116.0" - "@sentry/types" "7.116.0" - "@sentry/utils" "7.116.0" - "@sentry/node@8.4.0": version "8.4.0" resolved "https://registry.yarnpkg.com/@sentry/node/-/node-8.4.0.tgz#342a92c0937aa149fb428928f9ea7e0c3e8d2158" @@ -3127,17 +3025,6 @@ "@sentry/types" "8.4.0" "@sentry/utils" "8.4.0" -"@sentry/react@7.116.0": - version "7.116.0" - resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.116.0.tgz#7157200c66675949b126feaa5de155fe83510dd8" - integrity sha512-b7sYSIewK/h3dGzm7Rx6tBUzA6w7zw6m5rVIO3fWCy7T3xEUDggUaqklrFVHXUYx2yjzEgTFPg/Dd2NrSzua4w== - dependencies: - "@sentry/browser" "7.116.0" - "@sentry/core" "7.116.0" - "@sentry/types" "7.116.0" - "@sentry/utils" "7.116.0" - hoist-non-react-statics "^3.3.2" - "@sentry/react@8.4.0": version "8.4.0" resolved "https://registry.yarnpkg.com/@sentry/react/-/react-8.4.0.tgz#95f4fed03709b231770a4f32d3c960c544b0dc3c" @@ -3149,33 +3036,11 @@ "@sentry/utils" "8.4.0" hoist-non-react-statics "^3.3.2" -"@sentry/replay@7.116.0": - version "7.116.0" - resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.116.0.tgz#cde921133c8927be92d60baf03c2b0aea73380f1" - integrity sha512-OrpDtV54pmwZuKp3g7PDiJg6ruRMJKOCzK08TF7IPsKrr4x4UQn56rzMOiABVuTjuS8lNfAWDar6c6vxXFz5KA== - dependencies: - "@sentry-internal/tracing" "7.116.0" - "@sentry/core" "7.116.0" - "@sentry/types" "7.116.0" - "@sentry/utils" "7.116.0" - -"@sentry/types@7.116.0": - version "7.116.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.116.0.tgz#0be3434e7e53c86db4993e668af1c3a65bfb7519" - integrity sha512-QCCvG5QuQrwgKzV11lolNQPP2k67Q6HHD9vllZ/C4dkxkjoIym8Gy+1OgAN3wjsR0f/kG9o5iZyglgNpUVRapQ== - "@sentry/types@8.4.0": version "8.4.0" resolved "https://registry.yarnpkg.com/@sentry/types/-/types-8.4.0.tgz#42500005a198ff8c247490434ed55e0a9f975ad1" integrity sha512-mHUaaYEQCNukzYsTLp4rP2NNO17vUf+oSGS6qmhrsGqmGNICKw2CIwJlPPGeAkq9Y4tiUOye2m5OT1xsOtxLIw== -"@sentry/utils@7.116.0": - version "7.116.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.116.0.tgz#f32463ab10f76f464274233a9df202e5357d17ff" - integrity sha512-Vn9fcvwTq91wJvCd7WTMWozimqMi+dEZ3ie3EICELC2diONcN16ADFdzn65CQQbYwmUzRjN9EjDN2k41pKZWhQ== - dependencies: - "@sentry/types" "7.116.0" - "@sentry/utils@8.4.0": version "8.4.0" resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-8.4.0.tgz#1b816e65d8dbf055c5e1554361aaf9a8a8a94102" @@ -3183,17 +3048,6 @@ dependencies: "@sentry/types" "8.4.0" -"@sentry/vercel-edge@7.116.0": - version "7.116.0" - resolved "https://registry.yarnpkg.com/@sentry/vercel-edge/-/vercel-edge-7.116.0.tgz#09be1df26e381f0cd9580eb43737d58f6f74d1e7" - integrity sha512-II956v8ch99+DwhkFh7MDcYlnDURIO2rjy7U60Tol+xhlU5RcyySzRt/Ki1Zw2DiKXBuAk7C1JMioTr0FF9mAQ== - dependencies: - "@sentry-internal/tracing" "7.116.0" - "@sentry/core" "7.116.0" - "@sentry/integrations" "7.116.0" - "@sentry/types" "7.116.0" - "@sentry/utils" "7.116.0" - "@sentry/vercel-edge@8.4.0": version "8.4.0" resolved "https://registry.yarnpkg.com/@sentry/vercel-edge/-/vercel-edge-8.4.0.tgz#64905348220a90fb9f1a747aea26e84735518ae0" @@ -3203,14 +3057,6 @@ "@sentry/types" "8.4.0" "@sentry/utils" "8.4.0" -"@sentry/webpack-plugin@1.21.0": - version "1.21.0" - resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.21.0.tgz#bbe7cb293751f80246a4a56f9a7dd6de00f14b58" - integrity sha512-x0PYIMWcsTauqxgl7vWUY6sANl+XGKtx7DCVnnY7aOIIlIna0jChTAPANTfA2QrK+VK+4I/4JxatCEZBnXh3Og== - dependencies: - "@sentry/cli" "^1.77.1" - webpack-sources "^2.0.0 || ^3.0.0" - "@sentry/webpack-plugin@2.16.0": version "2.16.0" resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-2.16.0.tgz#4764577edb10c9575a8b4ce03135493f995f56b9" @@ -8690,11 +8536,6 @@ ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== -immediate@~3.0.5: - version "3.0.6" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" - integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== - import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -9401,13 +9242,6 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -lie@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" - integrity sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw== - dependencies: - immediate "~3.0.5" - lilconfig@3.1.1, lilconfig@^3.0.0, lilconfig@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.1.tgz#9d8a246fa753106cfc205fd2d77042faca56e5e3" @@ -9482,13 +9316,6 @@ loader-utils@^2.0.0: emojis-list "^3.0.0" json5 "^2.1.2" -localforage@^1.8.1: - version "1.10.0" - resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.10.0.tgz#5c465dc5f62b2807c3a84c0c6a1b1b3212781dd4" - integrity sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg== - dependencies: - lie "3.1.1" - locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -10118,13 +9945,6 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -mkdirp@^0.5.5: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - mkdirp@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" @@ -12035,13 +11855,6 @@ rollup-plugin-terser@^7.0.0: serialize-javascript "^4.0.0" terser "^5.0.0" -rollup@2.78.0: - version "2.78.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.78.0.tgz#00995deae70c0f712ea79ad904d5f6b033209d9e" - integrity sha512-4+YfbQC9QEVvKTanHhIAFVUFSRsezvQF8vFOJwtGfb9Bb+r014S+qryr9PSmw8x6sMnPkmFBGAvIFVQxvJxjtg== - optionalDependencies: - fsevents "~2.3.2" - rollup@3.29.4: version "3.29.4" resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981" @@ -13748,7 +13561,7 @@ webpack-sources@^1.4.3: source-list-map "^2.0.0" source-map "~0.6.1" -"webpack-sources@^2.0.0 || ^3.0.0", webpack-sources@^3.2.3: +webpack-sources@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== From 2e6ad61f49ad92df5428bf2ace8ac7e895a80a99 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Mon, 27 May 2024 16:04:05 +0530 Subject: [PATCH 17/77] fix: sibling issue redirection and fetching issue resolved (#4603) --- .../issues/issue-detail/parent/root.tsx | 2 +- .../issue-detail/parent/sibling-item.tsx | 11 +++++----- .../issues/issue-detail/parent/siblings.tsx | 22 +++++++++++-------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/web/components/issues/issue-detail/parent/root.tsx b/web/components/issues/issue-detail/parent/root.tsx index abc2a95012d..b4521bdaace 100644 --- a/web/components/issues/issue-detail/parent/root.tsx +++ b/web/components/issues/issue-detail/parent/root.tsx @@ -56,7 +56,7 @@ export const IssueParentDetail: FC = observer((props) => { Sibling issues
- + issueOperations.update(workspaceSlug, projectId, issueId, { parent_id: null })} diff --git a/web/components/issues/issue-detail/parent/sibling-item.tsx b/web/components/issues/issue-detail/parent/sibling-item.tsx index c6eef2a9e32..c66a1889943 100644 --- a/web/components/issues/issue-detail/parent/sibling-item.tsx +++ b/web/components/issues/issue-detail/parent/sibling-item.tsx @@ -1,4 +1,5 @@ import { FC } from "react"; +import { observer } from "mobx-react"; import Link from "next/link"; // ui import { CustomMenu, LayersIcon } from "@plane/ui"; @@ -6,15 +7,15 @@ import { CustomMenu, LayersIcon } from "@plane/ui"; import { useIssueDetail, useProject } from "@/hooks/store"; type TIssueParentSiblingItem = { + workspaceSlug: string; issueId: string; }; -export const IssueParentSiblingItem: FC = (props) => { - const { issueId } = props; +export const IssueParentSiblingItem: FC = observer((props) => { + const { workspaceSlug, issueId } = props; // hooks const { getProjectById } = useProject(); const { - peekIssue, issue: { getIssueById }, } = useIssueDetail(); @@ -27,7 +28,7 @@ export const IssueParentSiblingItem: FC = (props) => { <> @@ -36,4 +37,4 @@ export const IssueParentSiblingItem: FC = (props) => { ); -}; +}); diff --git a/web/components/issues/issue-detail/parent/siblings.tsx b/web/components/issues/issue-detail/parent/siblings.tsx index 56e93fc0f11..e23d8a595fe 100644 --- a/web/components/issues/issue-detail/parent/siblings.tsx +++ b/web/components/issues/issue-detail/parent/siblings.tsx @@ -1,4 +1,5 @@ import { FC } from "react"; +import { observer } from "mobx-react"; import useSWR from "swr"; import { TIssue } from "@plane/types"; // components @@ -8,25 +9,25 @@ import { useIssueDetail } from "@/hooks/store"; import { IssueParentSiblingItem } from "./sibling-item"; export type TIssueParentSiblings = { + workspaceSlug: string; currentIssue: TIssue; parentIssue: TIssue; }; -export const IssueParentSiblings: FC = (props) => { - const { currentIssue, parentIssue } = props; +export const IssueParentSiblings: FC = observer((props) => { + const { workspaceSlug, currentIssue, parentIssue } = props; // hooks const { - peekIssue, fetchSubIssues, subIssues: { subIssuesByIssueId }, } = useIssueDetail(); const { isLoading } = useSWR( - peekIssue && parentIssue && parentIssue.project_id - ? `ISSUE_PARENT_CHILD_ISSUES_${peekIssue?.workspaceSlug}_${parentIssue.project_id}_${parentIssue.id}` + parentIssue && parentIssue.project_id + ? `ISSUE_PARENT_CHILD_ISSUES_${workspaceSlug}_${parentIssue.project_id}_${parentIssue.id}` : null, - peekIssue && parentIssue && parentIssue.project_id - ? () => fetchSubIssues(peekIssue?.workspaceSlug, parentIssue.project_id, parentIssue.id) + parentIssue && parentIssue.project_id + ? () => fetchSubIssues(workspaceSlug, parentIssue.project_id, parentIssue.id) : null ); @@ -40,7 +41,10 @@ export const IssueParentSiblings: FC = (props) => {
) : subIssueIds && subIssueIds.length > 0 ? ( subIssueIds.map( - (issueId) => currentIssue.id != issueId && + (issueId) => + currentIssue.id != issueId && ( + + ) ) ) : (
@@ -49,4 +53,4 @@ export const IssueParentSiblings: FC = (props) => { )}
); -}; +}); From 8730049c008c97e121a752f62a1a16b95487efe0 Mon Sep 17 00:00:00 2001 From: sriram veeraghanta Date: Mon, 27 May 2024 16:51:05 +0530 Subject: [PATCH 18/77] fix: updated deploy docker compose file with restart no with quotes --- deploy/selfhost/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/selfhost/docker-compose.yml b/deploy/selfhost/docker-compose.yml index c75e9cfee4f..10f64fd1cba 100644 --- a/deploy/selfhost/docker-compose.yml +++ b/deploy/selfhost/docker-compose.yml @@ -128,7 +128,7 @@ services: image: ${DOCKERHUB_USER:-makeplane}/plane-backend:${APP_RELEASE:-stable} platform: ${DOCKER_PLATFORM:-} pull_policy: ${PULL_POLICY:-always} - restart: no + restart: "no" command: ./bin/docker-entrypoint-migrator.sh volumes: - logs_migrator:/code/plane/logs From 44f743d52c0a1f139e09e76fdcad121cb667bee2 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Mon, 27 May 2024 17:51:13 +0530 Subject: [PATCH 19/77] chore: cycle and module sidebar state filter implementation (#4522) --- .../core/sidebar/sidebar-progress-stats.tsx | 42 ++++++++++++------- web/components/cycles/sidebar.tsx | 17 +++++--- web/components/modules/sidebar.tsx | 17 +++++--- 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/web/components/core/sidebar/sidebar-progress-stats.tsx b/web/components/core/sidebar/sidebar-progress-stats.tsx index db9d94a8fd7..0194ba01f19 100644 --- a/web/components/core/sidebar/sidebar-progress-stats.tsx +++ b/web/components/core/sidebar/sidebar-progress-stats.tsx @@ -1,5 +1,5 @@ import React from "react"; - +import { observer } from "mobx-react"; import Image from "next/image"; // headless ui import { Tab } from "@headlessui/react"; @@ -15,6 +15,7 @@ import { // hooks import { Avatar, StateGroupIcon } from "@plane/ui"; import { SingleProgressStats } from "@/components/core"; +import { useProjectState } from "@/hooks/store"; import useLocalStorage from "@/hooks/use-local-storage"; // images import emptyLabel from "public/empty-state/empty_label.svg"; @@ -44,20 +45,23 @@ type Props = { handleFiltersUpdate: (key: keyof IIssueFilterOptions, value: string | string[]) => void; }; -export const SidebarProgressStats: React.FC = ({ - distribution, - groupedIssues, - totalIssues, - module, - roundedTab, - noBackground, - isPeekView = false, - isCompleted = false, - filters, - handleFiltersUpdate, -}) => { +export const SidebarProgressStats: React.FC = observer((props) => { + const { + distribution, + groupedIssues, + totalIssues, + module, + roundedTab, + noBackground, + isPeekView = false, + isCompleted = false, + filters, + handleFiltersUpdate, + } = props; const { storedValue: tab, setValue: setTab } = useLocalStorage("tab", "Assignees"); + const { groupedProjectStates } = useProjectState(); + const currentValue = (tab: string | null) => { switch (tab) { case "Assignees": @@ -71,6 +75,12 @@ export const SidebarProgressStats: React.FC = ({ } }; + const getStateGroupState = (stateGroup: string) => { + const stateGroupStates = groupedProjectStates?.[stateGroup]; + const stateGroupStatesId = stateGroupStates?.map((state) => state.id); + return stateGroupStatesId; + }; + return ( = ({ } completed={groupedIssues[group]} total={totalIssues} + {...(!isPeekView && + !isCompleted && { + onClick: () => handleFiltersUpdate("state", getStateGroupState(group) ?? []), + })} /> ))} ); -}; +}); diff --git a/web/components/cycles/sidebar.tsx b/web/components/cycles/sidebar.tsx index 2aa3afc48cd..b2562aa7718 100644 --- a/web/components/cycles/sidebar.tsx +++ b/web/components/cycles/sidebar.tsx @@ -1,5 +1,6 @@ import React, { useCallback, useEffect, useState } from "react"; import isEmpty from "lodash/isEmpty"; +import isEqual from "lodash/isEqual"; import { observer } from "mobx-react"; import { useRouter } from "next/router"; import { Controller, useForm } from "react-hook-form"; @@ -199,14 +200,18 @@ export const CycleDetailsSidebar: React.FC = observer((props) => { const handleFiltersUpdate = useCallback( (key: keyof IIssueFilterOptions, value: string | string[]) => { if (!workspaceSlug || !projectId) return; - const newValues = issueFilters?.filters?.[key] ?? []; + let newValues = issueFilters?.filters?.[key] ?? []; if (Array.isArray(value)) { - // this validation is majorly for the filter start_date, target_date custom - value.forEach((val) => { - if (!newValues.includes(val)) newValues.push(val); - else newValues.splice(newValues.indexOf(val), 1); - }); + if (key === "state") { + if (isEqual(newValues, value)) newValues = []; + else newValues = value; + } else { + value.forEach((val) => { + if (!newValues.includes(val)) newValues.push(val); + else newValues.splice(newValues.indexOf(val), 1); + }); + } } else { if (issueFilters?.filters?.[key]?.includes(value)) newValues.splice(newValues.indexOf(value), 1); else newValues.push(value); diff --git a/web/components/modules/sidebar.tsx b/web/components/modules/sidebar.tsx index d2c847eccd7..15163b188ce 100644 --- a/web/components/modules/sidebar.tsx +++ b/web/components/modules/sidebar.tsx @@ -1,4 +1,5 @@ import React, { useCallback, useEffect, useState } from "react"; +import isEqual from "lodash/isEqual"; import { observer } from "mobx-react-lite"; import { useRouter } from "next/router"; import { Controller, useForm } from "react-hook-form"; @@ -252,14 +253,18 @@ export const ModuleDetailsSidebar: React.FC = observer((props) => { const handleFiltersUpdate = useCallback( (key: keyof IIssueFilterOptions, value: string | string[]) => { if (!workspaceSlug || !projectId) return; - const newValues = issueFilters?.filters?.[key] ?? []; + let newValues = issueFilters?.filters?.[key] ?? []; if (Array.isArray(value)) { - // this validation is majorly for the filter start_date, target_date custom - value.forEach((val) => { - if (!newValues.includes(val)) newValues.push(val); - else newValues.splice(newValues.indexOf(val), 1); - }); + if (key === "state") { + if (isEqual(newValues, value)) newValues = []; + else newValues = value; + } else { + value.forEach((val) => { + if (!newValues.includes(val)) newValues.push(val); + else newValues.splice(newValues.indexOf(val), 1); + }); + } } else { if (issueFilters?.filters?.[key]?.includes(value)) newValues.splice(newValues.indexOf(value), 1); else newValues.push(value); From b93fa4a3405001aa6da68a4e8533a463618bdf31 Mon Sep 17 00:00:00 2001 From: rahulramesha <71900764+rahulramesha@users.noreply.github.com> Date: Mon, 27 May 2024 19:20:26 +0530 Subject: [PATCH 20/77] [WEB-1416] chore: Refactor project sidebar dnd and remove @hello-pangea dnd (#4581) * upgrade cmdk version to 1.0 to fix a critical issue * project side bar dnd * add some comments * slight logic change for highlighting on drop --- web/components/project/sidebar-list-item.tsx | 157 ++++++++-- web/components/project/sidebar-list.tsx | 295 +++++++++---------- web/helpers/project.helper.ts | 17 +- web/package.json | 1 - yarn.lock | 70 +---- 5 files changed, 280 insertions(+), 260 deletions(-) diff --git a/web/components/project/sidebar-list-item.tsx b/web/components/project/sidebar-list-item.tsx index 5dcc31c3fc4..4d45a515fa7 100644 --- a/web/components/project/sidebar-list-item.tsx +++ b/web/components/project/sidebar-list-item.tsx @@ -1,8 +1,13 @@ -import { useRef, useState } from "react"; -import { DraggableProvided, DraggableStateSnapshot } from "@hello-pangea/dnd"; +import { useEffect, useRef, useState } from "react"; +import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; +import { draggable, dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; +import { pointerOutsideOfPreview } from "@atlaskit/pragmatic-drag-and-drop/element/pointer-outside-of-preview"; +import { setCustomNativeDragPreview } from "@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview"; +import { attachInstruction, extractInstruction } from "@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item"; import { observer } from "mobx-react"; import Link from "next/link"; import { useRouter } from "next/router"; +import { createRoot } from "react-dom/client"; import { MoreVertical, PenSquare, @@ -28,6 +33,7 @@ import { ContrastIcon, LayersIcon, setPromiseToast, + DropIndicator, } from "@plane/ui"; import { LeaveProjectModal, ProjectLogo, PublishProjectModal } from "@/components/project"; import { EUserProjectRoles } from "@/constants/project"; @@ -36,17 +42,23 @@ import { cn } from "@/helpers/common.helper"; import { useAppTheme, useEventTracker, useProject } from "@/hooks/store"; import useOutsideClickDetector from "@/hooks/use-outside-click-detector"; import { usePlatformOS } from "@/hooks/use-platform-os"; +import { HIGHLIGHT_CLASS, highlightIssueOnDrop } from "../issues/issue-layouts/utils"; // helpers // components type Props = { projectId: string; - provided?: DraggableProvided; - snapshot?: DraggableStateSnapshot; handleCopyText: () => void; - shortContextMenu?: boolean; + handleOnProjectDrop?: ( + sourceId: string | undefined, + destinationId: string | undefined, + shouldDropAtEnd: boolean + ) => void; + projectListType: "JOINED" | "FAVORITES"; disableDrag?: boolean; + disableDrop?: boolean; + isLastChild: boolean; }; const navigation = (workspaceSlug: string, projectId: string) => [ @@ -89,7 +101,8 @@ const navigation = (workspaceSlug: string, projectId: string) => [ export const ProjectSidebarListItem: React.FC = observer((props) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { projectId, provided, snapshot, handleCopyText, shortContextMenu = false, disableDrag } = props; + const { projectId, handleCopyText, disableDrag, disableDrop, isLastChild, handleOnProjectDrop, projectListType } = + props; // store hooks const { sidebarCollapsed: isCollapsed, toggleSidebar } = useAppTheme(); const { setTrackElement } = useEventTracker(); @@ -99,8 +112,12 @@ export const ProjectSidebarListItem: React.FC = observer((props) => { const [leaveProjectModalOpen, setLeaveProjectModal] = useState(false); const [publishModalOpen, setPublishModal] = useState(false); const [isMenuActive, setIsMenuActive] = useState(false); + const [isDragging, setIsDragging] = useState(false); + const [instruction, setInstruction] = useState<"DRAG_OVER" | "DRAG_BELOW" | undefined>(undefined); // refs const actionSectionRef = useRef(null); + const projectRef = useRef(null); + const dragHandleRef = useRef(null); // router const router = useRouter(); const { workspaceSlug, projectId: URLProjectId } = router.query; @@ -160,7 +177,97 @@ export const ProjectSidebarListItem: React.FC = observer((props) => { } }; + useEffect(() => { + const element = projectRef.current; + const dragHandleElement = dragHandleRef.current; + + if (!element) return; + + return combine( + draggable({ + element, + canDrag: () => !disableDrag, + dragHandle: dragHandleElement ?? undefined, + getInitialData: () => ({ id: projectId, dragInstanceId: "PROJECTS" }), + onDragStart: () => { + setIsDragging(true); + }, + onDrop: () => { + setIsDragging(false); + }, + onGenerateDragPreview: ({ nativeSetDragImage }) => { + // Add a custom drag image + setCustomNativeDragPreview({ + getOffset: pointerOutsideOfPreview({ x: "0px", y: "0px" }), + render: ({ container }) => { + const root = createRoot(container); + root.render( +
+
+ {project && } +
+

{project?.name}

+
+ ); + return () => root.unmount(); + }, + nativeSetDragImage, + }); + }, + }), + dropTargetForElements({ + element, + canDrop: ({ source }) => + !disableDrop && source?.data?.id !== projectId && source?.data?.dragInstanceId === "PROJECTS", + getData: ({ input, element }) => { + const data = { id: projectId }; + + // attach instruction for last in list + return attachInstruction(data, { + input, + element, + currentLevel: 0, + indentPerLevel: 0, + mode: isLastChild ? "last-in-group" : "standard", + }); + }, + onDrag: ({ self }) => { + const extractedInstruction = extractInstruction(self?.data)?.type; + // check if the highlight is to be shown above or below + setInstruction( + extractedInstruction + ? extractedInstruction === "reorder-below" && isLastChild + ? "DRAG_BELOW" + : "DRAG_OVER" + : undefined + ); + }, + onDragLeave: () => { + setInstruction(undefined); + }, + onDrop: ({ self, source }) => { + setInstruction(undefined); + const extractedInstruction = extractInstruction(self?.data)?.type; + const currentInstruction = extractedInstruction + ? extractedInstruction === "reorder-below" && isLastChild + ? "DRAG_BELOW" + : "DRAG_OVER" + : undefined; + if (!currentInstruction) return; + + const sourceId = source?.data?.id as string | undefined; + const destinationId = self?.data?.id as string | undefined; + + handleOnProjectDrop && handleOnProjectDrop(sourceId, destinationId, currentInstruction === "DRAG_BELOW"); + + highlightIssueOnDrop(`sidebar-${sourceId}-${projectListType}`); + }, + }) + ); + }, [projectRef?.current, dragHandleRef?.current, projectId, isLastChild, projectListType, handleOnProjectDrop]); + useOutsideClickDetector(actionSectionRef, () => setIsMenuActive(false)); + useOutsideClickDetector(projectRef, () => projectRef?.current?.classList?.remove(HIGHLIGHT_CLASS)); if (!project) return null; @@ -168,48 +275,47 @@ export const ProjectSidebarListItem: React.FC = observer((props) => { <> setPublishModal(false)} /> - + {({ open }) => ( - <> +
+
- {provided && !disableDrag && ( + {!disableDrag && ( )} - + = observer((props) => { )} >
-
+
{!isCollapsed &&

{project.name}

} @@ -380,7 +486,8 @@ export const ProjectSidebarListItem: React.FC = observer((props) => { })} - + {isLastChild && } +
)} diff --git a/web/components/project/sidebar-list.tsx b/web/components/project/sidebar-list.tsx index ed1c90692bf..b6eb0c70820 100644 --- a/web/components/project/sidebar-list.tsx +++ b/web/components/project/sidebar-list.tsx @@ -1,5 +1,6 @@ import { useState, FC, useRef, useEffect } from "react"; -import { DragDropContext, Draggable, DropResult, Droppable } from "@hello-pangea/dnd"; +import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; +import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element"; import { observer } from "mobx-react"; import { useRouter } from "next/router"; import { ChevronDown, ChevronRight, Plus } from "lucide-react"; @@ -54,21 +55,28 @@ export const ProjectSidebarList: FC = observer(() => { }); }; - const onDragEnd = (result: DropResult) => { - const { source, destination, draggableId } = result; - if (!destination || !workspaceSlug) return; - if (source.index === destination.index) return; + const handleOnProjectDrop = ( + sourceId: string | undefined, + destinationId: string | undefined, + shouldDropAtEnd: boolean + ) => { + if (!sourceId || !destinationId || !workspaceSlug) return; + if (sourceId === destinationId) return; const joinedProjectsList: IProject[] = []; joinedProjects.map((projectId) => { const projectDetails = getProjectById(projectId); if (projectDetails) joinedProjectsList.push(projectDetails); }); + + const sourceIndex = joinedProjects.indexOf(sourceId); + const destinationIndex = shouldDropAtEnd ? joinedProjects.length : joinedProjects.indexOf(destinationId); + if (joinedProjectsList.length <= 0) return; - const updatedSortOrder = orderJoinedProjects(source.index, destination.index, draggableId, joinedProjectsList); + const updatedSortOrder = orderJoinedProjects(sourceIndex, destinationIndex, sourceId, joinedProjectsList); if (updatedSortOrder != undefined) - updateProjectView(workspaceSlug.toString(), draggableId, { sort_order: updatedSortOrder }).catch(() => { + updateProjectView(workspaceSlug.toString(), sourceId, { sort_order: updatedSortOrder }).catch(() => { setToast({ type: TOAST_TYPE.ERROR, title: "Error!", @@ -98,7 +106,21 @@ export const ProjectSidebarList: FC = observer(() => { currentContainerRef.removeEventListener("scroll", handleScroll); } }; - }, []); + }, [containerRef]); + + useEffect(() => { + const element = containerRef.current; + + if (!element) return; + + return combine( + autoScrollForElements({ + element, + canScroll: ({ source }) => source?.data?.dragInstanceId === "PROJECTS", + getAllowedAxis: () => "vertical", + }) + ); + }, [containerRef]); return ( <> @@ -123,156 +145,117 @@ export const ProjectSidebarList: FC = observer(() => { } )} > - - - {(provided) => ( -
- {favoriteProjects && favoriteProjects.length > 0 && ( - - {({ open }) => ( - <> - {!isCollapsed && ( -
- - Favorites - {open ? ( - - ) : ( - - )} - - {isAuthorizedUser && ( - - )} -
- )} - + {favoriteProjects && favoriteProjects.length > 0 && ( + + {({ open }) => ( + <> + {!isCollapsed && ( +
+ + Favorites + {open ? : } + + {isAuthorizedUser && ( +
- )} - - - - - {(provided) => ( -
- {joinedProjects && joinedProjects.length > 0 && ( - - {({ open }) => ( - <> - {!isCollapsed && ( -
- - Your projects - {open ? ( - - ) : ( - - )} - - {isAuthorizedUser && ( - - )} -
- )} - + + )} +
+ )} + + + {favoriteProjects.map((projectId, index) => ( + handleCopyText(projectId)} + projectListType="FAVORITES" + disableDrag + disableDrop + isLastChild={index === favoriteProjects.length - 1} + /> + ))} + + + + )} +
+ )} +
+
+ {joinedProjects && joinedProjects.length > 0 && ( + + {({ open }) => ( + <> + {!isCollapsed && ( +
+ + Your projects + {open ? : } + + {isAuthorizedUser && ( +
- )} - - + + + )} +
+ )} + + + {joinedProjects.map((projectId, index) => ( + handleCopyText(projectId)} + isLastChild={index === joinedProjects.length - 1} + handleOnProjectDrop={handleOnProjectDrop} + /> + ))} + + + + )} + + )} +
{isAuthorizedUser && joinedProjects && joinedProjects.length === 0 && (
@@ -160,6 +162,7 @@ export const InboxIssueEditRoot: FC = observer((props) => { variant="primary" size="sm" type="button" + ref={submitBtnRef} loading={formSubmitting} disabled={isTitleLengthMoreThan255Character} onClick={handleFormSubmit} diff --git a/web/components/inbox/modals/create-edit-modal/issue-description.tsx b/web/components/inbox/modals/create-edit-modal/issue-description.tsx index 882fb0f955e..4b4cb261e74 100644 --- a/web/components/inbox/modals/create-edit-modal/issue-description.tsx +++ b/web/components/inbox/modals/create-edit-modal/issue-description.tsx @@ -18,11 +18,13 @@ type TInboxIssueDescription = { data: Partial; handleData: (issueKey: keyof Partial, issueValue: Partial[keyof Partial]) => void; editorRef: RefObject; + onEnterKeyPress?: (e?: any) => void; }; // TODO: have to implement GPT Assistance export const InboxIssueDescription: FC = observer((props) => { - const { containerClassName, workspaceSlug, projectId, workspaceId, data, handleData, editorRef } = props; + const { containerClassName, workspaceSlug, projectId, workspaceId, data, handleData, editorRef, onEnterKeyPress } = + props; // hooks const { loader } = useProjectInbox(); @@ -44,6 +46,7 @@ export const InboxIssueDescription: FC = observer((props onChange={(_description: object, description_html: string) => handleData("description_html", description_html)} placeholder={getDescriptionPlaceholder} containerClassName={containerClassName} + onEnterKeyPress={onEnterKeyPress} /> ); }); diff --git a/web/components/issues/issue-modal/form.tsx b/web/components/issues/issue-modal/form.tsx index 4c608f83a3a..a8a43ced887 100644 --- a/web/components/issues/issue-modal/form.tsx +++ b/web/components/issues/issue-modal/form.tsx @@ -109,6 +109,7 @@ export const IssueFormRoot: FC = observer((props) => { const [iAmFeelingLucky, setIAmFeelingLucky] = useState(false); // refs const editorRef = useRef(null); + const submitBtnRef = useRef(null); // router const router = useRouter(); const { workspaceSlug } = router.query; @@ -470,6 +471,7 @@ export const IssueFormRoot: FC = observer((props) => { onChange(description_html); handleFormChange(); }} + onEnterKeyPress={() => submitBtnRef?.current?.click()} ref={editorRef} tabIndex={getTabIndex("description_html")} placeholder={getDescriptionPlaceholder} @@ -770,6 +772,7 @@ export const IssueFormRoot: FC = observer((props) => { variant="primary" type="submit" size="sm" + ref={submitBtnRef} loading={isSubmitting} tabIndex={isDraft ? getTabIndex("submit_button") : getTabIndex("draft_button")} > From c9586bfdcf4f1b8aad8c7ee35463d6f541573830 Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Tue, 28 May 2024 11:49:14 +0530 Subject: [PATCH 24/77] style: fix all empty states size of inconsistency. (#4613) --- web/components/issues/issue-layouts/empty-states/cycle.tsx | 2 -- .../issues/issue-layouts/empty-states/draft-issues.tsx | 2 -- .../issues/issue-layouts/empty-states/project-issues.tsx | 2 -- .../issues/issue-layouts/roots/all-issue-layout-root.tsx | 3 +-- 4 files changed, 1 insertion(+), 8 deletions(-) diff --git a/web/components/issues/issue-layouts/empty-states/cycle.tsx b/web/components/issues/issue-layouts/empty-states/cycle.tsx index 04ce2cb504d..5f1984516aa 100644 --- a/web/components/issues/issue-layouts/empty-states/cycle.tsx +++ b/web/components/issues/issue-layouts/empty-states/cycle.tsx @@ -68,7 +68,6 @@ export const CycleEmptyState: React.FC = observer((props) => { ? EmptyStateType.PROJECT_EMPTY_FILTER : EmptyStateType.PROJECT_CYCLE_NO_ISSUES; const additionalPath = isCompletedAndEmpty ? undefined : activeLayout ?? "list"; - const emptyStateSize = isEmptyFilters ? "lg" : "sm"; return ( <> @@ -84,7 +83,6 @@ export const CycleEmptyState: React.FC = observer((props) => { { diff --git a/web/components/issues/issue-layouts/empty-states/draft-issues.tsx b/web/components/issues/issue-layouts/empty-states/draft-issues.tsx index 07cb70ceb37..7fc6811c857 100644 --- a/web/components/issues/issue-layouts/empty-states/draft-issues.tsx +++ b/web/components/issues/issue-layouts/empty-states/draft-issues.tsx @@ -41,14 +41,12 @@ export const ProjectDraftEmptyState: React.FC = observer(() => { const emptyStateType = issueFilterCount > 0 ? EmptyStateType.PROJECT_DRAFT_EMPTY_FILTER : EmptyStateType.PROJECT_DRAFT_NO_ISSUES; const additionalPath = issueFilterCount > 0 ? activeLayout ?? "list" : undefined; - const emptyStateSize = issueFilterCount > 0 ? "lg" : "sm"; return (
0 ? handleClearAllFilters : undefined} />
diff --git a/web/components/issues/issue-layouts/empty-states/project-issues.tsx b/web/components/issues/issue-layouts/empty-states/project-issues.tsx index 8b496e96128..5682eaf7763 100644 --- a/web/components/issues/issue-layouts/empty-states/project-issues.tsx +++ b/web/components/issues/issue-layouts/empty-states/project-issues.tsx @@ -43,14 +43,12 @@ export const ProjectEmptyState: React.FC = observer(() => { const emptyStateType = issueFilterCount > 0 ? EmptyStateType.PROJECT_EMPTY_FILTER : EmptyStateType.PROJECT_NO_ISSUES; const additionalPath = issueFilterCount > 0 ? activeLayout ?? "list" : undefined; - const emptyStateSize = issueFilterCount > 0 ? "lg" : "sm"; return (
0 ? undefined diff --git a/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx b/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx index 51188fe7210..93a275f39fc 100644 --- a/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx +++ b/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx @@ -154,12 +154,11 @@ export const AllIssueLayoutRoot: React.FC = observer(() => { return (
-
+
{issueIds.length === 0 ? ( 0 ? currentView !== "custom-view" && currentView !== "subscribed" From 1d7b3efb805f746b225533664c25508a13559da2 Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Tue, 28 May 2024 11:50:04 +0530 Subject: [PATCH 25/77] [WEB-1148] chore: icons updates for consistency across platform. (#4571) * [WEB-1148] chore: icons updates for consistency across platform. * chore: update logic for rendering custom lead icon. * chore: update Icon prop name. * chore: update `Icon` prop to `icon`. --- packages/ui/src/icons/index.ts | 1 - packages/ui/src/icons/user-group-icon.tsx | 35 ------------------- .../actions/issue-actions/actions-list.tsx | 6 ++-- .../upcoming-cycles-list-item.tsx | 6 ++-- .../cycles/list/cycle-list-item-action.tsx | 6 ++-- web/components/cycles/sidebar.tsx | 4 +-- web/components/dropdowns/member/avatar.tsx | 15 +++++--- web/components/dropdowns/member/index.tsx | 6 ++-- .../inbox/content/issue-properties.tsx | 6 ++-- web/components/integration/github/root.tsx | 6 ++-- web/components/integration/jira/root.tsx | 6 ++-- .../activity/actions/assignee.tsx | 8 ++--- .../issues/issue-detail/sidebar.tsx | 4 +-- .../issues/peek-overview/properties.tsx | 5 +-- web/components/modules/module-card-item.tsx | 6 ++-- .../modules/module-list-item-action.tsx | 6 ++-- web/components/modules/sidebar.tsx | 9 ++--- web/components/workspace/sidebar-dropdown.tsx | 6 ++-- web/constants/spreadsheet.ts | 12 ++++--- web/pages/profile/index.tsx | 4 +-- 20 files changed, 64 insertions(+), 93 deletions(-) delete mode 100644 packages/ui/src/icons/user-group-icon.tsx diff --git a/packages/ui/src/icons/index.ts b/packages/ui/src/icons/index.ts index dbed6ba8939..5028848d8e2 100644 --- a/packages/ui/src/icons/index.ts +++ b/packages/ui/src/icons/index.ts @@ -19,4 +19,3 @@ export * from "./priority-icon"; export * from "./related-icon"; export * from "./side-panel-icon"; export * from "./transfer-icon"; -export * from "./user-group-icon"; diff --git a/packages/ui/src/icons/user-group-icon.tsx b/packages/ui/src/icons/user-group-icon.tsx deleted file mode 100644 index 7cad96d231c..00000000000 --- a/packages/ui/src/icons/user-group-icon.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import * as React from "react"; - -import { ISvgIcons } from "./type"; - -export const UserGroupIcon: React.FC = ({ className = "text-current", ...rest }) => ( - - - - - - -); diff --git a/web/components/command-palette/actions/issue-actions/actions-list.tsx b/web/components/command-palette/actions/issue-actions/actions-list.tsx index 6e835180456..040eb2e3ca7 100644 --- a/web/components/command-palette/actions/issue-actions/actions-list.tsx +++ b/web/components/command-palette/actions/issue-actions/actions-list.tsx @@ -1,10 +1,10 @@ import { Command } from "cmdk"; import { observer } from "mobx-react"; import { useRouter } from "next/router"; -import { LinkIcon, Signal, Trash2, UserMinus2, UserPlus2 } from "lucide-react"; +import { LinkIcon, Signal, Trash2, UserMinus2, UserPlus2, Users } from "lucide-react"; import { TIssue } from "@plane/types"; // hooks -import { DoubleCircleIcon, UserGroupIcon, TOAST_TYPE, setToast } from "@plane/ui"; +import { DoubleCircleIcon, TOAST_TYPE, setToast } from "@plane/ui"; // constants import { EIssuesStoreType } from "@/constants/issue"; // helpers @@ -115,7 +115,7 @@ export const CommandPaletteIssueActions: React.FC = observer((props) => { className="focus:outline-none" >
- + Assign to...
diff --git a/web/components/cycles/active-cycle/upcoming-cycles-list-item.tsx b/web/components/cycles/active-cycle/upcoming-cycles-list-item.tsx index 9b63b0f6f61..a66af73c39f 100644 --- a/web/components/cycles/active-cycle/upcoming-cycles-list-item.tsx +++ b/web/components/cycles/active-cycle/upcoming-cycles-list-item.tsx @@ -2,7 +2,7 @@ import { useRef } from "react"; import { observer } from "mobx-react"; import Link from "next/link"; import { useRouter } from "next/router"; -import { User2 } from "lucide-react"; +import { Users } from "lucide-react"; // ui import { Avatar, AvatarGroup, setPromiseToast } from "@plane/ui"; // components @@ -112,9 +112,7 @@ export const UpcomingCycleListItem: React.FC = observer((props) => { })} ) : ( - - - + )} = observer((props) => { })} ) : ( - - - + )}
diff --git a/web/components/cycles/sidebar.tsx b/web/components/cycles/sidebar.tsx index b2562aa7718..595fe9b7a48 100644 --- a/web/components/cycles/sidebar.tsx +++ b/web/components/cycles/sidebar.tsx @@ -10,10 +10,10 @@ import { ChevronDown, LinkIcon, Trash2, - UserCircle2, AlertCircle, ChevronRight, CalendarClock, + SquareUser, } from "lucide-react"; import { Disclosure, Transition } from "@headlessui/react"; // types @@ -432,7 +432,7 @@ export const CycleDetailsSidebar: React.FC = observer((props) => {
- + Lead
diff --git a/web/components/dropdowns/member/avatar.tsx b/web/components/dropdowns/member/avatar.tsx index 15e1fbd8c8f..868c286654f 100644 --- a/web/components/dropdowns/member/avatar.tsx +++ b/web/components/dropdowns/member/avatar.tsx @@ -1,16 +1,19 @@ import { observer } from "mobx-react"; +// icons +import { LucideIcon, Users } from "lucide-react"; +// ui +import { Avatar, AvatarGroup } from "@plane/ui"; // hooks -import { Avatar, AvatarGroup, UserGroupIcon } from "@plane/ui"; import { useMember } from "@/hooks/store"; -// ui type AvatarProps = { showTooltip: boolean; userIds: string | string[] | null; + icon?: LucideIcon; }; export const ButtonAvatars: React.FC = observer((props) => { - const { showTooltip, userIds } = props; + const { showTooltip, userIds, icon: Icon } = props; // store hooks const { getUserDetails } = useMember(); @@ -33,5 +36,9 @@ export const ButtonAvatars: React.FC = observer((props) => { } } - return ; + return Icon ? ( + + ) : ( + + ); }); diff --git a/web/components/dropdowns/member/index.tsx b/web/components/dropdowns/member/index.tsx index d14cf316fad..7af6f4fe1b6 100644 --- a/web/components/dropdowns/member/index.tsx +++ b/web/components/dropdowns/member/index.tsx @@ -1,6 +1,6 @@ import { Fragment, useRef, useState } from "react"; import { observer } from "mobx-react-lite"; -import { ChevronDown } from "lucide-react"; +import { ChevronDown, LucideIcon } from "lucide-react"; // headless ui import { Combobox } from "@headlessui/react"; // helpers @@ -19,6 +19,7 @@ import { MemberDropdownProps } from "./types"; type Props = { projectId?: string; + icon?: LucideIcon; onClose?: () => void; } & MemberDropdownProps; @@ -43,6 +44,7 @@ export const MemberDropdown: React.FC = observer((props) => { showTooltip = false, tabIndex, value, + icon, } = props; // states const [isOpen, setIsOpen] = useState(false); @@ -115,7 +117,7 @@ export const MemberDropdown: React.FC = observer((props) => { showTooltip={showTooltip} variant={buttonVariant} > - {!hideIcon && } + {!hideIcon && } {BUTTON_VARIANTS_WITH_TEXT.includes(buttonVariant) && ( {Array.isArray(value) && value.length > 0 diff --git a/web/components/inbox/content/issue-properties.tsx b/web/components/inbox/content/issue-properties.tsx index 9074f67ca5a..92205e626cd 100644 --- a/web/components/inbox/content/issue-properties.tsx +++ b/web/components/inbox/content/issue-properties.tsx @@ -1,9 +1,9 @@ import React from "react"; import { observer } from "mobx-react"; import { useRouter } from "next/router"; -import { CalendarCheck2, CopyPlus, Signal, Tag } from "lucide-react"; +import { CalendarCheck2, CopyPlus, Signal, Tag, Users } from "lucide-react"; import { TInboxDuplicateIssueDetails, TIssue } from "@plane/types"; -import { ControlLink, DoubleCircleIcon, Tooltip, UserGroupIcon } from "@plane/ui"; +import { ControlLink, DoubleCircleIcon, Tooltip } from "@plane/ui"; // components import { DateDropdown, PriorityDropdown, MemberDropdown, StateDropdown } from "@/components/dropdowns"; import { IssueLabel, TIssueOperations } from "@/components/issues"; @@ -64,7 +64,7 @@ export const InboxIssueContentProperties: React.FC = observer((props) => {/* Assignee */}
- + Assignees
= observer((props if (!activity) return <>; return ( } + icon={} activityId={activityId} ends={ends} > diff --git a/web/components/issues/issue-detail/sidebar.tsx b/web/components/issues/issue-detail/sidebar.tsx index a9a23ebdcbe..568dc4cedc5 100644 --- a/web/components/issues/issue-detail/sidebar.tsx +++ b/web/components/issues/issue-detail/sidebar.tsx @@ -12,6 +12,7 @@ import { Tag, Trash2, Triangle, + Users, XCircle, } from "lucide-react"; // hooks @@ -24,7 +25,6 @@ import { RelatedIcon, TOAST_TYPE, Tooltip, - UserGroupIcon, setToast, } from "@plane/ui"; import { @@ -219,7 +219,7 @@ export const IssueDetailsSidebar: React.FC = observer((props) => {
- + Assignees
= observer((pro {/* assignee */}
- + Assignees
= observer((props) => { ) : ( - - - + )}
diff --git a/web/components/modules/module-list-item-action.tsx b/web/components/modules/module-list-item-action.tsx index fa7d71577cf..2a5a3cdd04c 100644 --- a/web/components/modules/module-list-item-action.tsx +++ b/web/components/modules/module-list-item-action.tsx @@ -2,7 +2,7 @@ import React, { FC } from "react"; import { observer } from "mobx-react"; import { useRouter } from "next/router"; // icons -import { CalendarCheck2, CalendarClock, MoveRight, User2 } from "lucide-react"; +import { CalendarCheck2, CalendarClock, MoveRight, SquareUser } from "lucide-react"; // types import { IModule } from "@plane/types"; // ui @@ -140,9 +140,7 @@ export const ModuleListItemAction: FC = observer((props) => { ) : ( - - - + )} diff --git a/web/components/modules/sidebar.tsx b/web/components/modules/sidebar.tsx index 15163b188ce..3482afb1bcc 100644 --- a/web/components/modules/sidebar.tsx +++ b/web/components/modules/sidebar.tsx @@ -12,8 +12,9 @@ import { Info, LinkIcon, Plus, + SquareUser, Trash2, - UserCircle2, + Users, } from "lucide-react"; import { Disclosure, Transition } from "@headlessui/react"; import { IIssueFilterOptions, ILinkDetails, IModule, ModuleLink } from "@plane/types"; @@ -24,7 +25,6 @@ import { LayersIcon, CustomSelect, ModuleStatusIcon, - UserGroupIcon, TOAST_TYPE, setToast, ArchiveIcon, @@ -498,7 +498,7 @@ export const ModuleDetailsSidebar: React.FC = observer((props) => {
- + Lead
= observer((props) => { buttonVariant="background-with-text" placeholder="Lead" disabled={!isEditingAllowed || isArchived} + icon={SquareUser} />
)} @@ -523,7 +524,7 @@ export const ModuleDetailsSidebar: React.FC = observer((props) => {
- + Members
[ key: "my_activity", name: "My activity", href: `/${workspaceSlug}/profile/${userId}`, - icon: CircleUserRound, + icon: Activity, }, { key: "settings", @@ -39,7 +39,7 @@ const userLinks = (workspaceSlug: string, userId: string) => [ const profileLinks = (workspaceSlug: string, userId: string) => [ { name: "My activity", - icon: UserCircle2, + icon: Activity, link: `/${workspaceSlug}/profile/${userId}`, }, { diff --git a/web/constants/spreadsheet.ts b/web/constants/spreadsheet.ts index bad135994bf..d70a603a24e 100644 --- a/web/constants/spreadsheet.ts +++ b/web/constants/spreadsheet.ts @@ -1,7 +1,12 @@ import { FC } from "react"; +// icons +import { CalendarDays, Link2, Signal, Tag, Triangle, Paperclip, CalendarCheck2, CalendarClock, Users } from "lucide-react"; +// types +import { IIssueDisplayProperties, TIssue, TIssueOrderByOptions } from "@plane/types"; +// ui +import { LayersIcon, DoubleCircleIcon, DiceIcon, ContrastIcon } from "@plane/ui"; import { ISvgIcons } from "@plane/ui/src/icons/type"; -import { CalendarDays, Link2, Signal, Tag, Triangle, Paperclip, CalendarCheck2, CalendarClock } from "lucide-react"; -import { LayersIcon, DoubleCircleIcon, UserGroupIcon, DiceIcon, ContrastIcon } from "@plane/ui"; +// components import { SpreadsheetAssigneeColumn, SpreadsheetAttachmentColumn, @@ -18,7 +23,6 @@ import { SpreadsheetSubIssueColumn, SpreadsheetUpdatedOnColumn, } from "@/components/issues/issue-layouts/spreadsheet"; -import { IIssueDisplayProperties, TIssue, TIssueOrderByOptions } from "@plane/types"; export const SPREADSHEET_PROPERTY_DETAILS: { [key: string]: { @@ -42,7 +46,7 @@ export const SPREADSHEET_PROPERTY_DETAILS: { ascendingOrderTitle: "A", descendingOrderKey: "-assignees__first_name", descendingOrderTitle: "Z", - icon: UserGroupIcon, + icon: Users, Column: SpreadsheetAssigneeColumn, }, created_on: { diff --git a/web/pages/profile/index.tsx b/web/pages/profile/index.tsx index c49de68de48..a7415cf3ea9 100644 --- a/web/pages/profile/index.tsx +++ b/web/pages/profile/index.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState, ReactElement } from "react"; import { observer } from "mobx-react"; import { Controller, useForm } from "react-hook-form"; -import { ChevronDown, User2 } from "lucide-react"; +import { ChevronDown, CircleUserRound } from "lucide-react"; import { Disclosure, Transition } from "@headlessui/react"; // services // hooks @@ -172,7 +172,7 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => { + )} ))} diff --git a/web/pages/[workspaceSlug]/analytics.tsx b/web/pages/[workspaceSlug]/analytics.tsx index 75e6be7f93a..499efc9170d 100644 --- a/web/pages/[workspaceSlug]/analytics.tsx +++ b/web/pages/[workspaceSlug]/analytics.tsx @@ -34,23 +34,21 @@ const AnalyticsPage: NextPageWithLayout = observer(() => { {workspaceProjectIds && workspaceProjectIds.length > 0 ? (
- + {ANALYTICS_TABS.map((tab) => ( - - `rounded-0 w-full border-b border-custom-border-200 px-0 py-2 text-xs hover:bg-custom-background-80 focus:outline-none md:w-max md:rounded-3xl md:border md:px-4 ${ - selected - ? "border-custom-primary-100 text-custom-primary-100 md:border-custom-border-200 md:bg-custom-background-80 md:text-custom-text-200" - : "border-transparent" - }` - } - onClick={() => { - router.query.analytics_tab = tab.key; - router.push(router); - }} - > - {tab.title} + + {({ selected }) => ( + + )} ))} From a04ce5abfc04c7cf57b5b41e0a72d72285476606 Mon Sep 17 00:00:00 2001 From: sriram veeraghanta Date: Tue, 28 May 2024 13:08:37 +0530 Subject: [PATCH 29/77] fix: posthog proxy config using rewrites --- turbo.json | 1 - web/lib/posthog-provider.tsx | 11 ++++++----- web/next.config.js | 5 +++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/turbo.json b/turbo.json index 4fb34d29d89..fde4ffc79b5 100644 --- a/turbo.json +++ b/turbo.json @@ -8,7 +8,6 @@ "NEXT_PUBLIC_SPACE_BASE_URL", "NEXT_PUBLIC_SPACE_BASE_PATH", "NEXT_PUBLIC_WEB_BASE_URL", - "NEXT_PUBLIC_TRACK_EVENTS", "NEXT_PUBLIC_PLAUSIBLE_DOMAIN", "NEXT_PUBLIC_CRISP_ID", "NEXT_PUBLIC_ENABLE_SESSION_RECORDER", diff --git a/web/lib/posthog-provider.tsx b/web/lib/posthog-provider.tsx index 3517fb7a771..6a5bcbaaf2c 100644 --- a/web/lib/posthog-provider.tsx +++ b/web/lib/posthog-provider.tsx @@ -20,7 +20,7 @@ export interface IPosthogWrapper { } const PostHogProvider: FC = (props) => { - const { children, user, workspaceRole, currentWorkspaceId, projectRole, posthogAPIKey, posthogHost } = props; + const { children, user, workspaceRole, currentWorkspaceId, projectRole } = props; // states const [lastWorkspaceId, setLastWorkspaceId] = useState(currentWorkspaceId); // router @@ -42,15 +42,16 @@ const PostHogProvider: FC = (props) => { }, [user, workspaceRole, projectRole]); useEffect(() => { - if (posthogAPIKey && (process.env.NEXT_PUBLIC_POSTHOG_HOST || posthogHost)) { - posthog.init(posthogAPIKey, { - api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST || posthogHost || "https://app.posthog.com", + if (process.env.NEXT_PUBLIC_POSTHOG_KEY && process.env.NEXT_PUBLIC_POSTHOG_HOST) { + posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, { + api_host: "/ingest", + ui_host: process.env.NEXT_PUBLIC_POSTHOG_HOST, debug: process.env.NEXT_PUBLIC_POSTHOG_DEBUG === "1", // Debug mode based on the environment variable autocapture: false, capture_pageview: false, // Disable automatic pageview capture, as we capture manually }); } - }, [posthogAPIKey, posthogHost]); + }, []); useEffect(() => { // Join workspace group on workspace change diff --git a/web/next.config.js b/web/next.config.js index 0482f507fa9..2a69a01a7d5 100644 --- a/web/next.config.js +++ b/web/next.config.js @@ -55,14 +55,15 @@ const nextConfig = { ] }, async rewrites() { + const posthogHost = process.env.NEXT_PUBLIC_POSTHOG_HOST || "https://app.posthog.com" const rewrites = [ { source: "/ingest/static/:path*", - destination: "https://us-assets.i.posthog.com/static/:path*", + destination: `${posthogHost}/static/:path*`, }, { source: "/ingest/:path*", - destination: "https://us.i.posthog.com/:path*", + destination: `${posthogHost}/:path*`, }, ]; if (process.env.NEXT_PUBLIC_ADMIN_BASE_URL || process.env.NEXT_PUBLIC_ADMIN_BASE_PATH) { From ff03c0b718aef82b8467729ac7207f34ca741b16 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Sun, 26 May 2024 16:37:10 +0530 Subject: [PATCH 30/77] [WEB-1322] dev: conflict free pages collaboration (#4463) * chore: pages realtime * chore: empty binary response * chore: added a ypy package * feat: pages collaboration * chore: update fetching logic * chore: degrade ypy version * chore: replace useEffect fetch logic with useSWR * chore: move all the update logic to the page store * refactor: remove react-hook-form * chore: save description_html as well * chore: migrate old data logic * fix: added description_binary as field name * fix: code cleanup * refactor: create separate hook to handle page description * fix: build errors * chore: combine updates instead of using the whole document * chore: removed ypy package * chore: added conflict resolving logic to the client side * chore: add a save changes button * chore: add read-only validation * chore: remove saving state information * chore: added permission class * chore: removed the migration file * chore: corrected the model field * chore: rename pageStore to page * chore: update collaboration provider * chore: add try catch to handle error --------- Co-authored-by: NarayanBavisetti --- apiserver/plane/app/serializers/page.py | 4 +- apiserver/plane/app/urls/page.py | 11 ++ apiserver/plane/app/views/__init__.py | 1 + apiserver/plane/app/views/page/base.py | 47 ++++++ apiserver/plane/db/models/page.py | 2 +- packages/editor/core/src/hooks/use-editor.tsx | 41 ++--- .../core/src/hooks/use-read-only-editor.tsx | 4 + packages/editor/core/src/index.ts | 1 + packages/editor/core/src/lib/utils.ts | 19 +++ .../editor/core/src/types/editor-ref-api.ts | 1 + .../src/ui/extensions/core-without-props.tsx | 121 ++++++++++++++ .../image/image-extension-without-props.tsx | 33 ++++ .../src/ui/mentions/mention-without-props.tsx | 79 +++++++++ packages/editor/document-editor/package.json | 7 +- .../src/hooks/use-document-editor.ts | 85 ++++++++++ packages/editor/document-editor/src/index.ts | 2 + .../src/providers/collaboration-provider.ts | 60 +++++++ .../src/ui/extensions/index.tsx | 8 +- .../editor/document-editor/src/ui/index.tsx | 47 ++---- .../editor/document-editor/src/utils/yjs.ts | 76 +++++++++ .../editor/lite-text-editor/src/ui/index.tsx | 18 +-- .../editor/rich-text-editor/src/ui/index.tsx | 21 +-- web/components/headers/page-details.tsx | 48 +++--- web/components/pages/editor/editor-body.tsx | 88 +++++----- .../pages/editor/header/extra-options.tsx | 30 +--- .../pages/editor/header/info-popover.tsx | 6 +- .../pages/editor/header/mobile-root.tsx | 11 +- .../pages/editor/header/options-dropdown.tsx | 6 +- web/components/pages/editor/header/root.tsx | 14 +- web/components/pages/editor/title.tsx | 2 +- web/components/pages/index.ts | 1 - .../pages/loaders/page-content-loader.tsx | 125 +++++++++++--- .../pages/modals/delete-page-modal.tsx | 10 +- web/components/pages/page-detail/index.ts | 3 - web/components/pages/page-detail/loader.tsx | 118 -------------- web/components/pages/page-detail/root.tsx | 54 ------- web/hooks/use-page-description.ts | 153 ++++++++++++++++++ .../projects/[projectId]/pages/[pageId].tsx | 73 +++------ web/services/api.service.ts | 7 +- web/services/page.service.ts | 29 ++++ web/store/pages/page.store.ts | 125 +++++++------- yarn.lock | 52 ++++++ 42 files changed, 1134 insertions(+), 509 deletions(-) create mode 100644 packages/editor/core/src/ui/extensions/core-without-props.tsx create mode 100644 packages/editor/core/src/ui/extensions/image/image-extension-without-props.tsx create mode 100644 packages/editor/core/src/ui/mentions/mention-without-props.tsx create mode 100644 packages/editor/document-editor/src/hooks/use-document-editor.ts create mode 100644 packages/editor/document-editor/src/providers/collaboration-provider.ts create mode 100644 packages/editor/document-editor/src/utils/yjs.ts delete mode 100644 web/components/pages/page-detail/index.ts delete mode 100644 web/components/pages/page-detail/loader.tsx delete mode 100644 web/components/pages/page-detail/root.tsx create mode 100644 web/hooks/use-page-description.ts diff --git a/apiserver/plane/app/serializers/page.py b/apiserver/plane/app/serializers/page.py index 4f3cde39bb5..41f46c6e457 100644 --- a/apiserver/plane/app/serializers/page.py +++ b/apiserver/plane/app/serializers/page.py @@ -106,7 +106,9 @@ class PageDetailSerializer(PageSerializer): description_html = serializers.CharField() class Meta(PageSerializer.Meta): - fields = PageSerializer.Meta.fields + ["description_html"] + fields = PageSerializer.Meta.fields + [ + "description_html", + ] class SubPageSerializer(BaseSerializer): diff --git a/apiserver/plane/app/urls/page.py b/apiserver/plane/app/urls/page.py index 1a73e4ed306..a6d43600f12 100644 --- a/apiserver/plane/app/urls/page.py +++ b/apiserver/plane/app/urls/page.py @@ -6,6 +6,7 @@ PageFavoriteViewSet, PageLogEndpoint, SubPagesEndpoint, + PagesDescriptionViewSet, ) @@ -79,4 +80,14 @@ SubPagesEndpoint.as_view(), name="sub-page", ), + path( + "workspaces//projects//pages//description/", + PagesDescriptionViewSet.as_view( + { + "get": "retrieve", + "patch": "partial_update", + } + ), + name="page-description", + ), ] diff --git a/apiserver/plane/app/views/__init__.py b/apiserver/plane/app/views/__init__.py index bf765e7192f..0c489593d63 100644 --- a/apiserver/plane/app/views/__init__.py +++ b/apiserver/plane/app/views/__init__.py @@ -177,6 +177,7 @@ PageFavoriteViewSet, PageLogEndpoint, SubPagesEndpoint, + PagesDescriptionViewSet, ) from .search import GlobalSearchEndpoint, IssueSearchEndpoint diff --git a/apiserver/plane/app/views/page/base.py b/apiserver/plane/app/views/page/base.py index 16ea7803367..c7f53b9fe88 100644 --- a/apiserver/plane/app/views/page/base.py +++ b/apiserver/plane/app/views/page/base.py @@ -1,5 +1,6 @@ # Python imports import json +import base64 from datetime import datetime from django.core.serializers.json import DjangoJSONEncoder @@ -8,6 +9,7 @@ from django.db.models import Exists, OuterRef, Q from django.utils.decorators import method_decorator from django.views.decorators.gzip import gzip_page +from django.http import StreamingHttpResponse # Third party imports from rest_framework import status @@ -388,3 +390,48 @@ def get(self, request, slug, project_id, page_id): return Response( SubPageSerializer(pages, many=True).data, status=status.HTTP_200_OK ) + + +class PagesDescriptionViewSet(BaseViewSet): + permission_classes = [ + ProjectEntityPermission, + ] + + def retrieve(self, request, slug, project_id, pk): + page = Page.objects.get( + pk=pk, workspace__slug=slug, project_id=project_id + ) + binary_data = page.description_binary + + def stream_data(): + if binary_data: + yield binary_data + else: + yield b"" + + response = StreamingHttpResponse( + stream_data(), content_type="application/octet-stream" + ) + response["Content-Disposition"] = ( + 'attachment; filename="page_description.bin"' + ) + return response + + def partial_update(self, request, slug, project_id, pk): + page = Page.objects.get( + pk=pk, workspace__slug=slug, project_id=project_id + ) + + base64_data = request.data.get("description_binary") + + if base64_data: + # Decode the base64 data to bytes + new_binary_data = base64.b64decode(base64_data) + + # Store the updated binary data + page.description_binary = new_binary_data + page.description_html = request.data.get("description_html") + page.save() + return Response({"message": "Updated successfully"}) + else: + return Response({"error": "No binary data provided"}) diff --git a/apiserver/plane/db/models/page.py b/apiserver/plane/db/models/page.py index 3602bce1fa5..e079dcbe581 100644 --- a/apiserver/plane/db/models/page.py +++ b/apiserver/plane/db/models/page.py @@ -18,6 +18,7 @@ def get_view_props(): class Page(ProjectBaseModel): name = models.CharField(max_length=255, blank=True) description = models.JSONField(default=dict, blank=True) + description_binary = models.BinaryField(null=True) description_html = models.TextField(blank=True, default="

") description_stripped = models.TextField(blank=True, null=True) owned_by = models.ForeignKey( @@ -43,7 +44,6 @@ class Page(ProjectBaseModel): is_locked = models.BooleanField(default=False) view_props = models.JSONField(default=get_view_props) logo_props = models.JSONField(default=dict) - description_binary = models.BinaryField(null=True) class Meta: verbose_name = "Page" diff --git a/packages/editor/core/src/hooks/use-editor.tsx b/packages/editor/core/src/hooks/use-editor.tsx index 778fdc5e4ec..2d2e1662ac0 100644 --- a/packages/editor/core/src/hooks/use-editor.tsx +++ b/packages/editor/core/src/hooks/use-editor.tsx @@ -13,17 +13,21 @@ import { EditorMenuItemNames, getEditorMenuItems } from "src/ui/menus/menu-items import { EditorRefApi } from "src/types/editor-ref-api"; import { IMarking, scrollSummary } from "src/helpers/scroll-to-node"; -interface CustomEditorProps { +export type TFileHandler = { + cancel: () => void; + delete: DeleteImage; + upload: UploadImage; + restore: RestoreImage; +}; + +export interface CustomEditorProps { id?: string; - uploadFile: UploadImage; - restoreFile: RestoreImage; - deleteFile: DeleteImage; - cancelUploadImage?: () => void; - initialValue: string; + fileHandler: TFileHandler; + initialValue?: string; editorClassName: string; // undefined when prop is not passed, null if intentionally passed to stop // swr syncing - value: string | null | undefined; + value?: string | null | undefined; onChange?: (json: object, html: string) => void; extensions?: any; editorProps?: EditorProps; @@ -38,19 +42,16 @@ interface CustomEditorProps { } export const useEditor = ({ - uploadFile, id = "", - deleteFile, - cancelUploadImage, editorProps = {}, initialValue, editorClassName, value, extensions = [], + fileHandler, onChange, forwardedRef, tabIndex, - restoreFile, handleEditorReady, mentionHandler, placeholder, @@ -67,10 +68,10 @@ export const useEditor = ({ mentionHighlights: mentionHandler.highlights ?? [], }, fileConfig: { - deleteFile, - restoreFile, - cancelUploadImage, - uploadFile, + uploadFile: fileHandler.upload, + deleteFile: fileHandler.delete, + restoreFile: fileHandler.restore, + cancelUploadImage: fileHandler.cancel, }, placeholder, tabIndex, @@ -139,7 +140,7 @@ export const useEditor = ({ } }, executeMenuItemCommand: (itemName: EditorMenuItemNames) => { - const editorItems = getEditorMenuItems(editorRef.current, uploadFile); + const editorItems = getEditorMenuItems(editorRef.current, fileHandler.upload); const getEditorMenuItem = (itemName: EditorMenuItemNames) => editorItems.find((item) => item.key === itemName); @@ -155,7 +156,7 @@ export const useEditor = ({ } }, isMenuItemActive: (itemName: EditorMenuItemNames): boolean => { - const editorItems = getEditorMenuItems(editorRef.current, uploadFile); + const editorItems = getEditorMenuItems(editorRef.current, fileHandler.upload); const getEditorMenuItem = (itemName: EditorMenuItemNames) => editorItems.find((item) => item.key === itemName); const item = getEditorMenuItem(itemName); @@ -177,6 +178,10 @@ export const useEditor = ({ const markdownOutput = editorRef.current?.storage.markdown.getMarkdown(); return markdownOutput; }, + getHTML: (): string => { + const htmlOutput = editorRef.current?.getHTML() ?? "

"; + return htmlOutput; + }, scrollSummary: (marking: IMarking): void => { if (!editorRef.current) return; scrollSummary(editorRef.current, marking); @@ -199,7 +204,7 @@ export const useEditor = ({ } }, }), - [editorRef, savedSelection, uploadFile] + [editorRef, savedSelection, fileHandler.upload] ); if (!editor) { diff --git a/packages/editor/core/src/hooks/use-read-only-editor.tsx b/packages/editor/core/src/hooks/use-read-only-editor.tsx index 9607586d8e7..8b16d1e7668 100644 --- a/packages/editor/core/src/hooks/use-read-only-editor.tsx +++ b/packages/editor/core/src/hooks/use-read-only-editor.tsx @@ -68,6 +68,10 @@ export const useReadOnlyEditor = ({ const markdownOutput = editorRef.current?.storage.markdown.getMarkdown(); return markdownOutput; }, + getHTML: (): string => { + const htmlOutput = editorRef.current?.getHTML() ?? "

"; + return htmlOutput; + }, scrollSummary: (marking: IMarking): void => { if (!editorRef.current) return; scrollSummary(editorRef.current, marking); diff --git a/packages/editor/core/src/index.ts b/packages/editor/core/src/index.ts index 336daed4363..86066eeba1d 100644 --- a/packages/editor/core/src/index.ts +++ b/packages/editor/core/src/index.ts @@ -24,6 +24,7 @@ export * from "src/ui/menus/menu-items"; export * from "src/lib/editor-commands"; // types +export type { CustomEditorProps, TFileHandler } from "src/hooks/use-editor"; export type { DeleteImage } from "src/types/delete-image"; export type { UploadImage } from "src/types/upload-image"; export type { EditorRefApi, EditorReadOnlyRefApi } from "src/types/editor-ref-api"; diff --git a/packages/editor/core/src/lib/utils.ts b/packages/editor/core/src/lib/utils.ts index 84ad7046ee2..137c70c2e71 100644 --- a/packages/editor/core/src/lib/utils.ts +++ b/packages/editor/core/src/lib/utils.ts @@ -1,5 +1,7 @@ +import { Extensions, generateJSON, getSchema } from "@tiptap/core"; import { Selection } from "@tiptap/pm/state"; import { clsx, type ClassValue } from "clsx"; +import { CoreEditorExtensionsWithoutProps } from "src/ui/extensions/core-without-props"; import { twMerge } from "tailwind-merge"; interface EditorClassNames { noBorder?: boolean; @@ -58,3 +60,20 @@ export const isValidHttpUrl = (string: string): boolean => { return url.protocol === "http:" || url.protocol === "https:"; }; + +/** + * @description return an object with contentJSON and editorSchema + * @description contentJSON- ProseMirror JSON from HTML content + * @description editorSchema- editor schema from extensions + * @param {string} html + * @returns {object} {contentJSON, editorSchema} + */ +export const generateJSONfromHTML = (html: string) => { + const extensions = CoreEditorExtensionsWithoutProps(); + const contentJSON = generateJSON(html ?? "

", extensions as Extensions); + const editorSchema = getSchema(extensions as Extensions); + return { + contentJSON, + editorSchema, + }; +}; diff --git a/packages/editor/core/src/types/editor-ref-api.ts b/packages/editor/core/src/types/editor-ref-api.ts index df5df2c7b4d..4eed815d62c 100644 --- a/packages/editor/core/src/types/editor-ref-api.ts +++ b/packages/editor/core/src/types/editor-ref-api.ts @@ -3,6 +3,7 @@ import { EditorMenuItemNames } from "src/ui/menus/menu-items"; export type EditorReadOnlyRefApi = { getMarkDown: () => string; + getHTML: () => string; clearEditor: () => void; setEditorValue: (content: string) => void; scrollSummary: (marking: IMarking) => void; diff --git a/packages/editor/core/src/ui/extensions/core-without-props.tsx b/packages/editor/core/src/ui/extensions/core-without-props.tsx new file mode 100644 index 00000000000..3bb00010b53 --- /dev/null +++ b/packages/editor/core/src/ui/extensions/core-without-props.tsx @@ -0,0 +1,121 @@ +import TaskItem from "@tiptap/extension-task-item"; +import TaskList from "@tiptap/extension-task-list"; +import TextStyle from "@tiptap/extension-text-style"; +import TiptapUnderline from "@tiptap/extension-underline"; +import Placeholder from "@tiptap/extension-placeholder"; +import { Markdown } from "tiptap-markdown"; + +import { Table } from "src/ui/extensions/table/table"; +import { TableCell } from "src/ui/extensions/table/table-cell/table-cell"; +import { TableHeader } from "src/ui/extensions/table/table-header/table-header"; +import { TableRow } from "src/ui/extensions/table/table-row/table-row"; + +import { isValidHttpUrl } from "src/lib/utils"; + +import { CustomCodeBlockExtension } from "src/ui/extensions/code"; +import { CustomKeymap } from "src/ui/extensions/keymap"; +import { CustomQuoteExtension } from "src/ui/extensions/quote"; + +import { CustomLinkExtension } from "src/ui/extensions/custom-link"; +import { CustomCodeInlineExtension } from "src/ui/extensions/code-inline"; +import { CustomTypographyExtension } from "src/ui/extensions/typography"; +import { CustomHorizontalRule } from "src/ui/extensions/horizontal-rule/horizontal-rule"; +import { CustomCodeMarkPlugin } from "src/ui/extensions/custom-code-inline/inline-code-plugin"; +import { MentionsWithoutProps } from "src/ui/mentions/mention-without-props"; +import { ImageExtensionWithoutProps } from "src/ui/extensions/image/image-extension-without-props"; + +import StarterKit from "@tiptap/starter-kit"; + +export const CoreEditorExtensionsWithoutProps = () => [ + StarterKit.configure({ + bulletList: { + HTMLAttributes: { + class: "list-disc pl-7 space-y-2", + }, + }, + orderedList: { + HTMLAttributes: { + class: "list-decimal pl-7 space-y-2", + }, + }, + listItem: { + HTMLAttributes: { + class: "not-prose space-y-2", + }, + }, + code: false, + codeBlock: false, + horizontalRule: false, + blockquote: false, + dropcursor: { + color: "rgba(var(--color-text-100))", + width: 1, + }, + }), + CustomQuoteExtension, + CustomHorizontalRule.configure({ + HTMLAttributes: { + class: "my-4 border-custom-border-400", + }, + }), + CustomKeymap, + // ListKeymap, + CustomLinkExtension.configure({ + openOnClick: true, + autolink: true, + linkOnPaste: true, + protocols: ["http", "https"], + validate: (url: string) => isValidHttpUrl(url), + HTMLAttributes: { + class: + "text-custom-primary-300 underline underline-offset-[3px] hover:text-custom-primary-500 transition-colors cursor-pointer", + }, + }), + CustomTypographyExtension, + ImageExtensionWithoutProps().configure({ + HTMLAttributes: { + class: "rounded-md", + }, + }), + TiptapUnderline, + TextStyle, + TaskList.configure({ + HTMLAttributes: { + class: "not-prose pl-2 space-y-2", + }, + }), + TaskItem.configure({ + HTMLAttributes: { + class: "flex", + }, + nested: true, + }), + CustomCodeBlockExtension.configure({ + HTMLAttributes: { + class: "", + }, + }), + CustomCodeMarkPlugin, + CustomCodeInlineExtension, + Markdown.configure({ + html: true, + transformPastedText: true, + }), + Table, + TableHeader, + TableCell, + TableRow, + MentionsWithoutProps(), + Placeholder.configure({ + placeholder: ({ editor, node }) => { + if (node.type.name === "heading") return `Heading ${node.attrs.level}`; + + const shouldHidePlaceholder = + editor.isActive("table") || editor.isActive("codeBlock") || editor.isActive("image"); + if (shouldHidePlaceholder) return ""; + + return "Press '/' for commands..."; + }, + includeChildren: true, + }), +]; diff --git a/packages/editor/core/src/ui/extensions/image/image-extension-without-props.tsx b/packages/editor/core/src/ui/extensions/image/image-extension-without-props.tsx new file mode 100644 index 00000000000..838a6a1c9a0 --- /dev/null +++ b/packages/editor/core/src/ui/extensions/image/image-extension-without-props.tsx @@ -0,0 +1,33 @@ +import ImageExt from "@tiptap/extension-image"; +import { insertLineBelowImageAction } from "./utilities/insert-line-below-image"; +import { insertLineAboveImageAction } from "./utilities/insert-line-above-image"; + +export const ImageExtensionWithoutProps = () => + ImageExt.extend({ + addKeyboardShortcuts() { + return { + ArrowDown: insertLineBelowImageAction, + ArrowUp: insertLineAboveImageAction, + }; + }, + + // storage to keep track of image states Map + addStorage() { + return { + images: new Map(), + uploadInProgress: false, + }; + }, + + addAttributes() { + return { + ...this.parent?.(), + width: { + default: "35%", + }, + height: { + default: null, + }, + }; + }, + }); diff --git a/packages/editor/core/src/ui/mentions/mention-without-props.tsx b/packages/editor/core/src/ui/mentions/mention-without-props.tsx new file mode 100644 index 00000000000..a0d22ef4f8f --- /dev/null +++ b/packages/editor/core/src/ui/mentions/mention-without-props.tsx @@ -0,0 +1,79 @@ +import { CustomMention } from "./custom"; +import { ReactRenderer } from "@tiptap/react"; +import { Editor } from "@tiptap/core"; +import tippy from "tippy.js"; + +import { MentionList } from "./mention-list"; + +export const MentionsWithoutProps = () => + CustomMention.configure({ + HTMLAttributes: { + class: "mention", + }, + // mentionHighlights: mentionHighlights, + suggestion: { + // @ts-expect-error - Tiptap types are incorrect + render: () => { + let component: ReactRenderer | null = null; + let popup: any | null = null; + + return { + onStart: (props: { editor: Editor; clientRect: DOMRect }) => { + if (!props.clientRect) { + return; + } + component = new ReactRenderer(MentionList, { + props: { ...props }, + editor: props.editor, + }); + props.editor.storage.mentionsOpen = true; + // @ts-expect-error - Tippy types are incorrect + popup = tippy("body", { + getReferenceClientRect: props.clientRect, + appendTo: () => document.querySelector(".active-editor") ?? document.querySelector("#editor-container"), + content: component.element, + showOnCreate: true, + interactive: true, + trigger: "manual", + placement: "bottom-start", + }); + }, + onUpdate: (props: { editor: Editor; clientRect: DOMRect }) => { + component?.updateProps(props); + + if (!props.clientRect) { + return; + } + + popup && + popup[0].setProps({ + getReferenceClientRect: props.clientRect, + }); + }, + + onKeyDown: (props: { event: KeyboardEvent }) => { + if (props.event.key === "Escape") { + popup?.[0].hide(); + + return true; + } + + const navigationKeys = ["ArrowUp", "ArrowDown", "Enter"]; + + if (navigationKeys.includes(props.event.key)) { + // @ts-expect-error - Tippy types are incorrect + component?.ref?.onKeyDown(props); + event?.stopPropagation(); + return true; + } + return false; + }, + onExit: (props: { editor: Editor; event: KeyboardEvent }) => { + props.editor.storage.mentionsOpen = false; + popup?.[0].destroy(); + component?.destroy(); + }, + }; + }, + }, + }); diff --git a/packages/editor/document-editor/package.json b/packages/editor/document-editor/package.json index 47e68a87e58..d3bfbd6aac2 100644 --- a/packages/editor/document-editor/package.json +++ b/packages/editor/document-editor/package.json @@ -34,12 +34,17 @@ "@plane/ui": "*", "@tippyjs/react": "^4.2.6", "@tiptap/core": "^2.1.13", + "@tiptap/extension-collaboration": "^2.3.2", "@tiptap/pm": "^2.1.13", "@tiptap/suggestion": "^2.1.13", "lucide-react": "^0.378.0", "react-popper": "^2.3.0", "tippy.js": "^6.3.7", - "uuid": "^9.0.1" + "uuid": "^9.0.1", + "y-indexeddb": "^9.0.12", + "y-prosemirror": "^1.2.5", + "y-protocols": "^1.0.6", + "yjs": "^13.6.15" }, "devDependencies": { "@types/node": "18.15.3", diff --git a/packages/editor/document-editor/src/hooks/use-document-editor.ts b/packages/editor/document-editor/src/hooks/use-document-editor.ts new file mode 100644 index 00000000000..c2070a9f39e --- /dev/null +++ b/packages/editor/document-editor/src/hooks/use-document-editor.ts @@ -0,0 +1,85 @@ +import { useEffect, useLayoutEffect, useMemo } from "react"; +import { EditorProps } from "@tiptap/pm/view"; +import { IndexeddbPersistence } from "y-indexeddb"; +import * as Y from "yjs"; +// editor-core +import { EditorRefApi, IMentionHighlight, IMentionSuggestion, TFileHandler, useEditor } from "@plane/editor-core"; +// custom provider +import { CollaborationProvider } from "src/providers/collaboration-provider"; +// extensions +import { DocumentEditorExtensions } from "src/ui/extensions"; + +type DocumentEditorProps = { + id: string; + fileHandler: TFileHandler; + value: Uint8Array; + editorClassName: string; + onChange: (updates: Uint8Array) => void; + editorProps?: EditorProps; + forwardedRef?: React.MutableRefObject; + mentionHandler: { + highlights: () => Promise; + suggestions?: () => Promise; + }; + handleEditorReady?: (value: boolean) => void; + placeholder?: string | ((isFocused: boolean, value: string) => string); + setHideDragHandleFunction: (hideDragHandlerFromDragDrop: () => void) => void; + tabIndex?: number; +}; + +export const useDocumentEditor = ({ + id, + editorProps = {}, + value, + editorClassName, + fileHandler, + onChange, + forwardedRef, + tabIndex, + handleEditorReady, + mentionHandler, + placeholder, + setHideDragHandleFunction, +}: DocumentEditorProps) => { + const provider = useMemo( + () => + new CollaborationProvider({ + name: id, + onChange, + }), + // eslint-disable-next-line react-hooks/exhaustive-deps + [id] + ); + + // update document on value change + useEffect(() => { + if (value.byteLength > 0) Y.applyUpdate(provider.document, value); + }, [value, provider.document]); + + // indexedDB provider + useLayoutEffect(() => { + const localProvider = new IndexeddbPersistence(id, provider.document); + return () => { + localProvider?.destroy(); + }; + }, [provider, id]); + + const editor = useEditor({ + id, + editorProps, + editorClassName, + fileHandler, + handleEditorReady, + forwardedRef, + mentionHandler, + extensions: DocumentEditorExtensions({ + uploadFile: fileHandler.upload, + setHideDragHandle: setHideDragHandleFunction, + provider, + }), + placeholder, + tabIndex, + }); + + return editor; +}; diff --git a/packages/editor/document-editor/src/index.ts b/packages/editor/document-editor/src/index.ts index f8eea14ce71..9e8407ce3f5 100644 --- a/packages/editor/document-editor/src/index.ts +++ b/packages/editor/document-editor/src/index.ts @@ -3,6 +3,8 @@ export { DocumentReadOnlyEditor, DocumentReadOnlyEditorWithRef } from "src/ui/re // hooks export { useEditorMarkings } from "src/hooks/use-editor-markings"; +// utils +export { proseMirrorJSONToBinaryString, applyUpdates, mergeUpdates } from "src/utils/yjs"; export type { EditorRefApi, EditorReadOnlyRefApi, EditorMenuItem, EditorMenuItemNames } from "@plane/editor-core"; diff --git a/packages/editor/document-editor/src/providers/collaboration-provider.ts b/packages/editor/document-editor/src/providers/collaboration-provider.ts new file mode 100644 index 00000000000..b61ceebd55d --- /dev/null +++ b/packages/editor/document-editor/src/providers/collaboration-provider.ts @@ -0,0 +1,60 @@ +import * as Y from "yjs"; + +export interface CompleteCollaboratorProviderConfiguration { + /** + * The identifier/name of your document + */ + name: string; + /** + * The actual Y.js document + */ + document: Y.Doc; + /** + * onChange callback + */ + onChange: (updates: Uint8Array) => void; +} + +export type CollaborationProviderConfiguration = Required> & + Partial; + +export class CollaborationProvider { + public configuration: CompleteCollaboratorProviderConfiguration = { + name: "", + // @ts-expect-error cannot be undefined + document: undefined, + onChange: () => {}, + }; + + constructor(configuration: CollaborationProviderConfiguration) { + this.setConfiguration(configuration); + + this.configuration.document = configuration.document ?? new Y.Doc(); + this.document.on("update", this.documentUpdateHandler.bind(this)); + this.document.on("destroy", this.documentDestroyHandler.bind(this)); + } + + public setConfiguration(configuration: Partial = {}): void { + this.configuration = { + ...this.configuration, + ...configuration, + }; + } + + get document() { + return this.configuration.document; + } + + documentUpdateHandler(update: Uint8Array, origin: any) { + // return if the update is from the provider itself + if (origin === this) return; + + // call onChange with the update + this.configuration.onChange?.(update); + } + + documentDestroyHandler() { + this.document.off("update", this.documentUpdateHandler); + this.document.off("destroy", this.documentDestroyHandler); + } +} diff --git a/packages/editor/document-editor/src/ui/extensions/index.tsx b/packages/editor/document-editor/src/ui/extensions/index.tsx index b2816974e11..10c9fa596e9 100644 --- a/packages/editor/document-editor/src/ui/extensions/index.tsx +++ b/packages/editor/document-editor/src/ui/extensions/index.tsx @@ -2,14 +2,20 @@ import { IssueWidgetPlaceholder } from "src/ui/extensions/widgets/issue-embed-wi import { SlashCommand, DragAndDrop } from "@plane/editor-extensions"; import { UploadImage } from "@plane/editor-core"; +import { CollaborationProvider } from "src/providers/collaboration-provider"; +import Collaboration from "@tiptap/extension-collaboration"; type TArguments = { uploadFile: UploadImage; setHideDragHandle?: (hideDragHandlerFromDragDrop: () => void) => void; + provider: CollaborationProvider; }; -export const DocumentEditorExtensions = ({ uploadFile, setHideDragHandle }: TArguments) => [ +export const DocumentEditorExtensions = ({ uploadFile, setHideDragHandle, provider }: TArguments) => [ SlashCommand(uploadFile), DragAndDrop(setHideDragHandle), IssueWidgetPlaceholder(), + Collaboration.configure({ + document: provider.document, + }), ]; diff --git a/packages/editor/document-editor/src/ui/index.tsx b/packages/editor/document-editor/src/ui/index.tsx index 1f1c5f70675..1cafe6de74e 100644 --- a/packages/editor/document-editor/src/ui/index.tsx +++ b/packages/editor/document-editor/src/ui/index.tsx @@ -1,30 +1,25 @@ import React, { useState } from "react"; +// editor-core import { - UploadImage, - DeleteImage, - RestoreImage, getEditorClassNames, - useEditor, EditorRefApi, IMentionHighlight, IMentionSuggestion, + TFileHandler, } from "@plane/editor-core"; -import { DocumentEditorExtensions } from "src/ui/extensions"; +// components import { PageRenderer } from "src/ui/components/page-renderer"; +// hooks +import { useDocumentEditor } from "src/hooks/use-document-editor"; interface IDocumentEditor { - initialValue: string; - value?: string; - fileHandler: { - cancel: () => void; - delete: DeleteImage; - upload: UploadImage; - restore: RestoreImage; - }; + id: string; + value: Uint8Array; + fileHandler: TFileHandler; handleEditorReady?: (value: boolean) => void; containerClassName?: string; editorClassName?: string; - onChange: (json: object, html: string) => void; + onChange: (updates: Uint8Array) => void; forwardedRef?: React.MutableRefObject; mentionHandler: { highlights: () => Promise; @@ -37,7 +32,7 @@ interface IDocumentEditor { const DocumentEditor = (props: IDocumentEditor) => { const { onChange, - initialValue, + id, value, fileHandler, containerClassName, @@ -50,32 +45,24 @@ const DocumentEditor = (props: IDocumentEditor) => { } = props; // states const [hideDragHandleOnMouseLeave, setHideDragHandleOnMouseLeave] = useState<() => void>(() => {}); - // this essentially sets the hideDragHandle function from the DragAndDrop extension as the Plugin // loads such that we can invoke it from react when the cursor leaves the container const setHideDragHandleFunction = (hideDragHandlerFromDragDrop: () => void) => { setHideDragHandleOnMouseLeave(() => hideDragHandlerFromDragDrop); }; - // use editor - const editor = useEditor({ - onChange(json, html) { - onChange(json, html); - }, + + // use document editor + const editor = useDocumentEditor({ + id, editorClassName, - restoreFile: fileHandler.restore, - uploadFile: fileHandler.upload, - deleteFile: fileHandler.delete, - cancelUploadImage: fileHandler.cancel, - initialValue, + fileHandler, value, + onChange, handleEditorReady, forwardedRef, mentionHandler, - extensions: DocumentEditorExtensions({ - uploadFile: fileHandler.upload, - setHideDragHandle: setHideDragHandleFunction, - }), placeholder, + setHideDragHandleFunction, tabIndex, }); diff --git a/packages/editor/document-editor/src/utils/yjs.ts b/packages/editor/document-editor/src/utils/yjs.ts new file mode 100644 index 00000000000..71a945d3cc5 --- /dev/null +++ b/packages/editor/document-editor/src/utils/yjs.ts @@ -0,0 +1,76 @@ +import { Schema } from "@tiptap/pm/model"; +import { prosemirrorJSONToYDoc } from "y-prosemirror"; +import * as Y from "yjs"; + +const defaultSchema: Schema = new Schema({ + nodes: { + text: {}, + doc: { content: "text*" }, + }, +}); + +/** + * @description converts ProseMirror JSON to Yjs document + * @param document prosemirror JSON + * @param fieldName + * @param schema + * @returns {Y.Doc} Yjs document + */ +export const proseMirrorJSONToBinaryString = ( + document: any, + fieldName: string | Array = "default", + schema?: Schema +): string => { + if (!document) { + throw new Error( + `You've passed an empty or invalid document to the Transformer. Make sure to pass ProseMirror-compatible JSON. Actually passed JSON: ${document}` + ); + } + + // allow a single field name + if (typeof fieldName === "string") { + const yDoc = prosemirrorJSONToYDoc(schema ?? defaultSchema, document, fieldName); + const docAsUint8Array = Y.encodeStateAsUpdate(yDoc); + const base64Doc = Buffer.from(docAsUint8Array).toString("base64"); + return base64Doc; + } + + const yDoc = new Y.Doc(); + + fieldName.forEach((field) => { + const update = Y.encodeStateAsUpdate(prosemirrorJSONToYDoc(schema ?? defaultSchema, document, field)); + + Y.applyUpdate(yDoc, update); + }); + + const docAsUint8Array = Y.encodeStateAsUpdate(yDoc); + const base64Doc = Buffer.from(docAsUint8Array).toString("base64"); + + return base64Doc; +}; + +/** + * @description apply updates to a doc and return the updated doc in base64(binary) format + * @param {Uint8Array} document + * @param {Uint8Array} updates + * @returns {string} base64(binary) form of the updated doc + */ +export const applyUpdates = (document: Uint8Array, updates: Uint8Array): string => { + const yDoc = new Y.Doc(); + Y.applyUpdate(yDoc, document); + Y.applyUpdate(yDoc, updates); + + const encodedDoc = Y.encodeStateAsUpdate(yDoc); + const base64Updates = Buffer.from(encodedDoc).toString("base64"); + return base64Updates; +}; + +/** + * @description merge multiple updates into one single update + * @param {Uint8Array[]} updates + * @returns {Uint8Array} merged updates + */ +export const mergeUpdates = (updates: Uint8Array[]): Uint8Array => { + const mergedUpdates = Y.mergeUpdates(updates); + return mergedUpdates; +}; diff --git a/packages/editor/lite-text-editor/src/ui/index.tsx b/packages/editor/lite-text-editor/src/ui/index.tsx index 6b22809d62a..77d3ca0ecff 100644 --- a/packages/editor/lite-text-editor/src/ui/index.tsx +++ b/packages/editor/lite-text-editor/src/ui/index.tsx @@ -1,27 +1,22 @@ import * as React from "react"; +// editor-core import { - UploadImage, - DeleteImage, IMentionSuggestion, - RestoreImage, EditorContainer, EditorContentWrapper, getEditorClassNames, useEditor, IMentionHighlight, EditorRefApi, + TFileHandler, } from "@plane/editor-core"; +// extensions import { LiteTextEditorExtensions } from "src/ui/extensions"; export interface ILiteTextEditor { initialValue: string; value?: string | null; - fileHandler: { - cancel: () => void; - delete: DeleteImage; - upload: UploadImage; - restore: RestoreImage; - }; + fileHandler: TFileHandler; containerClassName?: string; editorClassName?: string; onChange?: (json: object, html: string) => void; @@ -58,10 +53,7 @@ const LiteTextEditor = (props: ILiteTextEditor) => { value, id, editorClassName, - restoreFile: fileHandler.restore, - uploadFile: fileHandler.upload, - deleteFile: fileHandler.delete, - cancelUploadImage: fileHandler.cancel, + fileHandler, forwardedRef, extensions: LiteTextEditorExtensions(onEnterKeyPress), mentionHandler, diff --git a/packages/editor/rich-text-editor/src/ui/index.tsx b/packages/editor/rich-text-editor/src/ui/index.tsx index ec5aa7359cf..2b8348a62dd 100644 --- a/packages/editor/rich-text-editor/src/ui/index.tsx +++ b/packages/editor/rich-text-editor/src/ui/index.tsx @@ -1,30 +1,26 @@ "use client"; +import * as React from "react"; +// editor-core import { - DeleteImage, EditorContainer, EditorContentWrapper, getEditorClassNames, IMentionHighlight, IMentionSuggestion, - RestoreImage, - UploadImage, useEditor, EditorRefApi, + TFileHandler, } from "@plane/editor-core"; -import * as React from "react"; +// extensions import { RichTextEditorExtensions } from "src/ui/extensions"; +// components import { EditorBubbleMenu } from "src/ui/menus/bubble-menu"; export type IRichTextEditor = { initialValue: string; value?: string | null; dragDropEnabled?: boolean; - fileHandler: { - cancel: () => void; - delete: DeleteImage; - upload: UploadImage; - restore: RestoreImage; - }; + fileHandler: TFileHandler; id?: string; containerClassName?: string; editorClassName?: string; @@ -69,10 +65,7 @@ const RichTextEditor = (props: IRichTextEditor) => { const editor = useEditor({ id, editorClassName, - restoreFile: fileHandler.restore, - uploadFile: fileHandler.upload, - deleteFile: fileHandler.delete, - cancelUploadImage: fileHandler.cancel, + fileHandler, onChange, initialValue, value, diff --git a/web/components/headers/page-details.tsx b/web/components/headers/page-details.tsx index 0a02c1528de..3e54243056c 100644 --- a/web/components/headers/page-details.tsx +++ b/web/components/headers/page-details.tsx @@ -1,30 +1,26 @@ -import { FC } from "react"; import { observer } from "mobx-react"; import { useRouter } from "next/router"; import { FileText } from "lucide-react"; -// hooks // ui import { Breadcrumbs, Button } from "@plane/ui"; -// helpers -import { BreadcrumbLink } from "@/components/common"; // components +import { BreadcrumbLink } from "@/components/common"; import { ProjectLogo } from "@/components/project"; -import { useCommandPalette, usePage, useProject } from "@/hooks/store"; - -export interface IPagesHeaderProps { - showButton?: boolean; -} +// hooks +import { usePage, useProject } from "@/hooks/store"; +import { usePlatformOS } from "@/hooks/use-platform-os"; -export const PageDetailsHeader: FC = observer((props) => { - const { showButton = false } = props; +export const PageDetailsHeader = observer(() => { // router const router = useRouter(); const { workspaceSlug, pageId } = router.query; // store hooks - const { toggleCreatePageModal } = useCommandPalette(); const { currentProjectDetails } = useProject(); - - const { name } = usePage(pageId?.toString() ?? ""); + const { isContentEditable, isSubmitting, name } = usePage(pageId?.toString() ?? ""); + // use platform + const { platform } = usePlatformOS(); + // derived values + const isMac = platform === "MacOS"; return (
@@ -77,12 +73,24 @@ export const PageDetailsHeader: FC = observer((props) => {
- {showButton && ( -
- -
+ {isContentEditable && ( + )}
); diff --git a/web/components/pages/editor/editor-body.tsx b/web/components/pages/editor/editor-body.tsx index a896bcc5802..28f8790131d 100644 --- a/web/components/pages/editor/editor-body.tsx +++ b/web/components/pages/editor/editor-body.tsx @@ -1,8 +1,7 @@ import { useEffect } from "react"; import { observer } from "mobx-react"; import { useRouter } from "next/router"; -import { Control, Controller } from "react-hook-form"; -// document editor +// document-editor import { DocumentEditorWithRef, DocumentReadOnlyEditorWithRef, @@ -11,15 +10,15 @@ import { IMarking, } from "@plane/document-editor"; // types -import { IUserLite, TPage } from "@plane/types"; +import { IUserLite } from "@plane/types"; // components import { PageContentBrowser, PageContentLoader, PageEditorTitle } from "@/components/pages"; // helpers import { cn } from "@/helpers/common.helper"; // hooks import { useMember, useMention, useUser, useWorkspace } from "@/hooks/store"; +import { usePageDescription } from "@/hooks/use-page-description"; import { usePageFilters } from "@/hooks/use-page-filters"; -import useReloadConfirmations from "@/hooks/use-reload-confirmation"; // services import { FileService } from "@/services/file.service"; // store @@ -28,13 +27,10 @@ import { IPageStore } from "@/store/pages/page.store"; const fileService = new FileService(); type Props = { - control: Control; editorRef: React.RefObject; readOnlyEditorRef: React.RefObject; - swrPageDetails: TPage | undefined; - handleSubmit: () => void; markings: IMarking[]; - pageStore: IPageStore; + page: IPageStore; sidePeekVisible: boolean; handleEditorReady: (value: boolean) => void; handleReadOnlyEditorReady: (value: boolean) => void; @@ -43,15 +39,12 @@ type Props = { export const PageEditorBody: React.FC = observer((props) => { const { - control, handleReadOnlyEditorReady, handleEditorReady, editorRef, markings, readOnlyEditorRef, - handleSubmit, - pageStore, - swrPageDetails, + page, sidePeekVisible, updateMarkings, } = props; @@ -67,11 +60,19 @@ export const PageEditorBody: React.FC = observer((props) => { } = useMember(); // derived values const workspaceId = workspaceSlug ? getWorkspaceBySlug(workspaceSlug.toString())?.id ?? "" : ""; - const pageTitle = pageStore?.name ?? ""; - const pageDescription = pageStore?.description_html; - const { description_html, isContentEditable, updateTitle, isSubmitting, setIsSubmitting } = pageStore; + const pageId = page?.id; + const pageTitle = page?.name ?? ""; + const pageDescription = page?.description_html; + const { isContentEditable, updateTitle, setIsSubmitting } = page; const projectMemberIds = projectId ? getProjectMemberIds(projectId.toString()) : []; const projectMemberDetails = projectMemberIds?.map((id) => getUserDetails(id) as IUserLite); + // project-description + const { handleDescriptionChange, isDescriptionReady, pageDescriptionYJS } = usePageDescription({ + editorRef, + page, + projectId, + workspaceSlug, + }); // use-mention const { mentionHighlights, mentionSuggestions } = useMention({ workspaceSlug: workspaceSlug?.toString() ?? "", @@ -82,13 +83,11 @@ export const PageEditorBody: React.FC = observer((props) => { // page filters const { isFullWidth } = usePageFilters(); - const { setShowAlert } = useReloadConfirmations(isSubmitting === "submitting"); - useEffect(() => { - updateMarkings(description_html ?? "

"); - }, [description_html, updateMarkings]); + updateMarkings(pageDescription ?? "

"); + }, [pageDescription, updateMarkings]); - if (pageDescription === undefined) return ; + if (pageId === undefined || !pageDescriptionYJS || !isDescriptionReady) return ; return (
@@ -122,35 +121,24 @@ export const PageEditorBody: React.FC = observer((props) => { />
{isContentEditable ? ( - ( -

"} - value={swrPageDetails?.description_html ?? "

"} - ref={editorRef} - containerClassName="p-0 pb-64" - editorClassName="lg:px-10 pl-8" - onChange={(_description_json, description_html) => { - setIsSubmitting("submitting"); - setShowAlert(true); - onChange(description_html); - handleSubmit(); - }} - mentionHandler={{ - highlights: mentionHighlights, - suggestions: mentionSuggestions, - }} - /> - )} + ) : ( = observer((props) => { initialValue={pageDescription ?? "

"} handleEditorReady={handleReadOnlyEditorReady} containerClassName="p-0 pb-64 border-none" - editorClassName="lg:px-10 pl-8" + editorClassName="pl-10" mentionHandler={{ highlights: mentionHighlights, }} diff --git a/web/components/pages/editor/header/extra-options.tsx b/web/components/pages/editor/header/extra-options.tsx index dee77d19ec3..63279984647 100644 --- a/web/components/pages/editor/header/extra-options.tsx +++ b/web/components/pages/editor/header/extra-options.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; import { observer } from "mobx-react"; -import { Lock, RefreshCw, Sparkle } from "lucide-react"; +import { Lock, Sparkle } from "lucide-react"; // editor import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/document-editor"; // ui @@ -9,7 +9,6 @@ import { ArchiveIcon } from "@plane/ui"; import { GptAssistantPopover } from "@/components/core"; import { PageInfoPopover, PageOptionsDropdown } from "@/components/pages"; // helpers -import { cn } from "@/helpers/common.helper"; import { renderFormattedDate } from "@/helpers/date-time.helper"; // hooks import { useInstance } from "@/hooks/store"; @@ -19,20 +18,19 @@ import { IPageStore } from "@/store/pages/page.store"; type Props = { editorRef: React.RefObject; handleDuplicatePage: () => void; - isSyncing: boolean; - pageStore: IPageStore; + page: IPageStore; projectId: string; readOnlyEditorRef: React.RefObject; }; export const PageExtraOptions: React.FC = observer((props) => { - const { editorRef, handleDuplicatePage, isSyncing, pageStore, projectId, readOnlyEditorRef } = props; + const { editorRef, handleDuplicatePage, page, projectId, readOnlyEditorRef } = props; // states const [gptModalOpen, setGptModal] = useState(false); // store hooks const { config } = useInstance(); // derived values - const { archived_at, isContentEditable, isSubmitting, is_locked } = pageStore; + const { archived_at, isContentEditable, is_locked } = page; const handleAiAssistance = async (response: string) => { if (!editorRef) return; @@ -41,22 +39,6 @@ export const PageExtraOptions: React.FC = observer((props) => { return (
- {isContentEditable && ( -
- {isSubmitting === "submitting" && } - {isSubmitting === "submitting" ? "Saving..." : "Saved"} -
- )} - {isSyncing && ( -
- - Syncing... -
- )} {is_locked && (
@@ -93,11 +75,11 @@ export const PageExtraOptions: React.FC = observer((props) => { className="!min-w-[38rem]" /> )} - +
); diff --git a/web/components/pages/editor/header/info-popover.tsx b/web/components/pages/editor/header/info-popover.tsx index 55b4b28fb70..270da934b97 100644 --- a/web/components/pages/editor/header/info-popover.tsx +++ b/web/components/pages/editor/header/info-popover.tsx @@ -7,11 +7,11 @@ import { renderFormattedDate } from "@/helpers/date-time.helper"; import { IPageStore } from "@/store/pages/page.store"; type Props = { - pageStore: IPageStore; + page: IPageStore; }; export const PageInfoPopover: React.FC = (props) => { - const { pageStore } = props; + const { page } = props; // states const [isPopoverOpen, setIsPopoverOpen] = useState(false); // refs @@ -22,7 +22,7 @@ export const PageInfoPopover: React.FC = (props) => { placement: "bottom-start", }); // derived values - const { created_at, updated_at } = pageStore; + const { created_at, updated_at } = page; return (
setIsPopoverOpen(true)} onMouseLeave={() => setIsPopoverOpen(false)}> diff --git a/web/components/pages/editor/header/mobile-root.tsx b/web/components/pages/editor/header/mobile-root.tsx index de0425879ea..44cd9d38b41 100644 --- a/web/components/pages/editor/header/mobile-root.tsx +++ b/web/components/pages/editor/header/mobile-root.tsx @@ -11,9 +11,8 @@ type Props = { editorRef: React.RefObject; readOnlyEditorRef: React.RefObject; handleDuplicatePage: () => void; - isSyncing: boolean; markings: IMarking[]; - pageStore: IPageStore; + page: IPageStore; projectId: string; sidePeekVisible: boolean; setSidePeekVisible: (sidePeekState: boolean) => void; @@ -29,14 +28,13 @@ export const PageEditorMobileHeaderRoot: React.FC = observer((props) => { markings, readOnlyEditorReady, handleDuplicatePage, - isSyncing, - pageStore, + page, projectId, sidePeekVisible, setSidePeekVisible, } = props; // derived values - const { isContentEditable } = pageStore; + const { isContentEditable } = page; // page filters const { isFullWidth } = usePageFilters(); @@ -57,8 +55,7 @@ export const PageEditorMobileHeaderRoot: React.FC = observer((props) => { diff --git a/web/components/pages/editor/header/options-dropdown.tsx b/web/components/pages/editor/header/options-dropdown.tsx index 9d3c8627bf5..9aeb2a679e5 100644 --- a/web/components/pages/editor/header/options-dropdown.tsx +++ b/web/components/pages/editor/header/options-dropdown.tsx @@ -16,11 +16,11 @@ import { IPageStore } from "@/store/pages/page.store"; type Props = { editorRef: EditorRefApi | EditorReadOnlyRefApi | null; handleDuplicatePage: () => void; - pageStore: IPageStore; + page: IPageStore; }; export const PageOptionsDropdown: React.FC = observer((props) => { - const { editorRef, handleDuplicatePage, pageStore } = props; + const { editorRef, handleDuplicatePage, page } = props; // store values const { archived_at, @@ -33,7 +33,7 @@ export const PageOptionsDropdown: React.FC = observer((props) => { canCurrentUserDuplicatePage, canCurrentUserLockPage, restore, - } = pageStore; + } = page; // store hooks const { workspaceSlug, projectId } = useAppRouter(); // page filters diff --git a/web/components/pages/editor/header/root.tsx b/web/components/pages/editor/header/root.tsx index 7234f3ad4c2..7f17c43c3b8 100644 --- a/web/components/pages/editor/header/root.tsx +++ b/web/components/pages/editor/header/root.tsx @@ -13,9 +13,8 @@ type Props = { editorRef: React.RefObject; readOnlyEditorRef: React.RefObject; handleDuplicatePage: () => void; - isSyncing: boolean; markings: IMarking[]; - pageStore: IPageStore; + page: IPageStore; projectId: string; sidePeekVisible: boolean; setSidePeekVisible: (sidePeekState: boolean) => void; @@ -31,14 +30,13 @@ export const PageEditorHeaderRoot: React.FC = observer((props) => { markings, readOnlyEditorReady, handleDuplicatePage, - isSyncing, - pageStore, + page, projectId, sidePeekVisible, setSidePeekVisible, } = props; // derived values - const { isContentEditable } = pageStore; + const { isContentEditable } = page; // page filters const { isFullWidth } = usePageFilters(); @@ -67,8 +65,7 @@ export const PageEditorHeaderRoot: React.FC = observer((props) => { @@ -81,8 +78,7 @@ export const PageEditorHeaderRoot: React.FC = observer((props) => { readOnlyEditorReady={readOnlyEditorReady} markings={markings} handleDuplicatePage={handleDuplicatePage} - isSyncing={isSyncing} - pageStore={pageStore} + page={page} projectId={projectId} sidePeekVisible={sidePeekVisible} setSidePeekVisible={setSidePeekVisible} diff --git a/web/components/pages/editor/title.tsx b/web/components/pages/editor/title.tsx index f472ecb6dca..0c9473690da 100644 --- a/web/components/pages/editor/title.tsx +++ b/web/components/pages/editor/title.tsx @@ -33,7 +33,6 @@ export const PageEditorTitle: React.FC = observer((props) => { ) : ( <>