From ad8a011bb9ff7938e787c3024ac5d93b5f4bd446 Mon Sep 17 00:00:00 2001 From: Dakshesh Jain <65905942+dakshesh14@users.noreply.github.com> Date: Mon, 11 Sep 2023 11:44:16 +0530 Subject: [PATCH 01/11] fix: issue activity (#2127) --- web/components/web-view/activity-message.tsx | 419 ++++++++++++++++++ web/components/web-view/index.ts | 1 + web/components/web-view/issue-activity.tsx | 21 +- .../web-view/issue-web-view-form.tsx | 2 +- web/components/web-view/web-view-modal.tsx | 2 +- web/layouts/web-view-layout/index.tsx | 5 +- 6 files changed, 435 insertions(+), 15 deletions(-) create mode 100644 web/components/web-view/activity-message.tsx diff --git a/web/components/web-view/activity-message.tsx b/web/components/web-view/activity-message.tsx new file mode 100644 index 000000000..956dfb904 --- /dev/null +++ b/web/components/web-view/activity-message.tsx @@ -0,0 +1,419 @@ +import { useRouter } from "next/router"; + +// icons +import { Icon, Tooltip } from "components/ui"; +import { Squares2X2Icon } from "@heroicons/react/24/outline"; +import { BlockedIcon, BlockerIcon } from "components/icons"; +// helpers +import { renderShortDateWithYearFormat } from "helpers/date-time.helper"; +import { capitalizeFirstLetter } from "helpers/string.helper"; +// types +import { IIssueActivity } from "types"; + +const IssueLink = ({ activity }: { activity: IIssueActivity }) => ( + + + console.log( + "issue", + JSON.stringify({ + project_id: activity.project, + issue_id: activity.issue, + }) + ) + } + className="font-medium text-custom-text-100 inline-flex items-center gap-1 hover:underline" + > + {activity.issue_detail + ? `${activity.project_detail.identifier}-${activity.issue_detail.sequence_id}` + : "Issue"} + + + +); + +const UserLink = ({ activity }: { activity: IIssueActivity }) => ( + { + console.log("user", activity.actor); + }} + className="font-medium text-custom-text-100 inline-flex items-center hover:underline" + > + {activity.new_value && activity.new_value !== "" ? activity.new_value : activity.old_value} + +); + +const activityDetails: { + [key: string]: { + message: ( + activity: IIssueActivity, + showIssue: boolean, + workspaceSlug: string + ) => React.ReactNode; + icon: React.ReactNode; + }; +} = { + assignees: { + message: (activity, showIssue) => ( + <> + {activity.old_value === "" ? "added a new assignee " : "removed the assignee "} + + {showIssue && ( + <> + {" "} + to + > + )} + . + > + ), + icon: , + }, + + archived_at: { + message: (activity) => { + if (activity.new_value === "restore") return "restored the issue."; + else return "archived the issue."; + }, + icon: , + }, + + attachment: { + message: (activity, showIssue) => ( + <> + {activity.verb === "created" ? "uploaded a new " : "removed an "} + {activity.new_value && activity.new_value !== "" ? ( + console.log("attachment", activity.new_value)}> + attachment + + ) : ( + "attachment" + )} + {showIssue && activity.verb === "created" ? " to " : " from "} + {showIssue && } + > + ), + icon: , + }, + + blocking: { + message: (activity) => ( + <> + {activity.old_value === "" + ? "marked this issue is blocking issue " + : "removed the blocking issue "} + + {activity.old_value === "" ? activity.new_value : activity.old_value} + + . + > + ), + icon: , + }, + + blocks: { + message: (activity) => ( + <> + {activity.old_value === "" + ? "marked this issue is being blocked by issue " + : "removed this issue being blocked by issue "} + + {activity.old_value === "" ? activity.new_value : activity.old_value} + + . + > + ), + icon: , + }, + + cycles: { + message: (activity) => ( + <> + {activity.verb === "created" && "added this issue to the cycle "} + {activity.verb === "updated" && "set the cycle to "} + {activity.verb === "deleted" && "removed the issue from the cycle "} + + console.log( + "cycle", + JSON.stringify({ + cycle_id: activity.new_identifier, + project_id: activity.project, + }) + ) + } + className="font-medium text-custom-text-100 inline-flex items-center gap-1 hover:underline" + > + {activity.new_value} + + + > + ), + icon: , + }, + + description: { + message: (activity, showIssue) => ( + <> + updated the description + {showIssue && ( + <> + {" "} + of + > + )} + . + > + ), + icon: , + }, + + estimate_point: { + message: (activity, showIssue) => ( + <> + {activity.new_value ? "set the estimate point to " : "removed the estimate point "} + {activity.new_value && ( + {activity.new_value} + )} + {showIssue && ( + <> + {" "} + for + > + )} + > + ), + icon: , + }, + + issue: { + message: (activity) => { + if (activity.verb === "created") return "created the issue."; + else return "deleted an issue."; + }, + icon: , + }, + + labels: { + message: (activity, showIssue) => ( + <> + {activity.old_value === "" ? "added a new label " : "removed the label "} + + + + {activity.old_value === "" ? activity.new_value : activity.old_value} + + + {showIssue && ( + <> + {" "} + to + > + )} + > + ), + icon: , + }, + + link: { + message: (activity, showIssue) => ( + <> + {activity.verb === "created" && "added this "} + {activity.verb === "updated" && "updated this "} + {activity.verb === "deleted" && "removed this "} + + console.log( + "link", + activity.verb === "created" ? activity.new_value : activity.old_value + ) + } + className="font-medium text-custom-text-100 inline-flex items-center gap-1 hover:underline" + > + link + + + {showIssue && ( + <> + {" "} + to + > + )} + . + > + ), + icon: , + }, + + modules: { + message: (activity) => ( + <> + {activity.verb === "created" && "added this "} + {activity.verb === "updated" && "updated this "} + {activity.verb === "deleted" && "removed this "} + + console.log( + "module", + activity.verb === "created" ? activity.new_value : activity.old_value + ) + } + className="font-medium text-custom-text-100 inline-flex items-center gap-1 hover:underline" + > + module + + + . + > + ), + icon: , + }, + + name: { + message: (activity, showIssue) => ( + <> + set the name to {activity.new_value} + {showIssue && ( + <> + {" "} + of + > + )} + . + > + ), + icon: , + }, + + parent: { + message: (activity, showIssue) => ( + <> + {activity.new_value ? "set the parent to " : "removed the parent "} + + {activity.new_value ? activity.new_value : activity.old_value} + + {showIssue && ( + <> + {" "} + for + > + )} + . + > + ), + icon: , + }, + + priority: { + message: (activity, showIssue) => ( + <> + set the priority to{" "} + + {activity.new_value ? capitalizeFirstLetter(activity.new_value) : "None"} + + {showIssue && ( + <> + {" "} + for + > + )} + . + > + ), + icon: , + }, + + start_date: { + message: (activity, showIssue) => ( + <> + {activity.new_value ? "set the start date to " : "removed the start date "} + + {activity.new_value ? renderShortDateWithYearFormat(activity.new_value) : "None"} + + {showIssue && ( + <> + {" "} + for + > + )} + > + ), + icon: , + }, + + state: { + message: (activity, showIssue) => ( + <> + set the state to{" "} + {activity.new_value} + {showIssue && ( + <> + {" "} + for + > + )} + . + > + ), + icon: , + }, + + target_date: { + message: (activity, showIssue) => ( + <> + {activity.new_value ? "set the target date to " : "removed the target date "} + {activity.new_value && ( + + {renderShortDateWithYearFormat(activity.new_value)} + + )} + + {showIssue && ( + <> + {" "} + for + > + )} + > + ), + icon: , + }, +}; + +export const ActivityIcon = ({ activity }: { activity: IIssueActivity }) => ( + <>{activityDetails[activity.field as keyof typeof activityDetails]?.icon}> +); + +export const ActivityMessage = ({ + activity, + showIssue = false, +}: { + activity: IIssueActivity; + showIssue?: boolean; +}) => { + const router = useRouter(); + const { workspaceSlug } = router.query; + + return ( + <> + {activityDetails[activity.field as keyof typeof activityDetails]?.message( + activity, + showIssue, + workspaceSlug?.toString() ?? "" + )} + > + ); +}; diff --git a/web/components/web-view/index.ts b/web/components/web-view/index.ts index 342bc4838..915c891a9 100644 --- a/web/components/web-view/index.ts +++ b/web/components/web-view/index.ts @@ -15,3 +15,4 @@ export * from "./add-comment"; export * from "./select-parent"; export * from "./select-blocker"; export * from "./select-blocked"; +export * from "./activity-message"; diff --git a/web/components/web-view/issue-activity.tsx b/web/components/web-view/issue-activity.tsx index 55089d60d..4bd13eb5c 100644 --- a/web/components/web-view/issue-activity.tsx +++ b/web/components/web-view/issue-activity.tsx @@ -2,7 +2,6 @@ import React from "react"; // next -import Link from "next/link"; import { useRouter } from "next/router"; // swr @@ -16,12 +15,10 @@ import issuesService from "services/issues.service"; // hooks import useUser from "hooks/use-user"; -import useToast from "hooks/use-toast"; // components -import { Label, AddComment } from "components/web-view"; import { CommentCard } from "components/issues/comment"; -import { ActivityIcon, ActivityMessage } from "components/core"; +import { Label, AddComment, ActivityMessage, ActivityIcon } from "components/web-view"; // helpers import { timeAgo } from "helpers/date-time.helper"; @@ -183,15 +180,15 @@ export const IssueActivity: React.FC = (props) => { {activityItem.actor_detail.first_name} Bot ) : ( - console.log("user", activityItem.actor)} > - - {activityItem.actor_detail.is_bot - ? activityItem.actor_detail.first_name - : activityItem.actor_detail.display_name} - - + {activityItem.actor_detail.is_bot + ? activityItem.actor_detail.first_name + : activityItem.actor_detail.display_name} + )}{" "} {message}{" "} diff --git a/web/components/web-view/issue-web-view-form.tsx b/web/components/web-view/issue-web-view-form.tsx index 863464764..ff9383fd0 100644 --- a/web/components/web-view/issue-web-view-form.tsx +++ b/web/components/web-view/issue-web-view-form.tsx @@ -90,7 +90,7 @@ export const IssueWebViewForm: React.FC = (props) => { debouncedTitleSave(); }} required={true} - className="min-h-10 block w-full resize-none overflow-hidden rounded border-none bg-transparent px-3 py-2 text-xl outline-none ring-0 focus:ring-1 focus:ring-custom-primary" + className="min-h-10 block w-full resize-none overflow-hidden rounded border bg-transparent px-3 py-2 text-xl outline-none ring-0 focus:ring-1 focus:ring-custom-primary" role="textbox" disabled={!isAllowed} /> diff --git a/web/components/web-view/web-view-modal.tsx b/web/components/web-view/web-view-modal.tsx index 2be28a01c..39769dfcd 100644 --- a/web/components/web-view/web-view-modal.tsx +++ b/web/components/web-view/web-view-modal.tsx @@ -63,7 +63,7 @@ export const WebViewModal = (props: Props) => { - {children} + {children} diff --git a/web/layouts/web-view-layout/index.tsx b/web/layouts/web-view-layout/index.tsx index c5afdcc3d..2fb46b9df 100644 --- a/web/layouts/web-view-layout/index.tsx +++ b/web/layouts/web-view-layout/index.tsx @@ -18,7 +18,10 @@ type Props = { }; const getIfInWebview = (userAgent: NavigatorID["userAgent"]) => { - if (/iphone|ipod|ipad/.test(userAgent) || userAgent.includes("wv")) return true; + const safari = /safari/.test(userAgent); + + if (safari) return false; + else if (/iphone|ipod|ipad/.test(userAgent) || userAgent.includes("wv")) return true; else return false; }; From 5b228bd1eb85a86800756e60e92fd325cb309c26 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Mon, 11 Sep 2023 11:45:28 +0530 Subject: [PATCH 02/11] chore: update state icons and colors (#2126) * chore: update state icons and colors * chore: update icons --- .../issues/peek-overview/issue-properties.tsx | 1 - .../analytics/scope-and-demand/demand.tsx | 6 +- .../automation/auto-close-automation.tsx | 23 +++--- .../issue/change-issue-state.tsx | 23 ++++-- web/components/core/filters/filters-list.tsx | 16 ++-- .../core/sidebar/sidebar-progress-stats.tsx | 3 +- .../core/views/board-view/all-boards.tsx | 12 ++- .../core/views/board-view/board-header.tsx | 25 ++++-- .../core/views/list-view/single-list.tsx | 24 +++++- .../cycles/active-cycle-details.tsx | 6 +- web/components/icons/backlog-state-icon.tsx | 21 ----- web/components/icons/cancelled-state-icon.tsx | 78 ------------------- web/components/icons/completed-state-icon.tsx | 69 ---------------- web/components/icons/index.ts | 10 +-- web/components/icons/started-state-icon.tsx | 77 ------------------ web/components/icons/state-group-icon.tsx | 66 ---------------- web/components/icons/state/backlog.tsx | 24 ++++++ web/components/icons/state/cancelled.tsx | 34 ++++++++ web/components/icons/state/completed.tsx | 27 +++++++ web/components/icons/state/index.ts | 6 ++ web/components/icons/state/started.tsx | 25 ++++++ .../icons/state/state-group-icon.tsx | 74 ++++++++++++++++++ web/components/icons/state/unstarted.tsx | 24 ++++++ web/components/icons/unstarted-state-icon.tsx | 59 -------------- web/components/issues/gantt-chart/blocks.tsx | 4 +- .../my-issues/my-issues-select-filters.tsx | 6 +- .../issues/peek-overview/issue-properties.tsx | 7 +- web/components/issues/select/state.tsx | 11 ++- .../issues/sidebar-select/state.tsx | 13 +--- web/components/issues/view-select/state.tsx | 9 ++- web/components/states/single-state.tsx | 4 +- web/components/views/select-filters.tsx | 5 +- web/components/web-view/select-state.tsx | 4 +- web/components/workspace/issues-pie-chart.tsx | 6 +- web/constants/state.ts | 4 +- web/helpers/analytics.helper.ts | 5 +- 36 files changed, 351 insertions(+), 460 deletions(-) delete mode 100644 web/components/icons/backlog-state-icon.tsx delete mode 100644 web/components/icons/cancelled-state-icon.tsx delete mode 100644 web/components/icons/completed-state-icon.tsx delete mode 100644 web/components/icons/started-state-icon.tsx delete mode 100644 web/components/icons/state-group-icon.tsx create mode 100644 web/components/icons/state/backlog.tsx create mode 100644 web/components/icons/state/cancelled.tsx create mode 100644 web/components/icons/state/completed.tsx create mode 100644 web/components/icons/state/index.ts create mode 100644 web/components/icons/state/started.tsx create mode 100644 web/components/icons/state/state-group-icon.tsx create mode 100644 web/components/icons/state/unstarted.tsx delete mode 100644 web/components/icons/unstarted-state-icon.tsx diff --git a/space/components/issues/peek-overview/issue-properties.tsx b/space/components/issues/peek-overview/issue-properties.tsx index c7a08faed..f7ccab18f 100644 --- a/space/components/issues/peek-overview/issue-properties.tsx +++ b/space/components/issues/peek-overview/issue-properties.tsx @@ -44,7 +44,6 @@ export const PeekOverviewIssueProperties: React.FC = ({ issueDetails, mod {mode === "full" && ( - {/* {getStateGroupIcon(issue.state_detail.group, "16", "16", issue.state_detail.color)} */} {issueDetails.project_detail.identifier}-{issueDetails.sequence_id} diff --git a/web/components/analytics/scope-and-demand/demand.tsx b/web/components/analytics/scope-and-demand/demand.tsx index ad3781247..23af2b384 100644 --- a/web/components/analytics/scope-and-demand/demand.tsx +++ b/web/components/analytics/scope-and-demand/demand.tsx @@ -1,7 +1,7 @@ // icons import { PlayIcon } from "@heroicons/react/24/outline"; // types -import { IDefaultAnalyticsResponse } from "types"; +import { IDefaultAnalyticsResponse, TStateGroups } from "types"; // constants import { STATE_GROUP_COLORS } from "constants/state"; @@ -27,7 +27,7 @@ export const AnalyticsDemand: React.FC = ({ defaultAnalytics }) => ( {group.state_group} @@ -42,7 +42,7 @@ export const AnalyticsDemand: React.FC = ({ defaultAnalytics }) => ( className="absolute top-0 left-0 h-1 rounded duration-300" style={{ width: `${percentage}%`, - backgroundColor: STATE_GROUP_COLORS[group.state_group], + backgroundColor: STATE_GROUP_COLORS[group.state_group as TStateGroups], }} /> diff --git a/web/components/automation/auto-close-automation.tsx b/web/components/automation/auto-close-automation.tsx index 3e71b8329..ad65714aa 100644 --- a/web/components/automation/auto-close-automation.tsx +++ b/web/components/automation/auto-close-automation.tsx @@ -9,7 +9,7 @@ import { CustomSearchSelect, CustomSelect, ToggleSwitch } from "components/ui"; import { SelectMonthModal } from "components/automation"; // icons import { ChevronDownIcon, Squares2X2Icon } from "@heroicons/react/24/outline"; -import { getStateGroupIcon } from "components/icons"; +import { StateGroupIcon } from "components/icons"; // services import stateService from "services/state.service"; // constants @@ -46,7 +46,7 @@ export const AutoCloseAutomation: React.FC = ({ projectDetails, handleCha query: state.name, content: ( - {getStateGroupIcon(state.group, "16", "16", state.color)} + {state.name} ), @@ -140,14 +140,19 @@ export const AutoCloseAutomation: React.FC = ({ projectDetails, handleCha label={ {selectedOption ? ( - getStateGroupIcon(selectedOption.group, "16", "16", selectedOption.color) + ) : currentDefaultState ? ( - getStateGroupIcon( - currentDefaultState.group, - "16", - "16", - currentDefaultState.color - ) + ) : ( )} diff --git a/web/components/command-palette/issue/change-issue-state.tsx b/web/components/command-palette/issue/change-issue-state.tsx index 30e2cdb77..6bfc2874c 100644 --- a/web/components/command-palette/issue/change-issue-state.tsx +++ b/web/components/command-palette/issue/change-issue-state.tsx @@ -1,22 +1,24 @@ -import { useRouter } from "next/router"; import React, { Dispatch, SetStateAction, useCallback } from "react"; + +import { useRouter } from "next/router"; + import useSWR, { mutate } from "swr"; // cmdk import { Command } from "cmdk"; -// ui -import { Spinner } from "components/ui"; -// helpers -import { getStatesList } from "helpers/state.helper"; // services import issuesService from "services/issues.service"; import stateService from "services/state.service"; +// ui +import { Spinner } from "components/ui"; +// icons +import { CheckIcon, StateGroupIcon } from "components/icons"; +// helpers +import { getStatesList } from "helpers/state.helper"; // types import { ICurrentUserResponse, IIssue } from "types"; // fetch keys import { ISSUE_DETAILS, PROJECT_ISSUES_ACTIVITY, STATES_LIST } from "constants/fetch-keys"; -// icons -import { CheckIcon, getStateGroupIcon } from "components/icons"; type Props = { setIsPaletteOpen: Dispatch>; @@ -82,7 +84,12 @@ export const ChangeIssueState: React.FC = ({ setIsPaletteOpen, issue, use className="focus:outline-none" > - {getStateGroupIcon(state.group, "16", "16", state.color)} + {state.name} {state.id === issue.state && } diff --git a/web/components/core/filters/filters-list.tsx b/web/components/core/filters/filters-list.tsx index 8192bdf7d..10cd623f8 100644 --- a/web/components/core/filters/filters-list.tsx +++ b/web/components/core/filters/filters-list.tsx @@ -2,7 +2,7 @@ import React from "react"; // icons import { XMarkIcon } from "@heroicons/react/24/outline"; -import { getPriorityIcon, getStateGroupIcon } from "components/icons"; +import { getPriorityIcon, StateGroupIcon } from "components/icons"; // ui import { Avatar } from "components/ui"; // helpers @@ -71,12 +71,10 @@ export const FiltersList: React.FC = ({ }} > - {getStateGroupIcon( - state?.group ?? "backlog", - "12", - "12", - state?.color - )} + {state?.name ?? ""} = ({ backgroundColor: `${STATE_GROUP_COLORS[group]}20`, }} > - {getStateGroupIcon(group, "16", "16")} + + + {group} = ({ {group} diff --git a/web/components/core/views/board-view/all-boards.tsx b/web/components/core/views/board-view/all-boards.tsx index 2637e7c33..ea0f64ace 100644 --- a/web/components/core/views/board-view/all-boards.tsx +++ b/web/components/core/views/board-view/all-boards.tsx @@ -1,7 +1,7 @@ // components import { SingleBoard } from "components/core/views/board-view/single-board"; // icons -import { getStateGroupIcon } from "components/icons"; +import { StateGroupIcon } from "components/icons"; // helpers import { addSpaceIfCamelCase } from "helpers/string.helper"; // types @@ -82,8 +82,14 @@ export const AllBoards: React.FC = ({ className="flex items-center justify-between gap-2 rounded bg-custom-background-90 p-2 shadow" > - {currentState && - getStateGroupIcon(currentState.group, "16", "16", currentState.color)} + {currentState && ( + + )} {selectedGroup === "state" ? addSpaceIfCamelCase(currentState?.name ?? "") diff --git a/web/components/core/views/board-view/board-header.tsx b/web/components/core/views/board-view/board-header.tsx index 5392774d9..a1c2804b6 100644 --- a/web/components/core/views/board-view/board-header.tsx +++ b/web/components/core/views/board-view/board-header.tsx @@ -13,14 +13,16 @@ import useProjects from "hooks/use-projects"; import { Avatar, Icon } from "components/ui"; // icons import { PlusIcon } from "@heroicons/react/24/outline"; -import { getPriorityIcon, getStateGroupIcon } from "components/icons"; +import { StateGroupIcon, getPriorityIcon } from "components/icons"; // helpers import { addSpaceIfCamelCase } from "helpers/string.helper"; import { renderEmoji } from "helpers/emoji.helper"; // types -import { IIssueViewProps, IState } from "types"; +import { IIssueViewProps, IState, TStateGroups } from "types"; // fetch-keys import { PROJECT_ISSUE_LABELS, PROJECT_MEMBERS } from "constants/fetch-keys"; +// constants +import { STATE_GROUP_COLORS } from "constants/state"; type Props = { currentState?: IState | null; @@ -97,11 +99,24 @@ export const BoardHeader: React.FC = ({ switch (selectedGroup) { case "state": - icon = - currentState && getStateGroupIcon(currentState.group, "16", "16", currentState.color); + icon = currentState && ( + + ); break; case "state_detail.group": - icon = getStateGroupIcon(groupTitle as any, "16", "16"); + icon = ( + + ); break; case "priority": icon = getPriorityIcon(groupTitle, "text-lg"); diff --git a/web/components/core/views/list-view/single-list.tsx b/web/components/core/views/list-view/single-list.tsx index bd1c3c6ab..a005feef5 100644 --- a/web/components/core/views/list-view/single-list.tsx +++ b/web/components/core/views/list-view/single-list.tsx @@ -15,7 +15,7 @@ import { SingleListIssue } from "components/core"; import { Avatar, CustomMenu } from "components/ui"; // icons import { PlusIcon } from "@heroicons/react/24/outline"; -import { getPriorityIcon, getStateGroupIcon } from "components/icons"; +import { StateGroupIcon, getPriorityIcon } from "components/icons"; // helpers import { addSpaceIfCamelCase } from "helpers/string.helper"; import { renderEmoji } from "helpers/emoji.helper"; @@ -26,10 +26,13 @@ import { IIssueLabels, IIssueViewProps, IState, + TStateGroups, UserAuth, } from "types"; // fetch-keys import { PROJECT_ISSUE_LABELS, PROJECT_MEMBERS } from "constants/fetch-keys"; +// constants +import { STATE_GROUP_COLORS } from "constants/state"; type Props = { currentState?: IState | null; @@ -111,11 +114,24 @@ export const SingleList: React.FC = ({ switch (selectedGroup) { case "state": - icon = - currentState && getStateGroupIcon(currentState.group, "16", "16", currentState.color); + icon = currentState && ( + + ); break; case "state_detail.group": - icon = getStateGroupIcon(groupTitle as any, "16", "16"); + icon = ( + + ); break; case "priority": icon = getPriorityIcon(groupTitle, "text-lg"); diff --git a/web/components/cycles/active-cycle-details.tsx b/web/components/cycles/active-cycle-details.tsx index 23fd68e75..a2af4b289 100644 --- a/web/components/cycles/active-cycle-details.tsx +++ b/web/components/cycles/active-cycle-details.tsx @@ -28,7 +28,7 @@ import { TriangleExclamationIcon, AlarmClockIcon, LayerDiagonalIcon, - CompletedStateIcon, + StateGroupIcon, } from "components/icons"; import { StarIcon } from "@heroicons/react/24/outline"; // components @@ -385,8 +385,8 @@ export const ActiveCycleDetails: React.FC = () => { {cycle.total_issues} issues - - + + {cycle.completed_issues} issues diff --git a/web/components/icons/backlog-state-icon.tsx b/web/components/icons/backlog-state-icon.tsx deleted file mode 100644 index 2c140a112..000000000 --- a/web/components/icons/backlog-state-icon.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from "react"; - -import type { Props } from "./types"; - -export const BacklogStateIcon: React.FC = ({ - width = "20", - height = "20", - className, - color = "rgb(var(--color-text-200))", -}) => ( - - - -); diff --git a/web/components/icons/cancelled-state-icon.tsx b/web/components/icons/cancelled-state-icon.tsx deleted file mode 100644 index 5829146ff..000000000 --- a/web/components/icons/cancelled-state-icon.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import React from "react"; - -import type { Props } from "./types"; - -export const CancelledStateIcon: React.FC = ({ - width = "20", - height = "20", - className, - color = "#f2655a", -}) => ( - - - - - - - - - - - - - -); diff --git a/web/components/icons/completed-state-icon.tsx b/web/components/icons/completed-state-icon.tsx deleted file mode 100644 index 584245d58..000000000 --- a/web/components/icons/completed-state-icon.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React from "react"; - -import type { Props } from "./types"; - -export const CompletedStateIcon: React.FC = ({ - width = "20", - height = "20", - className, - color = "#438af3", -}) => ( - - - - - - - - - - - - -); diff --git a/web/components/icons/index.ts b/web/components/icons/index.ts index d3b311e40..d3be7f2a8 100644 --- a/web/components/icons/index.ts +++ b/web/components/icons/index.ts @@ -1,6 +1,7 @@ +export * from "./module"; +export * from "./state"; export * from "./alarm-clock-icon"; export * from "./attachment-icon"; -export * from "./backlog-state-icon"; export * from "./blocked-icon"; export * from "./blocker-icon"; export * from "./bolt-icon"; @@ -8,12 +9,10 @@ export * from "./calendar-before-icon"; export * from "./calendar-after-icon"; export * from "./calendar-month-icon"; export * from "./cancel-icon"; -export * from "./cancelled-state-icon"; export * from "./clipboard-icon"; export * from "./color-pallette-icon"; export * from "./comment-icon"; export * from "./completed-cycle-icon"; -export * from "./completed-state-icon"; export * from "./current-cycle-icon"; export * from "./cycle-icon"; export * from "./discord-icon"; @@ -23,11 +22,9 @@ export * from "./ellipsis-horizontal-icon"; export * from "./external-link-icon"; export * from "./github-icon"; export * from "./heartbeat-icon"; -export * from "./started-state-icon"; export * from "./layer-diagonal-icon"; export * from "./lock-icon"; export * from "./menu-icon"; -export * from "./module"; export * from "./pencil-scribble-icon"; export * from "./plus-icon"; export * from "./person-running-icon"; @@ -36,11 +33,8 @@ export * from "./question-mark-circle-icon"; export * from "./setting-icon"; export * from "./signal-cellular-icon"; export * from "./stacked-layers-icon"; -export * from "./started-state-icon"; -export * from "./state-group-icon"; export * from "./tag-icon"; export * from "./tune-icon"; -export * from "./unstarted-state-icon"; export * from "./upcoming-cycle-icon"; export * from "./user-group-icon"; export * from "./user-icon-circle"; diff --git a/web/components/icons/started-state-icon.tsx b/web/components/icons/started-state-icon.tsx deleted file mode 100644 index 20de01537..000000000 --- a/web/components/icons/started-state-icon.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import React from "react"; - -import type { Props } from "./types"; - -export const StartedStateIcon: React.FC = ({ - width = "20", - height = "20", - className, - color = "#fbb040", -}) => ( - - - - - - - - - - - - -); diff --git a/web/components/icons/state-group-icon.tsx b/web/components/icons/state-group-icon.tsx deleted file mode 100644 index 522e0b9dc..000000000 --- a/web/components/icons/state-group-icon.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { - BacklogStateIcon, - CancelledStateIcon, - CompletedStateIcon, - StartedStateIcon, - UnstartedStateIcon, -} from "components/icons"; -// constants -import { STATE_GROUP_COLORS } from "constants/state"; - -export const getStateGroupIcon = ( - stateGroup: "backlog" | "unstarted" | "started" | "completed" | "cancelled", - width = "20", - height = "20", - color?: string -) => { - switch (stateGroup) { - case "backlog": - return ( - - ); - case "unstarted": - return ( - - ); - case "started": - return ( - - ); - case "completed": - return ( - - ); - case "cancelled": - return ( - - ); - default: - return <>>; - } -}; diff --git a/web/components/icons/state/backlog.tsx b/web/components/icons/state/backlog.tsx new file mode 100644 index 000000000..eb00f800c --- /dev/null +++ b/web/components/icons/state/backlog.tsx @@ -0,0 +1,24 @@ +type Props = { + width?: string; + height?: string; + className?: string; + color?: string; +}; + +export const StateGroupBacklogIcon: React.FC = ({ + width = "20", + height = "20", + className, + color = "#a3a3a3", +}) => ( + + + +); diff --git a/web/components/icons/state/cancelled.tsx b/web/components/icons/state/cancelled.tsx new file mode 100644 index 000000000..1c3c4e3d2 --- /dev/null +++ b/web/components/icons/state/cancelled.tsx @@ -0,0 +1,34 @@ +type Props = { + width?: string; + height?: string; + className?: string; + color?: string; +}; + +export const StateGroupCancelledIcon: React.FC = ({ + width = "20", + height = "20", + className, + color = "#ef4444", +}) => ( + + + + + + + + + + +); diff --git a/web/components/icons/state/completed.tsx b/web/components/icons/state/completed.tsx new file mode 100644 index 000000000..b22cc8c81 --- /dev/null +++ b/web/components/icons/state/completed.tsx @@ -0,0 +1,27 @@ +type Props = { + width?: string; + height?: string; + className?: string; + color?: string; +}; + +export const StateGroupCompletedIcon: React.FC = ({ + width = "20", + height = "20", + className, + color = "#16a34a", +}) => ( + + + +); diff --git a/web/components/icons/state/index.ts b/web/components/icons/state/index.ts new file mode 100644 index 000000000..7fee13d8b --- /dev/null +++ b/web/components/icons/state/index.ts @@ -0,0 +1,6 @@ +export * from "./backlog"; +export * from "./cancelled"; +export * from "./completed"; +export * from "./started"; +export * from "./state-group-icon"; +export * from "./unstarted"; diff --git a/web/components/icons/state/started.tsx b/web/components/icons/state/started.tsx new file mode 100644 index 000000000..bf0892732 --- /dev/null +++ b/web/components/icons/state/started.tsx @@ -0,0 +1,25 @@ +type Props = { + width?: string; + height?: string; + className?: string; + color?: string; +}; + +export const StateGroupStartedIcon: React.FC = ({ + width = "20", + height = "20", + className, + color = "#f59e0b", +}) => ( + + + + +); diff --git a/web/components/icons/state/state-group-icon.tsx b/web/components/icons/state/state-group-icon.tsx new file mode 100644 index 000000000..df3b57dd8 --- /dev/null +++ b/web/components/icons/state/state-group-icon.tsx @@ -0,0 +1,74 @@ +// icons +import { + StateGroupBacklogIcon, + StateGroupCancelledIcon, + StateGroupCompletedIcon, + StateGroupStartedIcon, + StateGroupUnstartedIcon, +} from "components/icons"; +// types +import { TStateGroups } from "types"; +// constants +import { STATE_GROUP_COLORS } from "constants/state"; + +type Props = { + className?: string; + color?: string; + height?: string; + stateGroup: TStateGroups; + width?: string; +}; + +export const StateGroupIcon: React.FC = ({ + className = "", + color, + height = "12px", + width = "12px", + stateGroup, +}) => { + if (stateGroup === "backlog") + return ( + + ); + else if (stateGroup === "cancelled") + return ( + + ); + else if (stateGroup === "completed") + return ( + + ); + else if (stateGroup === "started") + return ( + + ); + else + return ( + + ); +}; diff --git a/web/components/icons/state/unstarted.tsx b/web/components/icons/state/unstarted.tsx new file mode 100644 index 000000000..61a782b1f --- /dev/null +++ b/web/components/icons/state/unstarted.tsx @@ -0,0 +1,24 @@ +type Props = { + width?: string; + height?: string; + className?: string; + color?: string; +}; + +export const StateGroupUnstartedIcon: React.FC = ({ + width = "20", + height = "20", + className, + color = "#3a3a3a", +}) => ( + + + +); diff --git a/web/components/icons/unstarted-state-icon.tsx b/web/components/icons/unstarted-state-icon.tsx deleted file mode 100644 index 161a0ab2a..000000000 --- a/web/components/icons/unstarted-state-icon.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import React from "react"; - -import type { Props } from "./types"; - -export const UnstartedStateIcon: React.FC = ({ - width = "20", - height = "20", - className, - color = "rgb(var(--color-text-200))", -}) => ( - - - - - - - - - - -); diff --git a/web/components/issues/gantt-chart/blocks.tsx b/web/components/issues/gantt-chart/blocks.tsx index 3ab7ea90b..0834e3e79 100644 --- a/web/components/issues/gantt-chart/blocks.tsx +++ b/web/components/issues/gantt-chart/blocks.tsx @@ -3,7 +3,7 @@ import { useRouter } from "next/router"; // ui import { Tooltip } from "components/ui"; // icons -import { getStateGroupIcon } from "components/icons"; +import { StateGroupIcon } from "components/icons"; // helpers import { findTotalDaysInRange, renderShortDate } from "helpers/date-time.helper"; // types @@ -52,7 +52,7 @@ export const IssueGanttSidebarBlock = ({ data }: { data: IIssue }) => { className="relative w-full flex items-center gap-2 h-full cursor-pointer" onClick={() => router.push(`/${workspaceSlug}/projects/${data?.project}/issues/${data?.id}`)} > - {getStateGroupIcon(data?.state_detail?.group, "14", "14", data?.state_detail?.color)} + {data?.project_detail?.identifier} {data?.sequence_id} diff --git a/web/components/issues/my-issues/my-issues-select-filters.tsx b/web/components/issues/my-issues/my-issues-select-filters.tsx index a453abb14..87aa36b9b 100644 --- a/web/components/issues/my-issues/my-issues-select-filters.tsx +++ b/web/components/issues/my-issues/my-issues-select-filters.tsx @@ -11,11 +11,11 @@ import { DateFilterModal } from "components/core"; // ui import { MultiLevelDropdown } from "components/ui"; // icons -import { getPriorityIcon, getStateGroupIcon } from "components/icons"; +import { StateGroupIcon, getPriorityIcon } from "components/icons"; // helpers import { checkIfArraysHaveSameElements } from "helpers/array.helper"; // types -import { IIssueFilterOptions, IQuery } from "types"; +import { IIssueFilterOptions, IQuery, TStateGroups } from "types"; // fetch-keys import { WORKSPACE_LABELS } from "constants/fetch-keys"; // constants @@ -104,7 +104,7 @@ export const MyIssuesSelectFilters: React.FC = ({ id: key, label: ( - {getStateGroupIcon(key as any, "16", "16")}{" "} + {GROUP_CHOICES[key as keyof typeof GROUP_CHOICES]} ), diff --git a/web/components/issues/peek-overview/issue-properties.tsx b/web/components/issues/peek-overview/issue-properties.tsx index 16728b148..98aa98316 100644 --- a/web/components/issues/peek-overview/issue-properties.tsx +++ b/web/components/issues/peek-overview/issue-properties.tsx @@ -2,7 +2,7 @@ import { observer } from "mobx-react-lite"; // headless ui import { Disclosure } from "@headlessui/react"; -import { getStateGroupIcon } from "components/icons"; +import { StateGroupIcon } from "components/icons"; // hooks import useToast from "hooks/use-toast"; import useUser from "hooks/use-user"; @@ -66,7 +66,10 @@ export const PeekOverviewIssueProperties: React.FC = ({ {mode === "full" && ( - {getStateGroupIcon(issue.state_detail.group, "16", "16", issue.state_detail.color)} + {issue.project_detail.identifier}-{issue.sequence_id} diff --git a/web/components/issues/select/state.tsx b/web/components/issues/select/state.tsx index d62daba76..22a4e6532 100644 --- a/web/components/issues/select/state.tsx +++ b/web/components/issues/select/state.tsx @@ -10,7 +10,7 @@ import stateService from "services/state.service"; import { CustomSearchSelect } from "components/ui"; // icons import { PlusIcon, Squares2X2Icon } from "@heroicons/react/24/outline"; -import { getStateGroupIcon } from "components/icons"; +import { StateGroupIcon } from "components/icons"; // helpers import { getStatesList } from "helpers/state.helper"; // fetch keys @@ -41,7 +41,7 @@ export const IssueStateSelect: React.FC = ({ setIsOpen, value, onChange, query: state.name, content: ( - {getStateGroupIcon(state.group, "16", "16", state.color)} + {state.name} ), @@ -58,9 +58,12 @@ export const IssueStateSelect: React.FC = ({ setIsOpen, value, onChange, label={ {selectedOption ? ( - getStateGroupIcon(selectedOption.group, "16", "16", selectedOption.color) + ) : currentDefaultState ? ( - getStateGroupIcon(currentDefaultState.group, "16", "16", currentDefaultState.color) + ) : ( )} diff --git a/web/components/issues/sidebar-select/state.tsx b/web/components/issues/sidebar-select/state.tsx index 5084c61bd..cf2cfe3b2 100644 --- a/web/components/issues/sidebar-select/state.tsx +++ b/web/components/issues/sidebar-select/state.tsx @@ -9,7 +9,7 @@ import stateService from "services/state.service"; // ui import { Spinner, CustomSelect } from "components/ui"; // icons -import { getStateGroupIcon } from "components/icons"; +import { StateGroupIcon } from "components/icons"; // helpers import { getStatesList } from "helpers/state.helper"; import { addSpaceIfCamelCase } from "helpers/string.helper"; @@ -42,17 +42,12 @@ export const SidebarStateSelect: React.FC = ({ value, onChange, disabled {selectedState ? ( - {getStateGroupIcon( - selectedState?.group ?? "backlog", - "14", - "14", - selectedState?.color ?? "" - )} + {addSpaceIfCamelCase(selectedState?.name ?? "")} ) : inboxIssueId ? ( - {getStateGroupIcon("backlog", "14", "14", "#ff7700")} + Triage ) : ( @@ -71,7 +66,7 @@ export const SidebarStateSelect: React.FC = ({ value, onChange, disabled states.map((state) => ( <> - {getStateGroupIcon(state.group, "16", "16", state.color)} + {state.name} > diff --git a/web/components/issues/view-select/state.tsx b/web/components/issues/view-select/state.tsx index 460a11272..08ca77d80 100644 --- a/web/components/issues/view-select/state.tsx +++ b/web/components/issues/view-select/state.tsx @@ -10,7 +10,7 @@ import trackEventServices from "services/track-event.service"; // ui import { CustomSearchSelect, Tooltip } from "components/ui"; // icons -import { getStateGroupIcon } from "components/icons"; +import { StateGroupIcon } from "components/icons"; // helpers import { getStatesList } from "helpers/state.helper"; // types @@ -59,7 +59,7 @@ export const ViewStateSelect: React.FC = ({ query: state.name, content: ( - {getStateGroupIcon(state.group, "16", "16", state.color)} + {state.name} ), @@ -75,8 +75,9 @@ export const ViewStateSelect: React.FC = ({ > - {selectedOption && - getStateGroupIcon(selectedOption.group, "14", "14", selectedOption.color)} + {selectedOption && ( + + )} {selectedOption?.name ?? "State"} diff --git a/web/components/states/single-state.tsx b/web/components/states/single-state.tsx index 813afdc79..e5c1bf8dd 100644 --- a/web/components/states/single-state.tsx +++ b/web/components/states/single-state.tsx @@ -15,7 +15,7 @@ import { PencilSquareIcon, TrashIcon, } from "@heroicons/react/24/outline"; -import { getStateGroupIcon } from "components/icons"; +import { StateGroupIcon } from "components/icons"; // helpers import { addSpaceIfCamelCase } from "helpers/string.helper"; import { groupBy, orderArrayBy } from "helpers/array.helper"; @@ -162,7 +162,7 @@ export const SingleState: React.FC = ({ return ( - {getStateGroupIcon(state.group, "20", "20", state.color)} + {addSpaceIfCamelCase(state.name)} {state.description} diff --git a/web/components/views/select-filters.tsx b/web/components/views/select-filters.tsx index 5755484c9..77ef80682 100644 --- a/web/components/views/select-filters.tsx +++ b/web/components/views/select-filters.tsx @@ -13,7 +13,7 @@ import { DateFilterModal } from "components/core"; // ui import { Avatar, MultiLevelDropdown } from "components/ui"; // icons -import { getPriorityIcon, getStateGroupIcon } from "components/icons"; +import { StateGroupIcon, getPriorityIcon } from "components/icons"; // helpers import { getStatesList } from "helpers/state.helper"; import { checkIfArraysHaveSameElements } from "helpers/array.helper"; @@ -118,7 +118,8 @@ export const SelectFilters: React.FC = ({ id: state.id, label: ( - {getStateGroupIcon(state.group, "16", "16", state.color)} {state.name} + + {state.name} ), value: { diff --git a/web/components/web-view/select-state.tsx b/web/components/web-view/select-state.tsx index 3d530dd48..c5bfa1257 100644 --- a/web/components/web-view/select-state.tsx +++ b/web/components/web-view/select-state.tsx @@ -17,7 +17,7 @@ import stateService from "services/state.service"; import { STATES_LIST } from "constants/fetch-keys"; // components -import { getStateGroupIcon } from "components/icons"; +import { StateGroupIcon } from "components/icons"; import { WebViewModal } from "./web-view-modal"; // helpers @@ -62,7 +62,7 @@ export const StateSelect: React.FC = (props) => { label: state.name, value: state.id, checked: state.id === selectedState?.id, - icon: getStateGroupIcon(state.group, "16", "16", state.color), + icon: , onClick: () => { setIsOpen(false); if (disabled) return; diff --git a/web/components/workspace/issues-pie-chart.tsx b/web/components/workspace/issues-pie-chart.tsx index 7d453d8a9..de1e199ff 100644 --- a/web/components/workspace/issues-pie-chart.tsx +++ b/web/components/workspace/issues-pie-chart.tsx @@ -1,9 +1,7 @@ // ui import { PieGraph } from "components/ui"; -// helpers -import { capitalizeFirstLetter } from "helpers/string.helper"; // types -import { IUserStateDistribution } from "types"; +import { IUserStateDistribution, TStateGroups } from "types"; // constants import { STATE_GROUP_COLORS } from "constants/state"; @@ -23,7 +21,7 @@ export const IssuesPieChart: React.FC = ({ groupedIssues }) => ( id: cell.state_group, label: cell.state_group, value: cell.state_count, - color: STATE_GROUP_COLORS[cell.state_group.toLowerCase()], + color: STATE_GROUP_COLORS[cell.state_group.toLowerCase() as TStateGroups], })) ?? [] } height="320px" diff --git a/web/constants/state.ts b/web/constants/state.ts index 735757822..13e8506ee 100644 --- a/web/constants/state.ts +++ b/web/constants/state.ts @@ -1,5 +1,7 @@ +import { TStateGroups } from "types"; + export const STATE_GROUP_COLORS: { - [key: string]: string; + [key in TStateGroups]: string; } = { backlog: "#d9d9d9", unstarted: "#3f76ff", diff --git a/web/helpers/analytics.helper.ts b/web/helpers/analytics.helper.ts index efc781794..08b763720 100644 --- a/web/helpers/analytics.helper.ts +++ b/web/helpers/analytics.helper.ts @@ -3,7 +3,7 @@ import { BarDatum } from "@nivo/bar"; // helpers import { capitalizeFirstLetter, generateRandomColor } from "helpers/string.helper"; // types -import { IAnalyticsData, IAnalyticsParams, IAnalyticsResponse } from "types"; +import { IAnalyticsData, IAnalyticsParams, IAnalyticsResponse, TStateGroups } from "types"; // constants import { STATE_GROUP_COLORS } from "constants/state"; import { MONTHS_LIST } from "constants/calendar"; @@ -72,7 +72,8 @@ export const generateBarColor = ( if (params[type] === "state__name" || params[type] === "labels__name") color = analytics?.extras?.colors.find((c) => c.name === value)?.color; - if (params[type] === "state__group") color = STATE_GROUP_COLORS[value.toLowerCase()]; + if (params[type] === "state__group") + color = STATE_GROUP_COLORS[value.toLowerCase() as TStateGroups]; if (params[type] === "priority") { const priority = value.toLowerCase(); From 8de93d00813cdbeeca787403cf12244122ddc0de Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Mon, 11 Sep 2023 12:13:00 +0530 Subject: [PATCH 03/11] chore: remove getServerSideProps (#2130) --- .../[workspace_slug]/[project_slug]/index.tsx | 15 ++---- web/pages/installations/[provider]/index.tsx | 53 ++++++------------- 2 files changed, 19 insertions(+), 49 deletions(-) diff --git a/space/pages/[workspace_slug]/[project_slug]/index.tsx b/space/pages/[workspace_slug]/[project_slug]/index.tsx index 220a5b8c7..e50c01c18 100644 --- a/space/pages/[workspace_slug]/[project_slug]/index.tsx +++ b/space/pages/[workspace_slug]/[project_slug]/index.tsx @@ -1,7 +1,8 @@ -import useSWR from "swr"; -import type { GetServerSideProps } from "next"; -import { useRouter } from "next/router"; import Head from "next/head"; +import { useRouter } from "next/router"; + +import useSWR from "swr"; + /// layouts import ProjectLayout from "layouts/project-layout"; // components @@ -39,12 +40,4 @@ const WorkspaceProjectPage = (props: any) => { ); }; -// export const getServerSideProps: GetServerSideProps = async ({ query: { workspace_slug, project_slug } }) => { -// const res = await fetch( -// `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/public/workspaces/${workspace_slug}/project-boards/${project_slug}/settings/` -// ); -// const project_settings = await res.json(); -// return { props: { project_settings } }; -// }; - export default WorkspaceProjectPage; diff --git a/web/pages/installations/[provider]/index.tsx b/web/pages/installations/[provider]/index.tsx index 2becb1f88..ad5b5a284 100644 --- a/web/pages/installations/[provider]/index.tsx +++ b/web/pages/installations/[provider]/index.tsx @@ -1,37 +1,20 @@ import React, { useEffect } from "react"; -// services -import appinstallationsService from "services/app-installations.service"; - -import useToast from "hooks/use-toast"; - -// components -import { Spinner } from "components/ui"; - import { useRouter } from "next/router"; -interface IGithuPostInstallationProps { - installation_id: string; - setup_action: string; - state: string; - provider: string; - code: string; -} +// services +import appInstallationsService from "services/app-installations.service"; +// ui +import { Spinner } from "components/ui"; -// TODO:Change getServerSideProps to router.query -const AppPostInstallation = ({ - installation_id, - setup_action, - state, - provider, - code, -}: IGithuPostInstallationProps) => { - const { setToastAlert } = useToast(); +const AppPostInstallation = () => { + const router = useRouter(); + const { installation_id, setup_action, state, provider, code } = router.query; useEffect(() => { if (provider === "github" && state && installation_id) { - appinstallationsService - .addInstallationApp(state, provider, { installation_id }) + appInstallationsService + .addInstallationApp(state.toString(), provider, { installation_id }) .then(() => { window.opener = null; window.open("", "_self"); @@ -41,10 +24,10 @@ const AppPostInstallation = ({ console.log(err); }); } else if (provider === "slack" && state && code) { - appinstallationsService - .getSlackAuthDetails(code) + appInstallationsService + .getSlackAuthDetails(code.toString()) .then((res) => { - const [workspaceSlug, projectId, integrationId] = state.split(","); + const [workspaceSlug, projectId, integrationId] = state.toString().split(","); if (!projectId) { const payload = { @@ -53,8 +36,8 @@ const AppPostInstallation = ({ }, }; - appinstallationsService - .addInstallationApp(state, provider, payload) + appInstallationsService + .addInstallationApp(state.toString(), provider, payload) .then((r) => { window.opener = null; window.open("", "_self"); @@ -73,7 +56,7 @@ const AppPostInstallation = ({ team_name: res.team.name, scopes: res.scope, }; - appinstallationsService + appInstallationsService .addSlackChannel(workspaceSlug, projectId, integrationId, payload) .then((r) => { window.opener = null; @@ -99,10 +82,4 @@ const AppPostInstallation = ({ ); }; -export async function getServerSideProps(context: any) { - return { - props: context.query, - }; -} - export default AppPostInstallation; From 7842c4b2ea6221f90485e7e5df256032572ce4b3 Mon Sep 17 00:00:00 2001 From: Dakshesh Jain <65905942+dakshesh14@users.noreply.github.com> Date: Mon, 11 Sep 2023 12:24:46 +0530 Subject: [PATCH 04/11] fix: authorize editor (#2122) --- web/layouts/web-view-layout/index.tsx | 5 +- web/pages/m/[workspaceSlug]/editor.tsx | 104 +++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 web/pages/m/[workspaceSlug]/editor.tsx diff --git a/web/layouts/web-view-layout/index.tsx b/web/layouts/web-view-layout/index.tsx index 2fb46b9df..8a58407c3 100644 --- a/web/layouts/web-view-layout/index.tsx +++ b/web/layouts/web-view-layout/index.tsx @@ -15,6 +15,7 @@ import { Spinner } from "components/ui"; type Props = { children: React.ReactNode; + fullScreen?: boolean; }; const getIfInWebview = (userAgent: NavigatorID["userAgent"]) => { @@ -30,7 +31,7 @@ const useMobileDetect = () => { return getIfInWebview(userAgent); }; -const WebViewLayout: React.FC = ({ children }) => { +const WebViewLayout: React.FC = ({ children, fullScreen = true }) => { const { data: currentUser, error } = useSWR(CURRENT_USER, () => userService.currentUser()); const isWebview = useMobileDetect(); @@ -47,7 +48,7 @@ const WebViewLayout: React.FC = ({ children }) => { } return ( - + {error || !isWebview ? ( diff --git a/web/pages/m/[workspaceSlug]/editor.tsx b/web/pages/m/[workspaceSlug]/editor.tsx new file mode 100644 index 000000000..296b05ac9 --- /dev/null +++ b/web/pages/m/[workspaceSlug]/editor.tsx @@ -0,0 +1,104 @@ +import { useEffect, useState } from "react"; + +// next +import type { NextPage } from "next"; +import { useRouter } from "next/router"; + +// cookies +import Cookies from "js-cookie"; + +// react-hook-form +import { Controller, useForm } from "react-hook-form"; + +// layouts +import WebViewLayout from "layouts/web-view-layout"; + +// components +import { TipTapEditor } from "components/tiptap"; +import { PrimaryButton, Spinner } from "components/ui"; + +const Editor: NextPage = () => { + const [isLoading, setIsLoading] = useState(false); + + const router = useRouter(); + const { workspaceSlug, editable } = router.query; + + const isEditable = editable === "true"; + + const { + watch, + setValue, + control, + formState: { errors }, + } = useForm({ + defaultValues: { + data: "", + data_html: "", + }, + }); + + useEffect(() => { + setIsLoading(true); + if (!isEditable) return; + setIsLoading(false); + const data_html = Cookies.get("data_html"); + setValue("data_html", data_html ?? ""); + }, [isEditable, setValue]); + + return ( + + {isLoading ? ( + + + + ) : ( + <> + ( + { + onChange(description_html); + setValue("data_html", description_html); + setValue("data", JSON.stringify(description)); + }} + /> + )} + /> + {isEditable && ( + { + console.log( + "submitted", + JSON.stringify({ + data_html: watch("data_html"), + }) + ); + }} + > + Submit + + )} + > + )} + + ); +}; + +export default Editor; From 4447a4b5191d9575c4718c667233ddaf1c87c1ac Mon Sep 17 00:00:00 2001 From: "M. Palanikannan" <73993394+Palanikannan1437@users.noreply.github.com> Date: Mon, 11 Sep 2023 12:54:19 +0530 Subject: [PATCH 05/11] fix: Tiptap comment card fix for space (#2129) * fix:(space) fixed comment card's editor integration * regression: removed content being set twice * chore: added controller to manage tiptap editor * chore: remove unused functions --------- Co-authored-by: Aaryan Khandelwal --- .../peek-overview/comment/comment-detail-card.tsx | 14 +++++++++++--- space/components/tiptap/index.tsx | 6 ------ web/components/tiptap/index.tsx | 6 ------ 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/space/components/issues/peek-overview/comment/comment-detail-card.tsx b/space/components/issues/peek-overview/comment/comment-detail-card.tsx index 7c785d988..0b4d2d5b0 100644 --- a/space/components/issues/peek-overview/comment/comment-detail-card.tsx +++ b/space/components/issues/peek-overview/comment/comment-detail-card.tsx @@ -3,7 +3,7 @@ import React, { useState } from "react"; // mobx import { observer } from "mobx-react-lite"; // react-hook-form -import { useForm, Controller } from "react-hook-form"; +import { Controller, useForm } from "react-hook-form"; // headless ui import { Menu, Transition } from "@headlessui/react"; // lib @@ -30,10 +30,13 @@ export const CommentCard: React.FC = observer((props) => { // states const [isEditing, setIsEditing] = useState(false); + const editorRef = React.useRef(null); + + const showEditorRef = React.useRef(null); const { + control, formState: { isSubmitting }, handleSubmit, - control, } = useForm({ defaultValues: { comment_html: comment.comment_html }, }); @@ -47,6 +50,9 @@ export const CommentCard: React.FC = observer((props) => { if (!workspaceSlug || !issueDetailStore.peekId) return; issueDetailStore.updateIssueComment(workspaceSlug, comment.project, issueDetailStore.peekId, comment.id, formData); setIsEditing(false); + + editorRef.current?.setEditorValue(formData.comment_html); + showEditorRef.current?.setEditorValue(formData.comment_html); }; return ( @@ -96,6 +102,7 @@ export const CommentCard: React.FC = observer((props) => { render={({ field: { onChange, value } }) => ( = observer((props) => { { }, }); - useEffect(() => { - if (editor) { - editor.commands.setContent(value); - } - }, [value]); - const editorRef: React.MutableRefObject = useRef(null); useImperativeHandle(forwardedRef, () => ({ diff --git a/web/components/tiptap/index.tsx b/web/components/tiptap/index.tsx index 28c8b1691..84f691c35 100644 --- a/web/components/tiptap/index.tsx +++ b/web/components/tiptap/index.tsx @@ -56,12 +56,6 @@ const Tiptap = (props: ITipTapRichTextEditor) => { }, }); - useEffect(() => { - if (editor) { - editor.commands.setContent(value); - } - }, [value]); - const editorRef: React.MutableRefObject = useRef(null); useImperativeHandle(forwardedRef, () => ({ From 1a37668f0b07ac1fc16a37b9de3decf0da013db0 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 11 Sep 2023 09:35:09 +0200 Subject: [PATCH 06/11] fix: husky was removed in commit #2086, but prepare still uses it (#2128) --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index eb6a23994..793a1922f 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,6 @@ "packages/*" ], "scripts": { - "prepare": "husky install", "build": "turbo run build", "dev": "turbo run dev", "start": "turbo run start", From 991258084e0884fbdd2a11cb821cc6a083690855 Mon Sep 17 00:00:00 2001 From: Dakshesh Jain <65905942+dakshesh14@users.noreply.github.com> Date: Mon, 11 Sep 2023 13:21:50 +0530 Subject: [PATCH 07/11] fix: query checking (#2137) fix: the logic should be to check if object exist not if it's true or false --- web/pages/m/[workspaceSlug]/editor.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/web/pages/m/[workspaceSlug]/editor.tsx b/web/pages/m/[workspaceSlug]/editor.tsx index 296b05ac9..2bfac63b8 100644 --- a/web/pages/m/[workspaceSlug]/editor.tsx +++ b/web/pages/m/[workspaceSlug]/editor.tsx @@ -25,12 +25,7 @@ const Editor: NextPage = () => { const isEditable = editable === "true"; - const { - watch, - setValue, - control, - formState: { errors }, - } = useForm({ + const { watch, setValue, control } = useForm({ defaultValues: { data: "", data_html: "", @@ -39,11 +34,11 @@ const Editor: NextPage = () => { useEffect(() => { setIsLoading(true); - if (!isEditable) return; + if (!router?.query?.["editable"]) return; setIsLoading(false); const data_html = Cookies.get("data_html"); setValue("data_html", data_html ?? ""); - }, [isEditable, setValue]); + }, [isEditable, setValue, router]); return ( From 7bb73b74baf3ff02e39c678c8e773d2ad09c9bf2 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Mon, 11 Sep 2023 14:35:58 +0530 Subject: [PATCH 08/11] refactor: priority icon component (#2132) --- .../analytics/custom-analytics/table.tsx | 8 ++-- .../issue/change-issue-priority.tsx | 12 +++--- web/components/core/filters/filters-list.tsx | 6 ++- .../core/views/board-view/board-header.tsx | 6 +-- web/components/core/views/issues-view.tsx | 5 ++- .../core/views/list-view/single-list.tsx | 5 ++- .../cycles/active-cycle-details.tsx | 4 +- web/components/icons/priority-icon.tsx | 41 ++++++++++--------- web/components/inbox/filters-dropdown.tsx | 4 +- web/components/inbox/filters-list.tsx | 8 +++- web/components/inbox/inbox-issue-card.tsx | 7 +--- web/components/inbox/inbox-main-content.tsx | 2 +- .../my-issues/my-issues-select-filters.tsx | 4 +- .../issues/my-issues/my-issues-view.tsx | 4 +- .../issues/peek-overview/issue-properties.tsx | 4 +- web/components/issues/select/priority.tsx | 15 +++++-- .../issues/sidebar-select/priority.tsx | 12 +++--- web/components/issues/sidebar.tsx | 2 +- .../issues/view-select/priority.tsx | 32 +++++++-------- .../profile/profile-issues-view.tsx | 4 +- web/components/views/select-filters.tsx | 5 ++- .../web-view/issue-properties-detail.tsx | 2 +- web/components/web-view/select-priority.tsx | 8 ++-- web/constants/project.ts | 4 +- .../archived-issues/[archivedIssueId].tsx | 2 +- .../projects/[projectId]/issues/[issueId].tsx | 2 +- web/types/issues.d.ts | 4 +- 27 files changed, 117 insertions(+), 95 deletions(-) diff --git a/web/components/analytics/custom-analytics/table.tsx b/web/components/analytics/custom-analytics/table.tsx index 75d1d7d40..5993bb63c 100644 --- a/web/components/analytics/custom-analytics/table.tsx +++ b/web/components/analytics/custom-analytics/table.tsx @@ -1,13 +1,13 @@ // nivo import { BarDatum } from "@nivo/bar"; // icons -import { getPriorityIcon } from "components/icons"; +import { PriorityIcon } from "components/icons"; // helpers import { addSpaceIfCamelCase } from "helpers/string.helper"; // helpers import { generateBarColor, renderMonthAndYear } from "helpers/analytics.helper"; // types -import { IAnalyticsParams, IAnalyticsResponse } from "types"; +import { IAnalyticsParams, IAnalyticsResponse, TIssuePriorities } from "types"; // constants import { ANALYTICS_X_AXIS_VALUES, ANALYTICS_Y_AXIS_VALUES, DATE_KEYS } from "constants/analytics"; @@ -53,7 +53,7 @@ export const AnalyticsTable: React.FC = ({ analytics, barGraphData, param > {params.segment === "priority" ? ( - getPriorityIcon(key) + ) : ( = ({ analytics, barGraphData, param }`} > {params.x_axis === "priority" ? ( - getPriorityIcon(`${item.name}`) + ) : ( >; @@ -54,7 +56,7 @@ export const ChangeIssuePriority: React.FC = ({ setIsPaletteOpen, issue, [workspaceSlug, issueId, projectId, user] ); - const handleIssueState = (priority: string | null) => { + const handleIssueState = (priority: TIssuePriorities) => { submitChanges({ priority }); setIsPaletteOpen(false); }; @@ -68,7 +70,7 @@ export const ChangeIssuePriority: React.FC = ({ setIsPaletteOpen, issue, className="focus:outline-none" > - {getPriorityIcon(priority)} + {priority ?? "None"} {priority === issue.priority && } diff --git a/web/components/core/filters/filters-list.tsx b/web/components/core/filters/filters-list.tsx index 10cd623f8..81a12bd86 100644 --- a/web/components/core/filters/filters-list.tsx +++ b/web/components/core/filters/filters-list.tsx @@ -2,7 +2,7 @@ import React from "react"; // icons import { XMarkIcon } from "@heroicons/react/24/outline"; -import { getPriorityIcon, StateGroupIcon } from "components/icons"; +import { PriorityIcon, StateGroupIcon } from "components/icons"; // ui import { Avatar } from "components/ui"; // helpers @@ -136,7 +136,9 @@ export const FiltersList: React.FC = ({ : "bg-custom-background-90 text-custom-text-200" }`} > - {getPriorityIcon(priority)} + + + {priority === "null" ? "None" : priority} = ({ ); break; case "priority": - icon = getPriorityIcon(groupTitle, "text-lg"); + icon = ; break; case "project": const project = projects?.find((p) => p.id === groupTitle); diff --git a/web/components/core/views/issues-view.tsx b/web/components/core/views/issues-view.tsx index 755b37aa1..556c4d98e 100644 --- a/web/components/core/views/issues-view.tsx +++ b/web/components/core/views/issues-view.tsx @@ -29,7 +29,7 @@ import { PlusIcon } from "@heroicons/react/24/outline"; import { getStatesList } from "helpers/state.helper"; import { orderArrayBy } from "helpers/array.helper"; // types -import { IIssue, IIssueFilterOptions, IState } from "types"; +import { IIssue, IIssueFilterOptions, IState, TIssuePriorities } from "types"; // fetch-keys import { CYCLE_DETAILS, @@ -184,7 +184,8 @@ export const IssuesView: React.FC = ({ // if the issue is moved to a different group, then we will change the group of the // dragged item(or issue) - if (selectedGroup === "priority") draggedItem.priority = destinationGroup; + if (selectedGroup === "priority") + draggedItem.priority = destinationGroup as TIssuePriorities; else if (selectedGroup === "state") { draggedItem.state = destinationGroup; draggedItem.state_detail = states?.find((s) => s.id === destinationGroup) as IState; diff --git a/web/components/core/views/list-view/single-list.tsx b/web/components/core/views/list-view/single-list.tsx index a005feef5..14829adc4 100644 --- a/web/components/core/views/list-view/single-list.tsx +++ b/web/components/core/views/list-view/single-list.tsx @@ -15,7 +15,7 @@ import { SingleListIssue } from "components/core"; import { Avatar, CustomMenu } from "components/ui"; // icons import { PlusIcon } from "@heroicons/react/24/outline"; -import { StateGroupIcon, getPriorityIcon } from "components/icons"; +import { PriorityIcon, StateGroupIcon } from "components/icons"; // helpers import { addSpaceIfCamelCase } from "helpers/string.helper"; import { renderEmoji } from "helpers/emoji.helper"; @@ -26,6 +26,7 @@ import { IIssueLabels, IIssueViewProps, IState, + TIssuePriorities, TStateGroups, UserAuth, } from "types"; @@ -134,7 +135,7 @@ export const SingleList: React.FC = ({ ); break; case "priority": - icon = getPriorityIcon(groupTitle, "text-lg"); + icon = ; break; case "project": const project = projects?.find((p) => p.id === groupTitle); diff --git a/web/components/cycles/active-cycle-details.tsx b/web/components/cycles/active-cycle-details.tsx index a2af4b289..062dd57e7 100644 --- a/web/components/cycles/active-cycle-details.tsx +++ b/web/components/cycles/active-cycle-details.tsx @@ -19,7 +19,7 @@ import { ActiveCycleProgressStats } from "components/cycles"; // icons import { CalendarDaysIcon } from "@heroicons/react/20/solid"; -import { getPriorityIcon } from "components/icons/priority-icon"; +import { PriorityIcon } from "components/icons/priority-icon"; import { TargetIcon, ContrastIcon, @@ -477,7 +477,7 @@ export const ActiveCycleDetails: React.FC = () => { : "border-orange-500/20 bg-orange-500/20 text-orange-500" }`} > - {getPriorityIcon(issue.priority, "text-sm")} + diff --git a/web/components/icons/priority-icon.tsx b/web/components/icons/priority-icon.tsx index 58212ca5a..8473e264b 100644 --- a/web/components/icons/priority-icon.tsx +++ b/web/components/icons/priority-icon.tsx @@ -1,22 +1,25 @@ -export const getPriorityIcon = (priority: string | null, className?: string) => { +// types +import { TIssuePriorities } from "types"; + +type Props = { + priority: TIssuePriorities | null; + className?: string; +}; + +export const PriorityIcon: React.FC = ({ priority, className = "" }) => { if (!className || className === "") className = "text-xs flex items-center"; - priority = priority?.toLowerCase() ?? null; - - switch (priority) { - case "urgent": - return error; - case "high": - return signal_cellular_alt; - case "medium": - return ( - signal_cellular_alt_2_bar - ); - case "low": - return ( - signal_cellular_alt_1_bar - ); - default: - return block; - } + return ( + + {priority === "urgent" + ? "error" + : priority === "high" + ? "signal_cellular_alt" + : priority === "medium" + ? "signal_cellular_alt_2_bar" + : priority === "low" + ? "signal_cellular_alt_1_bar" + : "block"} + + ); }; diff --git a/web/components/inbox/filters-dropdown.tsx b/web/components/inbox/filters-dropdown.tsx index 7bb601949..9220db899 100644 --- a/web/components/inbox/filters-dropdown.tsx +++ b/web/components/inbox/filters-dropdown.tsx @@ -3,7 +3,7 @@ import useInboxView from "hooks/use-inbox-view"; // ui import { MultiLevelDropdown } from "components/ui"; // icons -import { getPriorityIcon } from "components/icons"; +import { PriorityIcon } from "components/icons"; // constants import { PRIORITIES } from "constants/project"; import { INBOX_STATUS } from "constants/inbox"; @@ -42,7 +42,7 @@ export const FiltersDropdown: React.FC = () => { id: priority === null ? "null" : priority, label: ( - {getPriorityIcon(priority)} {priority ?? "None"} + {priority ?? "None"} ), value: { diff --git a/web/components/inbox/filters-list.tsx b/web/components/inbox/filters-list.tsx index 503c4ab04..7d07fb8d4 100644 --- a/web/components/inbox/filters-list.tsx +++ b/web/components/inbox/filters-list.tsx @@ -2,9 +2,11 @@ import useInboxView from "hooks/use-inbox-view"; // icons import { XMarkIcon } from "@heroicons/react/24/outline"; -import { getPriorityIcon } from "components/icons"; +import { PriorityIcon } from "components/icons"; // helpers import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper"; +// types +import { TIssuePriorities } from "types"; // constants import { INBOX_STATUS } from "constants/inbox"; @@ -48,7 +50,9 @@ export const InboxFiltersList = () => { : "bg-custom-background-90 text-custom-text-200" }`} > - {getPriorityIcon(priority)} + + + = (props) => { : "border-custom-border-200" }`} > - {getPriorityIcon( - issue.priority && issue.priority !== "" ? issue.priority ?? "" : "None", - "text-sm" - )} + = { name: "", description_html: "", estimate_point: null, diff --git a/web/components/issues/my-issues/my-issues-select-filters.tsx b/web/components/issues/my-issues/my-issues-select-filters.tsx index 87aa36b9b..ce8e03797 100644 --- a/web/components/issues/my-issues/my-issues-select-filters.tsx +++ b/web/components/issues/my-issues/my-issues-select-filters.tsx @@ -11,7 +11,7 @@ import { DateFilterModal } from "components/core"; // ui import { MultiLevelDropdown } from "components/ui"; // icons -import { StateGroupIcon, getPriorityIcon } from "components/icons"; +import { PriorityIcon, StateGroupIcon } from "components/icons"; // helpers import { checkIfArraysHaveSameElements } from "helpers/array.helper"; // types @@ -83,7 +83,7 @@ export const MyIssuesSelectFilters: React.FC = ({ id: priority === null ? "null" : priority, label: ( - {getPriorityIcon(priority)} {priority ?? "None"} + {priority ?? "None"} ), value: { diff --git a/web/components/issues/my-issues/my-issues-view.tsx b/web/components/issues/my-issues/my-issues-view.tsx index 3500e69e7..a66f4618b 100644 --- a/web/components/issues/my-issues/my-issues-view.tsx +++ b/web/components/issues/my-issues/my-issues-view.tsx @@ -18,7 +18,7 @@ import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues"; // helpers import { orderArrayBy } from "helpers/array.helper"; // types -import { IIssue, IIssueFilterOptions } from "types"; +import { IIssue, IIssueFilterOptions, TIssuePriorities } from "types"; // fetch-keys import { USER_ISSUES, WORKSPACE_LABELS } from "constants/fetch-keys"; import { PlusIcon } from "@heroicons/react/24/outline"; @@ -96,7 +96,7 @@ export const MyIssuesView: React.FC = ({ const sourceGroup = source.droppableId; const destinationGroup = destination.droppableId; - draggedItem[groupBy] = destinationGroup; + draggedItem[groupBy] = destinationGroup as TIssuePriorities; mutate<{ [key: string]: IIssue[]; diff --git a/web/components/issues/peek-overview/issue-properties.tsx b/web/components/issues/peek-overview/issue-properties.tsx index 98aa98316..d001634fc 100644 --- a/web/components/issues/peek-overview/issue-properties.tsx +++ b/web/components/issues/peek-overview/issue-properties.tsx @@ -19,7 +19,7 @@ import { CustomDatePicker, Icon } from "components/ui"; // helpers import { copyTextToClipboard } from "helpers/string.helper"; // types -import { IIssue } from "types"; +import { IIssue, TIssuePriorities } from "types"; type Props = { handleDeleteIssue: () => void; @@ -117,7 +117,7 @@ export const PeekOverviewIssueProperties: React.FC = ({ handleUpdateIssue({ priority: val })} + onChange={(val) => handleUpdateIssue({ priority: val })} disabled={readOnly} /> diff --git a/web/components/issues/select/priority.tsx b/web/components/issues/select/priority.tsx index b734e6a90..6a2a07cbd 100644 --- a/web/components/issues/select/priority.tsx +++ b/web/components/issues/select/priority.tsx @@ -3,12 +3,14 @@ import React from "react"; // ui import { CustomSelect } from "components/ui"; // icons -import { getPriorityIcon } from "components/icons/priority-icon"; +import { PriorityIcon } from "components/icons/priority-icon"; +// types +import { TIssuePriorities } from "types"; // constants import { PRIORITIES } from "constants/project"; type Props = { - value: string | null; + value: TIssuePriorities; onChange: (value: string) => void; }; @@ -18,7 +20,10 @@ export const IssuePrioritySelect: React.FC = ({ value, onChange }) => ( label={ - {getPriorityIcon(value, `text-xs ${value ? "" : "text-custom-text-200"}`)} + {value ?? "Priority"} @@ -32,7 +37,9 @@ export const IssuePrioritySelect: React.FC = ({ value, onChange }) => ( - {getPriorityIcon(priority)} + + + {priority ?? "None"} diff --git a/web/components/issues/sidebar-select/priority.tsx b/web/components/issues/sidebar-select/priority.tsx index 67ae5133d..543f79707 100644 --- a/web/components/issues/sidebar-select/priority.tsx +++ b/web/components/issues/sidebar-select/priority.tsx @@ -3,13 +3,15 @@ import React from "react"; // ui import { CustomSelect } from "components/ui"; // icons -import { getPriorityIcon } from "components/icons/priority-icon"; +import { PriorityIcon } from "components/icons/priority-icon"; +// types +import { TIssuePriorities } from "types"; // constants import { PRIORITIES } from "constants/project"; type Props = { - value: string | null; - onChange: (val: string) => void; + value: TIssuePriorities; + onChange: (val: TIssuePriorities) => void; disabled?: boolean; }; @@ -31,7 +33,7 @@ export const SidebarPrioritySelect: React.FC = ({ value, onChange, disabl }`} > - {getPriorityIcon(value ?? "None", "!text-sm")} + {value ?? "None"} @@ -44,7 +46,7 @@ export const SidebarPrioritySelect: React.FC = ({ value, onChange, disabl {PRIORITIES.map((option) => ( <> - {getPriorityIcon(option, "text-sm")} + {option ?? "None"} > diff --git a/web/components/issues/sidebar.tsx b/web/components/issues/sidebar.tsx index 4bdd30137..a33d17705 100644 --- a/web/components/issues/sidebar.tsx +++ b/web/components/issues/sidebar.tsx @@ -401,7 +401,7 @@ export const IssueDetailsSidebar: React.FC = ({ render={({ field: { value } }) => ( submitChanges({ priority: val })} + onChange={(val) => submitChanges({ priority: val })} disabled={memberRole.isGuest || memberRole.isViewer || uneditable} /> )} diff --git a/web/components/issues/view-select/priority.tsx b/web/components/issues/view-select/priority.tsx index f9872729c..1bdbf3428 100644 --- a/web/components/issues/view-select/priority.tsx +++ b/web/components/issues/view-select/priority.tsx @@ -2,18 +2,18 @@ import React from "react"; import { useRouter } from "next/router"; +// services +import trackEventServices from "services/track-event.service"; // ui import { CustomSelect, Tooltip } from "components/ui"; // icons -import { getPriorityIcon } from "components/icons/priority-icon"; +import { PriorityIcon } from "components/icons/priority-icon"; +// helpers +import { capitalizeFirstLetter } from "helpers/string.helper"; // types -import { ICurrentUserResponse, IIssue } from "types"; +import { ICurrentUserResponse, IIssue, TIssuePriorities } from "types"; // constants import { PRIORITIES } from "constants/project"; -// services -import trackEventServices from "services/track-event.service"; -// helper -import { capitalizeFirstLetter } from "helpers/string.helper"; type Props = { issue: IIssue; @@ -42,7 +42,7 @@ export const ViewPrioritySelect: React.FC = ({ return ( { + onChange={(data: TIssuePriorities) => { partialUpdateIssue({ priority: data }, issue); trackEventServices.trackIssuePartialPropertyUpdateEvent( { @@ -77,9 +77,9 @@ export const ViewPrioritySelect: React.FC = ({ position={tooltipPosition} > - {getPriorityIcon( - issue.priority && issue.priority !== "" ? issue.priority ?? "" : "None", - `text-sm ${ + = ({ : issue.priority === "low" ? "text-green-500" : "text-custom-text-200" - }` - )} - {noBorder - ? issue.priority && issue.priority !== "" - ? capitalizeFirstLetter(issue.priority) ?? "" - : "None" - : ""} + }`} + /> + {noBorder ? capitalizeFirstLetter(issue.priority ?? "None") : ""} @@ -108,7 +104,7 @@ export const ViewPrioritySelect: React.FC = ({ {PRIORITIES?.map((priority) => ( <> - {getPriorityIcon(priority, "text-sm")} + {priority ?? "None"} > diff --git a/web/components/profile/profile-issues-view.tsx b/web/components/profile/profile-issues-view.tsx index 353b55ae2..f4d75974e 100644 --- a/web/components/profile/profile-issues-view.tsx +++ b/web/components/profile/profile-issues-view.tsx @@ -18,7 +18,7 @@ import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues"; // helpers import { orderArrayBy } from "helpers/array.helper"; // types -import { IIssue, IIssueFilterOptions } from "types"; +import { IIssue, IIssueFilterOptions, TIssuePriorities } from "types"; // fetch-keys import { USER_PROFILE_PROJECT_SEGREGATION, WORKSPACE_LABELS } from "constants/fetch-keys"; @@ -108,7 +108,7 @@ export const ProfileIssuesView = () => { const sourceGroup = source.droppableId; const destinationGroup = destination.droppableId; - draggedItem[groupByProperty] = destinationGroup; + draggedItem[groupByProperty] = destinationGroup as TIssuePriorities; mutateProfileIssues((prevData: any) => { if (!prevData) return prevData; diff --git a/web/components/views/select-filters.tsx b/web/components/views/select-filters.tsx index 77ef80682..52671f41f 100644 --- a/web/components/views/select-filters.tsx +++ b/web/components/views/select-filters.tsx @@ -13,7 +13,7 @@ import { DateFilterModal } from "components/core"; // ui import { Avatar, MultiLevelDropdown } from "components/ui"; // icons -import { StateGroupIcon, getPriorityIcon } from "components/icons"; +import { PriorityIcon, StateGroupIcon } from "components/icons"; // helpers import { getStatesList } from "helpers/state.helper"; import { checkIfArraysHaveSameElements } from "helpers/array.helper"; @@ -99,7 +99,8 @@ export const SelectFilters: React.FC = ({ id: priority === null ? "null" : priority, label: ( - {getPriorityIcon(priority)} {priority ?? "None"} + + {priority ?? "None"} ), value: { diff --git a/web/components/web-view/issue-properties-detail.tsx b/web/components/web-view/issue-properties-detail.tsx index 6a247365b..2fe0356f5 100644 --- a/web/components/web-view/issue-properties-detail.tsx +++ b/web/components/web-view/issue-properties-detail.tsx @@ -109,7 +109,7 @@ export const IssuePropertiesDetail: React.FC = (props) => { render={({ field: { value } }) => ( submitChanges({ priority: val })} + onChange={(val) => submitChanges({ priority: val })} /> )} /> diff --git a/web/components/web-view/select-priority.tsx b/web/components/web-view/select-priority.tsx index 87067bc7d..ce7eef343 100644 --- a/web/components/web-view/select-priority.tsx +++ b/web/components/web-view/select-priority.tsx @@ -8,15 +8,17 @@ import { ChevronDown } from "lucide-react"; import { PRIORITIES } from "constants/project"; // components -import { getPriorityIcon } from "components/icons"; +import { PriorityIcon } from "components/icons"; import { WebViewModal } from "./web-view-modal"; // helpers import { capitalizeFirstLetter } from "helpers/string.helper"; +// types +import { TIssuePriorities } from "types"; type Props = { value: any; - onChange: (value: any) => void; + onChange: (value: TIssuePriorities) => void; disabled?: boolean; }; @@ -59,7 +61,7 @@ export const PrioritySelect: React.FC = (props) => { : "border-custom-border-200 text-custom-text-200" }`} > - {getPriorityIcon(priority, "text-sm")} + ), })) || [] diff --git a/web/constants/project.ts b/web/constants/project.ts index 374ce26b9..1a366ead6 100644 --- a/web/constants/project.ts +++ b/web/constants/project.ts @@ -1,3 +1,5 @@ +import { TIssuePriorities } from "types"; + export const NETWORK_CHOICES: { key: 0 | 2; label: string; icon: string }[] = [ { key: 0, @@ -19,7 +21,7 @@ export const GROUP_CHOICES = { cancelled: "Cancelled", }; -export const PRIORITIES = ["urgent", "high", "medium", "low", null]; +export const PRIORITIES: TIssuePriorities[] = ["urgent", "high", "medium", "low", null]; export const MONTHS = [ "January", diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/[archivedIssueId].tsx b/web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/[archivedIssueId].tsx index a48207db3..e4a1c37b2 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/[archivedIssueId].tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/[archivedIssueId].tsx @@ -26,7 +26,7 @@ import { PROJECT_ISSUES_ACTIVITY, ISSUE_DETAILS } from "constants/fetch-keys"; // helper import { truncateText } from "helpers/string.helper"; -const defaultValues = { +const defaultValues: Partial = { name: "", description: "", description_html: "", diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx b/web/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx index 916c0141e..c40f936de 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx @@ -27,7 +27,7 @@ import { PROJECT_ISSUES_ACTIVITY, ISSUE_DETAILS } from "constants/fetch-keys"; // helper import { truncateText } from "helpers/string.helper"; -const defaultValues = { +const defaultValues: Partial = { assignees_list: [], description: "", description_html: "", diff --git a/web/types/issues.d.ts b/web/types/issues.d.ts index 93e1598f3..cdc0a391a 100644 --- a/web/types/issues.d.ts +++ b/web/types/issues.d.ts @@ -102,7 +102,7 @@ export interface IIssue { name: string; parent: string | null; parent_detail: IIssueParent | null; - priority: string | null; + priority: TIssuePriorities; project: string; project_detail: IProjectLite; sequence_id: number; @@ -294,3 +294,5 @@ export interface IIssueViewProps { properties: Properties; showEmptyGroups: boolean; } + +export type TIssuePriorities = "urgent" | "high" | "medium" | "low" | null; From 6867154963ba19b681ec65e1e2340e838b2a9614 Mon Sep 17 00:00:00 2001 From: Henit Chobisa Date: Mon, 11 Sep 2023 18:02:56 +0530 Subject: [PATCH 09/11] chore: added pre-release tag for workflow publications (#2133) * chore: added pre-release tag for workflow publications * chore: added backend services under a single image * chore: exposed backend port for compose hub * chore: removed backend exposed ports --- .github/workflows/Update_Docker_Images.yml | 2 +- docker-compose-hub.yml | 4 ++-- docker-compose.yml | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/Update_Docker_Images.yml b/.github/workflows/Update_Docker_Images.yml index 57dbb4a67..64b7eb085 100644 --- a/.github/workflows/Update_Docker_Images.yml +++ b/.github/workflows/Update_Docker_Images.yml @@ -2,7 +2,7 @@ name: Update Docker Images for Plane on Release on: release: - types: [released] + types: [released, prereleased] jobs: build_push_backend: diff --git a/docker-compose-hub.yml b/docker-compose-hub.yml index 56dbbe670..0e42c83a8 100644 --- a/docker-compose-hub.yml +++ b/docker-compose-hub.yml @@ -85,7 +85,7 @@ services: plane-worker: container_name: planebgworker - image: makeplane/plane-worker:latest + image: makeplane/plane-backend:latest restart: always command: ./bin/worker env_file: @@ -99,7 +99,7 @@ services: plane-beat-worker: container_name: planebeatworker - image: makeplane/plane-worker:latest + image: makeplane/plane-backend:latest restart: always command: ./bin/beat env_file: diff --git a/docker-compose.yml b/docker-compose.yml index e51f88c55..cf631face 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -90,8 +90,6 @@ services: DOCKER_BUILDKIT: 1 restart: always command: ./bin/takeoff - ports: - - 8000:8000 env_file: - .env environment: From 9bff10de6d880ab0d9a7e3e076939bfd6f9dd710 Mon Sep 17 00:00:00 2001 From: Bavisetti Narayan <72156168+NarayanBavisetti@users.noreply.github.com> Date: Tue, 12 Sep 2023 13:06:49 +0530 Subject: [PATCH 10/11] chore: changed issue priority from NULL to none (#2142) * chore: changed issue priority from NULL to none * fix: deleted the migration file --- apiserver/plane/api/views/issue.py | 8 ++++---- apiserver/plane/api/views/workspace.py | 2 +- apiserver/plane/db/models/issue.py | 4 ++-- apiserver/plane/utils/issue_filters.py | 24 ++++-------------------- 4 files changed, 11 insertions(+), 27 deletions(-) diff --git a/apiserver/plane/api/views/issue.py b/apiserver/plane/api/views/issue.py index 334ad2514..cf4fa46d4 100644 --- a/apiserver/plane/api/views/issue.py +++ b/apiserver/plane/api/views/issue.py @@ -178,7 +178,7 @@ class IssueViewSet(BaseViewSet): filters = issue_filters(request.query_params, "GET") # Custom ordering for priority and state - priority_order = ["urgent", "high", "medium", "low", None] + priority_order = ["urgent", "high", "medium", "low", "none"] state_order = ["backlog", "unstarted", "started", "completed", "cancelled"] order_by_param = request.GET.get("order_by", "-created_at") @@ -331,7 +331,7 @@ class UserWorkSpaceIssues(BaseAPIView): try: filters = issue_filters(request.query_params, "GET") # Custom ordering for priority and state - priority_order = ["urgent", "high", "medium", "low", None] + priority_order = ["urgent", "high", "medium", "low", "none"] state_order = ["backlog", "unstarted", "started", "completed", "cancelled"] order_by_param = request.GET.get("order_by", "-created_at") @@ -1068,7 +1068,7 @@ class IssueArchiveViewSet(BaseViewSet): show_sub_issues = request.GET.get("show_sub_issues", "true") # Custom ordering for priority and state - priority_order = ["urgent", "high", "medium", "low", None] + priority_order = ["urgent", "high", "medium", "low", "none"] state_order = ["backlog", "unstarted", "started", "completed", "cancelled"] order_by_param = request.GET.get("order_by", "-created_at") @@ -2078,7 +2078,7 @@ class ProjectIssuesPublicEndpoint(BaseAPIView): filters = issue_filters(request.query_params, "GET") # Custom ordering for priority and state - priority_order = ["urgent", "high", "medium", "low", None] + priority_order = ["urgent", "high", "medium", "low", "none"] state_order = ["backlog", "unstarted", "started", "completed", "cancelled"] order_by_param = request.GET.get("order_by", "-created_at") diff --git a/apiserver/plane/api/views/workspace.py b/apiserver/plane/api/views/workspace.py index 2ec3f324a..2d1ee8132 100644 --- a/apiserver/plane/api/views/workspace.py +++ b/apiserver/plane/api/views/workspace.py @@ -1072,7 +1072,7 @@ class WorkspaceUserProfileStatsEndpoint(BaseAPIView): .order_by("state_group") ) - priority_order = ["urgent", "high", "medium", "low", None] + priority_order = ["urgent", "high", "medium", "low", "none"] priority_distribution = ( Issue.issue_objects.filter( diff --git a/apiserver/plane/db/models/issue.py b/apiserver/plane/db/models/issue.py index 78e958380..dd16cd963 100644 --- a/apiserver/plane/db/models/issue.py +++ b/apiserver/plane/db/models/issue.py @@ -38,6 +38,7 @@ class Issue(ProjectBaseModel): ("high", "High"), ("medium", "Medium"), ("low", "Low"), + ("none", "None") ) parent = models.ForeignKey( "self", @@ -64,8 +65,7 @@ class Issue(ProjectBaseModel): max_length=30, choices=PRIORITY_CHOICES, verbose_name="Issue Priority", - null=True, - blank=True, + default="none", ) start_date = models.DateField(null=True, blank=True) target_date = models.DateField(null=True, blank=True) diff --git a/apiserver/plane/utils/issue_filters.py b/apiserver/plane/utils/issue_filters.py index 34e1e8203..226d909cd 100644 --- a/apiserver/plane/utils/issue_filters.py +++ b/apiserver/plane/utils/issue_filters.py @@ -1,6 +1,7 @@ from django.utils.timezone import make_aware from django.utils.dateparse import parse_datetime + def filter_state(params, filter, method): if method == "GET": states = params.get("state").split(",") @@ -23,7 +24,6 @@ def filter_state_group(params, filter, method): return filter - def filter_estimate_point(params, filter, method): if method == "GET": estimate_points = params.get("estimate_point").split(",") @@ -39,25 +39,10 @@ def filter_priority(params, filter, method): if method == "GET": priorities = params.get("priority").split(",") if len(priorities) and "" not in priorities: - if len(priorities) == 1 and "null" in priorities: - filter["priority__isnull"] = True - elif len(priorities) > 1 and "null" in priorities: - filter["priority__isnull"] = True - filter["priority__in"] = [p for p in priorities if p != "null"] - else: - filter["priority__in"] = [p for p in priorities if p != "null"] - + filter["priority__in"] = priorities else: if params.get("priority", None) and len(params.get("priority")): - priorities = params.get("priority") - if len(priorities) == 1 and "null" in priorities: - filter["priority__isnull"] = True - elif len(priorities) > 1 and "null" in priorities: - filter["priority__isnull"] = True - filter["priority__in"] = [p for p in priorities if p != "null"] - else: - filter["priority__in"] = [p for p in priorities if p != "null"] - + filter["priority__in"] = params.get("priority") return filter @@ -229,7 +214,6 @@ def filter_issue_state_type(params, filter, method): return filter - def filter_project(params, filter, method): if method == "GET": projects = params.get("project").split(",") @@ -329,7 +313,7 @@ def issue_filters(query_params, method): "module": filter_module, "inbox_status": filter_inbox_status, "sub_issue": filter_sub_issue_toggle, - "subscriber": filter_subscribed_issues, + "subscriber": filter_subscribed_issues, "start_target_date": filter_start_target_date_issues, } From 2186db8bbaa07d8a5160d6a5897481cc11181477 Mon Sep 17 00:00:00 2001 From: Dakshesh Jain <65905942+dakshesh14@users.noreply.github.com> Date: Tue, 12 Sep 2023 13:35:15 +0530 Subject: [PATCH 11/11] feat: users can select timezone during onboarding (#2148) feat: using Intl timezone will be automatically selected but they have the option to change it --- web/components/onboarding/user-details.tsx | 40 +++++++++++++++++++++- web/helpers/date-time.helper.ts | 2 ++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/web/components/onboarding/user-details.tsx b/web/components/onboarding/user-details.tsx index 222fc1143..b2ba931c0 100644 --- a/web/components/onboarding/user-details.tsx +++ b/web/components/onboarding/user-details.tsx @@ -9,13 +9,16 @@ import useToast from "hooks/use-toast"; // services import userService from "services/user.service"; // ui -import { CustomSelect, Input, PrimaryButton } from "components/ui"; +import { CustomSearchSelect, CustomSelect, Input, PrimaryButton } from "components/ui"; // types import { ICurrentUserResponse, IUser } from "types"; // fetch-keys import { CURRENT_USER } from "constants/fetch-keys"; +// helpers +import { getUserTimeZoneFromWindow } from "helpers/date-time.helper"; // constants import { USER_ROLES } from "constants/workspace"; +import { TIME_ZONES } from "constants/timezones"; const defaultValues: Partial = { first_name: "", @@ -27,6 +30,12 @@ type Props = { user?: IUser; }; +const timeZoneOptions = TIME_ZONES.map((timeZone) => ({ + value: timeZone.value, + query: timeZone.label + " " + timeZone.value, + content: timeZone.label, +})); + export const UserDetails: React.FC = ({ user }) => { const { setToastAlert } = useToast(); @@ -84,6 +93,7 @@ export const UserDetails: React.FC = ({ user }) => { first_name: user.first_name, last_name: user.last_name, role: user.role, + user_timezone: getUserTimeZoneFromWindow(), }); } }, [user, reset]); @@ -162,6 +172,34 @@ export const UserDetails: React.FC = ({ user }) => { {errors.role && {errors.role.message}} + + What time zone are you in? + + ( + t.value === value)?.label ?? value + : "Select a timezone" + } + options={timeZoneOptions} + onChange={onChange} + verticalPosition="top" + optionsClassName="w-full" + input + /> + )} + /> + {errors?.user_timezone && ( + {errors.user_timezone.message} + )} + + diff --git a/web/helpers/date-time.helper.ts b/web/helpers/date-time.helper.ts index 39a68bf3b..6784a9aa6 100644 --- a/web/helpers/date-time.helper.ts +++ b/web/helpers/date-time.helper.ts @@ -403,3 +403,5 @@ export const findTotalDaysInRange = ( return diffInDays; }; + +export const getUserTimeZoneFromWindow = () => Intl.DateTimeFormat().resolvedOptions().timeZone;
{state.name}
{state.description}