Merge branch 'feat/list-autojoins' into chore/page-transactions

This commit is contained in:
Palanikannan1437 2024-03-27 17:07:49 +05:30
commit 51af9e4d12
21 changed files with 2147 additions and 549 deletions

View File

@ -1,8 +1,9 @@
name: "CodeQL" name: "CodeQL"
on: on:
workflow_dispatch:
push: push:
branches: ["master"] branches: ["develop", "preview", "master"]
pull_request: pull_request:
branches: ["develop", "preview", "master"] branches: ["develop", "preview", "master"]
schedule: schedule:

View File

@ -1,32 +1,33 @@
from lxml import html from django.core.exceptions import ValidationError
from django.core.validators import URLValidator
# Django imports # Django imports
from django.utils import timezone from django.utils import timezone
from django.core.validators import URLValidator from lxml import html
from django.core.exceptions import ValidationError
# Third party imports # Third party imports
from rest_framework import serializers from rest_framework import serializers
# Module imports # Module imports
from plane.db.models import ( from plane.db.models import (
User,
Issue, Issue,
State, IssueActivity,
IssueAssignee, IssueAssignee,
Label, IssueAttachment,
IssueComment,
IssueLabel, IssueLabel,
IssueLink, IssueLink,
IssueComment, Label,
IssueAttachment,
IssueActivity,
ProjectMember, ProjectMember,
State,
User,
) )
from .base import BaseSerializer from .base import BaseSerializer
from .cycle import CycleSerializer, CycleLiteSerializer from .cycle import CycleLiteSerializer, CycleSerializer
from .module import ModuleSerializer, ModuleLiteSerializer from .module import ModuleLiteSerializer, ModuleSerializer
from .user import UserLiteSerializer
from .state import StateLiteSerializer from .state import StateLiteSerializer
from .user import UserLiteSerializer
class IssueSerializer(BaseSerializer): class IssueSerializer(BaseSerializer):
@ -79,7 +80,7 @@ class IssueSerializer(BaseSerializer):
data["description_html"] = parsed_str data["description_html"] = parsed_str
except Exception as e: except Exception as e:
raise serializers.ValidationError(f"Invalid HTML: {str(e)}") raise serializers.ValidationError("Invalid HTML passed")
# Validate assignees are from project # Validate assignees are from project
if data.get("assignees", []): if data.get("assignees", []):
@ -294,7 +295,7 @@ class IssueLinkSerializer(BaseSerializer):
raise serializers.ValidationError("Invalid URL format.") raise serializers.ValidationError("Invalid URL format.")
# Check URL scheme # Check URL scheme
if not value.startswith(('http://', 'https://')): if not value.startswith(("http://", "https://")):
raise serializers.ValidationError("Invalid URL scheme.") raise serializers.ValidationError("Invalid URL scheme.")
return value return value
@ -366,7 +367,7 @@ class IssueCommentSerializer(BaseSerializer):
data["comment_html"] = parsed_str data["comment_html"] = parsed_str
except Exception as e: except Exception as e:
raise serializers.ValidationError(f"Invalid HTML: {str(e)}") raise serializers.ValidationError("Invalid HTML passed")
return data return data

View File

@ -103,7 +103,8 @@ class CycleViewSet(WebhookMixin, BaseViewSet):
.annotate(is_favorite=Exists(favorite_subquery)) .annotate(is_favorite=Exists(favorite_subquery))
.annotate( .annotate(
total_issues=Count( total_issues=Count(
"issue_cycle", "issue_cycle__issue__id",
distinct=True,
filter=Q( filter=Q(
issue_cycle__issue__archived_at__isnull=True, issue_cycle__issue__archived_at__isnull=True,
issue_cycle__issue__is_draft=False, issue_cycle__issue__is_draft=False,
@ -112,7 +113,8 @@ class CycleViewSet(WebhookMixin, BaseViewSet):
) )
.annotate( .annotate(
completed_issues=Count( completed_issues=Count(
"issue_cycle__issue__state__group", "issue_cycle__issue__id",
distinct=True,
filter=Q( filter=Q(
issue_cycle__issue__state__group="completed", issue_cycle__issue__state__group="completed",
issue_cycle__issue__archived_at__isnull=True, issue_cycle__issue__archived_at__isnull=True,
@ -122,7 +124,8 @@ class CycleViewSet(WebhookMixin, BaseViewSet):
) )
.annotate( .annotate(
cancelled_issues=Count( cancelled_issues=Count(
"issue_cycle__issue__state__group", "issue_cycle__issue__id",
distinct=True,
filter=Q( filter=Q(
issue_cycle__issue__state__group="cancelled", issue_cycle__issue__state__group="cancelled",
issue_cycle__issue__archived_at__isnull=True, issue_cycle__issue__archived_at__isnull=True,
@ -132,7 +135,8 @@ class CycleViewSet(WebhookMixin, BaseViewSet):
) )
.annotate( .annotate(
started_issues=Count( started_issues=Count(
"issue_cycle__issue__state__group", "issue_cycle__issue__id",
distinct=True,
filter=Q( filter=Q(
issue_cycle__issue__state__group="started", issue_cycle__issue__state__group="started",
issue_cycle__issue__archived_at__isnull=True, issue_cycle__issue__archived_at__isnull=True,
@ -142,7 +146,8 @@ class CycleViewSet(WebhookMixin, BaseViewSet):
) )
.annotate( .annotate(
unstarted_issues=Count( unstarted_issues=Count(
"issue_cycle__issue__state__group", "issue_cycle__issue__id",
distinct=True,
filter=Q( filter=Q(
issue_cycle__issue__state__group="unstarted", issue_cycle__issue__state__group="unstarted",
issue_cycle__issue__archived_at__isnull=True, issue_cycle__issue__archived_at__isnull=True,
@ -152,7 +157,8 @@ class CycleViewSet(WebhookMixin, BaseViewSet):
) )
.annotate( .annotate(
backlog_issues=Count( backlog_issues=Count(
"issue_cycle__issue__state__group", "issue_cycle__issue__id",
distinct=True,
filter=Q( filter=Q(
issue_cycle__issue__state__group="backlog", issue_cycle__issue__state__group="backlog",
issue_cycle__issue__archived_at__isnull=True, issue_cycle__issue__archived_at__isnull=True,

View File

@ -1,54 +1,57 @@
# Python imports # Python imports
import json import json
# Django Imports
from django.utils import timezone
from django.db.models import (
Prefetch,
F,
OuterRef,
Exists,
Count,
Q,
Func,
Subquery,
IntegerField,
)
from django.contrib.postgres.aggregates import ArrayAgg from django.contrib.postgres.aggregates import ArrayAgg
from django.contrib.postgres.fields import ArrayField from django.contrib.postgres.fields import ArrayField
from django.db.models import Value, UUIDField from django.db.models import (
Count,
Exists,
F,
Func,
IntegerField,
OuterRef,
Prefetch,
Q,
Subquery,
UUIDField,
Value,
)
from django.db.models.functions import Coalesce from django.db.models.functions import Coalesce
# Django Imports
from django.utils import timezone
from rest_framework import status
# Third party imports # Third party imports
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework import status
# Module imports
from .. import BaseViewSet, BaseAPIView, WebhookMixin
from plane.app.serializers import (
ModuleWriteSerializer,
ModuleSerializer,
ModuleLinkSerializer,
ModuleFavoriteSerializer,
ModuleUserPropertiesSerializer,
ModuleDetailSerializer,
)
from plane.app.permissions import ( from plane.app.permissions import (
ProjectEntityPermission, ProjectEntityPermission,
ProjectLitePermission, ProjectLitePermission,
) )
from plane.db.models import ( from plane.app.serializers import (
Module, ModuleDetailSerializer,
ModuleIssue, ModuleFavoriteSerializer,
Project, ModuleLinkSerializer,
Issue, ModuleSerializer,
ModuleLink, ModuleUserPropertiesSerializer,
ModuleFavorite, ModuleWriteSerializer,
ModuleUserProperties,
) )
from plane.bgtasks.issue_activites_task import issue_activity from plane.bgtasks.issue_activites_task import issue_activity
from plane.db.models import (
Issue,
Module,
ModuleFavorite,
ModuleIssue,
ModuleLink,
ModuleUserProperties,
Project,
)
from plane.utils.analytics_plot import burndown_plot from plane.utils.analytics_plot import burndown_plot
# Module imports
from .. import BaseAPIView, BaseViewSet, WebhookMixin
class ModuleViewSet(WebhookMixin, BaseViewSet): class ModuleViewSet(WebhookMixin, BaseViewSet):
model = Module model = Module
@ -392,9 +395,11 @@ class ModuleViewSet(WebhookMixin, BaseViewSet):
"completion_chart": {}, "completion_chart": {},
} }
if queryset.first().start_date and queryset.first().target_date: # Fetch the modules
modules = queryset.first()
if modules and modules.start_date and modules.target_date:
data["distribution"]["completion_chart"] = burndown_plot( data["distribution"]["completion_chart"] = burndown_plot(
queryset=queryset.first(), queryset=modules,
slug=slug, slug=slug,
project_id=project_id, project_id=project_id,
module_id=pk, module_id=pk,

View File

@ -3,15 +3,10 @@ from rest_framework import status
from rest_framework.response import Response from rest_framework.response import Response
# Module imports # Module imports
from plane.app.permissions import WorkspaceEntityPermission
from plane.app.serializers import WorkspaceEstimateSerializer from plane.app.serializers import WorkspaceEstimateSerializer
from plane.app.views.base import BaseAPIView from plane.app.views.base import BaseAPIView
from plane.db.models import Project, Estimate from plane.db.models import Estimate, Project
from plane.app.permissions import WorkspaceEntityPermission
# Django imports
from django.db.models import (
Prefetch,
)
from plane.utils.cache import cache_response from plane.utils.cache import cache_response
@ -25,15 +20,11 @@ class WorkspaceEstimatesEndpoint(BaseAPIView):
estimate_ids = Project.objects.filter( estimate_ids = Project.objects.filter(
workspace__slug=slug, estimate__isnull=False workspace__slug=slug, estimate__isnull=False
).values_list("estimate_id", flat=True) ).values_list("estimate_id", flat=True)
estimates = Estimate.objects.filter( estimates = (
pk__in=estimate_ids Estimate.objects.filter(pk__in=estimate_ids, workspace__slug=slug)
).prefetch_related( .prefetch_related("points")
Prefetch( .select_related("workspace", "project")
"points",
queryset=Project.objects.select_related(
"estimate", "workspace"
),
)
) )
serializer = WorkspaceEstimateSerializer(estimates, many=True) serializer = WorkspaceEstimateSerializer(estimates, many=True)
return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.data, status=status.HTTP_200_OK)

File diff suppressed because it is too large Load Diff

View File

@ -4,18 +4,15 @@ import { Node } from "@tiptap/pm/model";
import { findListItemPos } from "src/ui/extensions/custom-list-keymap/list-helpers/find-list-item-pos"; import { findListItemPos } from "src/ui/extensions/custom-list-keymap/list-helpers/find-list-item-pos";
import { hasListBefore } from "src/ui/extensions/custom-list-keymap/list-helpers/has-list-before"; import { hasListBefore } from "src/ui/extensions/custom-list-keymap/list-helpers/has-list-before";
import { hasListItemBefore } from "src/ui/extensions/custom-list-keymap/list-helpers/has-list-item-before";
import { listItemHasSubList } from "src/ui/extensions/custom-list-keymap/list-helpers/list-item-has-sub-list";
export const handleBackspace = (editor: Editor, name: string, parentListTypes: string[]) => { export const handleBackspace = (editor: Editor, name: string, parentListTypes: string[]) => {
// this is required to still handle the undo handling // this is required to still handle the undo handling
if (editor.commands.undoInputRule()) { if (editor.commands.undoInputRule()) {
return true; return true;
} }
// if the cursor is not at the start of a node
// do nothing and proceed
if (!isAtStartOfNode(editor.state)) {
return false;
}
// if the current item is NOT inside a list item & // if the current item is NOT inside a list item &
// the previous item is a list (orderedList or bulletList) // the previous item is a list (orderedList or bulletList)
// move the cursor into the list and delete the current item // move the cursor into the list and delete the current item
@ -53,14 +50,31 @@ export const handleBackspace = (editor: Editor, name: string, parentListTypes: s
return false; return false;
} }
// if the cursor is not at the start of a node
// do nothing and proceed
if (!isAtStartOfNode(editor.state)) {
return false;
}
const listItemPos = findListItemPos(name, editor.state); const listItemPos = findListItemPos(name, editor.state);
if (!listItemPos) { if (!listItemPos) {
return false; return false;
} }
// if current node is a list item and cursor it at start of a list node, const $prev = editor.state.doc.resolve(listItemPos.$pos.pos - 2);
// simply lift the list item i.e. remove it as a list item (task/bullet/ordered) const prevNode = $prev.node(listItemPos.depth);
// irrespective of above node being a list or not
const previousListItemHasSubList = listItemHasSubList(name, editor.state, prevNode);
// if the previous item is a list item and doesn't have a sublist, join the list items
if (hasListItemBefore(name, editor.state) && previousListItemHasSubList) {
return editor.chain().liftListItem(name).run();
// return editor.commands.joinItemBackward();
}
// otherwise in the end, a backspace should
// always just lift the list item if
// joining / merging is not possible
return editor.chain().liftListItem(name).run(); return editor.chain().liftListItem(name).run();
}; };

View File

@ -0,0 +1,21 @@
import { getNodeType } from "@tiptap/core";
import { Node } from "@tiptap/pm/model";
import { EditorState } from "@tiptap/pm/state";
export const listItemHasSubList = (typeOrName: string, state: EditorState, node?: Node) => {
if (!node) {
return false;
}
const nodeType = getNodeType(typeOrName, state.schema);
let hasSubList = false;
node.descendants((child) => {
if (child.type === nodeType) {
hasSubList = true;
}
});
return hasSubList;
};

View File

@ -41,12 +41,12 @@ export const CoreEditorExtensions = (
StarterKit.configure({ StarterKit.configure({
bulletList: { bulletList: {
HTMLAttributes: { HTMLAttributes: {
class: "list-disc list-outside leading-3 -mt-2", class: "list-disc list-outside leading-3",
}, },
}, },
orderedList: { orderedList: {
HTMLAttributes: { HTMLAttributes: {
class: "list-decimal list-outside leading-3 -mt-2", class: "list-decimal list-outside leading-3 -mt-2 -mb-2",
}, },
}, },
listItem: { listItem: {
@ -98,7 +98,7 @@ export const CoreEditorExtensions = (
}), }),
TaskItem.configure({ TaskItem.configure({
HTMLAttributes: { HTMLAttributes: {
class: "flex items-start my-4", class: "flex items-start mt-4",
}, },
nested: true, nested: true,
}), }),

View File

@ -1,4 +1,7 @@
import { Extension } from "@tiptap/core"; import { Extension } from "@tiptap/core";
import { Plugin, PluginKey, Transaction } from "@tiptap/pm/state";
import { canJoin } from "@tiptap/pm/transform";
import { NodeType } from "@tiptap/pm/model";
declare module "@tiptap/core" { declare module "@tiptap/core" {
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
@ -12,6 +15,51 @@ declare module "@tiptap/core" {
} }
} }
function autoJoin(tr: Transaction, newTr: Transaction, nodeType: NodeType) {
if (!tr.isGeneric) return false;
// Find all ranges where we might want to join.
const ranges: Array<number> = [];
for (let i = 0; i < tr.mapping.maps.length; i++) {
const map = tr.mapping.maps[i];
for (let j = 0; j < ranges.length; j++) ranges[j] = map.map(ranges[j]);
map.forEach((_s, _e, from, to) => ranges.push(from, to));
}
// Figure out which joinable points exist inside those ranges,
// by checking all node boundaries in their parent nodes.
const joinable = [];
for (let i = 0; i < ranges.length; i += 2) {
const from = ranges[i],
to = ranges[i + 1];
const $from = tr.doc.resolve(from),
depth = $from.sharedDepth(to),
parent = $from.node(depth);
for (let index = $from.indexAfter(depth), pos = $from.after(depth + 1); pos <= to; ++index) {
const after = parent.maybeChild(index);
if (!after) break;
if (index && joinable.indexOf(pos) == -1) {
const before = parent.child(index - 1);
if (before.type == after.type && before.type === nodeType) joinable.push(pos);
}
pos += after.nodeSize;
}
}
let joined = false;
// Join the joinable points
joinable.sort((a, b) => a - b);
for (let i = joinable.length - 1; i >= 0; i--) {
if (canJoin(tr.doc, joinable[i])) {
newTr.join(joinable[i]);
joined = true;
}
}
return joined;
}
export const CustomKeymap = Extension.create({ export const CustomKeymap = Extension.create({
name: "CustomKeymap", name: "CustomKeymap",
@ -32,6 +80,42 @@ export const CustomKeymap = Extension.create({
}; };
}, },
addProseMirrorPlugins() {
return [
new Plugin({
key: new PluginKey("ordered-list-merging"),
appendTransaction(transactions, oldState, newState) {
// Create a new transaction.
const newTr = newState.tr;
let joined = false;
for (const transaction of transactions) {
const anotherJoin = autoJoin(transaction, newTr, newState.schema.nodes["orderedList"]);
joined = anotherJoin || joined;
}
if (joined) {
return newTr;
}
},
}),
new Plugin({
key: new PluginKey("unordered-list-merging"),
appendTransaction(transactions, oldState, newState) {
// Create a new transaction.
const newTr = newState.tr;
let joined = false;
for (const transaction of transactions) {
const anotherJoin = autoJoin(transaction, newTr, newState.schema.nodes["bulletList"]);
joined = anotherJoin || joined;
}
if (joined) {
return newTr;
}
},
}),
];
},
addKeyboardShortcuts() { addKeyboardShortcuts() {
return { return {
"Mod-a": ({ editor }) => { "Mod-a": ({ editor }) => {

View File

@ -28,12 +28,12 @@ export const CoreReadOnlyEditorExtensions = (mentionConfig: {
StarterKit.configure({ StarterKit.configure({
bulletList: { bulletList: {
HTMLAttributes: { HTMLAttributes: {
class: "list-disc list-outside leading-3 -mt-2", class: "list-disc list-outside leading-3",
}, },
}, },
orderedList: { orderedList: {
HTMLAttributes: { HTMLAttributes: {
class: "list-decimal list-outside leading-3 -mt-2", class: "list-decimal list-outside leading-3 -mt-2 -mb-2",
}, },
}, },
listItem: { listItem: {
@ -81,7 +81,7 @@ export const CoreReadOnlyEditorExtensions = (mentionConfig: {
}), }),
TaskItem.configure({ TaskItem.configure({
HTMLAttributes: { HTMLAttributes: {
class: "flex items-start my-4", class: "flex items-start mt-4",
}, },
nested: true, nested: true,
}), }),

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-var-requires */
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
require("dotenv").config({ path: ".env" }); require("dotenv").config({ path: ".env" });
const { withSentryConfig } = require("@sentry/nextjs"); const { withSentryConfig } = require("@sentry/nextjs");
@ -26,8 +27,11 @@ const nextConfig = {
output: "standalone", output: "standalone",
}; };
if (parseInt(process.env.NEXT_PUBLIC_ENABLE_SENTRY || "0")) { if (parseInt(process.env.NEXT_PUBLIC_ENABLE_SENTRY || "0"), 10) {
module.exports = withSentryConfig(nextConfig, { silent: true }, { hideSourceMaps: true }); module.exports = withSentryConfig(nextConfig,
{ silent: true, authToken: process.env.SENTRY_AUTH_TOKEN },
{ hideSourceMaps: true }
);
} else { } else {
module.exports = nextConfig; module.exports = nextConfig;
} }

View File

@ -22,7 +22,7 @@
"@plane/rich-text-editor": "*", "@plane/rich-text-editor": "*",
"@plane/types": "*", "@plane/types": "*",
"@plane/ui": "*", "@plane/ui": "*",
"@sentry/nextjs": "^7.85.0", "@sentry/nextjs": "^7.108.0",
"axios": "^1.3.4", "axios": "^1.3.4",
"clsx": "^2.0.0", "clsx": "^2.0.0",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",

View File

@ -17,37 +17,25 @@
"NEXT_PUBLIC_POSTHOG_KEY", "NEXT_PUBLIC_POSTHOG_KEY",
"NEXT_PUBLIC_POSTHOG_HOST", "NEXT_PUBLIC_POSTHOG_HOST",
"NEXT_PUBLIC_POSTHOG_DEBUG", "NEXT_PUBLIC_POSTHOG_DEBUG",
"JITSU_TRACKER_ACCESS_KEY", "SENTRY_AUTH_TOKEN"
"JITSU_TRACKER_HOST"
], ],
"pipeline": { "pipeline": {
"build": { "build": {
"dependsOn": [ "dependsOn": ["^build"],
"^build" "outputs": [".next/**", "dist/**"]
],
"outputs": [
".next/**",
"dist/**"
]
}, },
"develop": { "develop": {
"cache": false, "cache": false,
"persistent": true, "persistent": true,
"dependsOn": [ "dependsOn": ["^build"]
"^build"
]
}, },
"dev": { "dev": {
"cache": false, "cache": false,
"persistent": true, "persistent": true,
"dependsOn": [ "dependsOn": ["^build"]
"^build"
]
}, },
"test": { "test": {
"dependsOn": [ "dependsOn": ["^build"],
"^build"
],
"outputs": [] "outputs": []
}, },
"lint": { "lint": {

View File

@ -144,7 +144,7 @@ export const ImagePickerPopover: React.FC<Props> = observer((props) => {
useEffect(() => { useEffect(() => {
if (!unsplashImages || value !== null) return; if (!unsplashImages || value !== null) return;
onChange(unsplashImages[0].urls.regular); onChange(unsplashImages[0]?.urls.regular);
}, [value, onChange, unsplashImages]); }, [value, onChange, unsplashImages]);
const handleClose = () => { const handleClose = () => {

View File

@ -201,7 +201,7 @@ export const ActiveCycleStats: FC<ActiveCycleStatsProps> = observer((props) => {
as="div" as="div"
className="flex h-52 w-full flex-col gap-1 overflow-y-auto text-custom-text-200 vertical-scrollbar scrollbar-sm" className="flex h-52 w-full flex-col gap-1 overflow-y-auto text-custom-text-200 vertical-scrollbar scrollbar-sm"
> >
{cycleIssues.length > 0 ? ( {cycle?.distribution?.assignees && cycle.distribution.assignees.length > 0 ? (
cycle.distribution?.assignees?.map((assignee, index) => { cycle.distribution?.assignees?.map((assignee, index) => {
if (assignee.assignee_id) if (assignee.assignee_id)
return ( return (
@ -246,8 +246,8 @@ export const ActiveCycleStats: FC<ActiveCycleStatsProps> = observer((props) => {
as="div" as="div"
className="flex h-52 w-full flex-col gap-1 overflow-y-auto text-custom-text-200 vertical-scrollbar scrollbar-sm" className="flex h-52 w-full flex-col gap-1 overflow-y-auto text-custom-text-200 vertical-scrollbar scrollbar-sm"
> >
{cycleIssues.length > 0 ? ( {cycle?.distribution?.labels && cycle.distribution.labels.length > 0 ? (
cycle.distribution?.labels?.map((label, index) => ( cycle.distribution.labels?.map((label, index) => (
<SingleProgressStats <SingleProgressStats
key={label.label_id ?? `no-label-${index}`} key={label.label_id ?? `no-label-${index}`}
title={ title={

View File

@ -1,4 +1,5 @@
import React from "react"; import React from "react";
import { observer } from "mobx-react";
import { RefreshCw } from "lucide-react"; import { RefreshCw } from "lucide-react";
import { TIssue } from "@plane/types"; import { TIssue } from "@plane/types";
// types // types
@ -9,7 +10,7 @@ type Props = {
issueDetail?: TIssue; issueDetail?: TIssue;
}; };
export const IssueUpdateStatus: React.FC<Props> = (props) => { export const IssueUpdateStatus: React.FC<Props> = observer((props) => {
const { isSubmitting, issueDetail } = props; const { isSubmitting, issueDetail } = props;
// hooks // hooks
const { getProjectById } = useProject(); const { getProjectById } = useProject();
@ -33,4 +34,4 @@ export const IssueUpdateStatus: React.FC<Props> = (props) => {
</div> </div>
</> </>
); );
}; });

View File

@ -1,4 +1,5 @@
import React from "react"; import React from "react";
import { observer } from "mobx-react";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
// hooks // hooks
@ -6,7 +7,7 @@ import { EUserWorkspaceRoles, WORKSPACE_SETTINGS_LINKS } from "@/constants/works
import { useUser } from "@/hooks/store"; import { useUser } from "@/hooks/store";
// constants // constants
export const WorkspaceSettingsSidebar = () => { export const WorkspaceSettingsSidebar = observer(() => {
// router // router
const router = useRouter(); const router = useRouter();
const { workspaceSlug } = router.query; const { workspaceSlug } = router.query;
@ -44,4 +45,4 @@ export const WorkspaceSettingsSidebar = () => {
</div> </div>
</div> </div>
); );
}; });

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-var-requires */
require("dotenv").config({ path: ".env" }); require("dotenv").config({ path: ".env" });
const { withSentryConfig } = require("@sentry/nextjs"); const { withSentryConfig } = require("@sentry/nextjs");
@ -24,8 +25,11 @@ const nextConfig = {
output: "standalone", output: "standalone",
}; };
if (parseInt(process.env.NEXT_PUBLIC_ENABLE_SENTRY || "0")) { if (parseInt(process.env.NEXT_PUBLIC_ENABLE_SENTRY || "0"), 10) {
module.exports = withSentryConfig(nextConfig, { silent: true }, { hideSourceMaps: true }); module.exports = withSentryConfig(nextConfig,
{ silent: true, authToken: process.env.SENTRY_AUTH_TOKEN },
{ hideSourceMaps: true }
);
} else { } else {
module.exports = nextConfig; module.exports = nextConfig;
} }

View File

@ -28,7 +28,7 @@
"@plane/types": "*", "@plane/types": "*",
"@plane/ui": "*", "@plane/ui": "*",
"@popperjs/core": "^2.11.8", "@popperjs/core": "^2.11.8",
"@sentry/nextjs": "^7.85.0", "@sentry/nextjs": "^7.108.0",
"axios": "^1.1.3", "axios": "^1.1.3",
"clsx": "^2.0.0", "clsx": "^2.0.0",
"cmdk": "^0.2.0", "cmdk": "^0.2.0",

189
yarn.lock
View File

@ -2149,35 +2149,46 @@
dependencies: dependencies:
"@daybrush/utils" "^1.4.0" "@daybrush/utils" "^1.4.0"
"@sentry-internal/feedback@7.91.0": "@sentry-internal/feedback@7.108.0":
version "7.91.0" version "7.108.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-7.91.0.tgz#be09e5aec2959fcf503e2cf78496d5e2d263bc5a" resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-7.108.0.tgz#7033352abd304f1383ec47640e056a0dfd5132b7"
integrity sha512-SJKTSaz68F5YIwF79EttBm915M2LnacgZMYRnRumyTmMKnebGhYQLwWbZdpaDvOa1U18dgRajDX8Qed/8A3tXw== integrity sha512-8JcgZEnk1uWrXJhsd3iRvFtEiVeaWOEhN0NZwhwQXHfvODqep6JtrkY1yCIyxbpA37aZmrPc2JhyotRERGfUjg==
dependencies: dependencies:
"@sentry/core" "7.91.0" "@sentry/core" "7.108.0"
"@sentry/types" "7.91.0" "@sentry/types" "7.108.0"
"@sentry/utils" "7.91.0" "@sentry/utils" "7.108.0"
"@sentry-internal/tracing@7.91.0": "@sentry-internal/replay-canvas@7.108.0":
version "7.91.0" version "7.108.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.91.0.tgz#fbb6e1e3383e1eeee08633384e004da73ac1c37d" resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-7.108.0.tgz#641133c19c0e1c423617b8d791f53d6cd0b0a862"
integrity sha512-JH5y6gs6BS0its7WF2DhySu7nkhPDfZcdpAXldxzIlJpqFkuwQKLU5nkYJpiIyZz1NHYYtW5aum2bV2oCOdDRA== integrity sha512-R5tvjGqWUV5vSk0N1eBgVW7wIADinrkfDEBZ9FyKP2mXHBobsyNGt30heJDEqYmVqluRqjU2NuIRapsnnrpGnA==
dependencies: dependencies:
"@sentry/core" "7.91.0" "@sentry/core" "7.108.0"
"@sentry/types" "7.91.0" "@sentry/replay" "7.108.0"
"@sentry/utils" "7.91.0" "@sentry/types" "7.108.0"
"@sentry/utils" "7.108.0"
"@sentry/browser@7.91.0": "@sentry-internal/tracing@7.108.0":
version "7.91.0" version "7.108.0"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.91.0.tgz#de3b9ae3ca7716a35cfabc97ac376944a67e6e34" resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.108.0.tgz#d1e660701fb860cfae72b6ebfa8fb267533421fa"
integrity sha512-lJv3x/xekzC/biiyAsVCioq2XnKNOZhI6jY3ZzLJZClYV8eKRi7D3KCsHRvMiCdGak1d/6sVp8F4NYY+YiWy1Q== integrity sha512-zuK5XsTsb+U+hgn3SPetYDAogrXsM16U/LLoMW7+TlC6UjlHGYQvmX3o+M2vntejoU1QZS8m1bCAZSMWEypAEw==
dependencies: dependencies:
"@sentry-internal/feedback" "7.91.0" "@sentry/core" "7.108.0"
"@sentry-internal/tracing" "7.91.0" "@sentry/types" "7.108.0"
"@sentry/core" "7.91.0" "@sentry/utils" "7.108.0"
"@sentry/replay" "7.91.0"
"@sentry/types" "7.91.0" "@sentry/browser@7.108.0":
"@sentry/utils" "7.91.0" version "7.108.0"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.108.0.tgz#b95810bb6572b63781f253615896f5afb1a3a5c0"
integrity sha512-FNpzsdTvGvdHJMUelqEouUXMZU7jC+dpN7CdT6IoHVVFEkoAgrjMVUhXZoQ/dmCkdKWHmFSQhJ8Fm6V+e9Aq0A==
dependencies:
"@sentry-internal/feedback" "7.108.0"
"@sentry-internal/replay-canvas" "7.108.0"
"@sentry-internal/tracing" "7.108.0"
"@sentry/core" "7.108.0"
"@sentry/replay" "7.108.0"
"@sentry/types" "7.108.0"
"@sentry/utils" "7.108.0"
"@sentry/cli@^1.77.1": "@sentry/cli@^1.77.1":
version "1.77.1" version "1.77.1"
@ -2191,95 +2202,95 @@
proxy-from-env "^1.1.0" proxy-from-env "^1.1.0"
which "^2.0.2" which "^2.0.2"
"@sentry/core@7.91.0": "@sentry/core@7.108.0":
version "7.91.0" version "7.108.0"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.91.0.tgz#229334d7f03dd5d90a17495e61ce4215ab730b2a" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.108.0.tgz#a27e8d6f85f59c5730ce86071474f15ac899fde0"
integrity sha512-tu+gYq4JrTdrR+YSh5IVHF0fJi/Pi9y0HZ5H9HnYy+UMcXIotxf6hIEaC6ZKGeLWkGXffz2gKpQLe/g6vy/lPA== integrity sha512-I/VNZCFgLASxHZaD0EtxZRM34WG9w2gozqgrKGNMzAymwmQ3K9g/1qmBy4e6iS3YRptb7J5UhQkZQHrcwBbjWQ==
dependencies: dependencies:
"@sentry/types" "7.91.0" "@sentry/types" "7.108.0"
"@sentry/utils" "7.91.0" "@sentry/utils" "7.108.0"
"@sentry/integrations@7.91.0": "@sentry/integrations@7.108.0":
version "7.91.0" version "7.108.0"
resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.91.0.tgz#b0496c9e404783bc433b1d2464d8f9aa180ebc8e" resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.108.0.tgz#307c61966208f2a126c1a93e712277c8f86a3d3c"
integrity sha512-LGRfb+WfG3FaWHtDnJIhtupweat0imCQr2z/5SSbQKzqxHhtlaEU+9IExBmBdzq90n4lRBaVQHA3zGuU02uOhg== integrity sha512-b/WbK1f3x2rQ4aJJSA4VSwpBXrXFm1Nzrca3Y9qW0MI1wjZEYsDDrh9m6ulLdVBl4YDc2VqYp1COwU/NjuHlog==
dependencies: dependencies:
"@sentry/core" "7.91.0" "@sentry/core" "7.108.0"
"@sentry/types" "7.91.0" "@sentry/types" "7.108.0"
"@sentry/utils" "7.91.0" "@sentry/utils" "7.108.0"
localforage "^1.8.1" localforage "^1.8.1"
"@sentry/nextjs@^7.85.0": "@sentry/nextjs@^7.108.0":
version "7.91.0" version "7.108.0"
resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-7.91.0.tgz#42eb3af10ff230e8a3fe9f0e50cdbac94b7d290e" resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-7.108.0.tgz#31d903d75bbf4b4530046360daff4d51dcf62f53"
integrity sha512-wE83+OTEH4yYnDrhMw9eVEARSfZc6xY5qJb9xyYm5rW3+gVjNQZQaUY+wkM61Xdo0T35BN+7U4T88HbwzGeMqA== integrity sha512-etBrMSLRbNAzozetBeL6D+lR9lRAyHmV7NUBGCX9lQvgmcdxkQa15EX8pIKjsMejZ8xAZNsqYVIByIs67A77rg==
dependencies: dependencies:
"@rollup/plugin-commonjs" "24.0.0" "@rollup/plugin-commonjs" "24.0.0"
"@sentry/core" "7.91.0" "@sentry/core" "7.108.0"
"@sentry/integrations" "7.91.0" "@sentry/integrations" "7.108.0"
"@sentry/node" "7.91.0" "@sentry/node" "7.108.0"
"@sentry/react" "7.91.0" "@sentry/react" "7.108.0"
"@sentry/types" "7.91.0" "@sentry/types" "7.108.0"
"@sentry/utils" "7.91.0" "@sentry/utils" "7.108.0"
"@sentry/vercel-edge" "7.91.0" "@sentry/vercel-edge" "7.108.0"
"@sentry/webpack-plugin" "1.21.0" "@sentry/webpack-plugin" "1.21.0"
chalk "3.0.0" chalk "3.0.0"
resolve "1.22.8" resolve "1.22.8"
rollup "2.78.0" rollup "2.78.0"
stacktrace-parser "^0.1.10" stacktrace-parser "^0.1.10"
"@sentry/node@7.91.0": "@sentry/node@7.108.0":
version "7.91.0" version "7.108.0"
resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.91.0.tgz#26bf13c3daf988f9725afd1a3cc38ba2ff90d62a" resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.108.0.tgz#ed113dc1d39aaae32f7e9f681dcea41cf28eb5f1"
integrity sha512-hTIfSQxD7L+AKIqyjoq8CWBRkEQrrMZmA3GSZgPI5JFWBHgO0HBo5TH/8TU81oEJh6kqqHAl2ObMhmcnaFqlzg== integrity sha512-pMxc9txnDDkU4Z8k2Uw/DPSLPehNtWV3mjJ3+my0AMORGYrXLkJI93tddlE5z/7k+GEJdj1HsOLgxUN0OU+HGA==
dependencies: dependencies:
"@sentry-internal/tracing" "7.91.0" "@sentry-internal/tracing" "7.108.0"
"@sentry/core" "7.91.0" "@sentry/core" "7.108.0"
"@sentry/types" "7.91.0" "@sentry/types" "7.108.0"
"@sentry/utils" "7.91.0" "@sentry/utils" "7.108.0"
https-proxy-agent "^5.0.0"
"@sentry/react@7.91.0": "@sentry/react@7.108.0":
version "7.91.0" version "7.108.0"
resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.91.0.tgz#620e6ce9452af025d2cc1b2eca3dd1dd730dc439" resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.108.0.tgz#26a50324f6d7a9576f3753c099e7bcd8def94f3c"
integrity sha512-7JH2rWaX3WKHHvBcZQ4f/KnkYIXTf7hMojRFncUwPocdtDlhJw/JUvjAYNpEysixXIgsMes3B32lmtZjGjRhwQ== integrity sha512-C60arh5/gtO42eMU9l34aWlKDLZUO+1j1goaEf/XRSwUcyJS9tbJrs+mT4nbKxUsEG714It2gRbfSEvh1eXmCg==
dependencies: dependencies:
"@sentry/browser" "7.91.0" "@sentry/browser" "7.108.0"
"@sentry/types" "7.91.0" "@sentry/core" "7.108.0"
"@sentry/utils" "7.91.0" "@sentry/types" "7.108.0"
"@sentry/utils" "7.108.0"
hoist-non-react-statics "^3.3.2" hoist-non-react-statics "^3.3.2"
"@sentry/replay@7.91.0": "@sentry/replay@7.108.0":
version "7.91.0" version "7.108.0"
resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.91.0.tgz#95077868aee3c3cc670affe13156434f858e1755" resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.108.0.tgz#baa679bd19b4e3729e607d3f84cff5048aeb3415"
integrity sha512-XwbesnLLNtaVXKtDoyBB96GxJuhGi9zy3a662Ba/McmumCnkXrMQYpQPh08U7MgkTyDRgjDwm7PXDhiKpcb03g== integrity sha512-jo8fDOzcZJclP1+4n9jUtVxTlBFT9hXwxhAMrhrt70FV/nfmCtYQMD3bzIj79nwbhUtFP6pN39JH1o7Xqt1hxQ==
dependencies: dependencies:
"@sentry-internal/tracing" "7.91.0" "@sentry-internal/tracing" "7.108.0"
"@sentry/core" "7.91.0" "@sentry/core" "7.108.0"
"@sentry/types" "7.91.0" "@sentry/types" "7.108.0"
"@sentry/utils" "7.91.0" "@sentry/utils" "7.108.0"
"@sentry/types@7.91.0": "@sentry/types@7.108.0":
version "7.91.0" version "7.108.0"
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.91.0.tgz#5b68954e08986fecb0d4bef168df58eef62c32c7" resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.108.0.tgz#5ceb959c4dabe511fc441fec8c2465f2d624900f"
integrity sha512-bcQnb7J3P3equbCUc+sPuHog2Y47yGD2sCkzmnZBjvBT0Z1B4f36fI/5WjyZhTjLSiOdg3F2otwvikbMjmBDew== integrity sha512-bKtHITmBN3kqtqE5eVvL8mY8znM05vEodENwRpcm6TSrrBjC2RnwNWVwGstYDdHpNfFuKwC8mLY9bgMJcENo8g==
"@sentry/utils@7.91.0": "@sentry/utils@7.108.0":
version "7.91.0" version "7.108.0"
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.91.0.tgz#3b1a94c053c885877908cd3e1365e3d23e21a73f" resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.108.0.tgz#0231042956aed2ef35809891592238530349dfd9"
integrity sha512-fvxjrEbk6T6Otu++Ax9ntlQ0sGRiwSC179w68aC3u26Wr30FAIRKqHTCCdc2jyWk7Gd9uWRT/cq+g8NG/8BfSg== integrity sha512-a45yEFD5qtgZaIFRAcFkG8C8lnDzn6t4LfLXuV4OafGAy/3ZAN3XN8wDnrruHkiUezSSANGsLg3bXaLW/JLvJw==
dependencies: dependencies:
"@sentry/types" "7.91.0" "@sentry/types" "7.108.0"
"@sentry/vercel-edge@7.91.0": "@sentry/vercel-edge@7.108.0":
version "7.91.0" version "7.108.0"
resolved "https://registry.yarnpkg.com/@sentry/vercel-edge/-/vercel-edge-7.91.0.tgz#df67ee39d10570b71eccf831a181c064974d62b1" resolved "https://registry.yarnpkg.com/@sentry/vercel-edge/-/vercel-edge-7.108.0.tgz#c5ca35094bc46029ec5a72f7ee09fd3705582baa"
integrity sha512-CounqhXPwFh67zf6L/q4ACBHHqknT6YY9LdgIAnUd0GGgHzrJPyKcthvh8Je4lNdpo5LFg2gnR+6g6JS8DDYDQ== integrity sha512-dUuUEswaVIzsJnzTfaJxrvkfOowrlJxxHo2AybPDym2rob7CdaLdDJIYJa83X7QeAKMkTgLny/gYSQYC0E4UyA==
dependencies: dependencies:
"@sentry-internal/tracing" "7.91.0" "@sentry-internal/tracing" "7.108.0"
"@sentry/core" "7.91.0" "@sentry/core" "7.108.0"
"@sentry/types" "7.91.0" "@sentry/types" "7.108.0"
"@sentry/utils" "7.91.0" "@sentry/utils" "7.108.0"
"@sentry/webpack-plugin@1.21.0": "@sentry/webpack-plugin@1.21.0":
version "1.21.0" version "1.21.0"