Group by
@@ -336,6 +335,7 @@ const SingleCycle: React.FC
= () => {
groupByOptions.find((option) => option.key === groupByProperty)
?.name ?? "Select"
}
+ width="auto"
>
{groupByOptions.map((option) => (
= () => {
orderByOptions.find((option) => option.key === orderBy)?.name ??
"Select"
}
+ width="auto"
>
{orderByOptions.map((option) =>
groupByProperty === "priority" && option.key === "priority" ? null : (
@@ -374,6 +375,7 @@ const SingleCycle: React.FC = () => {
filterIssueOptions.find((option) => option.key === filterIssue)
?.name ?? "Select"
}
+ width="auto"
>
{filterIssueOptions.map((option) => (
= () => {
selectedGroup={groupByProperty}
properties={properties}
openCreateIssueModal={openCreateIssueModal}
- openIssuesListModal={() => {
- return;
- }}
+ openIssuesListModal={openIssuesListModal}
removeIssueFromCycle={removeIssueFromCycle}
/>
) : (
@@ -434,9 +434,7 @@ const SingleCycle: React.FC = () => {
selectedGroup={groupByProperty}
members={members}
openCreateIssueModal={openCreateIssueModal}
- openIssuesListModal={() => {
- return;
- }}
+ openIssuesListModal={openIssuesListModal}
/>
)}
diff --git a/apps/app/pages/projects/[projectId]/cycles/index.tsx b/apps/app/pages/projects/[projectId]/cycles/index.tsx
index 16d3d2227..1106d5134 100644
--- a/apps/app/pages/projects/[projectId]/cycles/index.tsx
+++ b/apps/app/pages/projects/[projectId]/cycles/index.tsx
@@ -5,46 +5,31 @@ import { useRouter } from "next/router";
import type { NextPage } from "next";
// swr
import useSWR from "swr";
+// hoc
+import withAuth from "lib/hoc/withAuthWrapper";
// services
import sprintService from "lib/services/cycles.service";
// hooks
import useUser from "lib/hooks/useUser";
-import useIssuesProperties from "lib/hooks/useIssuesProperties";
-// fetching keys
-import { CYCLE_LIST } from "constants/fetch-keys";
-// hoc
-import withAuth from "lib/hoc/withAuthWrapper";
// layouts
import AppLayout from "layouts/app-layout";
// components
-import CycleIssuesListModal from "components/project/cycles/CycleIssuesListModal";
-import ConfirmIssueDeletion from "components/project/issues/confirm-issue-deletion";
-import ConfirmSprintDeletion from "components/project/cycles/ConfirmCycleDeletion";
-import CreateUpdateIssuesModal from "components/project/issues/CreateUpdateIssueModal";
-import CreateUpdateSprintsModal from "components/project/cycles/CreateUpdateCyclesModal";
+import CreateUpdateCycleModal from "components/project/cycles/create-update-cycle-modal";
import CycleStatsView from "components/project/cycles/stats-view";
-// headless ui
-import { Popover, Transition } from "@headlessui/react";
// ui
import { BreadcrumbItem, Breadcrumbs, HeaderButton, Spinner, EmptySpace, EmptySpaceItem } from "ui";
// icons
-import { ArrowPathIcon, ChevronDownIcon, PlusIcon } from "@heroicons/react/24/outline";
+import { ArrowPathIcon, PlusIcon } from "@heroicons/react/24/outline";
// types
-import { IIssue, ICycle, SelectSprintType, SelectIssue, Properties } from "types";
-// constants
-import { classNames, replaceUnderscoreIfSnakeCase } from "constants/common";
+import { ICycle, SelectSprintType } from "types";
+// fetching keys
+import { CYCLE_LIST } from "constants/fetch-keys";
const ProjectSprints: NextPage = () => {
- const [isOpen, setIsOpen] = useState(false);
- const [selectedSprint, setSelectedSprint] = useState
();
+ const [selectedCycle, setSelectedCycle] = useState();
+ const [createUpdateCycleModal, setCreateUpdateCycleModal] = useState(false);
- const [isIssueModalOpen, setIsIssueModalOpen] = useState(false);
- const [selectedIssues, setSelectedIssues] = useState();
- const [deleteIssue, setDeleteIssue] = useState();
- const [cycleIssuesListModal, setCycleIssuesListModal] = useState(false);
- const [cycleId, setCycleId] = useState("");
-
- const { activeWorkspace, activeProject, issues } = useUser();
+ const { activeWorkspace, activeProject } = useUser();
const router = useRouter();
@@ -57,45 +42,13 @@ const ProjectSprints: NextPage = () => {
: null
);
- const [properties, setProperties] = useIssuesProperties(
- activeWorkspace?.slug,
- projectId as string
- );
-
- const openCreateIssueModal = (
- cycleId: string,
- issue?: IIssue,
- actionType: "create" | "edit" | "delete" = "create"
- ) => {
- const cycle = cycles?.find((cycle) => cycle.id === cycleId);
- if (cycle) {
- setSelectedSprint({
- ...cycle,
- actionType: "create-issue",
- });
- if (issue) setSelectedIssues({ ...issue, actionType });
- setIsIssueModalOpen(true);
- }
- };
-
- const openIssuesListModal = (cycleId: string) => {
- setCycleId(cycleId);
- setCycleIssuesListModal(true);
- };
-
useEffect(() => {
- if (isOpen) return;
+ if (createUpdateCycleModal) return;
const timer = setTimeout(() => {
- setSelectedSprint(undefined);
+ setSelectedCycle(undefined);
clearTimeout(timer);
}, 500);
- }, [isOpen]);
-
- useEffect(() => {
- if (selectedIssues?.actionType === "delete") {
- setDeleteIssue(selectedIssues.id);
- }
- }, [selectedIssues]);
+ }, [createUpdateCycleModal]);
return (
{
}
right={
-
-
- {({ open }) => (
- <>
-
- View
-
-
-
-
-
-
-
-
Properties
-
- {Object.keys(properties).map((key) => (
-
- ))}
-
-
-
-
-
- >
- )}
-
-
setIsOpen(true)} />
-
+ {
+ const e = new KeyboardEvent("keydown", {
+ ctrlKey: true,
+ key: "q",
+ });
+ document.dispatchEvent(e);
+ }}
+ />
}
>
-
-
- setDeleteIssue(undefined)}
- isOpen={!!deleteIssue}
- data={selectedIssues}
- />
-
- setCycleIssuesListModal(false)}
- issues={issues}
- cycleId={cycleId}
+ data={selectedCycle}
/>
{cycles ? (
cycles.length > 0 ? (
-
+
) : (
@@ -221,7 +106,7 @@ const ProjectSprints: NextPage = () => {
}
Icon={PlusIcon}
- action={() => setIsOpen(true)}
+ action={() => setCreateUpdateCycleModal(true)}
/>
diff --git a/apps/app/pages/projects/[projectId]/issues/[issueId].tsx b/apps/app/pages/projects/[projectId]/issues/[issueId].tsx
index 3940e3a1e..83d47f4ac 100644
--- a/apps/app/pages/projects/[projectId]/issues/[issueId].tsx
+++ b/apps/app/pages/projects/[projectId]/issues/[issueId].tsx
@@ -8,7 +8,7 @@ import React, { useCallback, useEffect, useState } from "react";
// swr
import useSWR, { mutate } from "swr";
// react hook form
-import { useForm, Controller } from "react-hook-form";
+import { useForm } from "react-hook-form";
// headless ui
import { Disclosure, Menu, Tab, Transition } from "@headlessui/react";
// services
@@ -28,7 +28,7 @@ import AppLayout from "layouts/app-layout";
// components
import CreateUpdateIssuesModal from "components/project/issues/CreateUpdateIssueModal";
import IssueCommentSection from "components/project/issues/issue-detail/comment/IssueCommentSection";
-import AddAsSubIssue from "components/command-palette/addAsSubIssue";
+import AddAsSubIssue from "components/project/issues/issue-detail/add-as-sub-issue";
import ConfirmIssueDeletion from "components/project/issues/confirm-issue-deletion";
// common
import { debounce } from "constants/common";
diff --git a/apps/app/pages/projects/[projectId]/issues/index.tsx b/apps/app/pages/projects/[projectId]/issues/index.tsx
index da5df3104..12657cf60 100644
--- a/apps/app/pages/projects/[projectId]/issues/index.tsx
+++ b/apps/app/pages/projects/[projectId]/issues/index.tsx
@@ -219,6 +219,7 @@ const ProjectIssues: NextPage = () => {
groupByOptions.find((option) => option.key === groupByProperty)?.name ??
"Select"
}
+ width="auto"
>
{groupByOptions.map((option) => (
{
orderByOptions.find((option) => option.key === orderBy)?.name ??
"Select"
}
+ width="auto"
>
{orderByOptions.map((option) =>
groupByProperty === "priority" && option.key === "priority" ? null : (
@@ -257,6 +259,7 @@ const ProjectIssues: NextPage = () => {
filterIssueOptions.find((option) => option.key === filterIssue)?.name ??
"Select"
}
+ width="auto"
>
{filterIssueOptions.map((option) => (
{
+ const { activeWorkspace, activeProject } = useUser();
+
+ const router = useRouter();
+ const { projectId } = router.query;
+
+ const { data: modules } = useSWR(
+ activeWorkspace && projectId ? MODULE_LIST(projectId as string) : null,
+ activeWorkspace && projectId
+ ? () => modulesService.getModules(activeWorkspace.slug, projectId as string)
+ : null
+ );
+
+ console.log(modules);
+
+ return (
+
+
+
+
+ }
+ right={
+ {
+ const e = new KeyboardEvent("keydown", {
+ ctrlKey: true,
+ key: "m",
+ });
+ document.dispatchEvent(e);
+ }}
+ />
+ }
+ >
+ {modules ? (
+ modules.length > 0 ? (
+
+ {modules.map((module) => (
+
+
{module.name}
+
{module.description}
+
+ ))}
+
+ ) : (
+
+
+
+ Use Ctrl/Command + Q
{" "}
+ shortcut to create a new cycle
+
+ }
+ Icon={PlusIcon}
+ action={() => {
+ return;
+ }}
+ />
+
+
+ )
+ ) : (
+
+
+
+ )}
+
+ );
+};
+
+export default withAuth(ProjectModules);
diff --git a/apps/app/pages/projects/index.tsx b/apps/app/pages/projects/index.tsx
index f8cfd12b5..fdc75542d 100644
--- a/apps/app/pages/projects/index.tsx
+++ b/apps/app/pages/projects/index.tsx
@@ -57,7 +57,23 @@ const Projects: NextPage = () => {
};
return (
-
+
+
+
+ }
+ right={
+ {
+ const e = new KeyboardEvent("keydown", { key: "p", ctrlKey: true });
+ document.dispatchEvent(e);
+ }}
+ />
+ }
+ >
setDeleteProject(null)}
@@ -91,20 +107,6 @@ const Projects: NextPage = () => {
) : (
-
-
-
-
-
Projects
- {
- const e = new KeyboardEvent("keydown", { key: "p", ctrlKey: true });
- document.dispatchEvent(e);
- }}
- />
-
{projects.map((item) => (
= {
[Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends object
diff --git a/apps/app/types/issues.d.ts b/apps/app/types/issues.d.ts
index 484b54eb9..1a2fb9b38 100644
--- a/apps/app/types/issues.d.ts
+++ b/apps/app/types/issues.d.ts
@@ -1,4 +1,4 @@
-import type { IState, IUser, IProject } from "./";
+import type { IState, IUser, IProject, ICycle } from "./";
export interface IssueResponse {
next_cursor: string;
@@ -17,6 +17,7 @@ export interface IIssue {
label_details: any[];
assignee_details: IUser[];
assignees_list: string[];
+ bridge?: string;
blocked_by_issue_details: any[];
blocked_issues: BlockeIssue[];
blocker_issues: BlockeIssue[];
@@ -26,6 +27,18 @@ export interface IIssue {
updated_at: Date;
name: string;
// TODO change type of description
+ issue_cycle: {
+ created_at: Date;
+ created_by: string;
+ cycle: string;
+ cycle_detail: ICycle;
+ id: string;
+ issue: string;
+ project: string;
+ updated_at: Date;
+ updated_by: string;
+ workspace: string;
+ };
description: any;
priority: string | null;
start_date: string | null;
diff --git a/apps/app/types/modules.d.ts b/apps/app/types/modules.d.ts
new file mode 100644
index 000000000..f6d6d3acb
--- /dev/null
+++ b/apps/app/types/modules.d.ts
@@ -0,0 +1,28 @@
+import type { IUser, IIssue, IProject } from ".";
+
+export interface IModule {
+ created_at: Date;
+ created_by: string;
+ description: string;
+ description_text: any;
+ description_html: any;
+ id: string;
+ lead: string | null;
+ lead_detail: IUserLite;
+ members_list: string[];
+ name: string;
+ project: string;
+ project_detail: IProject;
+ start_date: Date | null;
+ status: "backlog" | "planned" | "in-progress" | "paused" | "completed" | "cancelled";
+ target_date: Date | null;
+ updated_at: Date;
+ updated_by: string;
+ workspace: string;
+}
+
+export type SelectModuleType =
+ | (IModule & { actionType: "edit" | "delete" | "create-issue" })
+ | undefined;
+
+export type SelectIssue = (IIssue & { actionType: "edit" | "delete" | "create" }) | undefined;
diff --git a/apps/app/ui/Button/index.tsx b/apps/app/ui/Button/index.tsx
index 878a6678d..3aea14920 100644
--- a/apps/app/ui/Button/index.tsx
+++ b/apps/app/ui/Button/index.tsx
@@ -20,7 +20,7 @@ const Button = React.forwardRef(
onClick,
type = "button",
size = "sm",
- className,
+ className = "",
theme = "primary",
disabled = false,
},
@@ -39,7 +39,7 @@ const Button = React.forwardRef(
disabled ? "opacity-70" : ""
} text-white shadow-sm bg-theme hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 border border-transparent`
: theme === "secondary"
- ? "border bg-white"
+ ? "border bg-white hover:bg-gray-100"
: theme === "success"
? `${
disabled ? "opacity-70" : ""
@@ -54,7 +54,7 @@ const Button = React.forwardRef(
: size === "lg"
? "px-4 py-2 text-base"
: "px-2.5 py-2 text-sm",
- className || ""
+ className
)}
>
{children}
diff --git a/apps/app/ui/CustomMenu/index.tsx b/apps/app/ui/CustomMenu/index.tsx
index 9618e6da1..211c413c1 100644
--- a/apps/app/ui/CustomMenu/index.tsx
+++ b/apps/app/ui/CustomMenu/index.tsx
@@ -4,28 +4,41 @@ import Link from "next/link";
// headless ui
import { Menu, Transition } from "@headlessui/react";
// icons
-import { ChevronDownIcon } from "@heroicons/react/20/solid";
-// commons
-import { classNames } from "constants/common";
+import { ChevronDownIcon, EllipsisHorizontalIcon } from "@heroicons/react/24/outline";
// types
import type { MenuItemProps, Props } from "./types";
+// constants
+import { classNames } from "constants/common";
-const CustomMenu = ({ children, label, textAlignment }: Props) => {
+const CustomMenu = ({
+ children,
+ label,
+ className = "",
+ ellipsis = false,
+ width,
+ textAlignment,
+}: Props) => {
return (
-