diff --git a/apiserver/plane/app/views/project/base.py b/apiserver/plane/app/views/project/base.py index 3ca03446797..9095e4e3be2 100644 --- a/apiserver/plane/app/views/project/base.py +++ b/apiserver/plane/app/views/project/base.py @@ -413,20 +413,9 @@ def create(self, request, slug): status=status.HTTP_410_GONE, ) + @allow_permission([ROLE.ADMIN]) def partial_update(self, request, slug, pk=None): try: - if not ProjectMember.objects.filter( - member=request.user, - workspace__slug=slug, - project_id=pk, - role=20, - is_active=True, - ).exists(): - return Response( - {"error": "You don't have the required permissions."}, - status=status.HTTP_403_FORBIDDEN, - ) - workspace = Workspace.objects.get(slug=slug) project = Project.objects.get(pk=pk) diff --git a/web/core/components/issues/issue-layouts/calendar/quick-add-issue-actions.tsx b/web/core/components/issues/issue-layouts/calendar/quick-add-issue-actions.tsx index a7a0a5c0acb..9fa0d4cf329 100644 --- a/web/core/components/issues/issue-layouts/calendar/quick-add-issue-actions.tsx +++ b/web/core/components/issues/issue-layouts/calendar/quick-add-issue-actions.tsx @@ -8,7 +8,7 @@ import { PlusIcon } from "lucide-react"; // types import { ISearchIssueResponse, TIssue } from "@plane/types"; // ui -import { TOAST_TYPE, setToast, CustomMenu } from "@plane/ui"; +import { CustomMenu, setPromiseToast } from "@plane/ui"; // components import { ExistingIssuesListModal } from "@/components/core"; import { QuickAddIssueRoot } from "@/components/issues"; @@ -45,22 +45,21 @@ export const CalendarQuickAddIssueActions: FC = o if (!workspaceSlug || !projectId) return; const issueIds = data.map((i) => i.id); + const updatePromise = Promise.all( + data.map((issue) => updateIssue(workspaceSlug.toString(), projectId.toString(), issue.id, prePopulatedData ?? {})) + ).then(() => addIssuesToView?.(issueIds)); - try { - // To handle all updates in parallel - await Promise.all( - data.map((issue) => - updateIssue(workspaceSlug.toString(), projectId.toString(), issue.id, prePopulatedData ?? {}) - ) - ); - await addIssuesToView?.(issueIds); - } catch (error) { - setToast({ - type: TOAST_TYPE.ERROR, + setPromiseToast(updatePromise, { + loading: `Adding ${issueIds.length > 1 ? "issues" : "issue"} to cycle...`, + success: { + title: "Success!", + message: () => `${issueIds.length > 1 ? "Issues" : "Issue"} added to cycle successfully.`, + }, + error: { title: "Error!", - message: "Something went wrong. Please try again.", - }); - } + message: (err) => err?.message || "Something went wrong. Please try again.", + }, + }); }; const handleNewIssue = () => { diff --git a/web/helpers/string.helper.ts b/web/helpers/string.helper.ts index e4b4dc6651e..1182feeb0a7 100644 --- a/web/helpers/string.helper.ts +++ b/web/helpers/string.helper.ts @@ -270,7 +270,7 @@ export const isCommentEmpty = (comment: string | undefined): boolean => { export const checkURLValidity = (url: string): boolean => { if (!url) return false; // regex to match valid URLs (with or without http/https) - const urlPattern = /^(https?:\/\/)?([\w.-]+\.[a-z]{2,6})(\/[\w\-.~:/?#[\]@!$&'()*+,;=%]*)?$/i; + const urlPattern = /^(https?:\/\/)?([\da-z.-]+)\.([a-z]{2,6})(\/[\w.-]*)*\/?(\?[=&\w.-]*)?$/i; // test if the URL matches the pattern return urlPattern.test(url); };