From fb189ca447bc4904dabb3c04e406459aea8f745f Mon Sep 17 00:00:00 2001 From: Nikhil <118773738+pablohashescobar@users.noreply.github.com> Date: Tue, 26 Mar 2024 15:49:44 +0530 Subject: [PATCH 01/12] fix: cycle issue subquery filter when adding multiple assignees (#4066) --- apiserver/plane/app/views/cycle/base.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/apiserver/plane/app/views/cycle/base.py b/apiserver/plane/app/views/cycle/base.py index 48e475a74..d323a0f63 100644 --- a/apiserver/plane/app/views/cycle/base.py +++ b/apiserver/plane/app/views/cycle/base.py @@ -103,7 +103,8 @@ class CycleViewSet(WebhookMixin, BaseViewSet): .annotate(is_favorite=Exists(favorite_subquery)) .annotate( total_issues=Count( - "issue_cycle", + "issue_cycle__issue__id", + distinct=True, filter=Q( issue_cycle__issue__archived_at__isnull=True, issue_cycle__issue__is_draft=False, @@ -112,7 +113,8 @@ class CycleViewSet(WebhookMixin, BaseViewSet): ) .annotate( completed_issues=Count( - "issue_cycle__issue__state__group", + "issue_cycle__issue__id", + distinct=True, filter=Q( issue_cycle__issue__state__group="completed", issue_cycle__issue__archived_at__isnull=True, @@ -122,7 +124,8 @@ class CycleViewSet(WebhookMixin, BaseViewSet): ) .annotate( cancelled_issues=Count( - "issue_cycle__issue__state__group", + "issue_cycle__issue__id", + distinct=True, filter=Q( issue_cycle__issue__state__group="cancelled", issue_cycle__issue__archived_at__isnull=True, @@ -132,7 +135,8 @@ class CycleViewSet(WebhookMixin, BaseViewSet): ) .annotate( started_issues=Count( - "issue_cycle__issue__state__group", + "issue_cycle__issue__id", + distinct=True, filter=Q( issue_cycle__issue__state__group="started", issue_cycle__issue__archived_at__isnull=True, @@ -142,7 +146,8 @@ class CycleViewSet(WebhookMixin, BaseViewSet): ) .annotate( unstarted_issues=Count( - "issue_cycle__issue__state__group", + "issue_cycle__issue__id", + distinct=True, filter=Q( issue_cycle__issue__state__group="unstarted", issue_cycle__issue__archived_at__isnull=True, @@ -152,7 +157,8 @@ class CycleViewSet(WebhookMixin, BaseViewSet): ) .annotate( backlog_issues=Count( - "issue_cycle__issue__state__group", + "issue_cycle__issue__id", + distinct=True, filter=Q( issue_cycle__issue__state__group="backlog", issue_cycle__issue__archived_at__isnull=True, From 51683e6b2f45c8df96a6f82dc41567d9e207924d Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Tue, 26 Mar 2024 15:53:52 +0530 Subject: [PATCH 02/12] fix: active cycle stats empty state (#4067) --- web/components/cycles/active-cycle/cycle-stats.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/components/cycles/active-cycle/cycle-stats.tsx b/web/components/cycles/active-cycle/cycle-stats.tsx index fd4bc9318..2eb128763 100644 --- a/web/components/cycles/active-cycle/cycle-stats.tsx +++ b/web/components/cycles/active-cycle/cycle-stats.tsx @@ -201,7 +201,7 @@ export const ActiveCycleStats: FC = observer((props) => { as="div" 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) => { if (assignee.assignee_id) return ( @@ -246,8 +246,8 @@ export const ActiveCycleStats: FC = observer((props) => { as="div" 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?.map((label, index) => ( + {cycle?.distribution?.labels && cycle.distribution.labels.length > 0 ? ( + cycle.distribution.labels?.map((label, index) => ( Date: Tue, 26 Mar 2024 15:55:47 +0530 Subject: [PATCH 03/12] fix: adding workflow dispatch to codeql --- .github/workflows/codeql.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 92b44af5b..a858bcc59 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,6 +1,7 @@ name: "CodeQL" on: + workflow_dispatch: push: branches: ["master"] pull_request: From f3fd48dd431541bd3f1ee400023792a7e183930f Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Tue, 26 Mar 2024 16:30:57 +0530 Subject: [PATCH 04/12] chore: image picker popover improvement (#4068) --- web/components/core/image-picker-popover.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/components/core/image-picker-popover.tsx b/web/components/core/image-picker-popover.tsx index 53e1179dc..1397039d1 100644 --- a/web/components/core/image-picker-popover.tsx +++ b/web/components/core/image-picker-popover.tsx @@ -144,7 +144,7 @@ export const ImagePickerPopover: React.FC = observer((props) => { useEffect(() => { if (!unsplashImages || value !== null) return; - onChange(unsplashImages[0].urls.regular); + onChange(unsplashImages[0]?.urls.regular); }, [value, onChange, unsplashImages]); const handleClose = () => { From 1c3619a4d6d7416e1a9206cafa937c6e3d509e1f Mon Sep 17 00:00:00 2001 From: Bavisetti Narayan <72156168+NarayanBavisetti@users.noreply.github.com> Date: Tue, 26 Mar 2024 16:59:23 +0530 Subject: [PATCH 05/12] chore: workspace estimate project filter (#4070) --- apiserver/plane/app/views/workspace/estimate.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/apiserver/plane/app/views/workspace/estimate.py b/apiserver/plane/app/views/workspace/estimate.py index fa75d5b88..8ca24efd7 100644 --- a/apiserver/plane/app/views/workspace/estimate.py +++ b/apiserver/plane/app/views/workspace/estimate.py @@ -25,15 +25,11 @@ class WorkspaceEstimatesEndpoint(BaseAPIView): estimate_ids = Project.objects.filter( workspace__slug=slug, estimate__isnull=False ).values_list("estimate_id", flat=True) - estimates = Estimate.objects.filter( - pk__in=estimate_ids - ).prefetch_related( - Prefetch( - "points", - queryset=Project.objects.select_related( - "estimate", "workspace" - ), - ) + estimates = ( + Estimate.objects.filter(pk__in=estimate_ids, workspace__slug=slug) + .prefetch_related("points") + .select_related("workspace", "project") ) + serializer = WorkspaceEstimateSerializer(estimates, many=True) return Response(serializer.data, status=status.HTTP_200_OK) From 5235b78cb8f205ce8a6b7ad181f07ba24a1cddae Mon Sep 17 00:00:00 2001 From: sriram veeraghanta Date: Tue, 26 Mar 2024 19:24:42 +0530 Subject: [PATCH 06/12] fix: sentry config fixes --- space/next.config.js | 8 +- space/package.json | 2 +- turbo.json | 24 ++---- web/next.config.js | 8 +- web/package.json | 2 +- yarn.lock | 189 +++++++++++++++++++++++-------------------- 6 files changed, 120 insertions(+), 113 deletions(-) diff --git a/space/next.config.js b/space/next.config.js index 18b9275a1..b36368720 100644 --- a/space/next.config.js +++ b/space/next.config.js @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ /** @type {import('next').NextConfig} */ require("dotenv").config({ path: ".env" }); const { withSentryConfig } = require("@sentry/nextjs"); @@ -26,8 +27,11 @@ const nextConfig = { output: "standalone", }; -if (parseInt(process.env.NEXT_PUBLIC_ENABLE_SENTRY || "0")) { - module.exports = withSentryConfig(nextConfig, { silent: true }, { hideSourceMaps: true }); +if (parseInt(process.env.NEXT_PUBLIC_ENABLE_SENTRY || "0"), 10) { + module.exports = withSentryConfig(nextConfig, + { silent: true, authToken: process.env.SENTRY_AUTH_TOKEN }, + { hideSourceMaps: true } + ); } else { module.exports = nextConfig; } diff --git a/space/package.json b/space/package.json index 4951d5e30..3d6127edb 100644 --- a/space/package.json +++ b/space/package.json @@ -22,7 +22,7 @@ "@plane/rich-text-editor": "*", "@plane/types": "*", "@plane/ui": "*", - "@sentry/nextjs": "^7.85.0", + "@sentry/nextjs": "^7.108.0", "axios": "^1.3.4", "clsx": "^2.0.0", "dotenv": "^16.3.1", diff --git a/turbo.json b/turbo.json index 9302a7183..4e8c4ee81 100644 --- a/turbo.json +++ b/turbo.json @@ -17,37 +17,25 @@ "NEXT_PUBLIC_POSTHOG_KEY", "NEXT_PUBLIC_POSTHOG_HOST", "NEXT_PUBLIC_POSTHOG_DEBUG", - "JITSU_TRACKER_ACCESS_KEY", - "JITSU_TRACKER_HOST" + "SENTRY_AUTH_TOKEN" ], "pipeline": { "build": { - "dependsOn": [ - "^build" - ], - "outputs": [ - ".next/**", - "dist/**" - ] + "dependsOn": ["^build"], + "outputs": [".next/**", "dist/**"] }, "develop": { "cache": false, "persistent": true, - "dependsOn": [ - "^build" - ] + "dependsOn": ["^build"] }, "dev": { "cache": false, "persistent": true, - "dependsOn": [ - "^build" - ] + "dependsOn": ["^build"] }, "test": { - "dependsOn": [ - "^build" - ], + "dependsOn": ["^build"], "outputs": [] }, "lint": { diff --git a/web/next.config.js b/web/next.config.js index e018ea317..a7c658b59 100644 --- a/web/next.config.js +++ b/web/next.config.js @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ require("dotenv").config({ path: ".env" }); const { withSentryConfig } = require("@sentry/nextjs"); @@ -24,8 +25,11 @@ const nextConfig = { output: "standalone", }; -if (parseInt(process.env.NEXT_PUBLIC_ENABLE_SENTRY || "0")) { - module.exports = withSentryConfig(nextConfig, { silent: true }, { hideSourceMaps: true }); +if (parseInt(process.env.NEXT_PUBLIC_ENABLE_SENTRY || "0"), 10) { + module.exports = withSentryConfig(nextConfig, + { silent: true, authToken: process.env.SENTRY_AUTH_TOKEN }, + { hideSourceMaps: true } + ); } else { module.exports = nextConfig; } diff --git a/web/package.json b/web/package.json index bdd880ce1..3ec941b80 100644 --- a/web/package.json +++ b/web/package.json @@ -28,7 +28,7 @@ "@plane/types": "*", "@plane/ui": "*", "@popperjs/core": "^2.11.8", - "@sentry/nextjs": "^7.85.0", + "@sentry/nextjs": "^7.108.0", "axios": "^1.1.3", "clsx": "^2.0.0", "cmdk": "^0.2.0", diff --git a/yarn.lock b/yarn.lock index 6f50b05ac..4442a5cd5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2149,35 +2149,46 @@ dependencies: "@daybrush/utils" "^1.4.0" -"@sentry-internal/feedback@7.91.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-7.91.0.tgz#be09e5aec2959fcf503e2cf78496d5e2d263bc5a" - integrity sha512-SJKTSaz68F5YIwF79EttBm915M2LnacgZMYRnRumyTmMKnebGhYQLwWbZdpaDvOa1U18dgRajDX8Qed/8A3tXw== +"@sentry-internal/feedback@7.108.0": + version "7.108.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-7.108.0.tgz#7033352abd304f1383ec47640e056a0dfd5132b7" + integrity sha512-8JcgZEnk1uWrXJhsd3iRvFtEiVeaWOEhN0NZwhwQXHfvODqep6JtrkY1yCIyxbpA37aZmrPc2JhyotRERGfUjg== dependencies: - "@sentry/core" "7.91.0" - "@sentry/types" "7.91.0" - "@sentry/utils" "7.91.0" + "@sentry/core" "7.108.0" + "@sentry/types" "7.108.0" + "@sentry/utils" "7.108.0" -"@sentry-internal/tracing@7.91.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.91.0.tgz#fbb6e1e3383e1eeee08633384e004da73ac1c37d" - integrity sha512-JH5y6gs6BS0its7WF2DhySu7nkhPDfZcdpAXldxzIlJpqFkuwQKLU5nkYJpiIyZz1NHYYtW5aum2bV2oCOdDRA== +"@sentry-internal/replay-canvas@7.108.0": + version "7.108.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-7.108.0.tgz#641133c19c0e1c423617b8d791f53d6cd0b0a862" + integrity sha512-R5tvjGqWUV5vSk0N1eBgVW7wIADinrkfDEBZ9FyKP2mXHBobsyNGt30heJDEqYmVqluRqjU2NuIRapsnnrpGnA== dependencies: - "@sentry/core" "7.91.0" - "@sentry/types" "7.91.0" - "@sentry/utils" "7.91.0" + "@sentry/core" "7.108.0" + "@sentry/replay" "7.108.0" + "@sentry/types" "7.108.0" + "@sentry/utils" "7.108.0" -"@sentry/browser@7.91.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.91.0.tgz#de3b9ae3ca7716a35cfabc97ac376944a67e6e34" - integrity sha512-lJv3x/xekzC/biiyAsVCioq2XnKNOZhI6jY3ZzLJZClYV8eKRi7D3KCsHRvMiCdGak1d/6sVp8F4NYY+YiWy1Q== +"@sentry-internal/tracing@7.108.0": + version "7.108.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.108.0.tgz#d1e660701fb860cfae72b6ebfa8fb267533421fa" + integrity sha512-zuK5XsTsb+U+hgn3SPetYDAogrXsM16U/LLoMW7+TlC6UjlHGYQvmX3o+M2vntejoU1QZS8m1bCAZSMWEypAEw== dependencies: - "@sentry-internal/feedback" "7.91.0" - "@sentry-internal/tracing" "7.91.0" - "@sentry/core" "7.91.0" - "@sentry/replay" "7.91.0" - "@sentry/types" "7.91.0" - "@sentry/utils" "7.91.0" + "@sentry/core" "7.108.0" + "@sentry/types" "7.108.0" + "@sentry/utils" "7.108.0" + +"@sentry/browser@7.108.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": version "1.77.1" @@ -2191,95 +2202,95 @@ proxy-from-env "^1.1.0" which "^2.0.2" -"@sentry/core@7.91.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.91.0.tgz#229334d7f03dd5d90a17495e61ce4215ab730b2a" - integrity sha512-tu+gYq4JrTdrR+YSh5IVHF0fJi/Pi9y0HZ5H9HnYy+UMcXIotxf6hIEaC6ZKGeLWkGXffz2gKpQLe/g6vy/lPA== +"@sentry/core@7.108.0": + version "7.108.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.108.0.tgz#a27e8d6f85f59c5730ce86071474f15ac899fde0" + integrity sha512-I/VNZCFgLASxHZaD0EtxZRM34WG9w2gozqgrKGNMzAymwmQ3K9g/1qmBy4e6iS3YRptb7J5UhQkZQHrcwBbjWQ== dependencies: - "@sentry/types" "7.91.0" - "@sentry/utils" "7.91.0" + "@sentry/types" "7.108.0" + "@sentry/utils" "7.108.0" -"@sentry/integrations@7.91.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.91.0.tgz#b0496c9e404783bc433b1d2464d8f9aa180ebc8e" - integrity sha512-LGRfb+WfG3FaWHtDnJIhtupweat0imCQr2z/5SSbQKzqxHhtlaEU+9IExBmBdzq90n4lRBaVQHA3zGuU02uOhg== +"@sentry/integrations@7.108.0": + version "7.108.0" + resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.108.0.tgz#307c61966208f2a126c1a93e712277c8f86a3d3c" + integrity sha512-b/WbK1f3x2rQ4aJJSA4VSwpBXrXFm1Nzrca3Y9qW0MI1wjZEYsDDrh9m6ulLdVBl4YDc2VqYp1COwU/NjuHlog== dependencies: - "@sentry/core" "7.91.0" - "@sentry/types" "7.91.0" - "@sentry/utils" "7.91.0" + "@sentry/core" "7.108.0" + "@sentry/types" "7.108.0" + "@sentry/utils" "7.108.0" localforage "^1.8.1" -"@sentry/nextjs@^7.85.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-7.91.0.tgz#42eb3af10ff230e8a3fe9f0e50cdbac94b7d290e" - integrity sha512-wE83+OTEH4yYnDrhMw9eVEARSfZc6xY5qJb9xyYm5rW3+gVjNQZQaUY+wkM61Xdo0T35BN+7U4T88HbwzGeMqA== +"@sentry/nextjs@^7.108.0": + version "7.108.0" + resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-7.108.0.tgz#31d903d75bbf4b4530046360daff4d51dcf62f53" + integrity sha512-etBrMSLRbNAzozetBeL6D+lR9lRAyHmV7NUBGCX9lQvgmcdxkQa15EX8pIKjsMejZ8xAZNsqYVIByIs67A77rg== dependencies: "@rollup/plugin-commonjs" "24.0.0" - "@sentry/core" "7.91.0" - "@sentry/integrations" "7.91.0" - "@sentry/node" "7.91.0" - "@sentry/react" "7.91.0" - "@sentry/types" "7.91.0" - "@sentry/utils" "7.91.0" - "@sentry/vercel-edge" "7.91.0" + "@sentry/core" "7.108.0" + "@sentry/integrations" "7.108.0" + "@sentry/node" "7.108.0" + "@sentry/react" "7.108.0" + "@sentry/types" "7.108.0" + "@sentry/utils" "7.108.0" + "@sentry/vercel-edge" "7.108.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/node@7.91.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.91.0.tgz#26bf13c3daf988f9725afd1a3cc38ba2ff90d62a" - integrity sha512-hTIfSQxD7L+AKIqyjoq8CWBRkEQrrMZmA3GSZgPI5JFWBHgO0HBo5TH/8TU81oEJh6kqqHAl2ObMhmcnaFqlzg== +"@sentry/node@7.108.0": + version "7.108.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.108.0.tgz#ed113dc1d39aaae32f7e9f681dcea41cf28eb5f1" + integrity sha512-pMxc9txnDDkU4Z8k2Uw/DPSLPehNtWV3mjJ3+my0AMORGYrXLkJI93tddlE5z/7k+GEJdj1HsOLgxUN0OU+HGA== dependencies: - "@sentry-internal/tracing" "7.91.0" - "@sentry/core" "7.91.0" - "@sentry/types" "7.91.0" - "@sentry/utils" "7.91.0" - https-proxy-agent "^5.0.0" + "@sentry-internal/tracing" "7.108.0" + "@sentry/core" "7.108.0" + "@sentry/types" "7.108.0" + "@sentry/utils" "7.108.0" -"@sentry/react@7.91.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.91.0.tgz#620e6ce9452af025d2cc1b2eca3dd1dd730dc439" - integrity sha512-7JH2rWaX3WKHHvBcZQ4f/KnkYIXTf7hMojRFncUwPocdtDlhJw/JUvjAYNpEysixXIgsMes3B32lmtZjGjRhwQ== +"@sentry/react@7.108.0": + version "7.108.0" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.108.0.tgz#26a50324f6d7a9576f3753c099e7bcd8def94f3c" + integrity sha512-C60arh5/gtO42eMU9l34aWlKDLZUO+1j1goaEf/XRSwUcyJS9tbJrs+mT4nbKxUsEG714It2gRbfSEvh1eXmCg== dependencies: - "@sentry/browser" "7.91.0" - "@sentry/types" "7.91.0" - "@sentry/utils" "7.91.0" + "@sentry/browser" "7.108.0" + "@sentry/core" "7.108.0" + "@sentry/types" "7.108.0" + "@sentry/utils" "7.108.0" hoist-non-react-statics "^3.3.2" -"@sentry/replay@7.91.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.91.0.tgz#95077868aee3c3cc670affe13156434f858e1755" - integrity sha512-XwbesnLLNtaVXKtDoyBB96GxJuhGi9zy3a662Ba/McmumCnkXrMQYpQPh08U7MgkTyDRgjDwm7PXDhiKpcb03g== +"@sentry/replay@7.108.0": + version "7.108.0" + resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.108.0.tgz#baa679bd19b4e3729e607d3f84cff5048aeb3415" + integrity sha512-jo8fDOzcZJclP1+4n9jUtVxTlBFT9hXwxhAMrhrt70FV/nfmCtYQMD3bzIj79nwbhUtFP6pN39JH1o7Xqt1hxQ== dependencies: - "@sentry-internal/tracing" "7.91.0" - "@sentry/core" "7.91.0" - "@sentry/types" "7.91.0" - "@sentry/utils" "7.91.0" + "@sentry-internal/tracing" "7.108.0" + "@sentry/core" "7.108.0" + "@sentry/types" "7.108.0" + "@sentry/utils" "7.108.0" -"@sentry/types@7.91.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.91.0.tgz#5b68954e08986fecb0d4bef168df58eef62c32c7" - integrity sha512-bcQnb7J3P3equbCUc+sPuHog2Y47yGD2sCkzmnZBjvBT0Z1B4f36fI/5WjyZhTjLSiOdg3F2otwvikbMjmBDew== +"@sentry/types@7.108.0": + version "7.108.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.108.0.tgz#5ceb959c4dabe511fc441fec8c2465f2d624900f" + integrity sha512-bKtHITmBN3kqtqE5eVvL8mY8znM05vEodENwRpcm6TSrrBjC2RnwNWVwGstYDdHpNfFuKwC8mLY9bgMJcENo8g== -"@sentry/utils@7.91.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.91.0.tgz#3b1a94c053c885877908cd3e1365e3d23e21a73f" - integrity sha512-fvxjrEbk6T6Otu++Ax9ntlQ0sGRiwSC179w68aC3u26Wr30FAIRKqHTCCdc2jyWk7Gd9uWRT/cq+g8NG/8BfSg== +"@sentry/utils@7.108.0": + version "7.108.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.108.0.tgz#0231042956aed2ef35809891592238530349dfd9" + integrity sha512-a45yEFD5qtgZaIFRAcFkG8C8lnDzn6t4LfLXuV4OafGAy/3ZAN3XN8wDnrruHkiUezSSANGsLg3bXaLW/JLvJw== dependencies: - "@sentry/types" "7.91.0" + "@sentry/types" "7.108.0" -"@sentry/vercel-edge@7.91.0": - version "7.91.0" - resolved "https://registry.yarnpkg.com/@sentry/vercel-edge/-/vercel-edge-7.91.0.tgz#df67ee39d10570b71eccf831a181c064974d62b1" - integrity sha512-CounqhXPwFh67zf6L/q4ACBHHqknT6YY9LdgIAnUd0GGgHzrJPyKcthvh8Je4lNdpo5LFg2gnR+6g6JS8DDYDQ== +"@sentry/vercel-edge@7.108.0": + version "7.108.0" + resolved "https://registry.yarnpkg.com/@sentry/vercel-edge/-/vercel-edge-7.108.0.tgz#c5ca35094bc46029ec5a72f7ee09fd3705582baa" + integrity sha512-dUuUEswaVIzsJnzTfaJxrvkfOowrlJxxHo2AybPDym2rob7CdaLdDJIYJa83X7QeAKMkTgLny/gYSQYC0E4UyA== dependencies: - "@sentry-internal/tracing" "7.91.0" - "@sentry/core" "7.91.0" - "@sentry/types" "7.91.0" - "@sentry/utils" "7.91.0" + "@sentry-internal/tracing" "7.108.0" + "@sentry/core" "7.108.0" + "@sentry/types" "7.108.0" + "@sentry/utils" "7.108.0" "@sentry/webpack-plugin@1.21.0": version "1.21.0" From a1369311685bd00aa1173dfad1402e0c9ade7678 Mon Sep 17 00:00:00 2001 From: sriram veeraghanta Date: Tue, 26 Mar 2024 19:40:48 +0530 Subject: [PATCH 07/12] fix: codeql workflow push and pull request chanages --- .github/workflows/codeql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index a858bcc59..d7b94d245 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -3,7 +3,7 @@ name: "CodeQL" on: workflow_dispatch: push: - branches: ["master"] + branches: ["develop", "preview", "master"] pull_request: branches: ["develop", "preview", "master"] schedule: From f3d9053d81727a2e5a2a13659d2dd7546de42425 Mon Sep 17 00:00:00 2001 From: sriram veeraghanta Date: Tue, 26 Mar 2024 19:43:22 +0530 Subject: [PATCH 08/12] fix: unsafe external link fixes --- .../invitations/project_invitation.html | 2146 ++++++++++++++--- 1 file changed, 1806 insertions(+), 340 deletions(-) diff --git a/apiserver/templates/emails/invitations/project_invitation.html b/apiserver/templates/emails/invitations/project_invitation.html index 630a5eab3..def576601 100644 --- a/apiserver/templates/emails/invitations/project_invitation.html +++ b/apiserver/templates/emails/invitations/project_invitation.html @@ -1,349 +1,1815 @@ - - - - - - - {{ first_name }} invited you to join {{ project_name }} on Plane - - - - - - - - + + + + - - - - - - + + + + + + From 4c46b075b44480a87e2ec8ce7fc20fcb6dda0506 Mon Sep 17 00:00:00 2001 From: Nikhil <118773738+pablohashescobar@users.noreply.github.com> Date: Tue, 26 Mar 2024 19:48:52 +0530 Subject: [PATCH 09/12] fix: module endpoint validations (#4071) --- apiserver/plane/app/views/module/base.py | 75 ++++++++++--------- .../plane/app/views/workspace/estimate.py | 9 +-- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/apiserver/plane/app/views/module/base.py b/apiserver/plane/app/views/module/base.py index 7769aee3f..3fe3a078a 100644 --- a/apiserver/plane/app/views/module/base.py +++ b/apiserver/plane/app/views/module/base.py @@ -1,54 +1,57 @@ # Python imports 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.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 +# Django Imports +from django.utils import timezone +from rest_framework import status + # Third party imports 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 ( ProjectEntityPermission, ProjectLitePermission, ) -from plane.db.models import ( - Module, - ModuleIssue, - Project, - Issue, - ModuleLink, - ModuleFavorite, - ModuleUserProperties, +from plane.app.serializers import ( + ModuleDetailSerializer, + ModuleFavoriteSerializer, + ModuleLinkSerializer, + ModuleSerializer, + ModuleUserPropertiesSerializer, + ModuleWriteSerializer, ) 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 +# Module imports +from .. import BaseAPIView, BaseViewSet, WebhookMixin + class ModuleViewSet(WebhookMixin, BaseViewSet): model = Module @@ -392,9 +395,11 @@ class ModuleViewSet(WebhookMixin, BaseViewSet): "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( - queryset=queryset.first(), + queryset=modules, slug=slug, project_id=project_id, module_id=pk, diff --git a/apiserver/plane/app/views/workspace/estimate.py b/apiserver/plane/app/views/workspace/estimate.py index 8ca24efd7..59a23d867 100644 --- a/apiserver/plane/app/views/workspace/estimate.py +++ b/apiserver/plane/app/views/workspace/estimate.py @@ -3,15 +3,10 @@ from rest_framework import status from rest_framework.response import Response # Module imports +from plane.app.permissions import WorkspaceEntityPermission from plane.app.serializers import WorkspaceEstimateSerializer from plane.app.views.base import BaseAPIView -from plane.db.models import Project, Estimate -from plane.app.permissions import WorkspaceEntityPermission - -# Django imports -from django.db.models import ( - Prefetch, -) +from plane.db.models import Estimate, Project from plane.utils.cache import cache_response From 30cee781702a4354ad1fd44d5e23a74e26d380b1 Mon Sep 17 00:00:00 2001 From: Nikhil <118773738+pablohashescobar@users.noreply.github.com> Date: Tue, 26 Mar 2024 20:38:25 +0530 Subject: [PATCH 10/12] dev: fix api security error (#4072) --- apiserver/plane/api/serializers/issue.py | 31 ++++++++++++------------ 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/apiserver/plane/api/serializers/issue.py b/apiserver/plane/api/serializers/issue.py index b8f194b32..c78b109ef 100644 --- a/apiserver/plane/api/serializers/issue.py +++ b/apiserver/plane/api/serializers/issue.py @@ -1,32 +1,33 @@ -from lxml import html +from django.core.exceptions import ValidationError +from django.core.validators import URLValidator # Django imports from django.utils import timezone -from django.core.validators import URLValidator -from django.core.exceptions import ValidationError +from lxml import html # Third party imports from rest_framework import serializers # Module imports from plane.db.models import ( - User, Issue, - State, + IssueActivity, IssueAssignee, - Label, + IssueAttachment, + IssueComment, IssueLabel, IssueLink, - IssueComment, - IssueAttachment, - IssueActivity, + Label, ProjectMember, + State, + User, ) + from .base import BaseSerializer -from .cycle import CycleSerializer, CycleLiteSerializer -from .module import ModuleSerializer, ModuleLiteSerializer -from .user import UserLiteSerializer +from .cycle import CycleLiteSerializer, CycleSerializer +from .module import ModuleLiteSerializer, ModuleSerializer from .state import StateLiteSerializer +from .user import UserLiteSerializer class IssueSerializer(BaseSerializer): @@ -79,7 +80,7 @@ class IssueSerializer(BaseSerializer): data["description_html"] = parsed_str except Exception as e: - raise serializers.ValidationError(f"Invalid HTML: {str(e)}") + raise serializers.ValidationError("Invalid HTML passed") # Validate assignees are from project if data.get("assignees", []): @@ -294,7 +295,7 @@ class IssueLinkSerializer(BaseSerializer): raise serializers.ValidationError("Invalid URL format.") # Check URL scheme - if not value.startswith(('http://', 'https://')): + if not value.startswith(("http://", "https://")): raise serializers.ValidationError("Invalid URL scheme.") return value @@ -366,7 +367,7 @@ class IssueCommentSerializer(BaseSerializer): data["comment_html"] = parsed_str except Exception as e: - raise serializers.ValidationError(f"Invalid HTML: {str(e)}") + raise serializers.ValidationError("Invalid HTML passed") return data From 9249e6d5b9e66f28603b1e440104a91df87cac20 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Tue, 26 Mar 2024 20:38:54 +0530 Subject: [PATCH 11/12] [WEB-849] fix: issue detail identifier and workspace settings (#4073) * fix: issue detail identifier * fix: workspace settings user role validation --- web/components/issues/issue-update-status.tsx | 5 +++-- web/layouts/settings-layout/workspace/sidebar.tsx | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/web/components/issues/issue-update-status.tsx b/web/components/issues/issue-update-status.tsx index 277404dfa..a3a8ca83b 100644 --- a/web/components/issues/issue-update-status.tsx +++ b/web/components/issues/issue-update-status.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { observer } from "mobx-react"; import { RefreshCw } from "lucide-react"; import { TIssue } from "@plane/types"; // types @@ -9,7 +10,7 @@ type Props = { issueDetail?: TIssue; }; -export const IssueUpdateStatus: React.FC = (props) => { +export const IssueUpdateStatus: React.FC = observer((props) => { const { isSubmitting, issueDetail } = props; // hooks const { getProjectById } = useProject(); @@ -33,4 +34,4 @@ export const IssueUpdateStatus: React.FC = (props) => { ); -}; +}); diff --git a/web/layouts/settings-layout/workspace/sidebar.tsx b/web/layouts/settings-layout/workspace/sidebar.tsx index d6cb77cf9..f49eb84d9 100644 --- a/web/layouts/settings-layout/workspace/sidebar.tsx +++ b/web/layouts/settings-layout/workspace/sidebar.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { observer } from "mobx-react"; import Link from "next/link"; import { useRouter } from "next/router"; // hooks @@ -6,7 +7,7 @@ import { EUserWorkspaceRoles, WORKSPACE_SETTINGS_LINKS } from "@/constants/works import { useUser } from "@/hooks/store"; // constants -export const WorkspaceSettingsSidebar = () => { +export const WorkspaceSettingsSidebar = observer(() => { // router const router = useRouter(); const { workspaceSlug } = router.query; @@ -44,4 +45,4 @@ export const WorkspaceSettingsSidebar = () => { ); -}; +}); From 4b56cc55653474bc5415e84e7a2277a77880cd2f Mon Sep 17 00:00:00 2001 From: Palanikannan1437 <73993394+Palanikannan1437@users.noreply.github.com> Date: Wed, 27 Mar 2024 17:07:05 +0530 Subject: [PATCH 12/12] feat: list autojoining added --- .../list-helpers/handle-backspace.ts | 32 +++++-- .../list-helpers/list-item-has-sub-list.ts | 21 +++++ .../editor/core/src/ui/extensions/index.tsx | 6 +- .../editor/core/src/ui/extensions/keymap.tsx | 84 +++++++++++++++++++ .../core/src/ui/read-only/extensions.tsx | 6 +- 5 files changed, 134 insertions(+), 15 deletions(-) create mode 100644 packages/editor/core/src/ui/extensions/custom-list-keymap/list-helpers/list-item-has-sub-list.ts diff --git a/packages/editor/core/src/ui/extensions/custom-list-keymap/list-helpers/handle-backspace.ts b/packages/editor/core/src/ui/extensions/custom-list-keymap/list-helpers/handle-backspace.ts index a4f2d5db9..885169aab 100644 --- a/packages/editor/core/src/ui/extensions/custom-list-keymap/list-helpers/handle-backspace.ts +++ b/packages/editor/core/src/ui/extensions/custom-list-keymap/list-helpers/handle-backspace.ts @@ -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 { 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[]) => { // this is required to still handle the undo handling if (editor.commands.undoInputRule()) { 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 & // the previous item is a list (orderedList or bulletList) // 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; } + // 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); if (!listItemPos) { return false; } - // if current node is a list item and cursor it at start of a list node, - // simply lift the list item i.e. remove it as a list item (task/bullet/ordered) - // irrespective of above node being a list or not + const $prev = editor.state.doc.resolve(listItemPos.$pos.pos - 2); + const prevNode = $prev.node(listItemPos.depth); + + 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(); }; diff --git a/packages/editor/core/src/ui/extensions/custom-list-keymap/list-helpers/list-item-has-sub-list.ts b/packages/editor/core/src/ui/extensions/custom-list-keymap/list-helpers/list-item-has-sub-list.ts new file mode 100644 index 000000000..5c15a2b63 --- /dev/null +++ b/packages/editor/core/src/ui/extensions/custom-list-keymap/list-helpers/list-item-has-sub-list.ts @@ -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; +}; diff --git a/packages/editor/core/src/ui/extensions/index.tsx b/packages/editor/core/src/ui/extensions/index.tsx index 1a932d6d5..9b43875f9 100644 --- a/packages/editor/core/src/ui/extensions/index.tsx +++ b/packages/editor/core/src/ui/extensions/index.tsx @@ -41,12 +41,12 @@ export const CoreEditorExtensions = ( StarterKit.configure({ bulletList: { HTMLAttributes: { - class: "list-disc list-outside leading-3 -mt-2", + class: "list-disc list-outside leading-3", }, }, orderedList: { HTMLAttributes: { - class: "list-decimal list-outside leading-3 -mt-2", + class: "list-decimal list-outside leading-3 -mt-2 -mb-2", }, }, listItem: { @@ -98,7 +98,7 @@ export const CoreEditorExtensions = ( }), TaskItem.configure({ HTMLAttributes: { - class: "flex items-start my-4", + class: "flex items-start mt-4", }, nested: true, }), diff --git a/packages/editor/core/src/ui/extensions/keymap.tsx b/packages/editor/core/src/ui/extensions/keymap.tsx index 0caa194cd..2e0bdd1fe 100644 --- a/packages/editor/core/src/ui/extensions/keymap.tsx +++ b/packages/editor/core/src/ui/extensions/keymap.tsx @@ -1,4 +1,7 @@ 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" { // 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 = []; + 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({ 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() { return { "Mod-a": ({ editor }) => { diff --git a/packages/editor/core/src/ui/read-only/extensions.tsx b/packages/editor/core/src/ui/read-only/extensions.tsx index 93e1b3887..81af5c523 100644 --- a/packages/editor/core/src/ui/read-only/extensions.tsx +++ b/packages/editor/core/src/ui/read-only/extensions.tsx @@ -29,12 +29,12 @@ export const CoreReadOnlyEditorExtensions = (mentionConfig: { StarterKit.configure({ bulletList: { HTMLAttributes: { - class: "list-disc list-outside leading-3 -mt-2", + class: "list-disc list-outside leading-3", }, }, orderedList: { HTMLAttributes: { - class: "list-decimal list-outside leading-3 -mt-2", + class: "list-decimal list-outside leading-3 -mt-2 -mb-2", }, }, listItem: { @@ -82,7 +82,7 @@ export const CoreReadOnlyEditorExtensions = (mentionConfig: { }), TaskItem.configure({ HTMLAttributes: { - class: "flex items-start my-4", + class: "flex items-start mt-4", }, nested: true, }),