-
+
{store.issue.getFilteredIssuesByState(_state.id) &&
store.issue.getFilteredIssuesByState(_state.id).length > 0 ? (
-
+
{store.issue.getFilteredIssuesByState(_state.id).map((_issue: IIssue) => (
-
+
))}
) : (
-
- No Issues are available.
+
+
+ No issues in this state
)}
diff --git a/space/components/issues/board-views/list/block.tsx b/space/components/issues/board-views/list/block.tsx
new file mode 100644
index 000000000..bdf39b84f
--- /dev/null
+++ b/space/components/issues/board-views/list/block.tsx
@@ -0,0 +1,84 @@
+import { FC } from "react";
+import { useRouter } from "next/router";
+import { observer } from "mobx-react-lite";
+// components
+import { IssueBlockPriority } from "components/issues/board-views/block-priority";
+import { IssueBlockState } from "components/issues/board-views/block-state";
+import { IssueBlockLabels } from "components/issues/board-views/block-labels";
+import { IssueBlockDueDate } from "components/issues/board-views/block-due-date";
+// mobx hook
+import { useMobxStore } from "lib/mobx/store-provider";
+// interfaces
+import { IIssue } from "types/issue";
+// store
+import { RootStore } from "store/root";
+
+export const IssueListBlock: FC<{ issue: IIssue }> = observer((props) => {
+ const { issue } = props;
+ // store
+ const { project: projectStore, issueDetails: issueDetailStore }: RootStore = useMobxStore();
+ // router
+ const router = useRouter();
+ const { workspace_slug, project_slug, board } = router.query;
+
+ const handleBlockClick = () => {
+ issueDetailStore.setPeekId(issue.id);
+ router.push(
+ {
+ pathname: `/${workspace_slug?.toString()}/${project_slug}`,
+ query: {
+ board: board?.toString(),
+ peekId: issue.id,
+ },
+ },
+ undefined,
+ { shallow: true }
+ );
+ // router.push(`/${workspace_slug?.toString()}/${project_slug}?board=${board?.toString()}&peekId=${issue.id}`);
+ };
+
+ return (
+
+
+ {/* id */}
+
+ {projectStore?.project?.identifier}-{issue?.sequence_id}
+
+ {/* name */}
+
+ {issue.name}
+
+
+
+
+ {/* priority */}
+ {issue?.priority && (
+
+
+
+ )}
+
+ {/* state */}
+ {issue?.state_detail && (
+
+
+
+ )}
+
+ {/* labels */}
+ {issue?.label_details && issue?.label_details.length > 0 && (
+
+
+
+ )}
+
+ {/* due date */}
+ {issue?.target_date && (
+
+
+
+ )}
+
+
+ );
+});
diff --git a/apps/space/components/issues/board-views/kanban/header.tsx b/space/components/issues/board-views/list/header.tsx
similarity index 50%
rename from apps/space/components/issues/board-views/kanban/header.tsx
rename to space/components/issues/board-views/list/header.tsx
index 43c19f5f5..83312e7b9 100644
--- a/apps/space/components/issues/board-views/kanban/header.tsx
+++ b/space/components/issues/board-views/list/header.tsx
@@ -1,9 +1,9 @@
-"use client";
-
// mobx react lite
import { observer } from "mobx-react-lite";
// interfaces
-import { IIssueState } from "store/types/issue";
+import { IIssueState } from "types/issue";
+// icons
+import { StateGroupIcon } from "components/icons";
// constants
import { issueGroupFilter } from "constants/data";
// mobx hook
@@ -18,14 +18,12 @@ export const IssueListHeader = observer(({ state }: { state: IIssueState }) => {
if (stateGroup === null) return <>>;
return (
-
-
-
-
-
{state?.name}
-
- {store.issue.getCountOfIssuesByState(state.id)}
+
+
+
+
{state?.name}
+
{store.issue.getCountOfIssuesByState(state.id)}
);
});
diff --git a/space/components/issues/board-views/list/index.tsx b/space/components/issues/board-views/list/index.tsx
new file mode 100644
index 000000000..1c6900dd9
--- /dev/null
+++ b/space/components/issues/board-views/list/index.tsx
@@ -0,0 +1,38 @@
+import { observer } from "mobx-react-lite";
+// components
+import { IssueListHeader } from "components/issues/board-views/list/header";
+import { IssueListBlock } from "components/issues/board-views/list/block";
+// interfaces
+import { IIssueState, IIssue } from "types/issue";
+// mobx hook
+import { useMobxStore } from "lib/mobx/store-provider";
+// store
+import { RootStore } from "store/root";
+
+export const IssueListView = observer(() => {
+ const { issue: issueStore }: RootStore = useMobxStore();
+
+ return (
+ <>
+ {issueStore?.states &&
+ issueStore?.states.length > 0 &&
+ issueStore?.states.map((_state: IIssueState) => (
+
+
+ {issueStore.getFilteredIssuesByState(_state.id) &&
+ issueStore.getFilteredIssuesByState(_state.id).length > 0 ? (
+
+ {issueStore.getFilteredIssuesByState(_state.id).map((_issue: IIssue) => (
+
+ ))}
+
+ ) : (
+
+ No Issues are available.
+
+ )}
+
+ ))}
+ >
+ );
+});
diff --git a/apps/space/components/issues/board-views/spreadsheet/index.tsx b/space/components/issues/board-views/spreadsheet/index.tsx
similarity index 100%
rename from apps/space/components/issues/board-views/spreadsheet/index.tsx
rename to space/components/issues/board-views/spreadsheet/index.tsx
diff --git a/space/components/issues/filters-render/index.tsx b/space/components/issues/filters-render/index.tsx
new file mode 100644
index 000000000..d797d1506
--- /dev/null
+++ b/space/components/issues/filters-render/index.tsx
@@ -0,0 +1,53 @@
+import { useRouter } from "next/router";
+// mobx react lite
+import { observer } from "mobx-react-lite";
+// components
+import IssueStateFilter from "./state";
+import IssueLabelFilter from "./label";
+import IssuePriorityFilter from "./priority";
+// mobx hook
+import { useMobxStore } from "lib/mobx/store-provider";
+import { RootStore } from "store/root";
+
+const IssueFilter = observer(() => {
+ const store: RootStore = useMobxStore();
+
+ const router = useRouter();
+ const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
+
+ const clearAllFilters = () => {
+ // router.replace(
+ // store.issue.getURLDefinition(workspace_slug, project_slug, {
+ // key: "all",
+ // removeAll: true,
+ // })
+ // );
+ };
+
+ // if (store.issue.getIfFiltersIsEmpty()) return null;
+
+ return (
+
+
+ {/* state */}
+ {/* {store.issue.checkIfFilterExistsForKey("state") &&
} */}
+ {/* labels */}
+ {/* {store.issue.checkIfFilterExistsForKey("label") &&
} */}
+ {/* priority */}
+ {/* {store.issue.checkIfFilterExistsForKey("priority") &&
} */}
+ {/* clear all filters */}
+
+
Clear all filters
+
+ close
+
+
+
+
+ );
+});
+
+export default IssueFilter;
diff --git a/space/components/issues/filters-render/label/filter-label-block.tsx b/space/components/issues/filters-render/label/filter-label-block.tsx
new file mode 100644
index 000000000..a54fb65e4
--- /dev/null
+++ b/space/components/issues/filters-render/label/filter-label-block.tsx
@@ -0,0 +1,43 @@
+import { useRouter } from "next/router";
+// mobx react lite
+import { observer } from "mobx-react-lite";
+// mobx hook
+import { useMobxStore } from "lib/mobx/store-provider";
+// interfaces
+import { IIssueLabel } from "types/issue";
+
+export const RenderIssueLabel = observer(({ label }: { label: IIssueLabel }) => {
+ const store = useMobxStore();
+
+ const router = useRouter();
+ const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
+
+ const removeLabelFromFilter = () => {
+ // router.replace(
+ // store.issue.getURLDefinition(workspace_slug, project_slug, {
+ // key: "label",
+ // value: label?.id,
+ // })
+ // );
+ };
+
+ return (
+
+
+
+
{label?.name}
+
+ close
+
+
+ );
+});
diff --git a/space/components/issues/filters-render/label/index.tsx b/space/components/issues/filters-render/label/index.tsx
new file mode 100644
index 000000000..1d9a4f990
--- /dev/null
+++ b/space/components/issues/filters-render/label/index.tsx
@@ -0,0 +1,51 @@
+import { useRouter } from "next/router";
+// mobx react lite
+import { observer } from "mobx-react-lite";
+// components
+import { RenderIssueLabel } from "./filter-label-block";
+// interfaces
+import { IIssueLabel } from "types/issue";
+// mobx hook
+import { useMobxStore } from "lib/mobx/store-provider";
+import { RootStore } from "store/root";
+
+const IssueLabelFilter = observer(() => {
+ const store: RootStore = useMobxStore();
+
+ const router = useRouter();
+ const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
+
+ const clearLabelFilters = () => {
+ // router.replace(
+ // store.issue.getURLDefinition(workspace_slug, project_slug, {
+ // key: "label",
+ // removeAll: true,
+ // })
+ // );
+ };
+
+ return (
+ <>
+
+
Labels
+
+ {/* {store?.issue?.labels &&
+ store?.issue?.labels.map(
+ (_label: IIssueLabel, _index: number) =>
+ store.issue.getUserSelectedFilter("label", _label.id) && (
+
+ )
+ )} */}
+
+
+ close
+
+
+ >
+ );
+});
+
+export default IssueLabelFilter;
diff --git a/space/components/issues/filters-render/priority/filter-priority-block.tsx b/space/components/issues/filters-render/priority/filter-priority-block.tsx
new file mode 100644
index 000000000..5fd1ef1a7
--- /dev/null
+++ b/space/components/issues/filters-render/priority/filter-priority-block.tsx
@@ -0,0 +1,42 @@
+import { useRouter } from "next/router";
+// mobx react lite
+import { observer } from "mobx-react-lite";
+// mobx hook
+import { useMobxStore } from "lib/mobx/store-provider";
+// interfaces
+import { IIssuePriorityFilters } from "types/issue";
+
+export const RenderIssuePriority = observer(({ priority }: { priority: IIssuePriorityFilters }) => {
+ const store = useMobxStore();
+
+ const router = useRouter();
+ const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
+
+ const removePriorityFromFilter = () => {
+ // router.replace(
+ // store.issue.getURLDefinition(workspace_slug, project_slug, {
+ // key: "priority",
+ // value: priority?.key,
+ // })
+ // );
+ };
+
+ return (
+
+
+ {priority?.icon}
+
+
{priority?.title}
+
+ close
+
+
+ );
+});
diff --git a/space/components/issues/filters-render/priority/index.tsx b/space/components/issues/filters-render/priority/index.tsx
new file mode 100644
index 000000000..100ba1761
--- /dev/null
+++ b/space/components/issues/filters-render/priority/index.tsx
@@ -0,0 +1,53 @@
+import { useRouter } from "next/router";
+// mobx react lite
+import { observer } from "mobx-react-lite";
+// mobx hook
+import { useMobxStore } from "lib/mobx/store-provider";
+// components
+import { RenderIssuePriority } from "./filter-priority-block";
+// interfaces
+import { IIssuePriorityFilters } from "types/issue";
+// constants
+import { issuePriorityFilters } from "constants/data";
+
+const IssuePriorityFilter = observer(() => {
+ const store = useMobxStore();
+
+ const router = useRouter();
+ const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
+
+ const clearPriorityFilters = () => {
+ // router.replace(
+ // store.issue.getURLDefinition(workspace_slug, project_slug, {
+ // key: "priority",
+ // removeAll: true,
+ // })
+ // );
+ };
+
+ return (
+ <>
+
+
Priority
+
+ {/* {issuePriorityFilters.map(
+ (_priority: IIssuePriorityFilters, _index: number) =>
+ store.issue.getUserSelectedFilter("priority", _priority.key) && (
+
+ )
+ )} */}
+
+
{
+ clearPriorityFilters();
+ }}
+ >
+ close
+
+
+ >
+ );
+});
+
+export default IssuePriorityFilter;
diff --git a/space/components/issues/filters-render/state/filter-state-block.tsx b/space/components/issues/filters-render/state/filter-state-block.tsx
new file mode 100644
index 000000000..8445386a4
--- /dev/null
+++ b/space/components/issues/filters-render/state/filter-state-block.tsx
@@ -0,0 +1,43 @@
+import { useRouter } from "next/router";
+// mobx react lite
+import { observer } from "mobx-react-lite";
+// mobx hook
+import { useMobxStore } from "lib/mobx/store-provider";
+// interfaces
+import { IIssueState } from "types/issue";
+// constants
+import { issueGroupFilter } from "constants/data";
+
+export const RenderIssueState = observer(({ state }: { state: IIssueState }) => {
+ const store = useMobxStore();
+
+ const router = useRouter();
+ const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
+
+ const stateGroup = issueGroupFilter(state.group);
+
+ const removeStateFromFilter = () => {
+ // router.replace(
+ // store.issue.getURLDefinition(workspace_slug, project_slug, {
+ // key: "state",
+ // value: state?.id,
+ // })
+ // );
+ };
+
+ if (stateGroup === null) return <>>;
+ return (
+
+
+
+
+
{state?.name}
+
+ close
+
+
+ );
+});
diff --git a/space/components/issues/filters-render/state/index.tsx b/space/components/issues/filters-render/state/index.tsx
new file mode 100644
index 000000000..0198c5215
--- /dev/null
+++ b/space/components/issues/filters-render/state/index.tsx
@@ -0,0 +1,51 @@
+import { useRouter } from "next/router";
+// mobx react lite
+import { observer } from "mobx-react-lite";
+// components
+import { RenderIssueState } from "./filter-state-block";
+// interfaces
+import { IIssueState } from "types/issue";
+// mobx hook
+import { useMobxStore } from "lib/mobx/store-provider";
+import { RootStore } from "store/root";
+
+const IssueStateFilter = observer(() => {
+ const store: RootStore = useMobxStore();
+
+ const router = useRouter();
+ const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
+
+ const clearStateFilters = () => {
+ // router.replace(
+ // store.issue.getURLDefinition(workspace_slug, project_slug, {
+ // key: "state",
+ // removeAll: true,
+ // })
+ // );
+ };
+
+ return (
+ <>
+
+
State
+
+ {/* {store?.issue?.states &&
+ store?.issue?.states.map(
+ (_state: IIssueState, _index: number) =>
+ store.issue.getUserSelectedFilter("state", _state.id) && (
+
+ )
+ )} */}
+
+
+ close
+
+
+ >
+ );
+});
+
+export default IssueStateFilter;
diff --git a/space/components/issues/navbar/index.tsx b/space/components/issues/navbar/index.tsx
new file mode 100644
index 000000000..509d676b7
--- /dev/null
+++ b/space/components/issues/navbar/index.tsx
@@ -0,0 +1,121 @@
+import { useEffect } from "react";
+
+import Link from "next/link";
+import Image from "next/image";
+import { useRouter } from "next/router";
+
+// mobx
+import { observer } from "mobx-react-lite";
+// components
+import { NavbarSearch } from "./search";
+import { NavbarIssueBoardView } from "./issue-board-view";
+import { NavbarTheme } from "./theme";
+// ui
+import { PrimaryButton } from "components/ui";
+// lib
+import { useMobxStore } from "lib/mobx/store-provider";
+// store
+import { RootStore } from "store/root";
+
+const renderEmoji = (emoji: string | { name: string; color: string }) => {
+ if (!emoji) return;
+
+ if (typeof emoji === "object")
+ return (
+
+ {emoji.name}
+
+ );
+ else return isNaN(parseInt(emoji)) ? emoji : String.fromCodePoint(parseInt(emoji));
+};
+
+const IssueNavbar = observer(() => {
+ const { project: projectStore, user: userStore }: RootStore = useMobxStore();
+ // router
+ const router = useRouter();
+ const { workspace_slug, project_slug, board } = router.query;
+
+ const user = userStore?.currentUser;
+
+ useEffect(() => {
+ if (workspace_slug && project_slug) {
+ projectStore.fetchProjectSettings(workspace_slug.toString(), project_slug.toString());
+ }
+ }, [projectStore, workspace_slug, project_slug]);
+
+ useEffect(() => {
+ if (workspace_slug && project_slug) {
+ if (!board) {
+ router.push({
+ pathname: `/${workspace_slug}/${project_slug}`,
+ query: {
+ board: "list",
+ },
+ });
+ return projectStore.setActiveBoard("list");
+ }
+ projectStore.setActiveBoard(board.toString());
+ }
+ }, [board, workspace_slug, project_slug]);
+
+ return (
+
+ {/* project detail */}
+
+
+ {projectStore?.project && projectStore?.project?.emoji ? (
+ renderEmoji(projectStore?.project?.emoji)
+ ) : (
+
+ )}
+
+
+ {projectStore?.project?.name || `...`}
+
+
+
+ {/* issue search bar */}
+
+
+
+
+ {/* issue views */}
+
+
+
+
+ {/* theming */}
+
+
+
+
+ {user ? (
+
+ {user.avatar && user.avatar !== "" ? (
+
+ {/* eslint-disable-next-line @next/next/no-img-element */}
+
+
+ ) : (
+
+ {(user.display_name ?? "A")[0]}
+
+ )}
+
{user.display_name}
+
+ ) : (
+
+ )}
+
+ );
+});
+
+export default IssueNavbar;
diff --git a/space/components/issues/navbar/issue-board-view.tsx b/space/components/issues/navbar/issue-board-view.tsx
new file mode 100644
index 000000000..0ae71e8ee
--- /dev/null
+++ b/space/components/issues/navbar/issue-board-view.tsx
@@ -0,0 +1,49 @@
+import { useRouter } from "next/router";
+import { observer } from "mobx-react-lite";
+// constants
+import { issueViews } from "constants/data";
+// mobx
+import { useMobxStore } from "lib/mobx/store-provider";
+import { RootStore } from "store/root";
+
+export const NavbarIssueBoardView = observer(() => {
+ const { project: projectStore, issue: issueStore }: RootStore = useMobxStore();
+
+ const router = useRouter();
+ const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
+
+ const handleCurrentBoardView = (boardView: string) => {
+ projectStore.setActiveBoard(boardView);
+ router.push(`/${workspace_slug}/${project_slug}?board=${boardView}`);
+ };
+
+ return (
+ <>
+ {projectStore?.viewOptions &&
+ Object.keys(projectStore?.viewOptions).map((viewKey: string) => {
+ if (projectStore?.viewOptions[viewKey]) {
+ return (
+
handleCurrentBoardView(viewKey)}
+ title={viewKey}
+ >
+
+ {issueViews[viewKey]?.icon}
+
+
+ );
+ }
+ })}
+ >
+ );
+});
diff --git a/space/components/issues/navbar/issue-filter.tsx b/space/components/issues/navbar/issue-filter.tsx
new file mode 100644
index 000000000..852121a5e
--- /dev/null
+++ b/space/components/issues/navbar/issue-filter.tsx
@@ -0,0 +1,111 @@
+import { useRouter } from "next/router";
+import { observer } from "mobx-react-lite";
+// icons
+import { ChevronDownIcon } from "@heroicons/react/20/solid";
+// mobx
+import { useMobxStore } from "lib/mobx/store-provider";
+import { RootStore } from "store/root";
+// components
+import { Dropdown } from "components/ui/dropdown";
+// constants
+import { issueGroupFilter } from "constants/data";
+
+const PRIORITIES = ["urgent", "high", "medium", "low"];
+
+export const NavbarIssueFilter = observer(() => {
+ const store: RootStore = useMobxStore();
+
+ const router = useRouter();
+ const pathName = router.asPath;
+
+ const handleOnSelect = (key: "states" | "labels" | "priorities", value: string) => {
+ // if (key === "states") {
+ // store.issue.userSelectedStates = store.issue.userSelectedStates.includes(value)
+ // ? store.issue.userSelectedStates.filter((s) => s !== value)
+ // : [...store.issue.userSelectedStates, value];
+ // } else if (key === "labels") {
+ // store.issue.userSelectedLabels = store.issue.userSelectedLabels.includes(value)
+ // ? store.issue.userSelectedLabels.filter((l) => l !== value)
+ // : [...store.issue.userSelectedLabels, value];
+ // } else if (key === "priorities") {
+ // store.issue.userSelectedPriorities = store.issue.userSelectedPriorities.includes(value)
+ // ? store.issue.userSelectedPriorities.filter((p) => p !== value)
+ // : [...store.issue.userSelectedPriorities, value];
+ // }
+ // const paramsCommaSeparated = `${`board=${store.issue.currentIssueBoardView || "list"}`}${
+ // store.issue.userSelectedPriorities.length > 0 ? `&priorities=${store.issue.userSelectedPriorities.join(",")}` : ""
+ // }${store.issue.userSelectedStates.length > 0 ? `&states=${store.issue.userSelectedStates.join(",")}` : ""}${
+ // store.issue.userSelectedLabels.length > 0 ? `&labels=${store.issue.userSelectedLabels.join(",")}` : ""
+ // }`;
+ // router.replace(`${pathName}?${paramsCommaSeparated}`);
+ };
+
+ return (
+
+ Filters
+
+ >
+ }
+ items={[
+ {
+ display: "Priority",
+ children: PRIORITIES.map((priority) => ({
+ display: (
+
+
+ {priority === "urgent"
+ ? "error"
+ : priority === "high"
+ ? "signal_cellular_alt"
+ : priority === "medium"
+ ? "signal_cellular_alt_2_bar"
+ : "signal_cellular_alt_1_bar"}
+
+ {priority}
+
+ ),
+ onClick: () => handleOnSelect("priorities", priority),
+ isSelected: store.issue.filteredPriorities.includes(priority),
+ })),
+ },
+ {
+ display: "State",
+ children: (store.issue.states || []).map((state) => {
+ const stateGroup = issueGroupFilter(state.group);
+
+ return {
+ display: (
+
+ {stateGroup && }
+ {state.name}
+
+ ),
+ onClick: () => handleOnSelect("states", state.id),
+ isSelected: store.issue.filteredStates.includes(state.id),
+ };
+ }),
+ },
+ {
+ display: "Labels",
+ children: [...(store.issue.labels || [])].map((label) => ({
+ display: (
+
+
+ {label.name}
+
+ ),
+ onClick: () => handleOnSelect("labels", label.id),
+ isSelected: store.issue.filteredLabels.includes(label.id),
+ })),
+ },
+ ]}
+ />
+ );
+});
diff --git a/apps/space/components/issues/navbar/issue-view.tsx b/space/components/issues/navbar/issue-view.tsx
similarity index 100%
rename from apps/space/components/issues/navbar/issue-view.tsx
rename to space/components/issues/navbar/issue-view.tsx
diff --git a/apps/space/components/issues/navbar/search.tsx b/space/components/issues/navbar/search.tsx
similarity index 100%
rename from apps/space/components/issues/navbar/search.tsx
rename to space/components/issues/navbar/search.tsx
diff --git a/space/components/issues/navbar/theme.tsx b/space/components/issues/navbar/theme.tsx
new file mode 100644
index 000000000..7efb561a4
--- /dev/null
+++ b/space/components/issues/navbar/theme.tsx
@@ -0,0 +1,32 @@
+// next theme
+import { useTheme } from "next-themes";
+
+// mobx react lite
+import { observer } from "mobx-react-lite";
+import { useEffect, useState } from "react";
+
+export const NavbarTheme = observer(() => {
+ const [appTheme, setAppTheme] = useState("light");
+
+ const { setTheme, theme } = useTheme();
+
+ const handleTheme = () => {
+ setTheme(theme === "light" ? "dark" : "light");
+ };
+
+ useEffect(() => {
+ if (!theme) return;
+
+ setAppTheme(theme);
+ }, [theme]);
+
+ return (
+
+ {appTheme === "light" ? "dark_mode" : "light_mode"}
+
+ );
+});
diff --git a/space/components/issues/peek-overview/comment/add-comment.tsx b/space/components/issues/peek-overview/comment/add-comment.tsx
new file mode 100644
index 000000000..3ea4308d7
--- /dev/null
+++ b/space/components/issues/peek-overview/comment/add-comment.tsx
@@ -0,0 +1,104 @@
+import React, { useRef } from "react";
+import { useRouter } from "next/router";
+import { observer } from "mobx-react-lite";
+import { useForm, Controller } from "react-hook-form";
+// lib
+import { useMobxStore } from "lib/mobx/store-provider";
+// hooks
+import useToast from "hooks/use-toast";
+// ui
+import { SecondaryButton } from "components/ui";
+// types
+import { Comment } from "types/issue";
+// components
+import { TipTapEditor } from "components/tiptap";
+
+const defaultValues: Partial = {
+ comment_html: "",
+};
+
+type Props = {
+ disabled?: boolean;
+};
+
+export const AddComment: React.FC = observer((props) => {
+ const { disabled = false } = props;
+
+ const {
+ handleSubmit,
+ control,
+ setValue,
+ watch,
+ formState: { isSubmitting },
+ reset,
+ } = useForm({ defaultValues });
+
+ const router = useRouter();
+ const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
+
+ const { user: userStore, issueDetails: issueDetailStore } = useMobxStore();
+
+ const issueId = issueDetailStore.peekId;
+
+ const editorRef = useRef(null);
+
+ const { setToastAlert } = useToast();
+
+ const onSubmit = async (formData: Comment) => {
+ if (!workspace_slug || !project_slug || !issueId || isSubmitting || !formData.comment_html) return;
+
+ await issueDetailStore
+ .addIssueComment(workspace_slug, project_slug, issueId, formData)
+ .then(() => {
+ reset(defaultValues);
+ editorRef.current?.clearEditor();
+ })
+ .catch(() => {
+ setToastAlert({
+ type: "error",
+ title: "Error!",
+ message: "Comment could not be posted. Please try again.",
+ });
+ });
+ };
+
+ return (
+
+
+ (
+ {
+ onChange(comment_html);
+ }}
+ />
+ )}
+ />
+
+ {
+ userStore.requiredLogin(() => {
+ handleSubmit(onSubmit)(e);
+ });
+ }}
+ type="submit"
+ disabled={isSubmitting || disabled}
+ className="mt-2"
+ >
+ {isSubmitting ? "Adding..." : "Comment"}
+
+
+
+ );
+});
diff --git a/space/components/issues/peek-overview/comment/comment-detail-card.tsx b/space/components/issues/peek-overview/comment/comment-detail-card.tsx
new file mode 100644
index 000000000..0b4d2d5b0
--- /dev/null
+++ b/space/components/issues/peek-overview/comment/comment-detail-card.tsx
@@ -0,0 +1,204 @@
+import React, { useState } from "react";
+
+// mobx
+import { observer } from "mobx-react-lite";
+// react-hook-form
+import { Controller, useForm } from "react-hook-form";
+// headless ui
+import { Menu, Transition } from "@headlessui/react";
+// lib
+import { useMobxStore } from "lib/mobx/store-provider";
+// components
+import { TipTapEditor } from "components/tiptap";
+import { CommentReactions } from "components/issues/peek-overview";
+// icons
+import { ChatBubbleLeftEllipsisIcon, CheckIcon, XMarkIcon, EllipsisVerticalIcon } from "@heroicons/react/24/outline";
+// helpers
+import { timeAgo } from "helpers/date-time.helper";
+// types
+import { Comment } from "types/issue";
+
+type Props = {
+ workspaceSlug: string;
+ comment: Comment;
+};
+
+export const CommentCard: React.FC = observer((props) => {
+ const { comment, workspaceSlug } = props;
+ // store
+ const { user: userStore, issueDetails: issueDetailStore } = useMobxStore();
+ // states
+ const [isEditing, setIsEditing] = useState(false);
+
+ const editorRef = React.useRef(null);
+
+ const showEditorRef = React.useRef(null);
+ const {
+ control,
+ formState: { isSubmitting },
+ handleSubmit,
+ } = useForm({
+ defaultValues: { comment_html: comment.comment_html },
+ });
+
+ const handleDelete = () => {
+ if (!workspaceSlug || !issueDetailStore.peekId) return;
+ issueDetailStore.deleteIssueComment(workspaceSlug, comment.project, issueDetailStore.peekId, comment.id);
+ };
+
+ const handleCommentUpdate = async (formData: Comment) => {
+ 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 (
+
+
+ {comment.actor_detail.avatar && comment.actor_detail.avatar !== "" ? (
+ // eslint-disable-next-line @next/next/no-img-element
+
+ ) : (
+
+ {comment.actor_detail.is_bot
+ ? comment?.actor_detail?.first_name?.charAt(0)
+ : comment?.actor_detail?.display_name?.charAt(0)}
+
+ )}
+
+
+
+
+
+
+
+
+ {comment.actor_detail.is_bot ? comment.actor_detail.first_name + " Bot" : comment.actor_detail.display_name}
+
+
+ <>commented {timeAgo(comment.created_at)}>
+
+
+
+
+
+ {userStore?.currentUser?.id === comment?.actor_detail?.id && (
+
+ {}}
+ className="relative grid place-items-center rounded p-1 text-custom-text-200 hover:text-custom-text-100 outline-none cursor-pointer hover:bg-custom-background-80"
+ >
+
+
+
+
+
+
+ {({ active }) => (
+
+ {
+ setIsEditing(true);
+ }}
+ className={`w-full select-none truncate rounded px-1 py-1.5 text-left text-custom-text-200 hover:bg-custom-background-80 ${
+ active ? "bg-custom-background-80" : ""
+ }`}
+ >
+ Edit
+
+
+ )}
+
+
+ {({ active }) => (
+
+
+ Delete
+
+
+ )}
+
+
+
+
+ )}
+
+ );
+});
diff --git a/space/components/issues/peek-overview/comment/comment-reactions.tsx b/space/components/issues/peek-overview/comment/comment-reactions.tsx
new file mode 100644
index 000000000..4045d3edf
--- /dev/null
+++ b/space/components/issues/peek-overview/comment/comment-reactions.tsx
@@ -0,0 +1,131 @@
+import React from "react";
+
+import { useRouter } from "next/router";
+
+// mobx
+import { observer } from "mobx-react-lite";
+import { useMobxStore } from "lib/mobx/store-provider";
+// ui
+import { ReactionSelector, Tooltip } from "components/ui";
+// helpers
+import { groupReactions, renderEmoji } from "helpers/emoji.helper";
+
+type Props = {
+ commentId: string;
+ projectId: string;
+};
+
+export const CommentReactions: React.FC = observer((props) => {
+ const { commentId, projectId } = props;
+
+ const router = useRouter();
+ const { workspace_slug } = router.query;
+
+ const { issueDetails: issueDetailsStore, user: userStore } = useMobxStore();
+
+ const peekId = issueDetailsStore.peekId;
+ const user = userStore.currentUser;
+
+ const commentReactions = peekId
+ ? issueDetailsStore.details[peekId].comments.find((c) => c.id === commentId)?.comment_reactions
+ : [];
+ const groupedReactions = peekId ? groupReactions(commentReactions ?? [], "reaction") : {};
+
+ const userReactions = commentReactions?.filter((r) => r.actor_detail.id === user?.id);
+
+ const handleAddReaction = (reactionHex: string) => {
+ if (!workspace_slug || !projectId || !peekId) return;
+
+ issueDetailsStore.addCommentReaction(
+ workspace_slug.toString(),
+ projectId.toString(),
+ peekId,
+ commentId,
+ reactionHex
+ );
+ };
+
+ const handleRemoveReaction = (reactionHex: string) => {
+ if (!workspace_slug || !projectId || !peekId) return;
+
+ issueDetailsStore.removeCommentReaction(
+ workspace_slug.toString(),
+ projectId.toString(),
+ peekId,
+ commentId,
+ reactionHex
+ );
+ };
+
+ const handleReactionClick = (reactionHex: string) => {
+ const userReaction = userReactions?.find((r) => r.actor_detail.id === user?.id && r.reaction === reactionHex);
+
+ if (userReaction) handleRemoveReaction(reactionHex);
+ else handleAddReaction(reactionHex);
+ };
+
+ return (
+
+ {
+ userStore.requiredLogin(() => {
+ handleReactionClick(value);
+ });
+ }}
+ position="top"
+ selected={userReactions?.map((r) => r.reaction)}
+ size="md"
+ />
+
+ {Object.keys(groupedReactions || {}).map((reaction) => {
+ const reactions = groupedReactions?.[reaction] ?? [];
+ const REACTIONS_LIMIT = 1000;
+
+ if (reactions.length > 0)
+ return (
+
+ {reactions
+ .map((r) => r.actor_detail.display_name)
+ .splice(0, REACTIONS_LIMIT)
+ .join(", ")}
+ {reactions.length > REACTIONS_LIMIT && " and " + (reactions.length - REACTIONS_LIMIT) + " more"}
+
+ }
+ >
+ {
+ userStore.requiredLogin(() => {
+ handleReactionClick(reaction);
+ });
+ }}
+ className={`flex items-center gap-1 text-custom-text-100 text-sm h-full px-2 py-1 rounded-md ${
+ commentReactions?.some(
+ (r) => r.actor_detail.id === userStore.currentUser?.id && r.reaction === reaction
+ )
+ ? "bg-custom-primary-100/10"
+ : "bg-custom-background-80"
+ }`}
+ >
+ {renderEmoji(reaction)}
+ r.actor_detail.id === userStore.currentUser?.id && r.reaction === reaction
+ )
+ ? "text-custom-primary-100"
+ : ""
+ }
+ >
+ {groupedReactions?.[reaction].length}{" "}
+
+
+
+ );
+ })}
+
+ );
+});
diff --git a/space/components/issues/peek-overview/comment/index.ts b/space/components/issues/peek-overview/comment/index.ts
new file mode 100644
index 000000000..d217c0ddf
--- /dev/null
+++ b/space/components/issues/peek-overview/comment/index.ts
@@ -0,0 +1,3 @@
+export * from "./add-comment";
+export * from "./comment-detail-card";
+export * from "./comment-reactions";
diff --git a/space/components/issues/peek-overview/full-screen-peek-view.tsx b/space/components/issues/peek-overview/full-screen-peek-view.tsx
new file mode 100644
index 000000000..a40e6b16a
--- /dev/null
+++ b/space/components/issues/peek-overview/full-screen-peek-view.tsx
@@ -0,0 +1,71 @@
+import { useEffect } from "react";
+import { observer } from "mobx-react-lite";
+// lib
+import { useMobxStore } from "lib/mobx/store-provider";
+// components
+import {
+ PeekOverviewHeader,
+ PeekOverviewIssueActivity,
+ PeekOverviewIssueDetails,
+ PeekOverviewIssueProperties,
+} from "components/issues/peek-overview";
+// types
+import { Loader } from "components/ui/loader";
+import { IIssue } from "types/issue";
+
+type Props = {
+ handleClose: () => void;
+ issueDetails: IIssue | undefined;
+};
+
+export const FullScreenPeekView: React.FC
= observer((props) => {
+ const { handleClose, issueDetails } = props;
+
+ return (
+
+
+
+ {issueDetails ? (
+
+ {/* issue title and description */}
+
+ {/* divider */}
+
+ {/* issue activity/comments */}
+
+
+ ) : (
+
+
+
+
+
+
+
+
+ )}
+
+
+ {/* issue properties */}
+
+ {issueDetails ? (
+
+ ) : (
+
+
+
+
+
+
+ )}
+
+
+
+ );
+});
diff --git a/space/components/issues/peek-overview/header.tsx b/space/components/issues/peek-overview/header.tsx
new file mode 100644
index 000000000..7a0b43b98
--- /dev/null
+++ b/space/components/issues/peek-overview/header.tsx
@@ -0,0 +1,142 @@
+import React from "react";
+
+// mobx
+import { observer } from "mobx-react-lite";
+// headless ui
+import { Listbox, Transition } from "@headlessui/react";
+// hooks
+import useToast from "hooks/use-toast";
+// ui
+import { Icon } from "components/ui";
+// icons
+import { East } from "@mui/icons-material";
+// helpers
+import { copyTextToClipboard } from "helpers/string.helper";
+// store
+import { IPeekMode } from "store/issue_details";
+import { RootStore } from "store/root";
+// lib
+import { useMobxStore } from "lib/mobx/store-provider";
+// types
+import { IIssue } from "types/issue";
+
+type Props = {
+ handleClose: () => void;
+ issueDetails: IIssue | undefined;
+};
+
+const peekModes: {
+ key: IPeekMode;
+ icon: string;
+ label: string;
+}[] = [
+ { key: "side", icon: "side_navigation", label: "Side Peek" },
+ {
+ key: "modal",
+ icon: "dialogs",
+ label: "Modal Peek",
+ },
+ {
+ key: "full",
+ icon: "nearby",
+ label: "Full Screen Peek",
+ },
+];
+
+export const PeekOverviewHeader: React.FC = observer((props) => {
+ const { handleClose, issueDetails } = props;
+
+ const { issueDetails: issueDetailStore }: RootStore = useMobxStore();
+
+ const { setToastAlert } = useToast();
+
+ const handleCopyLink = () => {
+ const urlToCopy = window.location.href;
+
+ copyTextToClipboard(urlToCopy).then(() => {
+ setToastAlert({
+ type: "success",
+ title: "Link copied!",
+ message: "Issue link copied to clipboard",
+ });
+ });
+ };
+
+ return (
+ <>
+
+
+ {issueDetailStore.peekMode === "side" && (
+
+
+
+ )}
+
issueDetailStore.setPeekMode(val)}
+ className="relative flex-shrink-0 text-left"
+ >
+
+ m.key === issueDetailStore.peekMode)?.icon ?? ""} />
+
+
+
+
+
+ {peekModes.map((mode) => (
+
+ `cursor-pointer select-none truncate rounded px-1 py-1.5 ${
+ active || selected ? "bg-custom-background-80" : ""
+ } ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
+ }
+ >
+ {({ selected }) => (
+
+ )}
+
+ ))}
+
+
+
+
+
+ {(issueDetailStore.peekMode === "side" || issueDetailStore.peekMode === "modal") && (
+
+
+
+
+
+ )}
+
+ >
+ );
+});
diff --git a/space/components/issues/peek-overview/index.ts b/space/components/issues/peek-overview/index.ts
new file mode 100644
index 000000000..f42253e5e
--- /dev/null
+++ b/space/components/issues/peek-overview/index.ts
@@ -0,0 +1,11 @@
+export * from "./comment";
+export * from "./full-screen-peek-view";
+export * from "./header";
+export * from "./issue-activity";
+export * from "./issue-details";
+export * from "./issue-properties";
+export * from "./layout";
+export * from "./side-peek-view";
+export * from "./issue-reaction";
+export * from "./issue-vote-reactions";
+export * from "./issue-emoji-reactions";
diff --git a/space/components/issues/peek-overview/issue-activity.tsx b/space/components/issues/peek-overview/issue-activity.tsx
new file mode 100644
index 000000000..fde2fd878
--- /dev/null
+++ b/space/components/issues/peek-overview/issue-activity.tsx
@@ -0,0 +1,66 @@
+import React from "react";
+
+import Link from "next/link";
+import { useRouter } from "next/router";
+
+// mobx
+import { observer } from "mobx-react-lite";
+// lib
+import { useMobxStore } from "lib/mobx/store-provider";
+// components
+import { CommentCard, AddComment } from "components/issues/peek-overview";
+// ui
+import { Icon, PrimaryButton } from "components/ui";
+// types
+import { IIssue } from "types/issue";
+
+type Props = {
+ issueDetails: IIssue;
+};
+
+export const PeekOverviewIssueActivity: React.FC = observer((props) => {
+ const router = useRouter();
+ const { workspace_slug } = router.query;
+
+ const { issueDetails: issueDetailStore, project: projectStore, user: userStore } = useMobxStore();
+
+ const comments = issueDetailStore.details[issueDetailStore.peekId || ""]?.comments || [];
+
+ const user = userStore?.currentUser;
+
+ return (
+
+
Activity
+ {workspace_slug && (
+
+
+ {comments.map((comment: any) => (
+
+ ))}
+
+ {user ? (
+ <>
+ {projectStore.deploySettings?.comments && (
+
+ )}
+ >
+ ) : (
+
+
+
+ Sign in to add your comment
+
+
+
+ Sign in
+
+
+
+ )}
+
+ )}
+
+ );
+});
diff --git a/space/components/issues/peek-overview/issue-details.tsx b/space/components/issues/peek-overview/issue-details.tsx
new file mode 100644
index 000000000..0b329568c
--- /dev/null
+++ b/space/components/issues/peek-overview/issue-details.tsx
@@ -0,0 +1,40 @@
+import { IssueReactions } from "components/issues/peek-overview";
+import { TipTapEditor } from "components/tiptap";
+import { useRouter } from "next/router";
+// types
+import { IIssue } from "types/issue";
+
+type Props = {
+ issueDetails: IIssue;
+};
+
+export const PeekOverviewIssueDetails: React.FC = ({ issueDetails }) => {
+ const router = useRouter();
+ const { workspace_slug } = router.query;
+
+ return (
+
+
+ {issueDetails.project_detail.identifier}-{issueDetails.sequence_id}
+
+
{issueDetails.name}
+ {issueDetails.description_html !== "" && issueDetails.description_html !== "
" && (
+
"
+ : issueDetails.description_html
+ }
+ customClassName="p-3 min-h-[50px] shadow-sm"
+ debouncedUpdatesEnabled={false}
+ editable={false}
+ />
+ )}
+
+
+ );
+};
diff --git a/space/components/issues/peek-overview/issue-emoji-reactions.tsx b/space/components/issues/peek-overview/issue-emoji-reactions.tsx
new file mode 100644
index 000000000..b0c5b0361
--- /dev/null
+++ b/space/components/issues/peek-overview/issue-emoji-reactions.tsx
@@ -0,0 +1,109 @@
+import { useEffect } from "react";
+import { useRouter } from "next/router";
+import { observer } from "mobx-react-lite";
+// lib
+import { useMobxStore } from "lib/mobx/store-provider";
+// helpers
+import { groupReactions, renderEmoji } from "helpers/emoji.helper";
+// components
+import { ReactionSelector, Tooltip } from "components/ui";
+
+export const IssueEmojiReactions: React.FC = observer(() => {
+ // router
+ const router = useRouter();
+ const { workspace_slug, project_slug } = router.query;
+ // store
+ const { user: userStore, issueDetails: issueDetailsStore } = useMobxStore();
+
+ const user = userStore?.currentUser;
+ const issueId = issueDetailsStore.peekId;
+ const reactions = issueId ? issueDetailsStore.details[issueId]?.reactions || [] : [];
+ const groupedReactions = groupReactions(reactions, "reaction");
+
+ const userReactions = reactions?.filter((r) => r.actor_detail.id === user?.id);
+
+ const handleAddReaction = (reactionHex: string) => {
+ if (!workspace_slug || !project_slug || !issueId) return;
+
+ issueDetailsStore.addIssueReaction(workspace_slug.toString(), project_slug.toString(), issueId, reactionHex);
+ };
+
+ const handleRemoveReaction = (reactionHex: string) => {
+ if (!workspace_slug || !project_slug || !issueId) return;
+
+ issueDetailsStore.removeIssueReaction(workspace_slug.toString(), project_slug.toString(), issueId, reactionHex);
+ };
+
+ const handleReactionClick = (reactionHex: string) => {
+ const userReaction = userReactions?.find((r) => r.actor_detail.id === user?.id && r.reaction === reactionHex);
+
+ if (userReaction) handleRemoveReaction(reactionHex);
+ else handleAddReaction(reactionHex);
+ };
+
+ useEffect(() => {
+ if (user) return;
+ userStore.fetchCurrentUser();
+ }, [user, userStore]);
+
+ return (
+ <>
+ {
+ userStore.requiredLogin(() => {
+ handleReactionClick(value);
+ });
+ }}
+ selected={userReactions?.map((r) => r.reaction)}
+ size="md"
+ />
+
+ {Object.keys(groupedReactions || {}).map((reaction) => {
+ const reactions = groupedReactions?.[reaction] ?? [];
+ const REACTIONS_LIMIT = 1000;
+
+ if (reactions.length > 0)
+ return (
+
+ {reactions
+ .map((r) => r.actor_detail.display_name)
+ .splice(0, REACTIONS_LIMIT)
+ .join(", ")}
+ {reactions.length > REACTIONS_LIMIT && " and " + (reactions.length - REACTIONS_LIMIT) + " more"}
+
+ }
+ >
+ {
+ userStore.requiredLogin(() => {
+ handleReactionClick(reaction);
+ });
+ }}
+ className={`flex items-center gap-1 text-custom-text-100 text-sm h-full px-2 py-1 rounded-md ${
+ reactions?.some((r) => r.actor_detail.id === user?.id && r.reaction === reaction)
+ ? "bg-custom-primary-100/10"
+ : "bg-custom-background-80"
+ }`}
+ >
+ {renderEmoji(reaction)}
+ r.actor_detail.id === user?.id && r.reaction === reaction)
+ ? "text-custom-primary-100"
+ : ""
+ }
+ >
+ {groupedReactions?.[reaction].length}{" "}
+
+
+
+ );
+ })}
+
+ >
+ );
+});
diff --git a/space/components/issues/peek-overview/issue-properties.tsx b/space/components/issues/peek-overview/issue-properties.tsx
new file mode 100644
index 000000000..f7ccab18f
--- /dev/null
+++ b/space/components/issues/peek-overview/issue-properties.tsx
@@ -0,0 +1,123 @@
+// hooks
+import useToast from "hooks/use-toast";
+// icons
+import { Icon } from "components/ui";
+// helpers
+import { copyTextToClipboard, addSpaceIfCamelCase } from "helpers/string.helper";
+import { renderFullDate } from "helpers/date-time.helper";
+import { dueDateIconDetails } from "../board-views/block-due-date";
+// types
+import { IIssue } from "types/issue";
+import { IPeekMode } from "store/issue_details";
+// constants
+import { issueGroupFilter, issuePriorityFilter } from "constants/data";
+
+type Props = {
+ issueDetails: IIssue;
+ mode?: IPeekMode;
+};
+
+export const PeekOverviewIssueProperties: React.FC
= ({ issueDetails, mode }) => {
+ const { setToastAlert } = useToast();
+
+ const state = issueDetails.state_detail;
+ const stateGroup = issueGroupFilter(state.group);
+
+ const priority = issueDetails.priority ? issuePriorityFilter(issueDetails.priority) : null;
+
+ const dueDateIcon = dueDateIconDetails(issueDetails.target_date, state.group);
+
+ const handleCopyLink = () => {
+ const urlToCopy = window.location.href;
+
+ copyTextToClipboard(urlToCopy).then(() => {
+ setToastAlert({
+ type: "success",
+ title: "Link copied!",
+ message: "Issue link copied to clipboard",
+ });
+ });
+ };
+
+ return (
+
+ {mode === "full" && (
+
+
+ {issueDetails.project_detail.identifier}-{issueDetails.sequence_id}
+
+
+
+
+
+
+
+ )}
+
+
+
+
+ State
+
+
+ {stateGroup && (
+
+
+
+ {addSpaceIfCamelCase(state?.name ?? "")}
+
+
+ )}
+
+
+
+
+
+
+ Priority
+
+
+
+ {priority && (
+
+
+
+ )}
+ {priority?.title ?? "None"}
+
+
+
+
+
+
+ Due date
+
+
+ {issueDetails.target_date ? (
+
+
+ {dueDateIcon.iconName}
+
+ {renderFullDate(issueDetails.target_date)}
+
+ ) : (
+
Empty
+ )}
+
+
+
+
+ );
+};
diff --git a/space/components/issues/peek-overview/issue-reaction.tsx b/space/components/issues/peek-overview/issue-reaction.tsx
new file mode 100644
index 000000000..643ec7119
--- /dev/null
+++ b/space/components/issues/peek-overview/issue-reaction.tsx
@@ -0,0 +1,24 @@
+import { IssueEmojiReactions, IssueVotes } from "components/issues/peek-overview";
+import { useMobxStore } from "lib/mobx/store-provider";
+
+export const IssueReactions: React.FC = () => {
+ const { project: projectStore } = useMobxStore();
+
+ return (
+
+ {projectStore?.deploySettings?.votes && (
+ <>
+
+
+
+
+ >
+ )}
+ {projectStore?.deploySettings?.reactions && (
+
+
+
+ )}
+
+ );
+};
diff --git a/space/components/issues/peek-overview/issue-vote-reactions.tsx b/space/components/issues/peek-overview/issue-vote-reactions.tsx
new file mode 100644
index 000000000..ac20565ea
--- /dev/null
+++ b/space/components/issues/peek-overview/issue-vote-reactions.tsx
@@ -0,0 +1,129 @@
+import { useState, useEffect } from "react";
+
+import { useRouter } from "next/router";
+
+// mobx
+import { observer } from "mobx-react-lite";
+// lib
+import { useMobxStore } from "lib/mobx/store-provider";
+import { Tooltip } from "components/ui";
+
+export const IssueVotes: React.FC = observer(() => {
+ const [isSubmitting, setIsSubmitting] = useState(false);
+
+ const router = useRouter();
+
+ const { workspace_slug, project_slug } = router.query;
+
+ const { user: userStore, issueDetails: issueDetailsStore } = useMobxStore();
+
+ const user = userStore?.currentUser;
+ const issueId = issueDetailsStore.peekId;
+
+ const votes = issueId ? issueDetailsStore.details[issueId]?.votes : [];
+
+ const allUpVotes = votes?.filter((vote) => vote.vote === 1);
+ const allDownVotes = votes?.filter((vote) => vote.vote === -1);
+
+ const isUpVotedByUser = allUpVotes?.some((vote) => vote.actor === user?.id);
+ const isDownVotedByUser = allDownVotes?.some((vote) => vote.actor === user?.id);
+
+ const handleVote = async (e: any, voteValue: 1 | -1) => {
+ if (!workspace_slug || !project_slug || !issueId) return;
+
+ setIsSubmitting(true);
+
+ const actionPerformed = votes?.find((vote) => vote.actor === user?.id && vote.vote === voteValue);
+
+ if (actionPerformed)
+ await issueDetailsStore.removeIssueVote(workspace_slug.toString(), project_slug.toString(), issueId);
+ else
+ await issueDetailsStore.addIssueVote(workspace_slug.toString(), project_slug.toString(), issueId, {
+ vote: voteValue,
+ });
+
+ setIsSubmitting(false);
+ };
+
+ useEffect(() => {
+ if (user) return;
+
+ userStore.fetchCurrentUser();
+ }, [user, userStore]);
+
+ const VOTES_LIMIT = 1000;
+
+ return (
+
+ {/* upvote button 👇 */}
+
+ {allUpVotes.length > 0 ? (
+ <>
+ {allUpVotes
+ .map((r) => r.actor_detail.display_name)
+ .splice(0, VOTES_LIMIT)
+ .join(", ")}
+ {allUpVotes.length > VOTES_LIMIT && " and " + (allUpVotes.length - VOTES_LIMIT) + " more"}
+ >
+ ) : (
+ "No upvotes yet"
+ )}
+
+ }
+ >
+ {
+ userStore.requiredLogin(() => {
+ handleVote(e, 1);
+ });
+ }}
+ className={`flex items-center justify-center overflow-hidden px-2 gap-x-1 border rounded focus:outline-none ${
+ isUpVotedByUser ? "border-custom-primary-200 text-custom-primary-200" : "border-custom-border-300"
+ }`}
+ >
+ arrow_upward_alt
+ {allUpVotes.length}
+
+
+
+ {/* downvote button 👇 */}
+
+ {allDownVotes.length > 0 ? (
+ <>
+ {allDownVotes
+ .map((r) => r.actor_detail.display_name)
+ .splice(0, VOTES_LIMIT)
+ .join(", ")}
+ {allDownVotes.length > VOTES_LIMIT && " and " + (allDownVotes.length - VOTES_LIMIT) + " more"}
+ >
+ ) : (
+ "No downvotes yet"
+ )}
+
+ }
+ >
+
{
+ userStore.requiredLogin(() => {
+ handleVote(e, -1);
+ });
+ }}
+ className={`flex items-center justify-center overflow-hidden px-2 gap-x-1 border rounded focus:outline-none ${
+ isDownVotedByUser ? "border-red-600 text-red-600" : "border-custom-border-300"
+ }`}
+ >
+ arrow_downward_alt
+ {allDownVotes.length}
+
+
+
+ );
+});
diff --git a/space/components/issues/peek-overview/layout.tsx b/space/components/issues/peek-overview/layout.tsx
new file mode 100644
index 000000000..a3d7386eb
--- /dev/null
+++ b/space/components/issues/peek-overview/layout.tsx
@@ -0,0 +1,125 @@
+import React, { useEffect, useState } from "react";
+
+import { useRouter } from "next/router";
+
+// mobx
+import { observer } from "mobx-react-lite";
+// headless ui
+import { Dialog, Transition } from "@headlessui/react";
+// components
+import { FullScreenPeekView, SidePeekView } from "components/issues/peek-overview";
+// lib
+import { useMobxStore } from "lib/mobx/store-provider";
+
+type Props = {};
+
+export const IssuePeekOverview: React.FC
= observer((props) => {
+ const [isSidePeekOpen, setIsSidePeekOpen] = useState(false);
+ const [isModalPeekOpen, setIsModalPeekOpen] = useState(false);
+
+ // router
+ const router = useRouter();
+ const { workspace_slug, project_slug, peekId, board } = router.query;
+ // store
+ const { issueDetails: issueDetailStore, issue: issueStore } = useMobxStore();
+
+ const issueDetails = issueDetailStore.peekId && peekId ? issueDetailStore.details[peekId.toString()] : undefined;
+
+ useEffect(() => {
+ if (workspace_slug && project_slug && peekId && issueStore.issues && issueStore.issues.length > 0) {
+ if (!issueDetails) {
+ issueDetailStore.fetchIssueDetails(workspace_slug.toString(), project_slug.toString(), peekId.toString());
+ }
+ }
+ }, [workspace_slug, project_slug, issueDetailStore, issueDetails, peekId, issueStore.issues]);
+
+ const handleClose = () => {
+ issueDetailStore.setPeekId(null);
+ router.replace(
+ {
+ pathname: `/${workspace_slug?.toString()}/${project_slug}`,
+ query: {
+ board,
+ },
+ },
+ undefined,
+ { shallow: true }
+ );
+ };
+
+ useEffect(() => {
+ if (peekId) {
+ if (issueDetailStore.peekMode === "side") {
+ setIsSidePeekOpen(true);
+ setIsModalPeekOpen(false);
+ } else {
+ setIsModalPeekOpen(true);
+ setIsSidePeekOpen(false);
+ }
+ } else {
+ setIsSidePeekOpen(false);
+ setIsModalPeekOpen(false);
+ }
+ }, [peekId, issueDetailStore.peekMode]);
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {issueDetailStore.peekMode === "modal" && (
+
+ )}
+ {issueDetailStore.peekMode === "full" && (
+
+ )}
+
+
+
+
+
+ >
+ );
+});
diff --git a/space/components/issues/peek-overview/side-peek-view.tsx b/space/components/issues/peek-overview/side-peek-view.tsx
new file mode 100644
index 000000000..bacf83420
--- /dev/null
+++ b/space/components/issues/peek-overview/side-peek-view.tsx
@@ -0,0 +1,55 @@
+import { observer } from "mobx-react-lite";
+// components
+import {
+ PeekOverviewHeader,
+ PeekOverviewIssueActivity,
+ PeekOverviewIssueDetails,
+ PeekOverviewIssueProperties,
+} from "components/issues/peek-overview";
+
+import { Loader } from "components/ui/loader";
+import { IIssue } from "types/issue";
+
+type Props = {
+ handleClose: () => void;
+ issueDetails: IIssue | undefined;
+};
+
+export const SidePeekView: React.FC = observer((props) => {
+ const { handleClose, issueDetails } = props;
+
+ return (
+
+
+ {issueDetails ? (
+
+ {/* issue title and description */}
+
+ {/* issue properties */}
+
+ {/* divider */}
+
+ {/* issue activity/comments */}
+
+
+ ) : (
+
+
+
+
+
+
+
+
+ )}
+
+ );
+});
diff --git a/apps/app/components/tiptap/bubble-menu/index.tsx b/space/components/tiptap/bubble-menu/index.tsx
similarity index 91%
rename from apps/app/components/tiptap/bubble-menu/index.tsx
rename to space/components/tiptap/bubble-menu/index.tsx
index 7e72963b6..217317ea1 100644
--- a/apps/app/components/tiptap/bubble-menu/index.tsx
+++ b/space/components/tiptap/bubble-menu/index.tsx
@@ -77,14 +77,16 @@ export const EditorBubbleMenu: FC = (props: any) => {
{...bubbleMenuProps}
className="flex w-fit divide-x divide-custom-border-300 rounded border border-custom-border-300 bg-custom-background-100 shadow-xl"
>
- {!props.editor.isActive("table") && {
- setIsNodeSelectorOpen(!isNodeSelectorOpen);
- setIsLinkSelectorOpen(false);
- }}
- />}
+ {!props.editor.isActive("table") && (
+ {
+ setIsNodeSelectorOpen(!isNodeSelectorOpen);
+ setIsLinkSelectorOpen(false);
+ }}
+ />
+ )}
>
+ setIsOpen: Dispatch>;
}
-
export const LinkSelector: FC = ({ editor, isOpen, setIsOpen }) => {
const inputRef = useRef(null);
@@ -76,7 +75,9 @@ export const LinkSelector: FC = ({ editor, isOpen, setIsOpen
) : (
- {
onLinkSubmit();
}}
diff --git a/apps/app/components/tiptap/bubble-menu/node-selector.tsx b/space/components/tiptap/bubble-menu/node-selector.tsx
similarity index 98%
rename from apps/app/components/tiptap/bubble-menu/node-selector.tsx
rename to space/components/tiptap/bubble-menu/node-selector.tsx
index f6f1f18dc..34d40ec06 100644
--- a/apps/app/components/tiptap/bubble-menu/node-selector.tsx
+++ b/space/components/tiptap/bubble-menu/node-selector.tsx
@@ -13,7 +13,7 @@ import {
} from "lucide-react";
import { Dispatch, FC, SetStateAction } from "react";
-import { BubbleMenuItem } from "../bubble-menu";
+import { BubbleMenuItem } from ".";
import { cn } from "../utils";
interface NodeSelectorProps {
diff --git a/apps/app/components/tiptap/bubble-menu/utils/link-validator.tsx b/space/components/tiptap/bubble-menu/utils/link-validator.tsx
similarity index 99%
rename from apps/app/components/tiptap/bubble-menu/utils/link-validator.tsx
rename to space/components/tiptap/bubble-menu/utils/link-validator.tsx
index 5b05811d6..9af366c02 100644
--- a/apps/app/components/tiptap/bubble-menu/utils/link-validator.tsx
+++ b/space/components/tiptap/bubble-menu/utils/link-validator.tsx
@@ -9,4 +9,3 @@ export default function isValidHttpUrl(string: string): boolean {
return url.protocol === "http:" || url.protocol === "https:";
}
-
diff --git a/apps/app/components/tiptap/extensions/image-resize.tsx b/space/components/tiptap/extensions/image-resize.tsx
similarity index 78%
rename from apps/app/components/tiptap/extensions/image-resize.tsx
rename to space/components/tiptap/extensions/image-resize.tsx
index 7b2d1a2d3..448b8811c 100644
--- a/apps/app/components/tiptap/extensions/image-resize.tsx
+++ b/space/components/tiptap/extensions/image-resize.tsx
@@ -3,9 +3,7 @@ import Moveable from "react-moveable";
export const ImageResizer = ({ editor }: { editor: Editor }) => {
const updateMediaSize = () => {
- const imageInfo = document.querySelector(
- ".ProseMirror-selectednode",
- ) as HTMLImageElement;
+ const imageInfo = document.querySelector(".ProseMirror-selectednode") as HTMLImageElement;
if (imageInfo) {
const selection = editor.state.selection;
editor.commands.setImage({
@@ -28,13 +26,7 @@ export const ImageResizer = ({ editor }: { editor: Editor }) => {
keepRatio={true}
resizable={true}
throttleResize={0}
- onResize={({
- target,
- width,
- height,
- delta,
- }:
- any) => {
+ onResize={({ target, width, height, delta }: any) => {
delta[0] && (target!.style.width = `${width}px`);
delta[1] && (target!.style.height = `${height}px`);
}}
@@ -43,15 +35,10 @@ export const ImageResizer = ({ editor }: { editor: Editor }) => {
}}
scalable={true}
renderDirections={["w", "e"]}
- onScale={({
- target,
- transform,
- }:
- any) => {
+ onScale={({ target, transform }: any) => {
target!.style.transform = transform;
}}
/>
>
);
};
-
diff --git a/space/components/tiptap/extensions/index.tsx b/space/components/tiptap/extensions/index.tsx
new file mode 100644
index 000000000..f5dc11384
--- /dev/null
+++ b/space/components/tiptap/extensions/index.tsx
@@ -0,0 +1,153 @@
+import StarterKit from "@tiptap/starter-kit";
+import HorizontalRule from "@tiptap/extension-horizontal-rule";
+import TiptapLink from "@tiptap/extension-link";
+import Placeholder from "@tiptap/extension-placeholder";
+import TiptapUnderline from "@tiptap/extension-underline";
+import TextStyle from "@tiptap/extension-text-style";
+import { Color } from "@tiptap/extension-color";
+import TaskItem from "@tiptap/extension-task-item";
+import TaskList from "@tiptap/extension-task-list";
+import { Markdown } from "tiptap-markdown";
+import Highlight from "@tiptap/extension-highlight";
+import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
+import { lowlight } from "lowlight/lib/core";
+import SlashCommand from "../slash-command";
+import { InputRule } from "@tiptap/core";
+import Gapcursor from "@tiptap/extension-gapcursor";
+
+import ts from "highlight.js/lib/languages/typescript";
+
+import "highlight.js/styles/github-dark.css";
+import UniqueID from "@tiptap-pro/extension-unique-id";
+import UpdatedImage from "./updated-image";
+import isValidHttpUrl from "../bubble-menu/utils/link-validator";
+import { CustomTableCell } from "./table/table-cell";
+import { Table } from "./table/table";
+import { TableHeader } from "./table/table-header";
+import { TableRow } from "@tiptap/extension-table-row";
+
+lowlight.registerLanguage("ts", ts);
+
+export const TiptapExtensions = (
+ workspaceSlug: string,
+ setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
+) => [
+ StarterKit.configure({
+ bulletList: {
+ HTMLAttributes: {
+ class: "list-disc list-outside leading-3 -mt-2",
+ },
+ },
+ orderedList: {
+ HTMLAttributes: {
+ class: "list-decimal list-outside leading-3 -mt-2",
+ },
+ },
+ listItem: {
+ HTMLAttributes: {
+ class: "leading-normal -mb-2",
+ },
+ },
+ blockquote: {
+ HTMLAttributes: {
+ class: "border-l-4 border-custom-border-300",
+ },
+ },
+ code: {
+ HTMLAttributes: {
+ class:
+ "rounded-md bg-custom-primary-30 mx-1 px-1 py-1 font-mono font-medium text-custom-text-1000",
+ spellcheck: "false",
+ },
+ },
+ codeBlock: false,
+ horizontalRule: false,
+ dropcursor: {
+ color: "rgba(var(--color-text-100))",
+ width: 2,
+ },
+ gapcursor: false,
+ }),
+ CodeBlockLowlight.configure({
+ lowlight,
+ }),
+ HorizontalRule.extend({
+ addInputRules() {
+ return [
+ new InputRule({
+ find: /^(?:---|—-|___\s|\*\*\*\s)$/,
+ handler: ({ state, range, commands }) => {
+ commands.splitBlock();
+
+ const attributes = {};
+ const { tr } = state;
+ const start = range.from;
+ const end = range.to;
+ // @ts-ignore
+ tr.replaceWith(start - 1, end, this.type.create(attributes));
+ },
+ }),
+ ];
+ },
+ }).configure({
+ HTMLAttributes: {
+ class: "mb-6 border-t border-custom-border-300",
+ },
+ }),
+ Gapcursor,
+ TiptapLink.configure({
+ protocols: ["http", "https"],
+ validate: (url) => isValidHttpUrl(url),
+ HTMLAttributes: {
+ class:
+ "text-custom-primary-300 underline underline-offset-[3px] hover:text-custom-primary-500 transition-colors cursor-pointer",
+ },
+ }),
+ UpdatedImage.configure({
+ HTMLAttributes: {
+ class: "rounded-lg border border-custom-border-300",
+ },
+ }),
+ Placeholder.configure({
+ placeholder: ({ node }) => {
+ if (node.type.name === "heading") {
+ return `Heading ${node.attrs.level}`;
+ }
+ if (node.type.name === "image" || node.type.name === "table") {
+ return "";
+ }
+
+ return "Press '/' for commands...";
+ },
+ includeChildren: true,
+ }),
+ UniqueID.configure({
+ types: ["image"],
+ }),
+ SlashCommand(workspaceSlug, setIsSubmitting),
+ TiptapUnderline,
+ TextStyle,
+ Color,
+ Highlight.configure({
+ multicolor: true,
+ }),
+ TaskList.configure({
+ HTMLAttributes: {
+ class: "not-prose pl-2",
+ },
+ }),
+ TaskItem.configure({
+ HTMLAttributes: {
+ class: "flex items-start my-4",
+ },
+ nested: true,
+ }),
+ Markdown.configure({
+ html: true,
+ transformCopiedText: true,
+ }),
+ Table,
+ TableHeader,
+ CustomTableCell,
+ TableRow,
+ ];
diff --git a/apps/app/components/tiptap/extensions/table/table-cell.ts b/space/components/tiptap/extensions/table/table-cell.ts
similarity index 67%
rename from apps/app/components/tiptap/extensions/table/table-cell.ts
rename to space/components/tiptap/extensions/table/table-cell.ts
index 94c5aced2..643cb8c64 100644
--- a/apps/app/components/tiptap/extensions/table/table-cell.ts
+++ b/space/components/tiptap/extensions/table/table-cell.ts
@@ -6,8 +6,12 @@ export const CustomTableCell = TableCell.extend({
...this.parent?.(),
isHeader: {
default: false,
- parseHTML: (element) => { isHeader: element.tagName === "TD" },
- renderHTML: (attributes) => { tag: attributes.isHeader ? "th" : "td" }
+ parseHTML: (element) => {
+ isHeader: element.tagName === "TD";
+ },
+ renderHTML: (attributes) => {
+ tag: attributes.isHeader ? "th" : "td";
+ },
},
};
},
@@ -19,10 +23,7 @@ export const CustomTableCell = TableCell.extend({
...HTMLAttributes,
class: `relative ${HTMLAttributes.class}`,
},
- [
- "span",
- { class: "absolute top-0 right-0" },
- ],
+ ["span", { class: "absolute top-0 right-0" }],
0,
];
}
diff --git a/apps/app/components/tiptap/extensions/table/table-header.ts b/space/components/tiptap/extensions/table/table-header.ts
similarity index 86%
rename from apps/app/components/tiptap/extensions/table/table-header.ts
rename to space/components/tiptap/extensions/table/table-header.ts
index d04fe85d3..f23aa93ef 100644
--- a/apps/app/components/tiptap/extensions/table/table-header.ts
+++ b/space/components/tiptap/extensions/table/table-header.ts
@@ -1,7 +1,7 @@
import { TableHeader as BaseTableHeader } from "@tiptap/extension-table-header";
const TableHeader = BaseTableHeader.extend({
- content: "paragraph"
+ content: "paragraph",
});
export { TableHeader };
diff --git a/apps/app/components/tiptap/extensions/table/table.ts b/space/components/tiptap/extensions/table/table.ts
similarity index 83%
rename from apps/app/components/tiptap/extensions/table/table.ts
rename to space/components/tiptap/extensions/table/table.ts
index b05dedb3b..9b727bb51 100644
--- a/apps/app/components/tiptap/extensions/table/table.ts
+++ b/space/components/tiptap/extensions/table/table.ts
@@ -3,7 +3,7 @@ import { Table as BaseTable } from "@tiptap/extension-table";
const Table = BaseTable.configure({
resizable: true,
cellMinWidth: 100,
- allowTableNodeSelection: true
+ allowTableNodeSelection: true,
});
export { Table };
diff --git a/apps/app/components/tiptap/extensions/updated-image.tsx b/space/components/tiptap/extensions/updated-image.tsx
similarity index 95%
rename from apps/app/components/tiptap/extensions/updated-image.tsx
rename to space/components/tiptap/extensions/updated-image.tsx
index 01648dcd7..b62050953 100644
--- a/apps/app/components/tiptap/extensions/updated-image.tsx
+++ b/space/components/tiptap/extensions/updated-image.tsx
@@ -10,7 +10,7 @@ const UpdatedImage = Image.extend({
return {
...this.parent?.(),
width: {
- default: '35%',
+ default: "35%",
},
height: {
default: null,
diff --git a/apps/app/components/tiptap/index.tsx b/space/components/tiptap/index.tsx
similarity index 97%
rename from apps/app/components/tiptap/index.tsx
rename to space/components/tiptap/index.tsx
index 2ab6bf288..84f691c35 100644
--- a/apps/app/components/tiptap/index.tsx
+++ b/space/components/tiptap/index.tsx
@@ -1,9 +1,10 @@
+import { useImperativeHandle, useRef, forwardRef, useEffect } from "react";
import { useEditor, EditorContent, Editor } from "@tiptap/react";
import { useDebouncedCallback } from "use-debounce";
+// components
import { EditorBubbleMenu } from "./bubble-menu";
import { TiptapExtensions } from "./extensions";
import { TiptapEditorProps } from "./props";
-import { useImperativeHandle, useRef, forwardRef } from "react";
import { ImageResizer } from "./extensions/image-resize";
import { TableMenu } from "./table-menu";
diff --git a/space/components/tiptap/plugins/delete-image.tsx b/space/components/tiptap/plugins/delete-image.tsx
new file mode 100644
index 000000000..fdf515ccc
--- /dev/null
+++ b/space/components/tiptap/plugins/delete-image.tsx
@@ -0,0 +1,68 @@
+import { EditorState, Plugin, PluginKey, Transaction } from "@tiptap/pm/state";
+import { Node as ProseMirrorNode } from "@tiptap/pm/model";
+import fileService from "services/file.service";
+
+const deleteKey = new PluginKey("delete-image");
+const IMAGE_NODE_TYPE = "image";
+
+interface ImageNode extends ProseMirrorNode {
+ attrs: {
+ src: string;
+ id: string;
+ };
+}
+
+const TrackImageDeletionPlugin = (): Plugin =>
+ new Plugin({
+ key: deleteKey,
+ appendTransaction: (transactions: readonly Transaction[], oldState: EditorState, newState: EditorState) => {
+ const newImageSources = new Set();
+ newState.doc.descendants((node) => {
+ if (node.type.name === IMAGE_NODE_TYPE) {
+ newImageSources.add(node.attrs.src);
+ }
+ });
+
+ transactions.forEach((transaction) => {
+ if (!transaction.docChanged) return;
+
+ const removedImages: ImageNode[] = [];
+
+ oldState.doc.descendants((oldNode, oldPos) => {
+ if (oldNode.type.name !== IMAGE_NODE_TYPE) return;
+ if (oldPos < 0 || oldPos > newState.doc.content.size) return;
+ if (!newState.doc.resolve(oldPos).parent) return;
+
+ const newNode = newState.doc.nodeAt(oldPos);
+
+ // Check if the node has been deleted or replaced
+ if (!newNode || newNode.type.name !== IMAGE_NODE_TYPE) {
+ if (!newImageSources.has(oldNode.attrs.src)) {
+ removedImages.push(oldNode as ImageNode);
+ }
+ }
+ });
+
+ removedImages.forEach(async (node) => {
+ const src = node.attrs.src;
+ await onNodeDeleted(src);
+ });
+ });
+
+ return null;
+ },
+ });
+
+export default TrackImageDeletionPlugin;
+
+async function onNodeDeleted(src: string): Promise {
+ try {
+ const assetUrlWithWorkspaceId = new URL(src).pathname.substring(1);
+ const resStatus = await fileService.deleteImage(assetUrlWithWorkspaceId);
+ if (resStatus === 204) {
+ console.log("Image deleted successfully");
+ }
+ } catch (error) {
+ console.error("Error deleting image: ", error);
+ }
+}
diff --git a/apps/app/components/tiptap/plugins/upload-image.tsx b/space/components/tiptap/plugins/upload-image.tsx
similarity index 89%
rename from apps/app/components/tiptap/plugins/upload-image.tsx
rename to space/components/tiptap/plugins/upload-image.tsx
index a13f8e18a..bc0acdc54 100644
--- a/apps/app/components/tiptap/plugins/upload-image.tsx
+++ b/space/components/tiptap/plugins/upload-image.tsx
@@ -1,4 +1,3 @@
-// @ts-nocheck
import { EditorState, Plugin, PluginKey } from "@tiptap/pm/state";
import { Decoration, DecorationSet, EditorView } from "@tiptap/pm/view";
import fileService from "services/file.service";
@@ -22,10 +21,7 @@ const UploadImagesPlugin = () =>
const placeholder = document.createElement("div");
placeholder.setAttribute("class", "img-placeholder");
const image = document.createElement("img");
- image.setAttribute(
- "class",
- "opacity-10 rounded-lg border border-custom-border-300",
- );
+ image.setAttribute("class", "opacity-10 rounded-lg border border-custom-border-300");
image.src = src;
placeholder.appendChild(image);
const deco = Decoration.widget(pos + 1, placeholder, {
@@ -57,7 +53,13 @@ function findPlaceholder(state: EditorState, id: {}) {
return found.length ? found[0].from : null;
}
-export async function startImageUpload(file: File, view: EditorView, pos: number, workspaceSlug: string, setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void) {
+export async function startImageUpload(
+ file: File,
+ view: EditorView,
+ pos: number,
+ workspaceSlug: string,
+ setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
+) {
if (!file.type.includes("image/")) {
return;
}
@@ -83,7 +85,7 @@ export async function startImageUpload(file: File, view: EditorView, pos: number
if (!workspaceSlug) {
return;
}
- setIsSubmitting?.("submitting")
+ setIsSubmitting?.("submitting");
const src = await UploadImageHandler(file, workspaceSlug);
const { schema } = view.state;
pos = findPlaceholder(view.state, id);
diff --git a/apps/app/components/tiptap/props.tsx b/space/components/tiptap/props.tsx
similarity index 83%
rename from apps/app/components/tiptap/props.tsx
rename to space/components/tiptap/props.tsx
index 69cddca1f..8233e3ab4 100644
--- a/apps/app/components/tiptap/props.tsx
+++ b/space/components/tiptap/props.tsx
@@ -2,7 +2,10 @@ import { EditorProps } from "@tiptap/pm/view";
import { startImageUpload } from "./plugins/upload-image";
import { findTableAncestor } from "./table-menu";
-export function TiptapEditorProps(workspaceSlug: string, setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void): EditorProps {
+export function TiptapEditorProps(
+ workspaceSlug: string,
+ setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
+): EditorProps {
return {
attributes: {
class: `prose prose-brand max-w-full prose-headings:font-display font-default focus:outline-none`,
@@ -28,11 +31,7 @@ export function TiptapEditorProps(workspaceSlug: string, setIsSubmitting?: (isSu
}
}
}
- if (
- event.clipboardData &&
- event.clipboardData.files &&
- event.clipboardData.files[0]
- ) {
+ if (event.clipboardData && event.clipboardData.files && event.clipboardData.files[0]) {
event.preventDefault();
const file = event.clipboardData.files[0];
const pos = view.state.selection.from;
@@ -51,12 +50,7 @@ export function TiptapEditorProps(workspaceSlug: string, setIsSubmitting?: (isSu
}
}
}
- if (
- !moved &&
- event.dataTransfer &&
- event.dataTransfer.files &&
- event.dataTransfer.files[0]
- ) {
+ if (!moved && event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files[0]) {
event.preventDefault();
const file = event.dataTransfer.files[0];
const coordinates = view.posAtCoords({
diff --git a/apps/app/components/tiptap/slash-command/index.tsx b/space/components/tiptap/slash-command/index.tsx
similarity index 52%
rename from apps/app/components/tiptap/slash-command/index.tsx
rename to space/components/tiptap/slash-command/index.tsx
index c843f0762..46bf5ea5a 100644
--- a/apps/app/components/tiptap/slash-command/index.tsx
+++ b/space/components/tiptap/slash-command/index.tsx
@@ -56,143 +56,153 @@ const Command = Extension.create({
},
});
-const getSuggestionItems = (workspaceSlug: string, setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void) => ({ query }: { query: string }) =>
- [
- {
- title: "Text",
- description: "Just start typing with plain text.",
- searchTerms: ["p", "paragraph"],
- icon: ,
- command: ({ editor, range }: CommandProps) => {
- editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").run();
+const getSuggestionItems =
+ (
+ workspaceSlug: string,
+ setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
+ ) =>
+ ({ query }: { query: string }) =>
+ [
+ {
+ title: "Text",
+ description: "Just start typing with plain text.",
+ searchTerms: ["p", "paragraph"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").run();
+ },
},
- },
- {
- title: "Heading 1",
- description: "Big section heading.",
- searchTerms: ["title", "big", "large"],
- icon: ,
- command: ({ editor, range }: CommandProps) => {
- editor.chain().focus().deleteRange(range).setNode("heading", { level: 1 }).run();
+ {
+ title: "Heading 1",
+ description: "Big section heading.",
+ searchTerms: ["title", "big", "large"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 1 }).run();
+ },
},
- },
- {
- title: "Heading 2",
- description: "Medium section heading.",
- searchTerms: ["subtitle", "medium"],
- icon: ,
- command: ({ editor, range }: CommandProps) => {
- editor.chain().focus().deleteRange(range).setNode("heading", { level: 2 }).run();
+ {
+ title: "Heading 2",
+ description: "Medium section heading.",
+ searchTerms: ["subtitle", "medium"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 2 }).run();
+ },
},
- },
- {
- title: "Heading 3",
- description: "Small section heading.",
- searchTerms: ["subtitle", "small"],
- icon: ,
- command: ({ editor, range }: CommandProps) => {
- editor.chain().focus().deleteRange(range).setNode("heading", { level: 3 }).run();
+ {
+ title: "Heading 3",
+ description: "Small section heading.",
+ searchTerms: ["subtitle", "small"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 3 }).run();
+ },
},
- },
- {
- title: "To-do List",
- description: "Track tasks with a to-do list.",
- searchTerms: ["todo", "task", "list", "check", "checkbox"],
- icon: ,
- command: ({ editor, range }: CommandProps) => {
- editor.chain().focus().deleteRange(range).toggleTaskList().run();
+ {
+ title: "To-do List",
+ description: "Track tasks with a to-do list.",
+ searchTerms: ["todo", "task", "list", "check", "checkbox"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).toggleTaskList().run();
+ },
},
- },
- {
- title: "Bullet List",
- description: "Create a simple bullet list.",
- searchTerms: ["unordered", "point"],
- icon:
,
- command: ({ editor, range }: CommandProps) => {
- editor.chain().focus().deleteRange(range).toggleBulletList().run();
+ {
+ title: "Bullet List",
+ description: "Create a simple bullet list.",
+ searchTerms: ["unordered", "point"],
+ icon:
,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).toggleBulletList().run();
+ },
},
- },
- {
- title: "Divider",
- description: "Visually divide blocks",
- searchTerms: ["line", "divider", "horizontal", "rule", "separate"],
- icon: ,
- command: ({ editor, range }: CommandProps) => {
- editor.chain().focus().deleteRange(range).setHorizontalRule().run();
+ {
+ title: "Divider",
+ description: "Visually divide blocks",
+ searchTerms: ["line", "divider", "horizontal", "rule", "separate"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).setHorizontalRule().run();
+ },
},
- },
- {
- title: "Table",
- description: "Create a Table",
- searchTerms: ["table", "cell", "db", "data", "tabular"],
- icon: ,
- command: ({ editor, range }: CommandProps) => {
- editor.chain().focus().deleteRange(range).insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run();
+ {
+ title: "Table",
+ description: "Create a Table",
+ searchTerms: ["table", "cell", "db", "data", "tabular"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor
+ .chain()
+ .focus()
+ .deleteRange(range)
+ .insertTable({ rows: 3, cols: 3, withHeaderRow: true })
+ .run();
+ },
},
- },
- {
- title: "Numbered List",
- description: "Create a list with numbering.",
- searchTerms: ["ordered"],
- icon: ,
- command: ({ editor, range }: CommandProps) => {
- editor.chain().focus().deleteRange(range).toggleOrderedList().run();
+ {
+ title: "Numbered List",
+ description: "Create a list with numbering.",
+ searchTerms: ["ordered"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).toggleOrderedList().run();
+ },
},
- },
- {
- title: "Quote",
- description: "Capture a quote.",
- searchTerms: ["blockquote"],
- icon: ,
- command: ({ editor, range }: CommandProps) =>
- editor
- .chain()
- .focus()
- .deleteRange(range)
- .toggleNode("paragraph", "paragraph")
- .toggleBlockquote()
- .run(),
- },
- {
- title: "Code",
- description: "Capture a code snippet.",
- searchTerms: ["codeblock"],
- icon:
,
- command: ({ editor, range }: CommandProps) =>
- editor.chain().focus().deleteRange(range).toggleCodeBlock().run(),
- },
- {
- title: "Image",
- description: "Upload an image from your computer.",
- searchTerms: ["photo", "picture", "media"],
- icon: ,
- command: ({ editor, range }: CommandProps) => {
- editor.chain().focus().deleteRange(range).run();
- // upload image
- const input = document.createElement("input");
- input.type = "file";
- input.accept = "image/*";
- input.onchange = async () => {
- if (input.files?.length) {
- const file = input.files[0];
- const pos = editor.view.state.selection.from;
- startImageUpload(file, editor.view, pos, workspaceSlug, setIsSubmitting);
- }
- };
- input.click();
+ {
+ title: "Quote",
+ description: "Capture a quote.",
+ searchTerms: ["blockquote"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) =>
+ editor
+ .chain()
+ .focus()
+ .deleteRange(range)
+ .toggleNode("paragraph", "paragraph")
+ .toggleBlockquote()
+ .run(),
},
- },
- ].filter((item) => {
- if (typeof query === "string" && query.length > 0) {
- const search = query.toLowerCase();
- return (
- item.title.toLowerCase().includes(search) ||
- item.description.toLowerCase().includes(search) ||
- (item.searchTerms && item.searchTerms.some((term: string) => term.includes(search)))
- );
- }
- return true;
- });
+ {
+ title: "Code",
+ description: "Capture a code snippet.",
+ searchTerms: ["codeblock"],
+ icon:
,
+ command: ({ editor, range }: CommandProps) =>
+ editor.chain().focus().deleteRange(range).toggleCodeBlock().run(),
+ },
+ {
+ title: "Image",
+ description: "Upload an image from your computer.",
+ searchTerms: ["photo", "picture", "media"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).run();
+ // upload image
+ const input = document.createElement("input");
+ input.type = "file";
+ input.accept = "image/*";
+ input.onchange = async () => {
+ if (input.files?.length) {
+ const file = input.files[0];
+ const pos = editor.view.state.selection.from;
+ startImageUpload(file, editor.view, pos, workspaceSlug, setIsSubmitting);
+ }
+ };
+ input.click();
+ },
+ },
+ ].filter((item) => {
+ if (typeof query === "string" && query.length > 0) {
+ const search = query.toLowerCase();
+ return (
+ item.title.toLowerCase().includes(search) ||
+ item.description.toLowerCase().includes(search) ||
+ (item.searchTerms && item.searchTerms.some((term: string) => term.includes(search)))
+ );
+ }
+ return true;
+ });
export const updateScrollView = (container: HTMLElement, item: HTMLElement) => {
const containerHeight = container.offsetHeight;
@@ -341,7 +351,10 @@ const renderItems = () => {
};
};
-export const SlashCommand = (workspaceSlug: string, setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void) =>
+export const SlashCommand = (
+ workspaceSlug: string,
+ setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
+) =>
Command.configure({
suggestion: {
items: getSuggestionItems(workspaceSlug, setIsSubmitting),
diff --git a/space/components/tiptap/table-menu/InsertBottomTableIcon.tsx b/space/components/tiptap/table-menu/InsertBottomTableIcon.tsx
new file mode 100644
index 000000000..0e42ba648
--- /dev/null
+++ b/space/components/tiptap/table-menu/InsertBottomTableIcon.tsx
@@ -0,0 +1,16 @@
+const InsertBottomTableIcon = (props: any) => (
+
+
+
+);
+
+export default InsertBottomTableIcon;
diff --git a/space/components/tiptap/table-menu/InsertLeftTableIcon.tsx b/space/components/tiptap/table-menu/InsertLeftTableIcon.tsx
new file mode 100644
index 000000000..1fd75fe87
--- /dev/null
+++ b/space/components/tiptap/table-menu/InsertLeftTableIcon.tsx
@@ -0,0 +1,15 @@
+const InsertLeftTableIcon = (props: any) => (
+
+
+
+);
+export default InsertLeftTableIcon;
diff --git a/space/components/tiptap/table-menu/InsertRightTableIcon.tsx b/space/components/tiptap/table-menu/InsertRightTableIcon.tsx
new file mode 100644
index 000000000..1a6570969
--- /dev/null
+++ b/space/components/tiptap/table-menu/InsertRightTableIcon.tsx
@@ -0,0 +1,16 @@
+const InsertRightTableIcon = (props: any) => (
+
+
+
+);
+
+export default InsertRightTableIcon;
diff --git a/space/components/tiptap/table-menu/InsertTopTableIcon.tsx b/space/components/tiptap/table-menu/InsertTopTableIcon.tsx
new file mode 100644
index 000000000..8f04f4f61
--- /dev/null
+++ b/space/components/tiptap/table-menu/InsertTopTableIcon.tsx
@@ -0,0 +1,15 @@
+const InsertTopTableIcon = (props: any) => (
+
+
+
+);
+export default InsertTopTableIcon;
diff --git a/apps/app/components/tiptap/table-menu/index.tsx b/space/components/tiptap/table-menu/index.tsx
similarity index 85%
rename from apps/app/components/tiptap/table-menu/index.tsx
rename to space/components/tiptap/table-menu/index.tsx
index 0da68410e..94f9c0f8d 100644
--- a/apps/app/components/tiptap/table-menu/index.tsx
+++ b/space/components/tiptap/table-menu/index.tsx
@@ -2,6 +2,10 @@ import { useState, useEffect } from "react";
import { Rows, Columns, ToggleRight } from "lucide-react";
import { cn } from "../utils";
import { Tooltip } from "components/ui";
+import InsertLeftTableIcon from "./InsertLeftTableIcon";
+import InsertRightTableIcon from "./InsertRightTableIcon";
+import InsertTopTableIcon from "./InsertTopTableIcon";
+import InsertBottomTableIcon from "./InsertBottomTableIcon";
interface TableMenuItem {
command: () => void;
@@ -24,13 +28,25 @@ export const TableMenu = ({ editor }: { editor: any }) => {
const items: TableMenuItem[] = [
{
command: () => editor.chain().focus().addColumnBefore().run(),
- icon: Columns,
+ icon: InsertLeftTableIcon,
+ key: "insert-column-left",
+ name: "Insert 1 column left",
+ },
+ {
+ command: () => editor.chain().focus().addColumnAfter().run(),
+ icon: InsertRightTableIcon,
key: "insert-column-right",
name: "Insert 1 column right",
},
+ {
+ command: () => editor.chain().focus().addRowBefore().run(),
+ icon: InsertTopTableIcon,
+ key: "insert-row-above",
+ name: "Insert 1 row above",
+ },
{
command: () => editor.chain().focus().addRowAfter().run(),
- icon: Rows,
+ icon: InsertBottomTableIcon,
key: "insert-row-below",
name: "Insert 1 row below",
},
diff --git a/apps/app/components/tiptap/utils.ts b/space/components/tiptap/utils.ts
similarity index 100%
rename from apps/app/components/tiptap/utils.ts
rename to space/components/tiptap/utils.ts
diff --git a/space/components/ui/dropdown.tsx b/space/components/ui/dropdown.tsx
new file mode 100644
index 000000000..d1791de00
--- /dev/null
+++ b/space/components/ui/dropdown.tsx
@@ -0,0 +1,149 @@
+"use client";
+
+import { Fragment, useState, useRef } from "react";
+
+// next
+import Link from "next/link";
+
+// headless
+import { Popover, Transition } from "@headlessui/react";
+import { ChevronLeftIcon, CheckIcon } from "@heroicons/react/20/solid";
+
+// hooks
+import useOutSideClick from "hooks/use-outside-click";
+
+type ItemOptionType = {
+ display: React.ReactNode;
+ as?: "button" | "link" | "div";
+ href?: string;
+ isSelected?: boolean;
+ onClick?: () => void;
+ children?: ItemOptionType[] | null;
+};
+
+type DropdownItemProps = {
+ item: ItemOptionType;
+};
+
+type DropDownListProps = {
+ open: boolean;
+ handleClose?: () => void;
+ items: ItemOptionType[];
+};
+
+type DropdownProps = {
+ button: React.ReactNode | (() => React.ReactNode);
+ items: ItemOptionType[];
+};
+
+const DropdownList: React.FC = (props) => {
+ const { open, items, handleClose } = props;
+
+ const ref = useRef(null);
+
+ useOutSideClick(ref, () => {
+ if (handleClose) handleClose();
+ });
+
+ return (
+
+
+
+
+ {items.map((item, index) => (
+
+ ))}
+
+
+
+
+ );
+};
+
+const DropdownItem: React.FC = (props) => {
+ const { item } = props;
+ const { display, children, as: as_, href, onClick, isSelected } = item;
+
+ const [open, setOpen] = useState(false);
+
+ return (
+
+ {(!as_ || as_ === "button" || as_ === "div") && (
+ {
+ if (!children) {
+ if (onClick) onClick();
+ return;
+ }
+ setOpen((prev) => !prev);
+ }}
+ className={`w-full flex items-center gap-1 rounded px-1 py-1.5 text-custom-text-200 hover:bg-custom-background-80 ${
+ isSelected ? "bg-custom-background-80" : ""
+ }`}
+ >
+ {children && }
+ {!children && }
+ {display}
+
+
+ )}
+
+ {as_ === "link" && {display}}
+
+ {children && setOpen(false)} items={children} />}
+
+ );
+};
+
+const Dropdown: React.FC = (props) => {
+ const { button, items } = props;
+
+ return (
+
+ {({ open }) => (
+ <>
+
+ {typeof button === "function" ? button() : button}
+
+
+
+
+
+ {items.map((item, index) => (
+
+ ))}
+
+
+
+ >
+ )}
+
+ );
+};
+
+export { Dropdown };
diff --git a/space/components/ui/icon.tsx b/space/components/ui/icon.tsx
new file mode 100644
index 000000000..418186291
--- /dev/null
+++ b/space/components/ui/icon.tsx
@@ -0,0 +1,10 @@
+import React from "react";
+
+type Props = {
+ iconName: string;
+ className?: string;
+};
+
+export const Icon: React.FC = ({ iconName, className = "" }) => (
+ {iconName}
+);
diff --git a/space/components/ui/index.ts b/space/components/ui/index.ts
new file mode 100644
index 000000000..e44096909
--- /dev/null
+++ b/space/components/ui/index.ts
@@ -0,0 +1,8 @@
+export * from "./dropdown";
+export * from "./input";
+export * from "./loader";
+export * from "./primary-button";
+export * from "./secondary-button";
+export * from "./icon";
+export * from "./reaction-selector";
+export * from "./tooltip";
diff --git a/space/components/ui/input.tsx b/space/components/ui/input.tsx
new file mode 100644
index 000000000..b6be82ae5
--- /dev/null
+++ b/space/components/ui/input.tsx
@@ -0,0 +1,37 @@
+import React, { forwardRef, Ref } from "react";
+
+// types
+interface Props extends React.InputHTMLAttributes {
+ mode?: "primary" | "transparent" | "trueTransparent";
+ error?: boolean;
+ inputSize?: "rg" | "lg";
+ fullWidth?: boolean;
+}
+
+export const Input = forwardRef((props: Props, ref: Ref) => {
+ const { mode = "primary", error, className = "", type, fullWidth = true, id, inputSize = "rg", ...rest } = props;
+
+ return (
+
+ );
+});
+
+Input.displayName = "Input";
+
+export default Input;
diff --git a/apps/app/components/ui/loader.tsx b/space/components/ui/loader.tsx
similarity index 100%
rename from apps/app/components/ui/loader.tsx
rename to space/components/ui/loader.tsx
diff --git a/space/components/ui/primary-button.tsx b/space/components/ui/primary-button.tsx
new file mode 100644
index 000000000..b3e1b82ee
--- /dev/null
+++ b/space/components/ui/primary-button.tsx
@@ -0,0 +1,35 @@
+interface ButtonProps extends React.ButtonHTMLAttributes {
+ size?: "sm" | "md" | "lg";
+ outline?: boolean;
+ loading?: boolean;
+}
+
+export const PrimaryButton: React.FC = ({
+ children,
+ className = "",
+ onClick,
+ type = "button",
+ disabled = false,
+ loading = false,
+ size = "sm",
+ outline = false,
+}) => (
+
+ {children}
+
+);
diff --git a/space/components/ui/reaction-selector.tsx b/space/components/ui/reaction-selector.tsx
new file mode 100644
index 000000000..a7b67afa6
--- /dev/null
+++ b/space/components/ui/reaction-selector.tsx
@@ -0,0 +1,80 @@
+import { Fragment } from "react";
+
+// headless ui
+import { Popover, Transition } from "@headlessui/react";
+
+// helper
+import { renderEmoji } from "helpers/emoji.helper";
+
+// icons
+import { Icon } from "components/ui";
+
+const reactionEmojis = ["128077", "128078", "128516", "128165", "128533", "129505", "9992", "128064"];
+
+interface Props {
+ onSelect: (emoji: string) => void;
+ position?: "top" | "bottom";
+ selected?: string[];
+ size?: "sm" | "md" | "lg";
+}
+
+export const ReactionSelector: React.FC = (props) => {
+ const { onSelect, position, selected = [], size } = props;
+
+ return (
+
+ {({ open, close: closePopover }) => (
+ <>
+
+
+
+
+
+
+
+
+
+ {reactionEmojis.map((emoji) => (
+ {
+ onSelect(emoji);
+ closePopover();
+ }}
+ className={`grid place-items-center select-none rounded-md text-sm p-1 ${
+ selected.includes(emoji) ? "bg-custom-primary-100/10" : "hover:bg-custom-sidebar-background-80"
+ }`}
+ >
+ {renderEmoji(emoji)}
+
+ ))}
+
+
+
+
+ >
+ )}
+
+ );
+};
diff --git a/space/components/ui/secondary-button.tsx b/space/components/ui/secondary-button.tsx
new file mode 100644
index 000000000..2a9b3d528
--- /dev/null
+++ b/space/components/ui/secondary-button.tsx
@@ -0,0 +1,35 @@
+interface ButtonProps extends React.ButtonHTMLAttributes {
+ size?: "sm" | "md" | "lg";
+ outline?: boolean;
+ loading?: boolean;
+}
+
+export const SecondaryButton: React.FC = ({
+ children,
+ className = "",
+ onClick,
+ type = "button",
+ disabled = false,
+ loading = false,
+ size = "sm",
+ outline = false,
+}) => (
+
+ {children}
+
+);
diff --git a/apps/app/components/toast-alert/index.tsx b/space/components/ui/toast-alert.tsx
similarity index 100%
rename from apps/app/components/toast-alert/index.tsx
rename to space/components/ui/toast-alert.tsx
diff --git a/space/components/ui/tooltip.tsx b/space/components/ui/tooltip.tsx
new file mode 100644
index 000000000..994c0f32a
--- /dev/null
+++ b/space/components/ui/tooltip.tsx
@@ -0,0 +1,71 @@
+import React from "react";
+
+// next-themes
+import { useTheme } from "next-themes";
+// tooltip2
+import { Tooltip2 } from "@blueprintjs/popover2";
+
+type Props = {
+ tooltipHeading?: string;
+ tooltipContent: string | React.ReactNode;
+ position?:
+ | "top"
+ | "right"
+ | "bottom"
+ | "left"
+ | "auto"
+ | "auto-end"
+ | "auto-start"
+ | "bottom-left"
+ | "bottom-right"
+ | "left-bottom"
+ | "left-top"
+ | "right-bottom"
+ | "right-top"
+ | "top-left"
+ | "top-right";
+ children: JSX.Element;
+ disabled?: boolean;
+ className?: string;
+ openDelay?: number;
+ closeDelay?: number;
+};
+
+export const Tooltip: React.FC = ({
+ tooltipHeading,
+ tooltipContent,
+ position = "top",
+ children,
+ disabled = false,
+ className = "",
+ openDelay = 200,
+ closeDelay,
+}) => {
+ const { theme } = useTheme();
+
+ return (
+
+ {tooltipHeading && (
+
+ {tooltipHeading}
+
+ )}
+ {tooltipContent}
+
+ }
+ position={position}
+ renderTarget={({ isOpen: isTooltipOpen, ref: eleReference, ...tooltipProps }) =>
+ React.cloneElement(children, { ref: eleReference, ...tooltipProps, ...children.props })
+ }
+ />
+ );
+};
diff --git a/space/components/views/home.tsx b/space/components/views/home.tsx
new file mode 100644
index 000000000..999fce073
--- /dev/null
+++ b/space/components/views/home.tsx
@@ -0,0 +1,13 @@
+// mobx
+import { observer } from "mobx-react-lite";
+import { useMobxStore } from "lib/mobx/store-provider";
+// components
+import { SignInView, UserLoggedIn } from "components/accounts";
+
+export const HomeView = observer(() => {
+ const { user: userStore } = useMobxStore();
+
+ if (!userStore.currentUser) return
;
+
+ return
;
+});
diff --git a/space/components/views/index.ts b/space/components/views/index.ts
new file mode 100644
index 000000000..84d36cd29
--- /dev/null
+++ b/space/components/views/index.ts
@@ -0,0 +1 @@
+export * from "./home";
diff --git a/space/components/views/project-details.tsx b/space/components/views/project-details.tsx
new file mode 100644
index 000000000..1c9c6ddc9
--- /dev/null
+++ b/space/components/views/project-details.tsx
@@ -0,0 +1,98 @@
+import { useEffect } from "react";
+
+import Image from "next/image";
+import { useRouter } from "next/router";
+
+// mobx
+import { observer } from "mobx-react-lite";
+// components
+import { IssueListView } from "components/issues/board-views/list";
+import { IssueKanbanView } from "components/issues/board-views/kanban";
+import { IssueCalendarView } from "components/issues/board-views/calendar";
+import { IssueSpreadsheetView } from "components/issues/board-views/spreadsheet";
+import { IssueGanttView } from "components/issues/board-views/gantt";
+import { IssuePeekOverview } from "components/issues/peek-overview";
+// mobx store
+import { RootStore } from "store/root";
+import { useMobxStore } from "lib/mobx/store-provider";
+// assets
+import SomethingWentWrongImage from "public/something-went-wrong.svg";
+
+export const ProjectDetailsView = observer(() => {
+ const router = useRouter();
+ const { workspace_slug, project_slug, states, labels, priorities, board, peekId } = router.query;
+
+ const {
+ issue: issueStore,
+ project: projectStore,
+ issueDetails: issueDetailStore,
+ user: userStore,
+ }: RootStore = useMobxStore();
+
+ useEffect(() => {
+ if (!userStore.currentUser) {
+ userStore.fetchCurrentUser();
+ }
+ }, [userStore]);
+
+ useEffect(() => {
+ if (workspace_slug && project_slug) {
+ const params = {
+ state: states || null,
+ labels: labels || null,
+ priority: priorities || null,
+ };
+ issueStore.fetchPublicIssues(workspace_slug?.toString(), project_slug.toString(), params);
+ }
+ }, [workspace_slug, project_slug, issueStore, states, labels, priorities]);
+
+ useEffect(() => {
+ if (peekId && workspace_slug && project_slug) {
+ issueDetailStore.setPeekId(peekId.toString());
+ }
+ }, [peekId, issueDetailStore, project_slug, workspace_slug]);
+
+ return (
+
+ {workspace_slug &&
}
+
+ {issueStore?.loader && !issueStore.issues ? (
+
Loading...
+ ) : (
+ <>
+ {issueStore?.error ? (
+
+
+
+
Oops! Something went wrong.
+
The public board does not exist. Please check the URL.
+
+
+ ) : (
+ projectStore?.activeBoard && (
+ <>
+ {projectStore?.activeBoard === "list" && (
+
+
+
+ )}
+ {projectStore?.activeBoard === "kanban" && (
+
+
+
+ )}
+ {projectStore?.activeBoard === "calendar" &&
}
+ {projectStore?.activeBoard === "spreadsheet" &&
}
+ {projectStore?.activeBoard === "gantt" &&
}
+ >
+ )
+ )}
+ >
+ )}
+
+ );
+});
diff --git a/apps/space/constants/data.ts b/space/constants/data.ts
similarity index 67%
rename from apps/space/constants/data.ts
rename to space/constants/data.ts
index 81ccae116..29d411342 100644
--- a/apps/space/constants/data.ts
+++ b/space/constants/data.ts
@@ -7,7 +7,7 @@ import {
TIssueGroupKey,
IIssuePriorityFilters,
IIssueGroup,
-} from "store/types/issue";
+} from "types/issue";
// icons
import {
BacklogStateIcon,
@@ -18,69 +18,49 @@ import {
} from "components/icons";
// all issue views
-export const issueViews: IIssueBoardViews[] = [
- {
- key: "list",
+export const issueViews: any = {
+ list: {
title: "List View",
icon: "format_list_bulleted",
className: "",
},
- {
- key: "kanban",
+ kanban: {
title: "Board View",
icon: "grid_view",
className: "",
},
- // {
- // key: "calendar",
- // title: "Calendar View",
- // icon: "calendar_month",
- // className: "",
- // },
- // {
- // key: "spreadsheet",
- // title: "Spreadsheet View",
- // icon: "table_chart",
- // className: "",
- // },
- // {
- // key: "gantt",
- // title: "Gantt Chart View",
- // icon: "waterfall_chart",
- // className: "rotate-90",
- // },
-];
+};
// issue priority filters
export const issuePriorityFilters: IIssuePriorityFilters[] = [
{
key: "urgent",
title: "Urgent",
- className: "border border-red-500/50 bg-red-500/20 text-red-500",
+ className: "bg-red-500 border-red-500 text-white",
icon: "error",
},
{
key: "high",
title: "High",
- className: "border border-orange-500/50 bg-orange-500/20 text-orange-500",
+ className: "text-orange-500 border-custom-border-300",
icon: "signal_cellular_alt",
},
{
key: "medium",
title: "Medium",
- className: "border border-yellow-500/50 bg-yellow-500/20 text-yellow-500",
+ className: "text-yellow-500 border-custom-border-300",
icon: "signal_cellular_alt_2_bar",
},
{
key: "low",
title: "Low",
- className: "border border-green-500/50 bg-green-500/20 text-green-500",
+ className: "text-green-500 border-custom-border-300",
icon: "signal_cellular_alt_1_bar",
},
{
key: "none",
title: "None",
- className: "border border-gray-500/50 bg-gray-500/20 text-gray-500",
+ className: "text-gray-500 border-custom-border-300",
icon: "block",
},
];
@@ -111,35 +91,35 @@ export const issueGroups: IIssueGroup[] = [
key: "backlog",
title: "Backlog",
color: "#d9d9d9",
- className: `border-[#d9d9d9]/50 text-[#d9d9d9] bg-[#d9d9d9]/10`,
+ className: `text-[#d9d9d9] bg-[#d9d9d9]/10`,
icon: BacklogStateIcon,
},
{
key: "unstarted",
title: "Unstarted",
color: "#3f76ff",
- className: `border-[#3f76ff]/50 text-[#3f76ff] bg-[#3f76ff]/10`,
+ className: `text-[#3f76ff] bg-[#3f76ff]/10`,
icon: UnstartedStateIcon,
},
{
key: "started",
title: "Started",
color: "#f59e0b",
- className: `border-[#f59e0b]/50 text-[#f59e0b] bg-[#f59e0b]/10`,
+ className: `text-[#f59e0b] bg-[#f59e0b]/10`,
icon: StartedStateIcon,
},
{
key: "completed",
title: "Completed",
color: "#16a34a",
- className: `border-[#16a34a]/50 text-[#16a34a] bg-[#16a34a]/10`,
+ className: `text-[#16a34a] bg-[#16a34a]/10`,
icon: CompletedStateIcon,
},
{
key: "cancelled",
title: "Cancelled",
color: "#dc2626",
- className: `border-[#dc2626]/50 text-[#dc2626] bg-[#dc2626]/10`,
+ className: `text-[#dc2626] bg-[#dc2626]/10`,
icon: CancelledStateIcon,
},
];
diff --git a/space/constants/seo.ts b/space/constants/seo.ts
new file mode 100644
index 000000000..b2baca612
--- /dev/null
+++ b/space/constants/seo.ts
@@ -0,0 +1,7 @@
+export const SITE_NAME = "Plane Deploy | Make your Plane boards and roadmaps pubic with just one-click. ";
+export const SITE_TITLE = "Plane Deploy | Make your Plane boards public with one-click";
+export const SITE_DESCRIPTION = "Plane Deploy is a customer feedback management tool built on top of plane.so";
+export const SITE_KEYWORDS =
+ "software development, customer feedback, software, accelerate, code management, release management, project management, issue tracking, agile, scrum, kanban, collaboration";
+export const SITE_URL = "https://app.plane.so/";
+export const TWITTER_USER_NAME = "planepowers";
diff --git a/space/constants/workspace.ts b/space/constants/workspace.ts
new file mode 100644
index 000000000..5ae5a7cf4
--- /dev/null
+++ b/space/constants/workspace.ts
@@ -0,0 +1,12 @@
+export const USER_ROLES = [
+ { value: "Product / Project Manager", label: "Product / Project Manager" },
+ { value: "Development / Engineering", label: "Development / Engineering" },
+ { value: "Founder / Executive", label: "Founder / Executive" },
+ { value: "Freelancer / Consultant", label: "Freelancer / Consultant" },
+ { value: "Marketing / Growth", label: "Marketing / Growth" },
+ { value: "Sales / Business Development", label: "Sales / Business Development" },
+ { value: "Support / Operations", label: "Support / Operations" },
+ { value: "Student / Professor", label: "Student / Professor" },
+ { value: "Human Resources", label: "Human Resources" },
+ { value: "Other", label: "Other" },
+];
diff --git a/space/contexts/toast.context.tsx b/space/contexts/toast.context.tsx
new file mode 100644
index 000000000..a382b4fd2
--- /dev/null
+++ b/space/contexts/toast.context.tsx
@@ -0,0 +1,97 @@
+import React, { createContext, useCallback, useReducer } from "react";
+// uuid
+import { v4 as uuid } from "uuid";
+// components
+import ToastAlert from "components/ui/toast-alert";
+
+export const toastContext = createContext
({} as ContextType);
+
+// types
+type ToastAlert = {
+ id: string;
+ title: string;
+ message?: string;
+ type: "success" | "error" | "warning" | "info";
+};
+
+type ReducerActionType = {
+ type: "SET_TOAST_ALERT" | "REMOVE_TOAST_ALERT";
+ payload: ToastAlert;
+};
+
+type ContextType = {
+ alerts?: ToastAlert[];
+ removeAlert: (id: string) => void;
+ setToastAlert: (data: {
+ title: string;
+ type?: "success" | "error" | "warning" | "info" | undefined;
+ message?: string | undefined;
+ }) => void;
+};
+
+type StateType = {
+ toastAlerts?: ToastAlert[];
+};
+
+type ReducerFunctionType = (state: StateType, action: ReducerActionType) => StateType;
+
+export const initialState: StateType = {
+ toastAlerts: [],
+};
+
+export const reducer: ReducerFunctionType = (state, action) => {
+ const { type, payload } = action;
+
+ switch (type) {
+ case "SET_TOAST_ALERT":
+ return {
+ ...state,
+ toastAlerts: [...(state.toastAlerts ?? []), payload],
+ };
+
+ case "REMOVE_TOAST_ALERT":
+ return {
+ ...state,
+ toastAlerts: state.toastAlerts?.filter((toastAlert) => toastAlert.id !== payload.id),
+ };
+
+ default: {
+ return state;
+ }
+ }
+};
+
+export const ToastContextProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
+ const [state, dispatch] = useReducer(reducer, initialState);
+
+ const removeAlert = useCallback((id: string) => {
+ dispatch({
+ type: "REMOVE_TOAST_ALERT",
+ payload: { id, title: "", message: "", type: "success" },
+ });
+ }, []);
+
+ const setToastAlert = useCallback(
+ (data: { title: string; type?: "success" | "error" | "warning" | "info"; message?: string }) => {
+ const id = uuid();
+ const { title, type, message } = data;
+ dispatch({
+ type: "SET_TOAST_ALERT",
+ payload: { id, title, message, type: type ?? "success" },
+ });
+
+ const timer = setTimeout(() => {
+ removeAlert(id);
+ clearTimeout(timer);
+ }, 3000);
+ },
+ [removeAlert]
+ );
+
+ return (
+
+
+ {children}
+
+ );
+};
diff --git a/space/helpers/date-time.helper.ts b/space/helpers/date-time.helper.ts
new file mode 100644
index 000000000..f19a5358b
--- /dev/null
+++ b/space/helpers/date-time.helper.ts
@@ -0,0 +1,37 @@
+export const timeAgo = (time: any) => {
+ switch (typeof time) {
+ case "number":
+ break;
+ case "string":
+ time = +new Date(time);
+ break;
+ case "object":
+ if (time.constructor === Date) time = time.getTime();
+ break;
+ default:
+ time = +new Date();
+ }
+};
+
+/**
+ * @description Returns date and month, if date is of the current year
+ * @description Returns date, month adn year, if date is of a different year than current
+ * @param {string} date
+ * @example renderFullDate("2023-01-01") // 1 Jan
+ * @example renderFullDate("2021-01-01") // 1 Jan, 2021
+ */
+
+export const renderFullDate = (date: string): string => {
+ if (!date) return "";
+
+ const months: string[] = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
+
+ const currentDate: Date = new Date();
+ const [year, month, day]: number[] = date.split("-").map(Number);
+
+ const formattedMonth: string = months[month - 1];
+ const formattedDay: string = day < 10 ? `0${day}` : day.toString();
+
+ if (currentDate.getFullYear() === year) return `${formattedDay} ${formattedMonth}`;
+ else return `${formattedDay} ${formattedMonth}, ${year}`;
+};
diff --git a/apps/app/helpers/emoji.helper.tsx b/space/helpers/emoji.helper.tsx
similarity index 77%
rename from apps/app/helpers/emoji.helper.tsx
rename to space/helpers/emoji.helper.tsx
index 06bf8ba15..7c9f3cfcb 100644
--- a/apps/app/helpers/emoji.helper.tsx
+++ b/space/helpers/emoji.helper.tsx
@@ -41,13 +41,16 @@ export const groupReactions: (reactions: any[], key: string) => { [key: string]:
reactions: any,
key: string
) => {
- const groupedReactions = reactions.reduce((acc: any, reaction: any) => {
- if (!acc[reaction[key]]) {
- acc[reaction[key]] = [];
- }
- acc[reaction[key]].push(reaction);
- return acc;
- }, {} as { [key: string]: any[] });
+ const groupedReactions = reactions.reduce(
+ (acc: any, reaction: any) => {
+ if (!acc[reaction[key]]) {
+ acc[reaction[key]] = [];
+ }
+ acc[reaction[key]].push(reaction);
+ return acc;
+ },
+ {} as { [key: string]: any[] }
+ );
return groupedReactions;
};
diff --git a/space/helpers/string.helper.ts b/space/helpers/string.helper.ts
new file mode 100644
index 000000000..1b676ca57
--- /dev/null
+++ b/space/helpers/string.helper.ts
@@ -0,0 +1,31 @@
+export const addSpaceIfCamelCase = (str: string) => str.replace(/([a-z])([A-Z])/g, "$1 $2");
+
+const fallbackCopyTextToClipboard = (text: string) => {
+ var textArea = document.createElement("textarea");
+ textArea.value = text;
+
+ // Avoid scrolling to bottom
+ textArea.style.top = "0";
+ textArea.style.left = "0";
+ textArea.style.position = "fixed";
+
+ document.body.appendChild(textArea);
+ textArea.focus();
+ textArea.select();
+
+ try {
+ // FIXME: Even though we are using this as a fallback, execCommand is deprecated 👎. We should find a better way to do this.
+ // https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand
+ var successful = document.execCommand("copy");
+ } catch (err) {}
+
+ document.body.removeChild(textArea);
+};
+
+export const copyTextToClipboard = async (text: string) => {
+ if (!navigator.clipboard) {
+ fallbackCopyTextToClipboard(text);
+ return;
+ }
+ await navigator.clipboard.writeText(text);
+};
diff --git a/space/hooks/use-outside-click.tsx b/space/hooks/use-outside-click.tsx
new file mode 100644
index 000000000..f2bed415f
--- /dev/null
+++ b/space/hooks/use-outside-click.tsx
@@ -0,0 +1,21 @@
+"use client";
+
+import { useEffect } from "react";
+
+const useOutSideClick = (ref: any, callback: any) => {
+ const handleClick = (e: any) => {
+ if (ref.current && !ref.current.contains(e.target)) {
+ callback();
+ }
+ };
+
+ useEffect(() => {
+ document.addEventListener("click", handleClick);
+
+ return () => {
+ document.removeEventListener("click", handleClick);
+ };
+ });
+};
+
+export default useOutSideClick;
diff --git a/apps/app/hooks/use-timer.tsx b/space/hooks/use-timer.tsx
similarity index 100%
rename from apps/app/hooks/use-timer.tsx
rename to space/hooks/use-timer.tsx
diff --git a/apps/app/hooks/use-toast.tsx b/space/hooks/use-toast.tsx
similarity index 100%
rename from apps/app/hooks/use-toast.tsx
rename to space/hooks/use-toast.tsx
diff --git a/space/layouts/project-layout.tsx b/space/layouts/project-layout.tsx
new file mode 100644
index 000000000..1a0b7899e
--- /dev/null
+++ b/space/layouts/project-layout.tsx
@@ -0,0 +1,33 @@
+import Link from "next/link";
+import Image from "next/image";
+
+// mobx
+import { observer } from "mobx-react-lite";
+import planeLogo from "public/plane-logo.svg";
+// components
+import IssueNavbar from "components/issues/navbar";
+
+const ProjectLayout = ({ children }: { children: React.ReactNode }) => (
+
+);
+
+export default observer(ProjectLayout);
diff --git a/apps/space/lib/index.ts b/space/lib/index.ts
similarity index 100%
rename from apps/space/lib/index.ts
rename to space/lib/index.ts
diff --git a/space/lib/mobx/store-init.tsx b/space/lib/mobx/store-init.tsx
new file mode 100644
index 000000000..6e38d9c6d
--- /dev/null
+++ b/space/lib/mobx/store-init.tsx
@@ -0,0 +1,25 @@
+"use client";
+
+import { useEffect } from "react";
+// next imports
+import { useRouter } from "next/router";
+// mobx store
+import { useMobxStore } from "lib/mobx/store-provider";
+import { RootStore } from "store/root";
+
+const MobxStoreInit = () => {
+ const store: RootStore = useMobxStore();
+
+ const router = useRouter();
+ const { states, labels, priorities } = router.query as { states: string[]; labels: string[]; priorities: string[] };
+
+ // useEffect(() => {
+ // store.issue.userSelectedLabels = labels || [];
+ // store.issue.userSelectedPriorities = priorities || [];
+ // store.issue.userSelectedStates = states || [];
+ // }, [store.issue]);
+
+ return <>>;
+};
+
+export default MobxStoreInit;
diff --git a/apps/app/lib/mobx/store-provider.tsx b/space/lib/mobx/store-provider.tsx
similarity index 100%
rename from apps/app/lib/mobx/store-provider.tsx
rename to space/lib/mobx/store-provider.tsx
diff --git a/space/next.config.js b/space/next.config.js
new file mode 100644
index 000000000..392a4cab9
--- /dev/null
+++ b/space/next.config.js
@@ -0,0 +1,19 @@
+/** @type {import('next').NextConfig} */
+const path = require("path");
+const withImages = require("next-images");
+
+const nextConfig = {
+ reactStrictMode: false,
+ swcMinify: true,
+ experimental: {
+ outputFileTracingRoot: path.join(__dirname, "../"),
+ },
+ output: "standalone",
+};
+
+if (parseInt(process.env.NEXT_PUBLIC_DEPLOY_WITH_NGINX || "0")) {
+ const nextConfigWithNginx = withImages({ basePath: "/spaces", ...nextConfig });
+ module.exports = nextConfigWithNginx;
+} else {
+ module.exports = nextConfig;
+}
diff --git a/space/package.json b/space/package.json
new file mode 100644
index 000000000..768abb8ff
--- /dev/null
+++ b/space/package.json
@@ -0,0 +1,80 @@
+{
+ "name": "space",
+ "version": "0.0.1",
+ "private": true,
+ "scripts": {
+ "dev": "next dev -p 4000",
+ "build": "next build",
+ "start": "next start -p 4000",
+ "lint": "next lint"
+ },
+ "dependencies": {
+ "@blueprintjs/core": "^4.16.3",
+ "@blueprintjs/popover2": "^1.13.3",
+ "@emotion/react": "^11.11.1",
+ "@emotion/styled": "^11.11.0",
+ "@headlessui/react": "^1.7.13",
+ "@heroicons/react": "^2.0.12",
+ "@mui/icons-material": "^5.14.1",
+ "@mui/material": "^5.14.1",
+ "@tailwindcss/typography": "^0.5.9",
+ "@tiptap-pro/extension-unique-id": "^2.1.0",
+ "@tiptap/extension-code-block-lowlight": "^2.0.4",
+ "@tiptap/extension-color": "^2.0.4",
+ "@tiptap/extension-gapcursor": "^2.1.7",
+ "@tiptap/extension-highlight": "^2.0.4",
+ "@tiptap/extension-horizontal-rule": "^2.0.4",
+ "@tiptap/extension-image": "^2.0.4",
+ "@tiptap/extension-link": "^2.0.4",
+ "@tiptap/extension-placeholder": "^2.0.4",
+ "@tiptap/extension-table": "^2.1.6",
+ "@tiptap/extension-table-cell": "^2.1.6",
+ "@tiptap/extension-table-header": "^2.1.6",
+ "@tiptap/extension-table-row": "^2.1.6",
+ "@tiptap/extension-task-item": "^2.0.4",
+ "@tiptap/extension-task-list": "^2.0.4",
+ "@tiptap/extension-text-style": "^2.0.4",
+ "@tiptap/extension-underline": "^2.0.4",
+ "@tiptap/pm": "^2.0.4",
+ "@tiptap/react": "^2.0.4",
+ "@tiptap/starter-kit": "^2.0.4",
+ "@tiptap/suggestion": "^2.0.4",
+ "axios": "^1.3.4",
+ "clsx": "^2.0.0",
+ "js-cookie": "^3.0.1",
+ "lowlight": "^2.9.0",
+ "lucide-react": "^0.263.1",
+ "mobx": "^6.10.0",
+ "mobx-react-lite": "^4.0.3",
+ "next": "12.3.2",
+ "next-images": "^1.8.5",
+ "next-themes": "^0.2.1",
+ "nprogress": "^0.2.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-hook-form": "^7.38.0",
+ "react-moveable": "^0.54.1",
+ "swr": "^2.2.2",
+ "tailwind-merge": "^1.14.0",
+ "tiptap-markdown": "^0.8.2",
+ "typescript": "4.9.5",
+ "use-debounce": "^9.0.4",
+ "uuid": "^9.0.0"
+ },
+ "devDependencies": {
+ "@tailwindcss/typography": "^0.5.9",
+ "@types/js-cookie": "^3.0.3",
+ "@types/node": "18.14.1",
+ "@types/nprogress": "^0.2.0",
+ "@types/react": "18.0.28",
+ "@types/react-dom": "18.0.11",
+ "@types/uuid": "^9.0.1",
+ "autoprefixer": "^10.4.13",
+ "eslint": "8.34.0",
+ "eslint-config-custom": "*",
+ "eslint-config-next": "13.2.1",
+ "postcss": "^8.4.21",
+ "tsconfig": "*",
+ "tailwindcss": "^3.2.7"
+ }
+}
diff --git a/apps/space/pages/404.tsx b/space/pages/404.tsx
similarity index 90%
rename from apps/space/pages/404.tsx
rename to space/pages/404.tsx
index d10d95fb9..be40bd501 100644
--- a/apps/space/pages/404.tsx
+++ b/space/pages/404.tsx
@@ -1,12 +1,13 @@
// next imports
import Image from "next/image";
+import notFoundImage from "public/404.svg";
const Custom404Error = () => (
-
+
Oops! Something went wrong.
diff --git a/space/pages/[workspace_slug]/[project_slug]/index.tsx b/space/pages/[workspace_slug]/[project_slug]/index.tsx
new file mode 100644
index 000000000..e50c01c18
--- /dev/null
+++ b/space/pages/[workspace_slug]/[project_slug]/index.tsx
@@ -0,0 +1,43 @@
+import Head from "next/head";
+import { useRouter } from "next/router";
+
+import useSWR from "swr";
+
+/// layouts
+import ProjectLayout from "layouts/project-layout";
+// components
+import { ProjectDetailsView } from "components/views/project-details";
+// lib
+import { useMobxStore } from "lib/mobx/store-provider";
+
+const WorkspaceProjectPage = (props: any) => {
+ const SITE_TITLE = props?.project_settings?.project_details?.name || "Plane | Deploy";
+
+ const router = useRouter();
+ const { workspace_slug, project_slug, states, labels, priorities } = router.query;
+
+ const { project: projectStore, issue: issueStore } = useMobxStore();
+
+ useSWR("REVALIDATE_ALL", () => {
+ if (workspace_slug && project_slug) {
+ projectStore.fetchProjectSettings(workspace_slug.toString(), project_slug.toString());
+ const params = {
+ state: states || null,
+ labels: labels || null,
+ priority: priorities || null,
+ };
+ issueStore.fetchPublicIssues(workspace_slug.toString(), project_slug.toString(), params);
+ }
+ });
+
+ return (
+
+
+ {SITE_TITLE}
+
+
+
+ );
+};
+
+export default WorkspaceProjectPage;
diff --git a/apps/space/app/[workspace_slug]/page.tsx b/space/pages/[workspace_slug]/index.tsx
similarity index 92%
rename from apps/space/app/[workspace_slug]/page.tsx
rename to space/pages/[workspace_slug]/index.tsx
index c35662f5a..a844c0763 100644
--- a/apps/space/app/[workspace_slug]/page.tsx
+++ b/space/pages/[workspace_slug]/index.tsx
@@ -1,5 +1,3 @@
-"use client";
-
const WorkspaceProjectPage = () => (
Plane Workspace Space
);
diff --git a/space/pages/_app.tsx b/space/pages/_app.tsx
new file mode 100644
index 000000000..33c137d41
--- /dev/null
+++ b/space/pages/_app.tsx
@@ -0,0 +1,45 @@
+import Head from "next/head";
+import type { AppProps } from "next/app";
+import { ThemeProvider } from "next-themes";
+// styles
+import "styles/globals.css";
+import "styles/editor.css";
+// contexts
+import { ToastContextProvider } from "contexts/toast.context";
+// mobx store provider
+import { MobxStoreProvider } from "lib/mobx/store-provider";
+import MobxStoreInit from "lib/mobx/store-init";
+// constants
+import { SITE_NAME, SITE_DESCRIPTION, SITE_URL, TWITTER_USER_NAME, SITE_KEYWORDS, SITE_TITLE } from "constants/seo";
+
+const prefix = parseInt(process.env.NEXT_PUBLIC_DEPLOY_WITH_NGINX || "0") === 0 ? "/" : "/spaces/";
+
+function MyApp({ Component, pageProps }: AppProps) {
+ return (
+
+
+
+ {SITE_TITLE}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default MyApp;
diff --git a/apps/space/pages/_document.tsx b/space/pages/_document.tsx
similarity index 80%
rename from apps/space/pages/_document.tsx
rename to space/pages/_document.tsx
index 8b41d05fc..ca023f4a4 100644
--- a/apps/space/pages/_document.tsx
+++ b/space/pages/_document.tsx
@@ -5,7 +5,7 @@ class MyDocument extends Document {
return (
-
+
diff --git a/space/pages/index.tsx b/space/pages/index.tsx
new file mode 100644
index 000000000..fe0b7d33a
--- /dev/null
+++ b/space/pages/index.tsx
@@ -0,0 +1,8 @@
+import React from "react";
+
+// components
+import { HomeView } from "components/views";
+
+const HomePage = () =>
;
+
+export default HomePage;
diff --git a/space/pages/onboarding/index.tsx b/space/pages/onboarding/index.tsx
new file mode 100644
index 000000000..2f08ee648
--- /dev/null
+++ b/space/pages/onboarding/index.tsx
@@ -0,0 +1,52 @@
+import React, { useEffect } from "react";
+import Image from "next/image";
+// assets
+import BluePlaneLogoWithoutText from "public/plane-logos/blue-without-text.png";
+// mobx
+import { observer } from "mobx-react-lite";
+import { useMobxStore } from "lib/mobx/store-provider";
+// services
+import authenticationService from "services/authentication.service";
+// hooks
+import useToast from "hooks/use-toast";
+// components
+import { OnBoardingForm } from "components/accounts/onboarding-form";
+
+const OnBoardingPage = () => {
+ const { user: userStore } = useMobxStore();
+
+ const user = userStore?.currentUser;
+
+ const { setToastAlert } = useToast();
+
+ useEffect(() => {
+ const user = userStore?.currentUser;
+
+ if (!user) {
+ userStore.fetchCurrentUser();
+ }
+ }, [userStore]);
+
+ return (
+
+
+
+
+
+
+ {user?.email}
+
+
+
+
+
+
+
+ );
+};
+
+export default observer(OnBoardingPage);
diff --git a/apps/space/app/project-not-published/page.tsx b/space/pages/project-not-published/index.tsx
similarity index 87%
rename from apps/space/app/project-not-published/page.tsx
rename to space/pages/project-not-published/index.tsx
index 82a2ff5da..985b7bc41 100644
--- a/apps/space/app/project-not-published/page.tsx
+++ b/space/pages/project-not-published/index.tsx
@@ -1,12 +1,13 @@
// next imports
import Image from "next/image";
+import projectNotPublishedImage from "public/project-not-published.svg";
const CustomProjectNotPublishedError = () => (
-
+
Oops! The page you{`'`}re looking for isn{`'`}t live at the moment.
diff --git a/apps/app/postcss.config.js b/space/postcss.config.js
similarity index 100%
rename from apps/app/postcss.config.js
rename to space/postcss.config.js
diff --git a/apps/app/public/404.svg b/space/public/404.svg
similarity index 100%
rename from apps/app/public/404.svg
rename to space/public/404.svg
diff --git a/apps/app/public/favicon/android-chrome-192x192.png b/space/public/favicon/android-chrome-192x192.png
similarity index 100%
rename from apps/app/public/favicon/android-chrome-192x192.png
rename to space/public/favicon/android-chrome-192x192.png
diff --git a/apps/app/public/favicon/android-chrome-512x512.png b/space/public/favicon/android-chrome-512x512.png
similarity index 100%
rename from apps/app/public/favicon/android-chrome-512x512.png
rename to space/public/favicon/android-chrome-512x512.png
diff --git a/apps/app/public/favicon/apple-touch-icon.png b/space/public/favicon/apple-touch-icon.png
similarity index 100%
rename from apps/app/public/favicon/apple-touch-icon.png
rename to space/public/favicon/apple-touch-icon.png
diff --git a/apps/app/public/favicon/favicon-16x16.png b/space/public/favicon/favicon-16x16.png
similarity index 100%
rename from apps/app/public/favicon/favicon-16x16.png
rename to space/public/favicon/favicon-16x16.png
diff --git a/apps/app/public/favicon/favicon-32x32.png b/space/public/favicon/favicon-32x32.png
similarity index 100%
rename from apps/app/public/favicon/favicon-32x32.png
rename to space/public/favicon/favicon-32x32.png
diff --git a/apps/app/public/favicon/favicon.ico b/space/public/favicon/favicon.ico
similarity index 100%
rename from apps/app/public/favicon/favicon.ico
rename to space/public/favicon/favicon.ico
diff --git a/apps/app/public/favicon/site.webmanifest b/space/public/favicon/site.webmanifest
similarity index 100%
rename from apps/app/public/favicon/site.webmanifest
rename to space/public/favicon/site.webmanifest
diff --git a/space/public/logos/github-black.svg b/space/public/logos/github-black.svg
new file mode 100644
index 000000000..ad04a798e
--- /dev/null
+++ b/space/public/logos/github-black.svg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
diff --git a/space/public/logos/github-square.svg b/space/public/logos/github-square.svg
new file mode 100644
index 000000000..a7836db8f
--- /dev/null
+++ b/space/public/logos/github-square.svg
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
diff --git a/space/public/logos/github-white.svg b/space/public/logos/github-white.svg
new file mode 100644
index 000000000..90fe34d8b
--- /dev/null
+++ b/space/public/logos/github-white.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/space/public/plane-logo.svg b/space/public/plane-logo.svg
new file mode 100644
index 000000000..11179417c
--- /dev/null
+++ b/space/public/plane-logo.svg
@@ -0,0 +1,94 @@
+
+
+
+
diff --git a/apps/app/public/plane-logos/black-horizontal-with-blue-logo.svg b/space/public/plane-logos/black-horizontal-with-blue-logo.svg
similarity index 100%
rename from apps/app/public/plane-logos/black-horizontal-with-blue-logo.svg
rename to space/public/plane-logos/black-horizontal-with-blue-logo.svg
diff --git a/apps/app/public/plane-logos/blue-without-text.png b/space/public/plane-logos/blue-without-text.png
similarity index 100%
rename from apps/app/public/plane-logos/blue-without-text.png
rename to space/public/plane-logos/blue-without-text.png
diff --git a/apps/app/public/plane-logos/white-horizontal-with-blue-logo.svg b/space/public/plane-logos/white-horizontal-with-blue-logo.svg
similarity index 100%
rename from apps/app/public/plane-logos/white-horizontal-with-blue-logo.svg
rename to space/public/plane-logos/white-horizontal-with-blue-logo.svg
diff --git a/apps/app/public/plane-logos/white-horizontal.svg b/space/public/plane-logos/white-horizontal.svg
similarity index 100%
rename from apps/app/public/plane-logos/white-horizontal.svg
rename to space/public/plane-logos/white-horizontal.svg
diff --git a/apps/space/public/project-not-published.svg b/space/public/project-not-published.svg
similarity index 100%
rename from apps/space/public/project-not-published.svg
rename to space/public/project-not-published.svg
diff --git a/space/public/site.webmanifest.json b/space/public/site.webmanifest.json
new file mode 100644
index 000000000..4c32ec6e3
--- /dev/null
+++ b/space/public/site.webmanifest.json
@@ -0,0 +1,13 @@
+{
+ "name": "Plane Space",
+ "short_name": "Plane Space",
+ "description": "Plane helps you plan your issues, cycles, and product modules.",
+ "start_url": ".",
+ "display": "standalone",
+ "background_color": "#f9fafb",
+ "theme_color": "#3f76ff",
+ "icons": [
+ { "src": "/favicon/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" },
+ { "src": "/favicon/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" }
+ ]
+}
diff --git a/space/public/something-went-wrong.svg b/space/public/something-went-wrong.svg
new file mode 100644
index 000000000..bd51f7f49
--- /dev/null
+++ b/space/public/something-went-wrong.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/space/public/user-logged-in.svg b/space/public/user-logged-in.svg
new file mode 100644
index 000000000..e20b49e82
--- /dev/null
+++ b/space/public/user-logged-in.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/apps/space/services/api.service.ts b/space/services/api.service.ts
similarity index 87%
rename from apps/space/services/api.service.ts
rename to space/services/api.service.ts
index 4cf26d9ee..d3ad3949b 100644
--- a/apps/space/services/api.service.ts
+++ b/space/services/api.service.ts
@@ -90,6 +90,16 @@ abstract class APIService {
});
}
+ mediaUpload(url: string, data = {}, config = {}): Promise
{
+ return axios({
+ method: "post",
+ url: this.baseURL + url,
+ data,
+ headers: this.getAccessToken() ? { ...this.getHeaders(), "Content-Type": "multipart/form-data" } : {},
+ ...config,
+ });
+ }
+
request(config = {}) {
return axios(config);
}
diff --git a/space/services/authentication.service.ts b/space/services/authentication.service.ts
new file mode 100644
index 000000000..a6f1ec90f
--- /dev/null
+++ b/space/services/authentication.service.ts
@@ -0,0 +1,92 @@
+// services
+import APIService from "services/api.service";
+
+class AuthService extends APIService {
+ constructor() {
+ super(process.env.NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
+ }
+
+ async emailLogin(data: any) {
+ return this.post("/api/sign-in/", data, { headers: {} })
+ .then((response) => {
+ this.setAccessToken(response?.data?.access_token);
+ this.setRefreshToken(response?.data?.refresh_token);
+ return response?.data;
+ })
+ .catch((error) => {
+ throw error?.response?.data;
+ });
+ }
+
+ async emailSignUp(data: { email: string; password: string }) {
+ return this.post("/api/sign-up/", data, { headers: {} })
+ .then((response) => {
+ this.setAccessToken(response?.data?.access_token);
+ this.setRefreshToken(response?.data?.refresh_token);
+ return response?.data;
+ })
+ .catch((error) => {
+ throw error?.response?.data;
+ });
+ }
+
+ async socialAuth(data: any): Promise<{
+ access_token: string;
+ refresh_toke: string;
+ user: any;
+ }> {
+ return this.post("/api/social-auth/", data, { headers: {} })
+ .then((response) => {
+ this.setAccessToken(response?.data?.access_token);
+ this.setRefreshToken(response?.data?.refresh_token);
+ return response?.data;
+ })
+ .catch((error) => {
+ throw error?.response?.data;
+ });
+ }
+
+ async emailCode(data: any) {
+ return this.post("/api/magic-generate/", data, { headers: {} })
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response?.data;
+ });
+ }
+
+ async forgotPassword(data: { email: string }): Promise {
+ return this.post(`/api/forgot-password/`, data)
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
+ }
+
+ async magicSignIn(data: any) {
+ const response = await this.post("/api/magic-sign-in/", data, { headers: {} });
+ if (response?.status === 200) {
+ this.setAccessToken(response?.data?.access_token);
+ this.setRefreshToken(response?.data?.refresh_token);
+ return response?.data;
+ }
+ throw response.response.data;
+ }
+
+ async signOut() {
+ return this.post("/api/sign-out/", { refresh_token: this.getRefreshToken() })
+ .then((response) => {
+ this.purgeAccessToken();
+ this.purgeRefreshToken();
+ return response?.data;
+ })
+ .catch((error) => {
+ this.purgeAccessToken();
+ this.purgeRefreshToken();
+ throw error?.response?.data;
+ });
+ }
+}
+
+const authService = new AuthService();
+
+export default authService;
diff --git a/space/services/file.service.ts b/space/services/file.service.ts
new file mode 100644
index 000000000..5ef34fc76
--- /dev/null
+++ b/space/services/file.service.ts
@@ -0,0 +1,101 @@
+// services
+import APIService from "services/api.service";
+
+const { NEXT_PUBLIC_API_BASE_URL } = process.env;
+
+interface UnSplashImage {
+ id: string;
+ created_at: Date;
+ updated_at: Date;
+ promoted_at: Date;
+ width: number;
+ height: number;
+ color: string;
+ blur_hash: string;
+ description: null;
+ alt_description: string;
+ urls: UnSplashImageUrls;
+ [key: string]: any;
+}
+
+interface UnSplashImageUrls {
+ raw: string;
+ full: string;
+ regular: string;
+ small: string;
+ thumb: string;
+ small_s3: string;
+}
+
+class FileServices extends APIService {
+ constructor() {
+ super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
+ }
+
+ async uploadFile(workspaceSlug: string, file: FormData): Promise {
+ return this.mediaUpload(`/api/workspaces/${workspaceSlug}/file-assets/`, file)
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response?.data;
+ });
+ }
+
+ async deleteImage(assetUrlWithWorkspaceId: string): Promise {
+ return this.delete(`/api/workspaces/file-assets/${assetUrlWithWorkspaceId}/`)
+ .then((response) => response?.status)
+ .catch((error) => {
+ throw error?.response?.data;
+ });
+ }
+
+ async deleteFile(workspaceId: string, assetUrl: string): Promise {
+ const lastIndex = assetUrl.lastIndexOf("/");
+ const assetId = assetUrl.substring(lastIndex + 1);
+
+ return this.delete(`/api/workspaces/file-assets/${workspaceId}/${assetId}/`)
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response?.data;
+ });
+ }
+ async uploadUserFile(file: FormData): Promise {
+ return this.mediaUpload(`/api/users/file-assets/`, file)
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response?.data;
+ });
+ }
+
+ async deleteUserFile(assetUrl: string): Promise {
+ const lastIndex = assetUrl.lastIndexOf("/");
+ const assetId = assetUrl.substring(lastIndex + 1);
+
+ return this.delete(`/api/users/file-assets/${assetId}`)
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response?.data;
+ });
+ }
+
+ async getUnsplashImages(page: number = 1, query?: string): Promise {
+ const url = "/api/unsplash";
+
+ return this.request({
+ method: "get",
+ url,
+ params: {
+ page,
+ per_page: 20,
+ query,
+ },
+ })
+ .then((response) => response?.data?.results ?? response?.data)
+ .catch((error) => {
+ throw error?.response?.data;
+ });
+ }
+}
+
+const fileServices = new FileServices();
+
+export default fileServices;
diff --git a/space/services/issue.service.ts b/space/services/issue.service.ts
new file mode 100644
index 000000000..835778fb2
--- /dev/null
+++ b/space/services/issue.service.ts
@@ -0,0 +1,168 @@
+// services
+import APIService from "services/api.service";
+
+class IssueService extends APIService {
+ constructor() {
+ super(process.env.NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
+ }
+
+ async getPublicIssues(workspace_slug: string, project_slug: string, params: any): Promise {
+ return this.get(`/api/public/workspaces/${workspace_slug}/project-boards/${project_slug}/issues/`, {
+ params,
+ })
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
+ }
+
+ async getIssueById(workspaceSlug: string, projectId: string, issueId: string): Promise {
+ return this.get(`/api/public/workspaces/${workspaceSlug}/project-boards/${projectId}/issues/${issueId}/`)
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
+ }
+
+ async getIssueVotes(workspaceSlug: string, projectId: string, issueId: string): Promise {
+ return this.get(`/api/public/workspaces/${workspaceSlug}/project-boards/${projectId}/issues/${issueId}/votes/`)
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
+ }
+
+ async createIssueVote(workspaceSlug: string, projectId: string, issueId: string, data: any): Promise {
+ return this.post(
+ `/api/public/workspaces/${workspaceSlug}/project-boards/${projectId}/issues/${issueId}/votes/`,
+ data
+ )
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
+ }
+
+ async deleteIssueVote(workspaceSlug: string, projectId: string, issueId: string): Promise {
+ return this.delete(`/api/public/workspaces/${workspaceSlug}/project-boards/${projectId}/issues/${issueId}/votes/`)
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
+ }
+
+ async getIssueReactions(workspaceSlug: string, projectId: string, issueId: string): Promise {
+ return this.get(`/api/public/workspaces/${workspaceSlug}/project-boards/${projectId}/issues/${issueId}/reactions/`)
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
+ }
+
+ async createIssueReaction(workspaceSlug: string, projectId: string, issueId: string, data: any): Promise {
+ return this.post(
+ `/api/public/workspaces/${workspaceSlug}/project-boards/${projectId}/issues/${issueId}/reactions/`,
+ data
+ )
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
+ }
+
+ async deleteIssueReaction(
+ workspaceSlug: string,
+ projectId: string,
+ issueId: string,
+ reactionId: string
+ ): Promise {
+ return this.delete(
+ `/api/public/workspaces/${workspaceSlug}/project-boards/${projectId}/issues/${issueId}/reactions/${reactionId}/`
+ )
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
+ }
+
+ async getIssueComments(workspaceSlug: string, projectId: string, issueId: string): Promise {
+ return this.get(`/api/public/workspaces/${workspaceSlug}/project-boards/${projectId}/issues/${issueId}/comments/`)
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
+ }
+
+ async createIssueComment(workspaceSlug: string, projectId: string, issueId: string, data: any): Promise {
+ return this.post(
+ `/api/public/workspaces/${workspaceSlug}/project-boards/${projectId}/issues/${issueId}/comments/`,
+ data
+ )
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
+ }
+
+ async updateIssueComment(
+ workspaceSlug: string,
+ projectId: string,
+ issueId: string,
+ commentId: string,
+ data: any
+ ): Promise {
+ return this.patch(
+ `/api/public/workspaces/${workspaceSlug}/project-boards/${projectId}/issues/${issueId}/comments/${commentId}/`,
+ data
+ )
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
+ }
+
+ async deleteIssueComment(workspaceSlug: string, projectId: string, issueId: string, commentId: string): Promise {
+ return this.delete(
+ `/api/public/workspaces/${workspaceSlug}/project-boards/${projectId}/issues/${issueId}/comments/${commentId}/`
+ )
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
+ }
+
+ async createCommentReaction(
+ workspaceSlug: string,
+ projectId: string,
+ commentId: string,
+ data: {
+ reaction: string;
+ }
+ ): Promise {
+ return this.post(
+ `/api/public/workspaces/${workspaceSlug}/project-boards/${projectId}/comments/${commentId}/reactions/`,
+ data
+ )
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
+ }
+
+ async deleteCommentReaction(
+ workspaceSlug: string,
+ projectId: string,
+ commentId: string,
+ reactionHex: string
+ ): Promise {
+ return this.delete(
+ `/api/public/workspaces/${workspaceSlug}/project-boards/${projectId}/comments/${commentId}/reactions/${reactionHex}/`
+ )
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
+ }
+}
+
+export default IssueService;
diff --git a/apps/space/services/project.service.ts b/space/services/project.service.ts
similarity index 82%
rename from apps/space/services/project.service.ts
rename to space/services/project.service.ts
index 6f0275877..291a5f323 100644
--- a/apps/space/services/project.service.ts
+++ b/space/services/project.service.ts
@@ -6,7 +6,7 @@ class ProjectService extends APIService {
super(process.env.NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
}
- async getProjectSettingsAsync(workspace_slug: string, project_slug: string): Promise {
+ async getProjectSettings(workspace_slug: string, project_slug: string): Promise {
return this.get(`/api/public/workspaces/${workspace_slug}/project-boards/${project_slug}/settings/`)
.then((response) => response?.data)
.catch((error) => {
diff --git a/apps/space/services/user.service.ts b/space/services/user.service.ts
similarity index 66%
rename from apps/space/services/user.service.ts
rename to space/services/user.service.ts
index a84358a96..9a324bb95 100644
--- a/apps/space/services/user.service.ts
+++ b/space/services/user.service.ts
@@ -13,6 +13,14 @@ class UserService extends APIService {
throw error?.response;
});
}
+
+ async updateMe(data: any): Promise {
+ return this.patch("/api/users/me/", data)
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response?.data;
+ });
+ }
}
export default UserService;
diff --git a/space/store/issue.ts b/space/store/issue.ts
new file mode 100644
index 000000000..d47336984
--- /dev/null
+++ b/space/store/issue.ts
@@ -0,0 +1,103 @@
+import { observable, action, computed, makeObservable, runInAction, reaction } from "mobx";
+// services
+import IssueService from "services/issue.service";
+// store
+import { RootStore } from "./root";
+// types
+// import { IssueDetailType, TIssueBoardKeys } from "types/issue";
+import { IIssue, IIssueState, IIssueLabel } from "types/issue";
+
+export interface IIssueStore {
+ loader: boolean;
+ error: any;
+ // issue options
+ issues: IIssue[] | null;
+ states: IIssueState[] | null;
+ labels: IIssueLabel[] | null;
+ // filtering
+ filteredStates: string[];
+ filteredLabels: string[];
+ filteredPriorities: string[];
+ // service
+ issueService: any;
+ // actions
+ fetchPublicIssues: (workspace_slug: string, project_slug: string, params: any) => void;
+ getCountOfIssuesByState: (state: string) => number;
+ getFilteredIssuesByState: (state: string) => IIssue[];
+}
+
+class IssueStore implements IIssueStore {
+ loader: boolean = false;
+ error: any | null = null;
+
+ states: IIssueState[] | null = [];
+ labels: IIssueLabel[] | null = [];
+
+ filteredStates: string[] = [];
+ filteredLabels: string[] = [];
+ filteredPriorities: string[] = [];
+
+ issues: IIssue[] | null = [];
+ issue_detail: any = {};
+
+ rootStore: RootStore;
+ issueService: any;
+
+ constructor(_rootStore: any) {
+ makeObservable(this, {
+ // observable
+ loader: observable,
+ error: observable,
+ // issue options
+ states: observable.ref,
+ labels: observable.ref,
+ // filtering
+ filteredStates: observable.ref,
+ filteredLabels: observable.ref,
+ filteredPriorities: observable.ref,
+ // issues
+ issues: observable.ref,
+ issue_detail: observable.ref,
+ // actions
+ fetchPublicIssues: action,
+ getFilteredIssuesByState: action,
+ });
+
+ this.rootStore = _rootStore;
+ this.issueService = new IssueService();
+ }
+
+ fetchPublicIssues = async (workspaceSlug: string, projectId: string, params: any) => {
+ try {
+ this.loader = true;
+ this.error = null;
+
+ const response = await this.issueService.getPublicIssues(workspaceSlug, projectId, params);
+
+ if (response) {
+ const _states: IIssueState[] = [...response?.states];
+ const _labels: IIssueLabel[] = [...response?.labels];
+ const _issues: IIssue[] = [...response?.issues];
+ runInAction(() => {
+ this.states = _states;
+ this.labels = _labels;
+ this.issues = _issues;
+ this.loader = false;
+ });
+ }
+ } catch (error) {
+ this.loader = false;
+ this.error = error;
+ }
+ };
+
+ // computed
+ getCountOfIssuesByState(state_id: string): number {
+ return this.issues?.filter((issue) => issue.state == state_id).length || 0;
+ }
+
+ getFilteredIssuesByState = (state_id: string): IIssue[] | [] =>
+ this.issues?.filter((issue) => issue.state == state_id) || [];
+}
+
+export default IssueStore;
diff --git a/space/store/issue_details.ts b/space/store/issue_details.ts
new file mode 100644
index 000000000..346206e94
--- /dev/null
+++ b/space/store/issue_details.ts
@@ -0,0 +1,434 @@
+import { makeObservable, observable, action, runInAction } from "mobx";
+import { v4 as uuidv4 } from "uuid";
+// store
+import { RootStore } from "./root";
+// services
+import IssueService from "services/issue.service";
+import { IIssue, IVote } from "types/issue";
+
+export type IPeekMode = "side" | "modal" | "full";
+
+export interface IIssueDetailStore {
+ loader: boolean;
+ error: any;
+ // peek info
+ peekId: string | null;
+ peekMode: IPeekMode;
+ details: {
+ [key: string]: IIssue;
+ };
+ // peek actions
+ setPeekId: (issueId: string | null) => void;
+ setPeekMode: (mode: IPeekMode) => void;
+ // issue details
+ fetchIssueDetails: (workspaceId: string, projectId: string, issueId: string) => void;
+ // issue comments
+ addIssueComment: (workspaceId: string, projectId: string, issueId: string, data: any) => Promise;
+ updateIssueComment: (
+ workspaceId: string,
+ projectId: string,
+ issueId: string,
+ comment_id: string,
+ data: any
+ ) => Promise;
+ deleteIssueComment: (workspaceId: string, projectId: string, issueId: string, comment_id: string) => void;
+ addCommentReaction: (
+ workspaceId: string,
+ projectId: string,
+ issueId: string,
+ commentId: string,
+ reactionHex: string
+ ) => void;
+ removeCommentReaction: (
+ workspaceId: string,
+ projectId: string,
+ issueId: string,
+ commentId: string,
+ reactionHex: string
+ ) => void;
+ // issue reactions
+ addIssueReaction: (workspaceId: string, projectId: string, issueId: string, reactionHex: string) => void;
+ removeIssueReaction: (workspaceId: string, projectId: string, issueId: string, reactionHex: string) => void;
+ // issue votes
+ addIssueVote: (workspaceId: string, projectId: string, issueId: string, data: { vote: 1 | -1 }) => Promise;
+ removeIssueVote: (workspaceId: string, projectId: string, issueId: string) => Promise;
+}
+
+class IssueDetailStore implements IssueDetailStore {
+ loader: boolean = false;
+ error: any = null;
+ peekId: string | null = null;
+ peekMode: IPeekMode = "side";
+ details: {
+ [key: string]: IIssue;
+ } = {};
+ issueService;
+ rootStore: RootStore;
+
+ constructor(_rootStore: RootStore) {
+ makeObservable(this, {
+ loader: observable.ref,
+ error: observable.ref,
+ // peek
+ peekId: observable.ref,
+ peekMode: observable.ref,
+ details: observable.ref,
+ // actions
+ setPeekId: action,
+ setPeekMode: action,
+ fetchIssueDetails: action,
+ addIssueComment: action,
+ updateIssueComment: action,
+ deleteIssueComment: action,
+ addCommentReaction: action,
+ removeCommentReaction: action,
+ addIssueReaction: action,
+ removeIssueReaction: action,
+ addIssueVote: action,
+ removeIssueVote: action,
+ });
+ this.issueService = new IssueService();
+ this.rootStore = _rootStore;
+ }
+
+ setPeekId = (issueId: string | null) => {
+ this.peekId = issueId;
+ };
+
+ setPeekMode = (mode: IPeekMode) => {
+ this.peekMode = mode;
+ };
+
+ fetchIssueDetails = async (workspaceSlug: string, projectId: string, issueId: string) => {
+ try {
+ this.loader = true;
+ this.error = null;
+
+ const issueDetails = this.rootStore.issue.issues?.find((i) => i.id === issueId);
+ const commentsResponse = await this.issueService.getIssueComments(workspaceSlug, projectId, issueId);
+
+ if (issueDetails) {
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...(this.details[issueId] ?? issueDetails),
+ comments: commentsResponse,
+ },
+ };
+ });
+ }
+ } catch (error) {
+ this.loader = false;
+ this.error = error;
+ }
+ };
+
+ addIssueComment = async (workspaceSlug: string, projectId: string, issueId: string, data: any) => {
+ try {
+ const issueDetails = this.rootStore.issue.issues?.find((i) => i.id === issueId);
+ const issueCommentResponse = await this.issueService.createIssueComment(workspaceSlug, projectId, issueId, data);
+ if (issueDetails) {
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...issueDetails,
+ comments: [...this.details[issueId].comments, issueCommentResponse],
+ },
+ };
+ });
+ }
+ return issueCommentResponse;
+ } catch (error) {
+ console.log("Failed to add issue comment");
+ throw error;
+ }
+ };
+
+ updateIssueComment = async (
+ workspaceSlug: string,
+ projectId: string,
+ issueId: string,
+ commentId: string,
+ data: any
+ ) => {
+ try {
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...this.details[issueId],
+ comments: this.details[issueId].comments.map((c) => ({
+ ...c,
+ ...(c.id === commentId ? data : {}),
+ })),
+ },
+ };
+ });
+
+ await this.issueService.updateIssueComment(workspaceSlug, projectId, issueId, commentId, data);
+ } catch (error) {
+ const issueComments = await this.issueService.getIssueComments(workspaceSlug, projectId, issueId);
+
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...this.details[issueId],
+ comments: issueComments,
+ },
+ };
+ });
+ }
+ };
+
+ deleteIssueComment = async (workspaceSlug: string, projectId: string, issueId: string, comment_id: string) => {
+ try {
+ await this.issueService.deleteIssueComment(workspaceSlug, projectId, issueId, comment_id);
+ const remainingComments = this.details[issueId].comments.filter((c) => c.id != comment_id);
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...this.details[issueId],
+ comments: remainingComments,
+ },
+ };
+ });
+ } catch (error) {
+ console.log("Failed to add issue vote");
+ }
+ };
+
+ addCommentReaction = async (
+ workspaceSlug: string,
+ projectId: string,
+ issueId: string,
+ commentId: string,
+ reactionHex: string
+ ) => {
+ const newReaction = {
+ id: uuidv4(),
+ comment: commentId,
+ reaction: reactionHex,
+ actor_detail: this.rootStore.user.currentActor,
+ };
+ const newComments = this.details[issueId].comments.map((comment) => ({
+ ...comment,
+ comment_reactions:
+ comment.id === commentId ? [...comment.comment_reactions, newReaction] : comment.comment_reactions,
+ }));
+
+ try {
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...this.details[issueId],
+ comments: [...newComments],
+ },
+ };
+ });
+
+ await this.issueService.createCommentReaction(workspaceSlug, projectId, commentId, {
+ reaction: reactionHex,
+ });
+ } catch (error) {
+ const issueComments = await this.issueService.getIssueComments(workspaceSlug, projectId, issueId);
+
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...this.details[issueId],
+ comments: issueComments,
+ },
+ };
+ });
+ }
+ };
+
+ removeCommentReaction = async (
+ workspaceSlug: string,
+ projectId: string,
+ issueId: string,
+ commentId: string,
+ reactionHex: string
+ ) => {
+ try {
+ const comment = this.details[issueId].comments.find((c) => c.id === commentId);
+ const newCommentReactions = comment?.comment_reactions.filter((r) => r.reaction !== reactionHex) ?? [];
+
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...this.details[issueId],
+ comments: this.details[issueId].comments.map((c) => ({
+ ...c,
+ comment_reactions: c.id === commentId ? newCommentReactions : c.comment_reactions,
+ })),
+ },
+ };
+ });
+
+ await this.issueService.deleteCommentReaction(workspaceSlug, projectId, commentId, reactionHex);
+ } catch (error) {
+ const issueComments = await this.issueService.getIssueComments(workspaceSlug, projectId, issueId);
+
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...this.details[issueId],
+ comments: issueComments,
+ },
+ };
+ });
+ }
+ };
+
+ addIssueReaction = async (workspaceSlug: string, projectId: string, issueId: string, reactionHex: string) => {
+ try {
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...this.details[issueId],
+ reactions: [
+ ...this.details[issueId].reactions,
+ {
+ id: uuidv4(),
+ issue: issueId,
+ reaction: reactionHex,
+ actor_detail: this.rootStore.user.currentActor,
+ },
+ ],
+ },
+ };
+ });
+
+ await this.issueService.createIssueReaction(workspaceSlug, projectId, issueId, {
+ reaction: reactionHex,
+ });
+ } catch (error) {
+ console.log("Failed to add issue vote");
+ const issueReactions = await this.issueService.getIssueReactions(workspaceSlug, projectId, issueId);
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...this.details[issueId],
+ reactions: issueReactions,
+ },
+ };
+ });
+ }
+ };
+
+ removeIssueReaction = async (workspaceSlug: string, projectId: string, issueId: string, reactionHex: string) => {
+ try {
+ const newReactions = this.details[issueId].reactions.filter(
+ (_r) => !(_r.reaction === reactionHex && _r.actor_detail.id === this.rootStore.user.currentUser?.id)
+ );
+
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...this.details[issueId],
+ reactions: newReactions,
+ },
+ };
+ });
+
+ await this.issueService.deleteIssueReaction(workspaceSlug, projectId, issueId, reactionHex);
+ } catch (error) {
+ console.log("Failed to remove issue reaction");
+ const reactions = await this.issueService.getIssueReactions(workspaceSlug, projectId, issueId);
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...this.details[issueId],
+ reactions: reactions,
+ },
+ };
+ });
+ }
+ };
+
+ addIssueVote = async (workspaceSlug: string, projectId: string, issueId: string, data: { vote: 1 | -1 }) => {
+ const newVote: IVote = {
+ actor: this.rootStore.user.currentUser?.id ?? "",
+ actor_detail: this.rootStore.user.currentActor,
+ issue: issueId,
+ project: projectId,
+ workspace: workspaceSlug,
+ vote: data.vote,
+ };
+
+ const filteredVotes = this.details[issueId].votes.filter((v) => v.actor !== this.rootStore.user.currentUser?.id);
+
+ try {
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...this.details[issueId],
+ votes: [...filteredVotes, newVote],
+ },
+ };
+ });
+
+ await this.issueService.createIssueVote(workspaceSlug, projectId, issueId, data);
+ } catch (error) {
+ console.log("Failed to add issue vote");
+ const issueVotes = await this.issueService.getIssueVotes(workspaceSlug, projectId, issueId);
+
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...this.details[issueId],
+ votes: issueVotes,
+ },
+ };
+ });
+ }
+ };
+
+ removeIssueVote = async (workspaceSlug: string, projectId: string, issueId: string) => {
+ const newVotes = this.details[issueId].votes.filter((v) => v.actor !== this.rootStore.user.currentUser?.id);
+
+ try {
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...this.details[issueId],
+ votes: newVotes,
+ },
+ };
+ });
+
+ await this.issueService.deleteIssueVote(workspaceSlug, projectId, issueId);
+ } catch (error) {
+ console.log("Failed to remove issue vote");
+ const issueVotes = await this.issueService.getIssueVotes(workspaceSlug, projectId, issueId);
+
+ runInAction(() => {
+ this.details = {
+ ...this.details,
+ [issueId]: {
+ ...this.details[issueId],
+ votes: issueVotes,
+ },
+ };
+ });
+ }
+ };
+}
+
+export default IssueDetailStore;
diff --git a/apps/space/store/project.ts b/space/store/project.ts
similarity index 52%
rename from apps/space/store/project.ts
rename to space/store/project.ts
index e5ac58261..ddd589f9a 100644
--- a/apps/space/store/project.ts
+++ b/space/store/project.ts
@@ -3,15 +3,29 @@ import { observable, action, makeObservable, runInAction } from "mobx";
// service
import ProjectService from "services/project.service";
// types
-import { IProjectStore, IWorkspace, IProject, IProjectSettings } from "./types";
+import { IWorkspace, IProject, IProjectSettings } from "types/project";
+
+export interface IProjectStore {
+ loader: boolean;
+ error: any | null;
+ workspace: IWorkspace | null;
+ project: IProject | null;
+ deploySettings: IProjectSettings | null;
+ viewOptions: any;
+ activeBoard: string | null;
+ fetchProjectSettings: (workspace_slug: string, project_slug: string) => Promise;
+ setActiveBoard: (value: string) => void;
+}
class ProjectStore implements IProjectStore {
loader: boolean = false;
error: any | null = null;
-
+ // data
workspace: IWorkspace | null = null;
project: IProject | null = null;
- workspaceProjectSettings: IProjectSettings | null = null;
+ deploySettings: IProjectSettings | null = null;
+ viewOptions: any = null;
+ activeBoard: string | null = null;
// root store
rootStore;
// service
@@ -19,14 +33,18 @@ class ProjectStore implements IProjectStore {
constructor(_rootStore: any | null = null) {
makeObservable(this, {
+ // loaders and error observables
+ loader: observable,
+ error: observable.ref,
// observable
workspace: observable.ref,
project: observable.ref,
- workspaceProjectSettings: observable.ref,
- loader: observable,
- error: observable.ref,
- // action
- getProjectSettingsAsync: action,
+ deploySettings: observable.ref,
+ viewOptions: observable.ref,
+ activeBoard: observable.ref,
+ // actions
+ fetchProjectSettings: action,
+ setActiveBoard: action,
// computed
});
@@ -34,26 +52,23 @@ class ProjectStore implements IProjectStore {
this.projectService = new ProjectService();
}
- getProjectSettingsAsync = async (workspace_slug: string, project_slug: string) => {
+ fetchProjectSettings = async (workspace_slug: string, project_slug: string) => {
try {
this.loader = true;
this.error = null;
- const response = await this.projectService.getProjectSettingsAsync(workspace_slug, project_slug);
+ const response = await this.projectService.getProjectSettings(workspace_slug, project_slug);
if (response) {
const _project: IProject = { ...response?.project_details };
const _workspace: IWorkspace = { ...response?.workspace_detail };
- const _workspaceProjectSettings: IProjectSettings = {
- comments: response?.comments,
- reactions: response?.reactions,
- votes: response?.votes,
- views: { ...response?.views },
- };
+ const _viewOptions = { ...response?.views };
+ const _deploySettings = { ...response };
runInAction(() => {
this.project = _project;
this.workspace = _workspace;
- this.workspaceProjectSettings = _workspaceProjectSettings;
+ this.viewOptions = _viewOptions;
+ this.deploySettings = _deploySettings;
this.loader = false;
});
}
@@ -64,6 +79,10 @@ class ProjectStore implements IProjectStore {
return error;
}
};
+
+ setActiveBoard = (boardValue: string) => {
+ this.activeBoard = boardValue;
+ };
}
export default ProjectStore;
diff --git a/apps/space/store/root.ts b/space/store/root.ts
similarity index 57%
rename from apps/space/store/root.ts
rename to space/store/root.ts
index dd6d620c0..6b87020ef 100644
--- a/apps/space/store/root.ts
+++ b/space/store/root.ts
@@ -2,24 +2,22 @@
import { enableStaticRendering } from "mobx-react-lite";
// store imports
import UserStore from "./user";
-import ThemeStore from "./theme";
-import IssueStore from "./issue";
-import ProjectStore from "./project";
-// types
-import { IIssueStore, IProjectStore, IThemeStore, IUserStore } from "./types";
+import IssueStore, { IIssueStore } from "./issue";
+import ProjectStore, { IProjectStore } from "./project";
+import IssueDetailStore, { IIssueDetailStore } from "./issue_details";
enableStaticRendering(typeof window === "undefined");
export class RootStore {
- user: IUserStore;
- theme: IThemeStore;
+ user: UserStore;
issue: IIssueStore;
+ issueDetails: IIssueDetailStore;
project: IProjectStore;
constructor() {
this.user = new UserStore(this);
- this.theme = new ThemeStore(this);
this.issue = new IssueStore(this);
this.project = new ProjectStore(this);
+ this.issueDetails = new IssueDetailStore(this);
}
}
diff --git a/space/store/user.ts b/space/store/user.ts
new file mode 100644
index 000000000..3a76c2111
--- /dev/null
+++ b/space/store/user.ts
@@ -0,0 +1,88 @@
+// mobx
+import { observable, action, computed, makeObservable, runInAction } from "mobx";
+// service
+import UserService from "services/user.service";
+import { ActorDetail } from "types/issue";
+// types
+import { IUser } from "types/user";
+
+export interface IUserStore {
+ currentUser: any | null;
+ fetchCurrentUser: () => void;
+ currentActor: () => any;
+}
+
+class UserStore implements IUserStore {
+ currentUser: IUser | null = null;
+ // root store
+ rootStore;
+ // service
+ userService;
+
+ constructor(_rootStore: any) {
+ makeObservable(this, {
+ // observable
+ currentUser: observable.ref,
+ // actions
+ setCurrentUser: action,
+ // computed
+ currentActor: computed,
+ });
+ this.rootStore = _rootStore;
+ this.userService = new UserService();
+ }
+
+ setCurrentUser = (user: any) => {
+ runInAction(() => {
+ this.currentUser = { ...user };
+ });
+ };
+
+ get currentActor(): any {
+ return {
+ avatar: this.currentUser?.avatar,
+ display_name: this.currentUser?.display_name,
+ first_name: this.currentUser?.first_name,
+ id: this.currentUser?.id,
+ is_bot: false,
+ last_name: this.currentUser?.last_name,
+ };
+ }
+
+ /**
+ *
+ * @param callback
+ * @description A wrapper function to check user authentication; it redirects to the login page if not authenticated, otherwise, it executes a callback.
+ * @example this.requiredLogin(() => { // do something });
+ */
+
+ requiredLogin = (callback: () => void) => {
+ if (this.currentUser) {
+ callback();
+ return;
+ }
+
+ const currentPath = window.location.pathname + window.location.search;
+ this.fetchCurrentUser()
+ .then(() => {
+ if (!this.currentUser) window.location.href = `/?next_path=${currentPath}`;
+ else callback();
+ })
+ .catch(() => (window.location.href = `/?next_path=${currentPath}`));
+ };
+
+ fetchCurrentUser = async () => {
+ try {
+ const response = await this.userService.currentUser();
+ if (response) {
+ runInAction(() => {
+ this.currentUser = response;
+ });
+ }
+ } catch (error) {
+ console.error("Failed to fetch current user", error);
+ }
+ };
+}
+
+export default UserStore;
diff --git a/apps/app/styles/editor.css b/space/styles/editor.css
similarity index 100%
rename from apps/app/styles/editor.css
rename to space/styles/editor.css
diff --git a/space/styles/globals.css b/space/styles/globals.css
new file mode 100644
index 000000000..1782b9b81
--- /dev/null
+++ b/space/styles/globals.css
@@ -0,0 +1,234 @@
+@import url("https://fonts.googleapis.com/css2?family=Inter:wght@200;300;400;500;600;700;800&display=swap");
+@import url("https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@48,400,0,0&display=swap");
+
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+ html {
+ font-family: "Inter", sans-serif;
+ }
+
+ :root {
+ color-scheme: light !important;
+
+ --color-primary-10: 236, 241, 255;
+ --color-primary-20: 217, 228, 255;
+ --color-primary-30: 197, 214, 255;
+ --color-primary-40: 178, 200, 255;
+ --color-primary-50: 159, 187, 255;
+ --color-primary-60: 140, 173, 255;
+ --color-primary-70: 121, 159, 255;
+ --color-primary-80: 101, 145, 255;
+ --color-primary-90: 82, 132, 255;
+ --color-primary-100: 63, 118, 255;
+ --color-primary-200: 57, 106, 230;
+ --color-primary-300: 50, 94, 204;
+ --color-primary-400: 44, 83, 179;
+ --color-primary-500: 38, 71, 153;
+ --color-primary-600: 32, 59, 128;
+ --color-primary-700: 25, 47, 102;
+ --color-primary-800: 19, 35, 76;
+ --color-primary-900: 13, 24, 51;
+
+ --color-background-100: 255, 255, 255; /* primary bg */
+ --color-background-90: 250, 250, 250; /* secondary bg */
+ --color-background-80: 245, 245, 245; /* tertiary bg */
+
+ --color-text-100: 23, 23, 23; /* primary text */
+ --color-text-200: 58, 58, 58; /* secondary text */
+ --color-text-300: 82, 82, 82; /* tertiary text */
+ --color-text-400: 163, 163, 163; /* placeholder text */
+
+ --color-border-100: 245, 245, 245; /* subtle border= 1 */
+ --color-border-200: 229, 229, 229; /* subtle border- 2 */
+ --color-border-300: 212, 212, 212; /* strong border- 1 */
+ --color-border-400: 185, 185, 185; /* strong border- 2 */
+
+ --color-shadow-2xs: 0px 0px 1px 0px rgba(23, 23, 23, 0.06), 0px 1px 2px 0px rgba(23, 23, 23, 0.06),
+ 0px 1px 2px 0px rgba(23, 23, 23, 0.14);
+ --color-shadow-xs: 0px 1px 2px 0px rgba(0, 0, 0, 0.16), 0px 2px 4px 0px rgba(16, 24, 40, 0.12),
+ 0px 1px 8px -1px rgba(16, 24, 40, 0.1);
+ --color-shadow-sm: 0px 1px 4px 0px rgba(0, 0, 0, 0.01), 0px 4px 8px 0px rgba(0, 0, 0, 0.02),
+ 0px 1px 12px 0px rgba(0, 0, 0, 0.12);
+ --color-shadow-rg: 0px 3px 6px 0px rgba(0, 0, 0, 0.1), 0px 4px 4px 0px rgba(16, 24, 40, 0.08),
+ 0px 1px 12px 0px rgba(16, 24, 40, 0.04);
+ --color-shadow-md: 0px 4px 8px 0px rgba(0, 0, 0, 0.12), 0px 6px 12px 0px rgba(16, 24, 40, 0.12),
+ 0px 1px 16px 0px rgba(16, 24, 40, 0.12);
+ --color-shadow-lg: 0px 6px 12px 0px rgba(0, 0, 0, 0.12), 0px 8px 16px 0px rgba(0, 0, 0, 0.12),
+ 0px 1px 24px 0px rgba(16, 24, 40, 0.12);
+ --color-shadow-xl: 0px 0px 18px 0px rgba(0, 0, 0, 0.16), 0px 0px 24px 0px rgba(16, 24, 40, 0.16),
+ 0px 0px 52px 0px rgba(16, 24, 40, 0.16);
+ --color-shadow-2xl: 0px 8px 16px 0px rgba(0, 0, 0, 0.12), 0px 12px 24px 0px rgba(16, 24, 40, 0.12),
+ 0px 1px 32px 0px rgba(16, 24, 40, 0.12);
+ --color-shadow-3xl: 0px 12px 24px 0px rgba(0, 0, 0, 0.12), 0px 16px 32px 0px rgba(0, 0, 0, 0.12),
+ 0px 1px 48px 0px rgba(16, 24, 40, 0.12);
+
+ --color-sidebar-background-100: var(--color-background-100); /* primary sidebar bg */
+ --color-sidebar-background-90: var(--color-background-90); /* secondary sidebar bg */
+ --color-sidebar-background-80: var(--color-background-80); /* tertiary sidebar bg */
+
+ --color-sidebar-text-100: var(--color-text-100); /* primary sidebar text */
+ --color-sidebar-text-200: var(--color-text-200); /* secondary sidebar text */
+ --color-sidebar-text-300: var(--color-text-300); /* tertiary sidebar text */
+ --color-sidebar-text-400: var(--color-text-400); /* sidebar placeholder text */
+
+ --color-sidebar-border-100: var(--color-border-100); /* subtle sidebar border= 1 */
+ --color-sidebar-border-200: var(--color-border-100); /* subtle sidebar border- 2 */
+ --color-sidebar-border-300: var(--color-border-100); /* strong sidebar border- 1 */
+ --color-sidebar-border-400: var(--color-border-100); /* strong sidebar border- 2 */
+
+ --color-sidebar-shadow-2xs: var(--color-shadow-2xs);
+ --color-sidebar-shadow-xs: var(--color-shadow-xs);
+ --color-sidebar-shadow-sm: var(--color-shadow-sm);
+ --color-sidebar-shadow-rg: var(--color-shadow-rg);
+ --color-sidebar-shadow-md: var(--color-shadow-md);
+ --color-sidebar-shadow-lg: var(--color-shadow-lg);
+ --color-sidebar-shadow-xl: var(--color-shadow-xl);
+ --color-sidebar-shadow-2xl: var(--color-shadow-2xl);
+ --color-sidebar-shadow-3xl: var(--color-shadow-3xl);
+ }
+
+ [data-theme="light"],
+ [data-theme="light-contrast"] {
+ color-scheme: light !important;
+
+ --color-background-100: 255, 255, 255; /* primary bg */
+ --color-background-90: 250, 250, 250; /* secondary bg */
+ --color-background-80: 245, 245, 245; /* tertiary bg */
+ }
+
+ [data-theme="light"] {
+ --color-text-100: 23, 23, 23; /* primary text */
+ --color-text-200: 58, 58, 58; /* secondary text */
+ --color-text-300: 82, 82, 82; /* tertiary text */
+ --color-text-400: 163, 163, 163; /* placeholder text */
+
+ --color-border-100: 245, 245, 245; /* subtle border= 1 */
+ --color-border-200: 229, 229, 229; /* subtle border- 2 */
+ --color-border-300: 212, 212, 212; /* strong border- 1 */
+ --color-border-400: 185, 185, 185; /* strong border- 2 */
+ }
+
+ [data-theme="light-contrast"] {
+ --color-text-100: 11, 11, 11; /* primary text */
+ --color-text-200: 38, 38, 38; /* secondary text */
+ --color-text-300: 58, 58, 58; /* tertiary text */
+ --color-text-400: 115, 115, 115; /* placeholder text */
+
+ --color-border-100: 34, 34, 34; /* subtle border= 1 */
+ --color-border-200: 38, 38, 38; /* subtle border- 2 */
+ --color-border-300: 46, 46, 46; /* strong border- 1 */
+ --color-border-400: 58, 58, 58; /* strong border- 2 */
+ }
+
+ [data-theme="dark"],
+ [data-theme="dark-contrast"] {
+ color-scheme: dark !important;
+
+ --color-background-100: 7, 7, 7; /* primary bg */
+ --color-background-90: 11, 11, 11; /* secondary bg */
+ --color-background-80: 23, 23, 23; /* tertiary bg */
+
+ --color-shadow-2xs: 0px 0px 1px 0px rgba(0, 0, 0, 0.15), 0px 1px 3px 0px rgba(0, 0, 0, 0.5);
+ --color-shadow-xs: 0px 0px 2px 0px rgba(0, 0, 0, 0.2), 0px 2px 4px 0px rgba(0, 0, 0, 0.5);
+ --color-shadow-sm: 0px 0px 4px 0px rgba(0, 0, 0, 0.2), 0px 2px 6px 0px rgba(0, 0, 0, 0.5);
+ --color-shadow-rg: 0px 0px 6px 0px rgba(0, 0, 0, 0.2), 0px 4px 6px 0px rgba(0, 0, 0, 0.5);
+ --color-shadow-md: 0px 2px 8px 0px rgba(0, 0, 0, 0.2), 0px 4px 8px 0px rgba(0, 0, 0, 0.5);
+ --color-shadow-lg: 0px 4px 12px 0px rgba(0, 0, 0, 0.25), 0px 4px 10px 0px rgba(0, 0, 0, 0.55);
+ --color-shadow-xl: 0px 0px 14px 0px rgba(0, 0, 0, 0.25), 0px 6px 10px 0px rgba(0, 0, 0, 0.55);
+ --color-shadow-2xl: 0px 0px 18px 0px rgba(0, 0, 0, 0.25), 0px 8px 12px 0px rgba(0, 0, 0, 0.6);
+ --color-shadow-3xl: 0px 4px 24px 0px rgba(0, 0, 0, 0.3), 0px 12px 40px 0px rgba(0, 0, 0, 0.65);
+ }
+
+ [data-theme="dark"] {
+ --color-text-100: 229, 229, 229; /* primary text */
+ --color-text-200: 163, 163, 163; /* secondary text */
+ --color-text-300: 115, 115, 115; /* tertiary text */
+ --color-text-400: 82, 82, 82; /* placeholder text */
+
+ --color-border-100: 34, 34, 34; /* subtle border= 1 */
+ --color-border-200: 38, 38, 38; /* subtle border- 2 */
+ --color-border-300: 46, 46, 46; /* strong border- 1 */
+ --color-border-400: 58, 58, 58; /* strong border- 2 */
+ }
+
+ [data-theme="dark-contrast"] {
+ --color-text-100: 250, 250, 250; /* primary text */
+ --color-text-200: 241, 241, 241; /* secondary text */
+ --color-text-300: 212, 212, 212; /* tertiary text */
+ --color-text-400: 115, 115, 115; /* placeholder text */
+
+ --color-border-100: 245, 245, 245; /* subtle border= 1 */
+ --color-border-200: 229, 229, 229; /* subtle border- 2 */
+ --color-border-300: 212, 212, 212; /* strong border- 1 */
+ --color-border-400: 185, 185, 185; /* strong border- 2 */
+ }
+
+ [data-theme="light"],
+ [data-theme="dark"],
+ [data-theme="light-contrast"],
+ [data-theme="dark-contrast"] {
+ --color-primary-10: 236, 241, 255;
+ --color-primary-20: 217, 228, 255;
+ --color-primary-30: 197, 214, 255;
+ --color-primary-40: 178, 200, 255;
+ --color-primary-50: 159, 187, 255;
+ --color-primary-60: 140, 173, 255;
+ --color-primary-70: 121, 159, 255;
+ --color-primary-80: 101, 145, 255;
+ --color-primary-90: 82, 132, 255;
+ --color-primary-100: 63, 118, 255;
+ --color-primary-200: 57, 106, 230;
+ --color-primary-300: 50, 94, 204;
+ --color-primary-400: 44, 83, 179;
+ --color-primary-500: 38, 71, 153;
+ --color-primary-600: 32, 59, 128;
+ --color-primary-700: 25, 47, 102;
+ --color-primary-800: 19, 35, 76;
+ --color-primary-900: 13, 24, 51;
+
+ --color-sidebar-background-100: var(--color-background-100); /* primary sidebar bg */
+ --color-sidebar-background-90: var(--color-background-90); /* secondary sidebar bg */
+ --color-sidebar-background-80: var(--color-background-80); /* tertiary sidebar bg */
+
+ --color-sidebar-text-100: var(--color-text-100); /* primary sidebar text */
+ --color-sidebar-text-200: var(--color-text-200); /* secondary sidebar text */
+ --color-sidebar-text-300: var(--color-text-300); /* tertiary sidebar text */
+ --color-sidebar-text-400: var(--color-text-400); /* sidebar placeholder text */
+
+ --color-sidebar-border-100: var(--color-border-100); /* subtle sidebar border= 1 */
+ --color-sidebar-border-200: var(--color-border-100); /* subtle sidebar border- 2 */
+ --color-sidebar-border-300: var(--color-border-100); /* strong sidebar border- 1 */
+ --color-sidebar-border-400: var(--color-border-100); /* strong sidebar border- 2 */
+ }
+}
+
+::-webkit-scrollbar {
+ width: 5px;
+ height: 5px;
+ border-radius: 5px;
+}
+
+::-webkit-scrollbar-track {
+ background-color: rgba(var(--color-background-100));
+}
+
+::-webkit-scrollbar-thumb {
+ border-radius: 5px;
+ background-color: rgba(var(--color-background-80));
+}
+
+.hide-vertical-scrollbar::-webkit-scrollbar {
+ width: 0 !important;
+}
+
+.hide-horizontal-scrollbar::-webkit-scrollbar {
+ height: 0 !important;
+}
+
+.hide-both-scrollbars::-webkit-scrollbar {
+ height: 0 !important;
+ width: 0 !important;
+}
diff --git a/space/tailwind.config.js b/space/tailwind.config.js
new file mode 100644
index 000000000..0347ad9f9
--- /dev/null
+++ b/space/tailwind.config.js
@@ -0,0 +1,203 @@
+/** @type {import('tailwindcss').Config} */
+
+const convertToRGB = (variableName) => `rgba(var(${variableName}))`;
+
+module.exports = {
+ content: [
+ "./app/**/*.{js,ts,jsx,tsx}",
+ "./pages/**/*.{js,ts,jsx,tsx}",
+ "./layouts/**/*.tsx",
+ "./components/**/*.{js,ts,jsx,tsx}",
+ "./constants/**/*.{js,ts,jsx,tsx}",
+ ],
+ theme: {
+ extend: {
+ boxShadow: {
+ "custom-shadow-2xs": "var(--color-shadow-2xs)",
+ "custom-shadow-xs": "var(--color-shadow-xs)",
+ "custom-shadow-sm": "var(--color-shadow-sm)",
+ "custom-shadow-rg": "var(--color-shadow-rg)",
+ "custom-shadow-md": "var(--color-shadow-md)",
+ "custom-shadow-lg": "var(--color-shadow-lg)",
+ "custom-shadow-xl": "var(--color-shadow-xl)",
+ "custom-shadow-2xl": "var(--color-shadow-2xl)",
+ "custom-shadow-3xl": "var(--color-shadow-3xl)",
+ "custom-sidebar-shadow-2xs": "var(--color-sidebar-shadow-2xs)",
+ "custom-sidebar-shadow-xs": "var(--color-sidebar-shadow-xs)",
+ "custom-sidebar-shadow-sm": "var(--color-sidebar-shadow-sm)",
+ "custom-sidebar-shadow-rg": "var(--color-sidebar-shadow-rg)",
+ "custom-sidebar-shadow-md": "var(--color-sidebar-shadow-md)",
+ "custom-sidebar-shadow-lg": "var(--color-sidebar-shadow-lg)",
+ "custom-sidebar-shadow-xl": "var(--color-sidebar-shadow-xl)",
+ "custom-sidebar-shadow-2xl": "var(--color-sidebar-shadow-2xl)",
+ "custom-sidebar-shadow-3xl": "var(--color-sidebar-shadow-3xl)",
+ },
+ colors: {
+ custom: {
+ primary: {
+ 0: "rgb(255, 255, 255)",
+ 10: convertToRGB("--color-primary-10"),
+ 20: convertToRGB("--color-primary-20"),
+ 30: convertToRGB("--color-primary-30"),
+ 40: convertToRGB("--color-primary-40"),
+ 50: convertToRGB("--color-primary-50"),
+ 60: convertToRGB("--color-primary-60"),
+ 70: convertToRGB("--color-primary-70"),
+ 80: convertToRGB("--color-primary-80"),
+ 90: convertToRGB("--color-primary-90"),
+ 100: convertToRGB("--color-primary-100"),
+ 200: convertToRGB("--color-primary-200"),
+ 300: convertToRGB("--color-primary-300"),
+ 400: convertToRGB("--color-primary-400"),
+ 500: convertToRGB("--color-primary-500"),
+ 600: convertToRGB("--color-primary-600"),
+ 700: convertToRGB("--color-primary-700"),
+ 800: convertToRGB("--color-primary-800"),
+ 900: convertToRGB("--color-primary-900"),
+ 1000: "rgb(0, 0, 0)",
+ DEFAULT: convertToRGB("--color-primary-100"),
+ },
+ background: {
+ 0: "rgb(255, 255, 255)",
+ 10: convertToRGB("--color-background-10"),
+ 20: convertToRGB("--color-background-20"),
+ 30: convertToRGB("--color-background-30"),
+ 40: convertToRGB("--color-background-40"),
+ 50: convertToRGB("--color-background-50"),
+ 60: convertToRGB("--color-background-60"),
+ 70: convertToRGB("--color-background-70"),
+ 80: convertToRGB("--color-background-80"),
+ 90: convertToRGB("--color-background-90"),
+ 100: convertToRGB("--color-background-100"),
+ 200: convertToRGB("--color-background-200"),
+ 300: convertToRGB("--color-background-300"),
+ 400: convertToRGB("--color-background-400"),
+ 500: convertToRGB("--color-background-500"),
+ 600: convertToRGB("--color-background-600"),
+ 700: convertToRGB("--color-background-700"),
+ 800: convertToRGB("--color-background-800"),
+ 900: convertToRGB("--color-background-900"),
+ 1000: "rgb(0, 0, 0)",
+ DEFAULT: convertToRGB("--color-background-100"),
+ },
+ text: {
+ 0: "rgb(255, 255, 255)",
+ 10: convertToRGB("--color-text-10"),
+ 20: convertToRGB("--color-text-20"),
+ 30: convertToRGB("--color-text-30"),
+ 40: convertToRGB("--color-text-40"),
+ 50: convertToRGB("--color-text-50"),
+ 60: convertToRGB("--color-text-60"),
+ 70: convertToRGB("--color-text-70"),
+ 80: convertToRGB("--color-text-80"),
+ 90: convertToRGB("--color-text-90"),
+ 100: convertToRGB("--color-text-100"),
+ 200: convertToRGB("--color-text-200"),
+ 300: convertToRGB("--color-text-300"),
+ 400: convertToRGB("--color-text-400"),
+ 500: convertToRGB("--color-text-500"),
+ 600: convertToRGB("--color-text-600"),
+ 700: convertToRGB("--color-text-700"),
+ 800: convertToRGB("--color-text-800"),
+ 900: convertToRGB("--color-text-900"),
+ 1000: "rgb(0, 0, 0)",
+ DEFAULT: convertToRGB("--color-text-100"),
+ },
+ border: {
+ 0: "rgb(255, 255, 255)",
+ 100: convertToRGB("--color-border-100"),
+ 200: convertToRGB("--color-border-200"),
+ 300: convertToRGB("--color-border-300"),
+ 400: convertToRGB("--color-border-400"),
+ 1000: "rgb(0, 0, 0)",
+ DEFAULT: convertToRGB("--color-border-200"),
+ },
+ sidebar: {
+ background: {
+ 0: "rgb(255, 255, 255)",
+ 10: convertToRGB("--color-sidebar-background-10"),
+ 20: convertToRGB("--color-sidebar-background-20"),
+ 30: convertToRGB("--color-sidebar-background-30"),
+ 40: convertToRGB("--color-sidebar-background-40"),
+ 50: convertToRGB("--color-sidebar-background-50"),
+ 60: convertToRGB("--color-sidebar-background-60"),
+ 70: convertToRGB("--color-sidebar-background-70"),
+ 80: convertToRGB("--color-sidebar-background-80"),
+ 90: convertToRGB("--color-sidebar-background-90"),
+ 100: convertToRGB("--color-sidebar-background-100"),
+ 200: convertToRGB("--color-sidebar-background-200"),
+ 300: convertToRGB("--color-sidebar-background-300"),
+ 400: convertToRGB("--color-sidebar-background-400"),
+ 500: convertToRGB("--color-sidebar-background-500"),
+ 600: convertToRGB("--color-sidebar-background-600"),
+ 700: convertToRGB("--color-sidebar-background-700"),
+ 800: convertToRGB("--color-sidebar-background-800"),
+ 900: convertToRGB("--color-sidebar-background-900"),
+ 1000: "rgb(0, 0, 0)",
+ DEFAULT: convertToRGB("--color-sidebar-background-100"),
+ },
+ text: {
+ 0: "rgb(255, 255, 255)",
+ 10: convertToRGB("--color-sidebar-text-10"),
+ 20: convertToRGB("--color-sidebar-text-20"),
+ 30: convertToRGB("--color-sidebar-text-30"),
+ 40: convertToRGB("--color-sidebar-text-40"),
+ 50: convertToRGB("--color-sidebar-text-50"),
+ 60: convertToRGB("--color-sidebar-text-60"),
+ 70: convertToRGB("--color-sidebar-text-70"),
+ 80: convertToRGB("--color-sidebar-text-80"),
+ 90: convertToRGB("--color-sidebar-text-90"),
+ 100: convertToRGB("--color-sidebar-text-100"),
+ 200: convertToRGB("--color-sidebar-text-200"),
+ 300: convertToRGB("--color-sidebar-text-300"),
+ 400: convertToRGB("--color-sidebar-text-400"),
+ 500: convertToRGB("--color-sidebar-text-500"),
+ 600: convertToRGB("--color-sidebar-text-600"),
+ 700: convertToRGB("--color-sidebar-text-700"),
+ 800: convertToRGB("--color-sidebar-text-800"),
+ 900: convertToRGB("--color-sidebar-text-900"),
+ 1000: "rgb(0, 0, 0)",
+ DEFAULT: convertToRGB("--color-sidebar-text-100"),
+ },
+ border: {
+ 0: "rgb(255, 255, 255)",
+ 100: convertToRGB("--color-sidebar-border-100"),
+ 200: convertToRGB("--color-sidebar-border-200"),
+ 300: convertToRGB("--color-sidebar-border-300"),
+ 400: convertToRGB("--color-sidebar-border-400"),
+ 1000: "rgb(0, 0, 0)",
+ DEFAULT: convertToRGB("--color-sidebar-border-200"),
+ },
+ },
+ backdrop: "#131313",
+ },
+ },
+ typography: ({ theme }) => ({
+ brand: {
+ css: {
+ "--tw-prose-body": convertToRGB("--color-text-100"),
+ "--tw-prose-p": convertToRGB("--color-text-100"),
+ "--tw-prose-headings": convertToRGB("--color-text-100"),
+ "--tw-prose-lead": convertToRGB("--color-text-100"),
+ "--tw-prose-links": convertToRGB("--color-primary-100"),
+ "--tw-prose-bold": convertToRGB("--color-text-100"),
+ "--tw-prose-counters": convertToRGB("--color-text-100"),
+ "--tw-prose-bullets": convertToRGB("--color-text-100"),
+ "--tw-prose-hr": convertToRGB("--color-text-100"),
+ "--tw-prose-quotes": convertToRGB("--color-text-100"),
+ "--tw-prose-quote-borders": convertToRGB("--color-border"),
+ "--tw-prose-code": convertToRGB("--color-text-100"),
+ "--tw-prose-pre-code": convertToRGB("--color-text-100"),
+ "--tw-prose-pre-bg": convertToRGB("--color-background-100"),
+ "--tw-prose-th-borders": convertToRGB("--color-border"),
+ "--tw-prose-td-borders": convertToRGB("--color-border"),
+ },
+ },
+ }),
+ },
+ fontFamily: {
+ custom: ["Inter", "sans-serif"],
+ },
+ },
+ plugins: [require("@tailwindcss/typography")],
+};
diff --git a/apps/app/tsconfig.json b/space/tsconfig.json
similarity index 100%
rename from apps/app/tsconfig.json
rename to space/tsconfig.json
diff --git a/space/types/issue.ts b/space/types/issue.ts
new file mode 100644
index 000000000..206327fcd
--- /dev/null
+++ b/space/types/issue.ts
@@ -0,0 +1,168 @@
+export type TIssueBoardKeys = "list" | "kanban" | "calendar" | "spreadsheet" | "gantt";
+
+export interface IIssueBoardViews {
+ key: TIssueBoardKeys;
+ title: string;
+ icon: string;
+ className: string;
+}
+
+export type TIssuePriorityKey = "urgent" | "high" | "medium" | "low" | "none";
+export type TIssuePriorityTitle = "Urgent" | "High" | "Medium" | "Low" | "None";
+export interface IIssuePriorityFilters {
+ key: TIssuePriorityKey;
+ title: TIssuePriorityTitle;
+ className: string;
+ icon: string;
+}
+
+export type TIssueGroupKey = "backlog" | "unstarted" | "started" | "completed" | "cancelled";
+export type TIssueGroupTitle = "Backlog" | "Unstarted" | "Started" | "Completed" | "Cancelled";
+
+export interface IIssueGroup {
+ key: TIssueGroupKey;
+ title: TIssueGroupTitle;
+ color: string;
+ className: string;
+ icon: React.FC;
+}
+
+export interface IIssue {
+ id: string;
+ comments: Comment[];
+ description_html: string;
+ label_details: any;
+ name: string;
+ priority: TIssuePriorityKey | null;
+ project: string;
+ project_detail: any;
+ reactions: IIssueReaction[];
+ sequence_id: number;
+ start_date: any;
+ state: string;
+ state_detail: any;
+ target_date: any;
+ votes: IVote[];
+}
+
+export interface IIssueState {
+ id: string;
+ name: string;
+ group: TIssueGroupKey;
+ color: string;
+}
+
+export interface IIssueLabel {
+ id: string;
+ name: string;
+ color: string;
+}
+
+export interface IVote {
+ issue: string;
+ vote: -1 | 1;
+ workspace: string;
+ project: string;
+ actor: string;
+ actor_detail: ActorDetail;
+}
+
+export interface Comment {
+ actor_detail: ActorDetail;
+ access: string;
+ actor: string;
+ attachments: any[];
+ comment_html: string;
+ comment_reactions: {
+ actor_detail: ActorDetail;
+ comment: string;
+ id: string;
+ reaction: string;
+ }[];
+ comment_stripped: string;
+ created_at: Date;
+ created_by: string;
+ id: string;
+ is_member: boolean;
+ issue: string;
+ issue_detail: IssueDetail;
+ project: string;
+ project_detail: ProjectDetail;
+ updated_at: Date;
+ updated_by: string;
+ workspace: string;
+ workspace_detail: WorkspaceDetail;
+}
+
+export interface IIssueReaction {
+ actor_detail: ActorDetail;
+ id: string;
+ issue: string;
+ reaction: string;
+}
+
+export interface ActorDetail {
+ avatar?: string;
+ display_name?: string;
+ first_name?: string;
+ id?: string;
+ is_bot?: boolean;
+ last_name?: string;
+}
+
+export interface IssueDetail {
+ id: string;
+ name: string;
+ description: Description;
+ description_html: string;
+ priority: string;
+ start_date: null;
+ target_date: null;
+ sequence_id: number;
+ sort_order: number;
+}
+
+export interface Description {
+ type: string;
+ content: DescriptionContent[];
+}
+
+export interface DescriptionContent {
+ type: string;
+ attrs?: Attrs;
+ content: ContentContent[];
+}
+
+export interface Attrs {
+ level: number;
+}
+
+export interface ContentContent {
+ text: string;
+ type: string;
+}
+
+export interface ProjectDetail {
+ id: string;
+ identifier: string;
+ name: string;
+ cover_image: string;
+ icon_prop: null;
+ emoji: string;
+ description: string;
+}
+
+export interface WorkspaceDetail {
+ name: string;
+ slug: string;
+ id: string;
+}
+
+export interface IssueDetailType {
+ [issueId: string]: {
+ issue: IIssue;
+ comments: Comment[];
+ reactions: any[];
+ votes: any[];
+ };
+}
diff --git a/apps/space/store/types/project.ts b/space/types/project.ts
similarity index 64%
rename from apps/space/store/types/project.ts
rename to space/types/project.ts
index 41f4c2f44..e0e1bba9e 100644
--- a/apps/space/store/types/project.ts
+++ b/space/types/project.ts
@@ -27,14 +27,3 @@ export interface IProjectSettings {
spreadsheet: boolean;
};
}
-
-export interface IProjectStore {
- loader: boolean;
- error: any | null;
-
- workspace: IWorkspace | null;
- project: IProject | null;
- workspaceProjectSettings: IProjectSettings | null;
-
- getProjectSettingsAsync: (workspace_slug: string, project_slug: string) => Promise;
-}
diff --git a/apps/space/store/types/theme.ts b/space/types/theme.ts
similarity index 100%
rename from apps/space/store/types/theme.ts
rename to space/types/theme.ts
diff --git a/space/types/user.ts b/space/types/user.ts
new file mode 100644
index 000000000..8c6d5f681
--- /dev/null
+++ b/space/types/user.ts
@@ -0,0 +1,23 @@
+export interface IUser {
+ avatar: string;
+ cover_image: string | null;
+ created_at: Date;
+ created_location: string;
+ date_joined: Date;
+ email: string;
+ display_name: string;
+ first_name: string;
+ id: string;
+ is_email_verified: boolean;
+ is_onboarded: boolean;
+ is_tour_completed: boolean;
+ last_location: string;
+ last_login: Date;
+ last_name: string;
+ mobile_number: string;
+ role: string;
+ token: string;
+ updated_at: Date;
+ username: string;
+ user_timezone: string;
+}
diff --git a/turbo.json b/turbo.json
index 69da3c552..47b92f0db 100644
--- a/turbo.json
+++ b/turbo.json
@@ -24,7 +24,8 @@
"NEXT_PUBLIC_SLACK_CLIENT_SECRET",
"NEXT_PUBLIC_SUPABASE_URL",
"NEXT_PUBLIC_SUPABASE_ANON_KEY",
- "NEXT_PUBLIC_PLAUSIBLE_DOMAIN"
+ "NEXT_PUBLIC_PLAUSIBLE_DOMAIN",
+ "NEXT_PUBLIC_DEPLOY_WITH_NGINX"
],
"pipeline": {
"build": {
diff --git a/web/.env.example b/web/.env.example
new file mode 100644
index 000000000..50a6209b2
--- /dev/null
+++ b/web/.env.example
@@ -0,0 +1,26 @@
+# Base url for the API requests
+NEXT_PUBLIC_API_BASE_URL=""
+# Extra image domains that need to be added for Next Image
+NEXT_PUBLIC_EXTRA_IMAGE_DOMAINS=
+# Google Client ID for Google OAuth
+NEXT_PUBLIC_GOOGLE_CLIENTID=""
+# GitHub App ID for GitHub OAuth
+NEXT_PUBLIC_GITHUB_ID=""
+# GitHub App Name for GitHub Integration
+NEXT_PUBLIC_GITHUB_APP_NAME=""
+# Sentry DSN for error monitoring
+NEXT_PUBLIC_SENTRY_DSN=""
+# Enable/Disable OAUTH - default 0 for selfhosted instance
+NEXT_PUBLIC_ENABLE_OAUTH=0
+# Enable/Disable Sentry
+NEXT_PUBLIC_ENABLE_SENTRY=0
+# Enable/Disable session recording
+NEXT_PUBLIC_ENABLE_SESSION_RECORDER=0
+# Enable/Disable event tracking
+NEXT_PUBLIC_TRACK_EVENTS=0
+# Slack Client ID for Slack Integration
+NEXT_PUBLIC_SLACK_CLIENT_ID=""
+# For Telemetry, set it to "app.plane.so"
+NEXT_PUBLIC_PLAUSIBLE_DOMAIN=""
+# Public boards deploy URL
+NEXT_PUBLIC_DEPLOY_URL=""
\ No newline at end of file
diff --git a/web/.eslintrc.js b/web/.eslintrc.js
new file mode 100644
index 000000000..38e6a5f4c
--- /dev/null
+++ b/web/.eslintrc.js
@@ -0,0 +1,7 @@
+module.exports = {
+ root: true,
+ extends: ["custom"],
+ rules: {
+ "@next/next/no-img-element": "off",
+ },
+};
diff --git a/apps/app/.prettierrc b/web/.prettierrc
similarity index 100%
rename from apps/app/.prettierrc
rename to web/.prettierrc
diff --git a/apps/app/Dockerfile.dev b/web/Dockerfile.dev
similarity index 100%
rename from apps/app/Dockerfile.dev
rename to web/Dockerfile.dev
diff --git a/apps/space/Dockerfile.space b/web/Dockerfile.web
similarity index 69%
rename from apps/space/Dockerfile.space
rename to web/Dockerfile.web
index 0240ddbf7..40946fa2d 100644
--- a/apps/space/Dockerfile.space
+++ b/web/Dockerfile.web
@@ -7,7 +7,7 @@ ENV NEXT_PUBLIC_API_BASE_URL=http://NEXT_PUBLIC_API_BASE_URL_PLACEHOLDER
RUN yarn global add turbo
COPY . .
-RUN turbo prune --scope=space --docker
+RUN turbo prune --scope=web --docker
# Add lockfile and package.json's of isolated subworkspace
FROM node:18-alpine AS installer
@@ -15,6 +15,7 @@ FROM node:18-alpine AS installer
RUN apk add --no-cache libc6-compat
WORKDIR /app
ARG NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
+ARG NEXT_PUBLIC_DEPLOY_URL=http://localhost/spaces
# First install the dependencies (as they change less often)
COPY .gitignore .gitignore
@@ -29,12 +30,13 @@ COPY replace-env-vars.sh /usr/local/bin/
USER root
RUN chmod +x /usr/local/bin/replace-env-vars.sh
-RUN yarn turbo run build --filter=space
-
ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \
- BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
+ BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \
+ NEXT_PUBLIC_DEPLOY_URL=$NEXT_PUBLIC_DEPLOY_URL
-RUN /usr/local/bin/replace-env-vars.sh http://NEXT_PUBLIC_WEBAPP_URL_PLACEHOLDER ${NEXT_PUBLIC_API_BASE_URL} space
+RUN yarn turbo run build --filter=web
+
+RUN /usr/local/bin/replace-env-vars.sh http://NEXT_PUBLIC_WEBAPP_URL_PLACEHOLDER ${NEXT_PUBLIC_API_BASE_URL} web
FROM node:18-alpine AS runner
WORKDIR /app
@@ -44,18 +46,21 @@ RUN addgroup --system --gid 1001 plane
RUN adduser --system --uid 1001 captain
USER captain
-COPY --from=installer /app/apps/space/next.config.js .
-COPY --from=installer /app/apps/space/package.json .
+COPY --from=installer /app/web/next.config.js .
+COPY --from=installer /app/web/package.json .
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
-COPY --from=installer --chown=captain:plane /app/apps/space/.next/standalone ./
+COPY --from=installer --chown=captain:plane /app/web/.next/standalone ./
-COPY --from=installer --chown=captain:plane /app/apps/space/.next ./apps/space/.next
+COPY --from=installer --chown=captain:plane /app/web/.next ./web/.next
ARG NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
+ARG NEXT_PUBLIC_DEPLOY_URL=http://localhost/spaces
+
ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \
- BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
+ BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \
+ NEXT_PUBLIC_DEPLOY_URL=$NEXT_PUBLIC_DEPLOY_URL
USER root
COPY replace-env-vars.sh /usr/local/bin/
diff --git a/apps/app/components/account/email-code-form.tsx b/web/components/account/email-code-form.tsx
similarity index 100%
rename from apps/app/components/account/email-code-form.tsx
rename to web/components/account/email-code-form.tsx
diff --git a/apps/app/components/account/email-password-form.tsx b/web/components/account/email-password-form.tsx
similarity index 100%
rename from apps/app/components/account/email-password-form.tsx
rename to web/components/account/email-password-form.tsx
diff --git a/apps/app/components/account/email-reset-password-form.tsx b/web/components/account/email-reset-password-form.tsx
similarity index 100%
rename from apps/app/components/account/email-reset-password-form.tsx
rename to web/components/account/email-reset-password-form.tsx
diff --git a/apps/app/components/account/github-login-button.tsx b/web/components/account/github-login-button.tsx
similarity index 100%
rename from apps/app/components/account/github-login-button.tsx
rename to web/components/account/github-login-button.tsx
diff --git a/apps/app/components/account/google-login.tsx b/web/components/account/google-login.tsx
similarity index 100%
rename from apps/app/components/account/google-login.tsx
rename to web/components/account/google-login.tsx
diff --git a/apps/app/components/account/index.ts b/web/components/account/index.ts
similarity index 100%
rename from apps/app/components/account/index.ts
rename to web/components/account/index.ts
diff --git a/apps/app/components/analytics/custom-analytics/create-update-analytics-modal.tsx b/web/components/analytics/custom-analytics/create-update-analytics-modal.tsx
similarity index 100%
rename from apps/app/components/analytics/custom-analytics/create-update-analytics-modal.tsx
rename to web/components/analytics/custom-analytics/create-update-analytics-modal.tsx
diff --git a/apps/app/components/analytics/custom-analytics/custom-analytics.tsx b/web/components/analytics/custom-analytics/custom-analytics.tsx
similarity index 100%
rename from apps/app/components/analytics/custom-analytics/custom-analytics.tsx
rename to web/components/analytics/custom-analytics/custom-analytics.tsx
diff --git a/apps/app/components/analytics/custom-analytics/graph/custom-tooltip.tsx b/web/components/analytics/custom-analytics/graph/custom-tooltip.tsx
similarity index 100%
rename from apps/app/components/analytics/custom-analytics/graph/custom-tooltip.tsx
rename to web/components/analytics/custom-analytics/graph/custom-tooltip.tsx
diff --git a/apps/app/components/analytics/custom-analytics/graph/index.tsx b/web/components/analytics/custom-analytics/graph/index.tsx
similarity index 100%
rename from apps/app/components/analytics/custom-analytics/graph/index.tsx
rename to web/components/analytics/custom-analytics/graph/index.tsx
diff --git a/apps/app/components/analytics/custom-analytics/index.ts b/web/components/analytics/custom-analytics/index.ts
similarity index 100%
rename from apps/app/components/analytics/custom-analytics/index.ts
rename to web/components/analytics/custom-analytics/index.ts
diff --git a/apps/app/components/analytics/custom-analytics/select-bar.tsx b/web/components/analytics/custom-analytics/select-bar.tsx
similarity index 100%
rename from apps/app/components/analytics/custom-analytics/select-bar.tsx
rename to web/components/analytics/custom-analytics/select-bar.tsx
diff --git a/apps/app/components/analytics/custom-analytics/sidebar.tsx b/web/components/analytics/custom-analytics/sidebar.tsx
similarity index 100%
rename from apps/app/components/analytics/custom-analytics/sidebar.tsx
rename to web/components/analytics/custom-analytics/sidebar.tsx
diff --git a/apps/app/components/analytics/custom-analytics/table.tsx b/web/components/analytics/custom-analytics/table.tsx
similarity index 94%
rename from apps/app/components/analytics/custom-analytics/table.tsx
rename to web/components/analytics/custom-analytics/table.tsx
index 75d1d7d40..5993bb63c 100644
--- a/apps/app/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}`)
+
) : (
= ({ 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/apps/app/components/analytics/scope-and-demand/index.ts b/web/components/analytics/scope-and-demand/index.ts
similarity index 100%
rename from apps/app/components/analytics/scope-and-demand/index.ts
rename to web/components/analytics/scope-and-demand/index.ts
diff --git a/apps/app/components/analytics/scope-and-demand/leaderboard.tsx b/web/components/analytics/scope-and-demand/leaderboard.tsx
similarity index 100%
rename from apps/app/components/analytics/scope-and-demand/leaderboard.tsx
rename to web/components/analytics/scope-and-demand/leaderboard.tsx
diff --git a/apps/app/components/analytics/scope-and-demand/scope-and-demand.tsx b/web/components/analytics/scope-and-demand/scope-and-demand.tsx
similarity index 100%
rename from apps/app/components/analytics/scope-and-demand/scope-and-demand.tsx
rename to web/components/analytics/scope-and-demand/scope-and-demand.tsx
diff --git a/apps/app/components/analytics/scope-and-demand/scope.tsx b/web/components/analytics/scope-and-demand/scope.tsx
similarity index 100%
rename from apps/app/components/analytics/scope-and-demand/scope.tsx
rename to web/components/analytics/scope-and-demand/scope.tsx
diff --git a/apps/app/components/analytics/scope-and-demand/year-wise-issues.tsx b/web/components/analytics/scope-and-demand/year-wise-issues.tsx
similarity index 100%
rename from apps/app/components/analytics/scope-and-demand/year-wise-issues.tsx
rename to web/components/analytics/scope-and-demand/year-wise-issues.tsx
diff --git a/apps/app/components/analytics/select/index.ts b/web/components/analytics/select/index.ts
similarity index 100%
rename from apps/app/components/analytics/select/index.ts
rename to web/components/analytics/select/index.ts
diff --git a/apps/app/components/analytics/select/project.tsx b/web/components/analytics/select/project.tsx
similarity index 100%
rename from apps/app/components/analytics/select/project.tsx
rename to web/components/analytics/select/project.tsx
diff --git a/apps/app/components/analytics/select/segment.tsx b/web/components/analytics/select/segment.tsx
similarity index 100%
rename from apps/app/components/analytics/select/segment.tsx
rename to web/components/analytics/select/segment.tsx
diff --git a/apps/app/components/analytics/select/x-axis.tsx b/web/components/analytics/select/x-axis.tsx
similarity index 100%
rename from apps/app/components/analytics/select/x-axis.tsx
rename to web/components/analytics/select/x-axis.tsx
diff --git a/apps/app/components/analytics/select/y-axis.tsx b/web/components/analytics/select/y-axis.tsx
similarity index 100%
rename from apps/app/components/analytics/select/y-axis.tsx
rename to web/components/analytics/select/y-axis.tsx
diff --git a/apps/app/components/auth-screens/index.ts b/web/components/auth-screens/index.ts
similarity index 100%
rename from apps/app/components/auth-screens/index.ts
rename to web/components/auth-screens/index.ts
diff --git a/apps/app/components/auth-screens/not-authorized-view.tsx b/web/components/auth-screens/not-authorized-view.tsx
similarity index 100%
rename from apps/app/components/auth-screens/not-authorized-view.tsx
rename to web/components/auth-screens/not-authorized-view.tsx
diff --git a/apps/app/components/auth-screens/project/index.ts b/web/components/auth-screens/project/index.ts
similarity index 100%
rename from apps/app/components/auth-screens/project/index.ts
rename to web/components/auth-screens/project/index.ts
diff --git a/apps/app/components/auth-screens/project/join-project.tsx b/web/components/auth-screens/project/join-project.tsx
similarity index 100%
rename from apps/app/components/auth-screens/project/join-project.tsx
rename to web/components/auth-screens/project/join-project.tsx
diff --git a/apps/app/components/auth-screens/workspace/index.ts b/web/components/auth-screens/workspace/index.ts
similarity index 100%
rename from apps/app/components/auth-screens/workspace/index.ts
rename to web/components/auth-screens/workspace/index.ts
diff --git a/apps/app/components/auth-screens/workspace/not-a-member.tsx b/web/components/auth-screens/workspace/not-a-member.tsx
similarity index 100%
rename from apps/app/components/auth-screens/workspace/not-a-member.tsx
rename to web/components/auth-screens/workspace/not-a-member.tsx
diff --git a/apps/app/components/automation/auto-archive-automation.tsx b/web/components/automation/auto-archive-automation.tsx
similarity index 100%
rename from apps/app/components/automation/auto-archive-automation.tsx
rename to web/components/automation/auto-archive-automation.tsx
diff --git a/apps/app/components/automation/auto-close-automation.tsx b/web/components/automation/auto-close-automation.tsx
similarity index 89%
rename from apps/app/components/automation/auto-close-automation.tsx
rename to web/components/automation/auto-close-automation.tsx
index 3e71b8329..ad65714aa 100644
--- a/apps/app/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/apps/app/components/automation/index.ts b/web/components/automation/index.ts
similarity index 100%
rename from apps/app/components/automation/index.ts
rename to web/components/automation/index.ts
diff --git a/apps/app/components/automation/select-month-modal.tsx b/web/components/automation/select-month-modal.tsx
similarity index 100%
rename from apps/app/components/automation/select-month-modal.tsx
rename to web/components/automation/select-month-modal.tsx
diff --git a/apps/app/components/breadcrumbs/index.tsx b/web/components/breadcrumbs/index.tsx
similarity index 100%
rename from apps/app/components/breadcrumbs/index.tsx
rename to web/components/breadcrumbs/index.tsx
diff --git a/apps/app/components/command-palette/change-interface-theme.tsx b/web/components/command-palette/change-interface-theme.tsx
similarity index 100%
rename from apps/app/components/command-palette/change-interface-theme.tsx
rename to web/components/command-palette/change-interface-theme.tsx
diff --git a/apps/app/components/command-palette/command-k.tsx b/web/components/command-palette/command-k.tsx
similarity index 100%
rename from apps/app/components/command-palette/command-k.tsx
rename to web/components/command-palette/command-k.tsx
diff --git a/apps/app/components/command-palette/command-pallette.tsx b/web/components/command-palette/command-pallette.tsx
similarity index 80%
rename from apps/app/components/command-palette/command-pallette.tsx
rename to web/components/command-palette/command-pallette.tsx
index 4dc29afec..507d8a49c 100644
--- a/apps/app/components/command-palette/command-pallette.tsx
+++ b/web/components/command-palette/command-pallette.tsx
@@ -51,7 +51,7 @@ export const CommandPalette: React.FC = observer(() => {
workspaceSlug && projectId && issueId ? ISSUE_DETAILS(issueId as string) : null,
workspaceSlug && projectId && issueId
? () =>
- issuesService.retrieve(workspaceSlug as string, projectId as string, issueId as string)
+ issuesService.retrieve(workspaceSlug as string, projectId as string, issueId as string)
: null
);
@@ -89,37 +89,37 @@ export const CommandPalette: React.FC = observer(() => {
)
return;
- if (cmdClicked) {
- if (keyPressed === "k") {
- e.preventDefault();
- setIsPaletteOpen(true);
- } else if (keyPressed === "c" && altKey) {
- e.preventDefault();
- copyIssueUrlToClipboard();
- } else if (keyPressed === "b") {
- e.preventDefault();
- store.theme.setSidebarCollapsed(!store?.theme?.sidebarCollapsed);
- }
- } else {
- if (keyPressed === "c") {
- setIsIssueModalOpen(true);
- } else if (keyPressed === "p") {
- setIsProjectModalOpen(true);
- } else if (keyPressed === "v") {
- setIsCreateViewModalOpen(true);
- } else if (keyPressed === "d") {
- setIsCreateUpdatePageModalOpen(true);
- } else if (keyPressed === "h") {
- setIsShortcutsModalOpen(true);
- } else if (keyPressed === "q") {
- setIsCreateCycleModalOpen(true);
- } else if (keyPressed === "m") {
- setIsCreateModuleModalOpen(true);
- } else if (keyPressed === "backspace" || keyPressed === "delete") {
- e.preventDefault();
- setIsBulkDeleteIssuesModalOpen(true);
- }
+ if (cmdClicked) {
+ if (keyPressed === "k") {
+ e.preventDefault();
+ setIsPaletteOpen(true);
+ } else if (keyPressed === "c" && altKey) {
+ e.preventDefault();
+ copyIssueUrlToClipboard();
+ } else if (keyPressed === "b") {
+ e.preventDefault();
+ store.theme.setSidebarCollapsed(!store?.theme?.sidebarCollapsed);
}
+ } else {
+ if (keyPressed === "c") {
+ setIsIssueModalOpen(true);
+ } else if (keyPressed === "p") {
+ setIsProjectModalOpen(true);
+ } else if (keyPressed === "v") {
+ setIsCreateViewModalOpen(true);
+ } else if (keyPressed === "d") {
+ setIsCreateUpdatePageModalOpen(true);
+ } else if (keyPressed === "h") {
+ setIsShortcutsModalOpen(true);
+ } else if (keyPressed === "q") {
+ setIsCreateCycleModalOpen(true);
+ } else if (keyPressed === "m") {
+ setIsCreateModuleModalOpen(true);
+ } else if (keyPressed === "backspace" || keyPressed === "delete") {
+ e.preventDefault();
+ setIsBulkDeleteIssuesModalOpen(true);
+ }
+ }
},
[copyIssueUrlToClipboard]
);
@@ -196,4 +196,4 @@ export const CommandPalette: React.FC = observer(() => {
/>
>
);
-})
\ No newline at end of file
+});
diff --git a/apps/app/components/command-palette/helpers.tsx b/web/components/command-palette/helpers.tsx
similarity index 100%
rename from apps/app/components/command-palette/helpers.tsx
rename to web/components/command-palette/helpers.tsx
diff --git a/apps/app/components/command-palette/index.ts b/web/components/command-palette/index.ts
similarity index 100%
rename from apps/app/components/command-palette/index.ts
rename to web/components/command-palette/index.ts
diff --git a/apps/app/components/command-palette/issue/change-issue-assignee.tsx b/web/components/command-palette/issue/change-issue-assignee.tsx
similarity index 100%
rename from apps/app/components/command-palette/issue/change-issue-assignee.tsx
rename to web/components/command-palette/issue/change-issue-assignee.tsx
diff --git a/apps/app/components/command-palette/issue/change-issue-priority.tsx b/web/components/command-palette/issue/change-issue-priority.tsx
similarity index 89%
rename from apps/app/components/command-palette/issue/change-issue-priority.tsx
rename to web/components/command-palette/issue/change-issue-priority.tsx
index 07ba210a6..e1c0d52af 100644
--- a/apps/app/components/command-palette/issue/change-issue-priority.tsx
+++ b/web/components/command-palette/issue/change-issue-priority.tsx
@@ -1,5 +1,7 @@
-import { useRouter } from "next/router";
import React, { Dispatch, SetStateAction, useCallback } from "react";
+
+import { useRouter } from "next/router";
+
import { mutate } from "swr";
// cmdk
@@ -7,12 +9,12 @@ import { Command } from "cmdk";
// services
import issuesService from "services/issues.service";
// types
-import { ICurrentUserResponse, IIssue } from "types";
+import { ICurrentUserResponse, IIssue, TIssuePriorities } from "types";
// constants
import { ISSUE_DETAILS, PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys";
import { PRIORITIES } from "constants/project";
// icons
-import { CheckIcon, getPriorityIcon } from "components/icons";
+import { CheckIcon, PriorityIcon } from "components/icons";
type Props = {
setIsPaletteOpen: Dispatch
>;
@@ -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/apps/app/components/command-palette/issue/change-issue-state.tsx b/web/components/command-palette/issue/change-issue-state.tsx
similarity index 91%
rename from apps/app/components/command-palette/issue/change-issue-state.tsx
rename to web/components/command-palette/issue/change-issue-state.tsx
index 30e2cdb77..6bfc2874c 100644
--- a/apps/app/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/apps/app/components/command-palette/issue/index.ts b/web/components/command-palette/issue/index.ts
similarity index 100%
rename from apps/app/components/command-palette/issue/index.ts
rename to web/components/command-palette/issue/index.ts
diff --git a/apps/app/components/command-palette/shortcuts-modal.tsx b/web/components/command-palette/shortcuts-modal.tsx
similarity index 99%
rename from apps/app/components/command-palette/shortcuts-modal.tsx
rename to web/components/command-palette/shortcuts-modal.tsx
index 86b4aeb46..82f9b398c 100644
--- a/apps/app/components/command-palette/shortcuts-modal.tsx
+++ b/web/components/command-palette/shortcuts-modal.tsx
@@ -22,8 +22,6 @@ const shortcuts = [
{ keys: "↓", description: "Move down" },
{ keys: "←", description: "Move left" },
{ keys: "→", description: "Move right" },
- { keys: "Enter", description: "Select" },
- { keys: "Esc", description: "Close" },
],
},
{
diff --git a/apps/app/components/core/activity.tsx b/web/components/core/activity.tsx
similarity index 96%
rename from apps/app/components/core/activity.tsx
rename to web/components/core/activity.tsx
index 1b9de8d25..c8f6377b7 100644
--- a/apps/app/components/core/activity.tsx
+++ b/web/components/core/activity.tsx
@@ -353,6 +353,28 @@ const activityDetails: {
.
>
);
+ else if (activity.verb === "updated")
+ return (
+ <>
+ updated the{" "}
+
+ link
+
+
+ {showIssue && (
+ <>
+ {" "}
+ from
+ >
+ )}
+ .
+ >
+ );
else
return (
<>
diff --git a/apps/app/components/core/filters/date-filter-modal.tsx b/web/components/core/filters/date-filter-modal.tsx
similarity index 89%
rename from apps/app/components/core/filters/date-filter-modal.tsx
rename to web/components/core/filters/date-filter-modal.tsx
index abc2cc7c4..eb285fd6f 100644
--- a/apps/app/components/core/filters/date-filter-modal.tsx
+++ b/web/components/core/filters/date-filter-modal.tsx
@@ -1,15 +1,11 @@
import { Fragment } from "react";
-import { useRouter } from "next/router";
-
// react-hook-form
import { Controller, useForm } from "react-hook-form";
// react-datepicker
import DatePicker from "react-datepicker";
// headless ui
import { Dialog, Transition } from "@headlessui/react";
-// hooks
-import useIssuesView from "hooks/use-issues-view";
// components
import { DateFilterSelect } from "./date-filter-select";
// ui
@@ -23,8 +19,10 @@ import { IIssueFilterOptions } from "types";
type Props = {
title: string;
field: keyof IIssueFilterOptions;
- isOpen: boolean;
+ filters: IIssueFilterOptions;
handleClose: () => void;
+ isOpen: boolean;
+ onSelect: (option: any) => void;
};
type TFormValues = {
@@ -39,12 +37,14 @@ const defaultValues: TFormValues = {
date2: new Date(new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()),
};
-export const DateFilterModal: React.FC = ({ title, field, isOpen, handleClose }) => {
- const { filters, setFilters } = useIssuesView();
-
- const router = useRouter();
- const { viewId } = router.query;
-
+export const DateFilterModal: React.FC = ({
+ title,
+ field,
+ filters,
+ handleClose,
+ isOpen,
+ onSelect,
+}) => {
const { handleSubmit, watch, control } = useForm({
defaultValues,
});
@@ -53,10 +53,10 @@ export const DateFilterModal: React.FC = ({ title, field, isOpen, handleC
const { filterType, date1, date2 } = formData;
if (filterType === "range") {
- setFilters(
- { [field]: [`${renderDateFormat(date1)};after`, `${renderDateFormat(date2)};before`] },
- !Boolean(viewId)
- );
+ onSelect({
+ key: field,
+ value: [`${renderDateFormat(date1)};after`, `${renderDateFormat(date2)};before`],
+ });
} else {
const filteredArray = (filters?.[field] as string[])?.filter((item) => {
if (item?.includes(filterType)) return false;
@@ -66,17 +66,12 @@ export const DateFilterModal: React.FC = ({ title, field, isOpen, handleC
const filterOne = filteredArray && filteredArray?.length > 0 ? filteredArray[0] : null;
if (filterOne)
- setFilters(
- { [field]: [filterOne, `${renderDateFormat(date1)};${filterType}`] },
- !Boolean(viewId)
- );
+ onSelect({ key: field, value: [filterOne, `${renderDateFormat(date1)};${filterType}`] });
else
- setFilters(
- {
- [field]: [`${renderDateFormat(date1)};${filterType}`],
- },
- !Boolean(viewId)
- );
+ onSelect({
+ key: field,
+ value: [`${renderDateFormat(date1)};${filterType}`],
+ });
}
handleClose();
};
diff --git a/apps/app/components/core/filters/date-filter-select.tsx b/web/components/core/filters/date-filter-select.tsx
similarity index 100%
rename from apps/app/components/core/filters/date-filter-select.tsx
rename to web/components/core/filters/date-filter-select.tsx
diff --git a/apps/app/components/core/filters/filters-list.tsx b/web/components/core/filters/filters-list.tsx
similarity index 96%
rename from apps/app/components/core/filters/filters-list.tsx
rename to web/components/core/filters/filters-list.tsx
index 8192bdf7d..81a12bd86 100644
--- a/apps/app/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 { PriorityIcon, 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}
= ({
: "bg-custom-background-90 text-custom-text-200"
}`}
>
- {getPriorityIcon(priority)}
+
+
+
{priority === "null" ? "None" : priority}
{
: "text-custom-sidebar-text-200"
}`}
>
- View
+ Display
diff --git a/apps/app/components/core/image-picker-popover.tsx b/web/components/core/image-picker-popover.tsx
similarity index 98%
rename from apps/app/components/core/image-picker-popover.tsx
rename to web/components/core/image-picker-popover.tsx
index 402cba022..5f13d960e 100644
--- a/apps/app/components/core/image-picker-popover.tsx
+++ b/web/components/core/image-picker-popover.tsx
@@ -40,9 +40,15 @@ type Props = {
label: string | React.ReactNode;
value: string | null;
onChange: (data: string) => void;
+ disabled?: boolean;
};
-export const ImagePickerPopover: React.FC = ({ label, value, onChange }) => {
+export const ImagePickerPopover: React.FC = ({
+ label,
+ value,
+ onChange,
+ disabled = false,
+}) => {
const ref = useRef(null);
const router = useRouter();
@@ -117,6 +123,7 @@ export const ImagePickerPopover: React.FC = ({ label, value, onChange })
setIsOpen((prev) => !prev)}
+ disabled={disabled}
>
{label}
diff --git a/apps/app/components/core/index.ts b/web/components/core/index.ts
similarity index 100%
rename from apps/app/components/core/index.ts
rename to web/components/core/index.ts
diff --git a/apps/app/components/core/modals/bulk-delete-issues-modal.tsx b/web/components/core/modals/bulk-delete-issues-modal.tsx
similarity index 100%
rename from apps/app/components/core/modals/bulk-delete-issues-modal.tsx
rename to web/components/core/modals/bulk-delete-issues-modal.tsx
diff --git a/apps/app/components/core/modals/existing-issues-list-modal.tsx b/web/components/core/modals/existing-issues-list-modal.tsx
similarity index 99%
rename from apps/app/components/core/modals/existing-issues-list-modal.tsx
rename to web/components/core/modals/existing-issues-list-modal.tsx
index 5a9f68d8b..ed3902a4a 100644
--- a/apps/app/components/core/modals/existing-issues-list-modal.tsx
+++ b/web/components/core/modals/existing-issues-list-modal.tsx
@@ -212,7 +212,7 @@ export const ExistingIssuesListModal: React.FC = ({
onClick={() => setIsWorkspaceLevel((prevData) => !prevData)}
className="flex-shrink-0"
>
- workspace level
+ Workspace Level
diff --git a/apps/app/components/core/modals/gpt-assistant-modal.tsx b/web/components/core/modals/gpt-assistant-modal.tsx
similarity index 100%
rename from apps/app/components/core/modals/gpt-assistant-modal.tsx
rename to web/components/core/modals/gpt-assistant-modal.tsx
diff --git a/apps/app/components/core/modals/image-upload-modal.tsx b/web/components/core/modals/image-upload-modal.tsx
similarity index 100%
rename from apps/app/components/core/modals/image-upload-modal.tsx
rename to web/components/core/modals/image-upload-modal.tsx
diff --git a/apps/app/components/core/modals/index.ts b/web/components/core/modals/index.ts
similarity index 100%
rename from apps/app/components/core/modals/index.ts
rename to web/components/core/modals/index.ts
diff --git a/apps/app/components/core/modals/link-modal.tsx b/web/components/core/modals/link-modal.tsx
similarity index 100%
rename from apps/app/components/core/modals/link-modal.tsx
rename to web/components/core/modals/link-modal.tsx
diff --git a/apps/app/components/core/reaction-selector.tsx b/web/components/core/reaction-selector.tsx
similarity index 97%
rename from apps/app/components/core/reaction-selector.tsx
rename to web/components/core/reaction-selector.tsx
index 06b410785..43d77de9e 100644
--- a/apps/app/components/core/reaction-selector.tsx
+++ b/web/components/core/reaction-selector.tsx
@@ -61,7 +61,7 @@ export const ReactionSelector: React.FC = (props) => {
position === "top" ? "-top-12" : "-bottom-12"
}`}
>
-
+
{reactionEmojis.map((emoji) => (
= ({
{group}
diff --git a/apps/app/components/core/sidebar/single-progress-stats.tsx b/web/components/core/sidebar/single-progress-stats.tsx
similarity index 100%
rename from apps/app/components/core/sidebar/single-progress-stats.tsx
rename to web/components/core/sidebar/single-progress-stats.tsx
diff --git a/apps/app/components/core/theme/color-picker-input.tsx b/web/components/core/theme/color-picker-input.tsx
similarity index 100%
rename from apps/app/components/core/theme/color-picker-input.tsx
rename to web/components/core/theme/color-picker-input.tsx
diff --git a/apps/app/components/core/theme/custom-theme-selector.tsx b/web/components/core/theme/custom-theme-selector.tsx
similarity index 100%
rename from apps/app/components/core/theme/custom-theme-selector.tsx
rename to web/components/core/theme/custom-theme-selector.tsx
diff --git a/apps/app/components/core/theme/index.ts b/web/components/core/theme/index.ts
similarity index 100%
rename from apps/app/components/core/theme/index.ts
rename to web/components/core/theme/index.ts
diff --git a/apps/app/components/core/theme/theme-switch.tsx b/web/components/core/theme/theme-switch.tsx
similarity index 100%
rename from apps/app/components/core/theme/theme-switch.tsx
rename to web/components/core/theme/theme-switch.tsx
diff --git a/apps/app/components/core/views/all-views.tsx b/web/components/core/views/all-views.tsx
similarity index 97%
rename from apps/app/components/core/views/all-views.tsx
rename to web/components/core/views/all-views.tsx
index 79d5d6b11..eb54ccb2a 100644
--- a/apps/app/components/core/views/all-views.tsx
+++ b/web/components/core/views/all-views.tsx
@@ -53,6 +53,7 @@ type Props = {
handleOnDragEnd: (result: DropResult) => Promise;
openIssuesListModal: (() => void) | null;
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
+ disableAddIssueOption?: boolean;
trashBox: boolean;
setTrashBox: React.Dispatch>;
viewProps: IIssueViewProps;
@@ -68,6 +69,7 @@ export const AllViews: React.FC = ({
handleOnDragEnd,
openIssuesListModal,
removeIssue,
+ disableAddIssueOption = false,
trashBox,
setTrashBox,
viewProps,
@@ -127,6 +129,7 @@ export const AllViews: React.FC = ({
openIssuesListModal={cycleId || moduleId ? openIssuesListModal : null}
removeIssue={removeIssue}
disableUserActions={disableUserActions}
+ disableAddIssueOption={disableAddIssueOption}
user={user}
userAuth={memberRole}
viewProps={viewProps}
@@ -135,6 +138,7 @@ export const AllViews: React.FC = ({
void;
disableUserActions: boolean;
+ disableAddIssueOption?: boolean;
dragDisabled: boolean;
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
handleTrashBox: (isDragging: boolean) => void;
@@ -24,6 +25,7 @@ type Props = {
export const AllBoards: React.FC = ({
addIssueToGroup,
disableUserActions,
+ disableAddIssueOption = false,
dragDisabled,
handleIssueAction,
handleTrashBox,
@@ -52,6 +54,7 @@ export const AllBoards: React.FC = ({
addIssueToGroup={() => addIssueToGroup(singleGroup)}
currentState={currentState}
disableUserActions={disableUserActions}
+ disableAddIssueOption={disableAddIssueOption}
dragDisabled={dragDisabled}
groupTitle={singleGroup}
handleIssueAction={handleIssueAction}
@@ -79,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/apps/app/components/core/views/board-view/board-header.tsx b/web/components/core/views/board-view/board-header.tsx
similarity index 86%
rename from apps/app/components/core/views/board-view/board-header.tsx
rename to web/components/core/views/board-view/board-header.tsx
index d5b11f5f0..144bdb826 100644
--- a/apps/app/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 { PriorityIcon, StateGroupIcon } 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, TIssuePriorities, 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;
@@ -29,6 +31,7 @@ type Props = {
isCollapsed: boolean;
setIsCollapsed: React.Dispatch>;
disableUserActions: boolean;
+ disableAddIssue: boolean;
viewProps: IIssueViewProps;
};
@@ -39,6 +42,7 @@ export const BoardHeader: React.FC = ({
isCollapsed,
setIsCollapsed,
disableUserActions,
+ disableAddIssue,
viewProps,
}) => {
const router = useRouter();
@@ -95,14 +99,27 @@ 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");
+ icon = ;
break;
case "project":
const project = projects?.find((p) => p.id === groupTitle);
@@ -181,7 +198,7 @@ export const BoardHeader: React.FC = ({
)}
- {!disableUserActions && selectedGroup !== "created_by" && (
+ {!disableAddIssue && !disableUserActions && selectedGroup !== "created_by" && (
void;
currentState?: IState | null;
disableUserActions: boolean;
+ disableAddIssueOption?: boolean;
dragDisabled: boolean;
groupTitle: string;
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
@@ -36,6 +37,7 @@ export const SingleBoard: React.FC = ({
currentState,
groupTitle,
disableUserActions,
+ disableAddIssueOption = false,
dragDisabled,
handleIssueAction,
handleTrashBox,
@@ -70,6 +72,7 @@ export const SingleBoard: React.FC = ({
isCollapsed={isCollapsed}
setIsCollapsed={setIsCollapsed}
disableUserActions={disableUserActions}
+ disableAddIssue={disableAddIssueOption}
viewProps={viewProps}
/>
{isCollapsed && (
@@ -150,41 +153,41 @@ export const SingleBoard: React.FC = ({
{selectedGroup !== "created_by" && (
- {type === "issue" ? (
-
-
- Add Issue
-
- ) : (
- !disableUserActions && (
-
-
- Add Issue
-
- }
- position="left"
- noBorder
- >
-
- Create new
-
- {openIssuesListModal && (
-
- Add an existing issue
+ {type === "issue"
+ ? !disableAddIssueOption && (
+
+
+ Add Issue
+
+ )
+ : !disableUserActions && (
+
+
+ Add Issue
+
+ }
+ position="left"
+ noBorder
+ >
+
+ Create new
- )}
-
- )
- )}
+ {openIssuesListModal && (
+
+ Add an existing issue
+
+ )}
+
+ )}
)}
diff --git a/apps/app/components/core/views/board-view/single-issue.tsx b/web/components/core/views/board-view/single-issue.tsx
similarity index 99%
rename from apps/app/components/core/views/board-view/single-issue.tsx
rename to web/components/core/views/board-view/single-issue.tsx
index b676e809c..455ba48e6 100644
--- a/apps/app/components/core/views/board-view/single-issue.tsx
+++ b/web/components/core/views/board-view/single-issue.tsx
@@ -350,7 +350,7 @@ export const SingleBoardIssue: React.FC
= ({
/>
)}
{properties.labels && issue.labels.length > 0 && (
-
+
)}
{properties.assignee && (
= ({
// 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/apps/app/components/core/views/list-view/all-lists.tsx b/web/components/core/views/list-view/all-lists.tsx
similarity index 93%
rename from apps/app/components/core/views/list-view/all-lists.tsx
rename to web/components/core/views/list-view/all-lists.tsx
index 64cbebdcd..84ef02962 100644
--- a/apps/app/components/core/views/list-view/all-lists.tsx
+++ b/web/components/core/views/list-view/all-lists.tsx
@@ -11,6 +11,7 @@ type Props = {
openIssuesListModal?: (() => void) | null;
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
disableUserActions: boolean;
+ disableAddIssueOption?: boolean;
user: ICurrentUserResponse | undefined;
userAuth: UserAuth;
viewProps: IIssueViewProps;
@@ -20,6 +21,7 @@ export const AllLists: React.FC = ({
addIssueToGroup,
handleIssueAction,
disableUserActions,
+ disableAddIssueOption = false,
openIssuesListModal,
removeIssue,
states,
@@ -49,6 +51,7 @@ export const AllLists: React.FC = ({
openIssuesListModal={openIssuesListModal}
removeIssue={removeIssue}
disableUserActions={disableUserActions}
+ disableAddIssueOption={disableAddIssueOption}
user={user}
userAuth={userAuth}
viewProps={viewProps}
diff --git a/apps/app/components/core/views/list-view/index.ts b/web/components/core/views/list-view/index.ts
similarity index 100%
rename from apps/app/components/core/views/list-view/index.ts
rename to web/components/core/views/list-view/index.ts
diff --git a/apps/app/components/core/views/list-view/single-issue.tsx b/web/components/core/views/list-view/single-issue.tsx
similarity index 94%
rename from apps/app/components/core/views/list-view/single-issue.tsx
rename to web/components/core/views/list-view/single-issue.tsx
index eafe74612..d89ef6927 100644
--- a/apps/app/components/core/views/list-view/single-issue.tsx
+++ b/web/components/core/views/list-view/single-issue.tsx
@@ -36,9 +36,21 @@ import { LayerDiagonalIcon } from "components/icons";
import { copyTextToClipboard } from "helpers/string.helper";
import { handleIssuesMutation } from "constants/issue";
// types
-import { ICurrentUserResponse, IIssue, IIssueViewProps, ISubIssueResponse, UserAuth } from "types";
+import {
+ ICurrentUserResponse,
+ IIssue,
+ IIssueViewProps,
+ ISubIssueResponse,
+ IUserProfileProjectSegregation,
+ UserAuth,
+} from "types";
// fetch-keys
-import { CYCLE_DETAILS, MODULE_DETAILS, SUB_ISSUES } from "constants/fetch-keys";
+import {
+ CYCLE_DETAILS,
+ MODULE_DETAILS,
+ SUB_ISSUES,
+ USER_PROFILE_PROJECT_SEGREGATION,
+} from "constants/fetch-keys";
type Props = {
type?: string;
@@ -74,7 +86,7 @@ export const SingleListIssue: React.FC = ({
const [contextMenuPosition, setContextMenuPosition] = useState(null);
const router = useRouter();
- const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
+ const { workspaceSlug, projectId, cycleId, moduleId, userId } = router.query;
const isArchivedIssues = router.pathname.includes("archived-issues");
const { setToastAlert } = useToast();
@@ -126,6 +138,11 @@ export const SingleListIssue: React.FC = ({
.then(() => {
mutateIssues();
+ if (userId)
+ mutate(
+ USER_PROFILE_PROJECT_SEGREGATION(workspaceSlug.toString(), userId.toString())
+ );
+
if (cycleId) mutate(CYCLE_DETAILS(cycleId as string));
if (moduleId) mutate(MODULE_DETAILS(moduleId as string));
});
@@ -134,6 +151,7 @@ export const SingleListIssue: React.FC = ({
workspaceSlug,
cycleId,
moduleId,
+ userId,
groupTitle,
index,
selectedGroup,
@@ -261,7 +279,7 @@ export const SingleListIssue: React.FC = ({
isNotAllowed={isNotAllowed}
/>
)}
- {properties.labels && }
+ {properties.labels && }
{properties.assignee && (
void) | null;
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
disableUserActions: boolean;
+ disableAddIssueOption?: boolean;
user: ICurrentUserResponse | undefined;
userAuth: UserAuth;
viewProps: IIssueViewProps;
@@ -52,6 +57,7 @@ export const SingleList: React.FC = ({
openIssuesListModal,
removeIssue,
disableUserActions,
+ disableAddIssueOption = false,
user,
userAuth,
viewProps,
@@ -109,14 +115,27 @@ 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");
+ icon = ;
break;
case "project":
const project = projects?.find((p) => p.id === groupTitle);
@@ -180,13 +199,15 @@ export const SingleList: React.FC = ({
{isArchivedIssues ? (
""
) : type === "issue" ? (
-
-
-
+ !disableAddIssueOption && (
+
+
+
+ )
) : disableUserActions ? (
""
) : (
diff --git a/apps/app/components/core/views/spreadsheet-view/index.ts b/web/components/core/views/spreadsheet-view/index.ts
similarity index 100%
rename from apps/app/components/core/views/spreadsheet-view/index.ts
rename to web/components/core/views/spreadsheet-view/index.ts
diff --git a/apps/app/components/core/views/spreadsheet-view/single-issue.tsx b/web/components/core/views/spreadsheet-view/single-issue.tsx
similarity index 99%
rename from apps/app/components/core/views/spreadsheet-view/single-issue.tsx
rename to web/components/core/views/spreadsheet-view/single-issue.tsx
index 53869a638..731d7f921 100644
--- a/apps/app/components/core/views/spreadsheet-view/single-issue.tsx
+++ b/web/components/core/views/spreadsheet-view/single-issue.tsx
@@ -323,7 +323,7 @@ export const SingleSpreadsheetIssue: React.FC = ({
)}
{properties.labels && (
-
+
)}
diff --git a/apps/app/components/core/views/spreadsheet-view/spreadsheet-columns.tsx b/web/components/core/views/spreadsheet-view/spreadsheet-columns.tsx
similarity index 100%
rename from apps/app/components/core/views/spreadsheet-view/spreadsheet-columns.tsx
rename to web/components/core/views/spreadsheet-view/spreadsheet-columns.tsx
diff --git a/apps/app/components/core/views/spreadsheet-view/spreadsheet-issues.tsx b/web/components/core/views/spreadsheet-view/spreadsheet-issues.tsx
similarity index 100%
rename from apps/app/components/core/views/spreadsheet-view/spreadsheet-issues.tsx
rename to web/components/core/views/spreadsheet-view/spreadsheet-issues.tsx
diff --git a/apps/app/components/core/views/spreadsheet-view/spreadsheet-view.tsx b/web/components/core/views/spreadsheet-view/spreadsheet-view.tsx
similarity index 100%
rename from apps/app/components/core/views/spreadsheet-view/spreadsheet-view.tsx
rename to web/components/core/views/spreadsheet-view/spreadsheet-view.tsx
diff --git a/apps/app/components/cycles/active-cycle-details.tsx b/web/components/cycles/active-cycle-details.tsx
similarity index 93%
rename from apps/app/components/cycles/active-cycle-details.tsx
rename to web/components/cycles/active-cycle-details.tsx
index bec200bd9..062dd57e7 100644
--- a/apps/app/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,
@@ -28,9 +28,11 @@ import {
TriangleExclamationIcon,
AlarmClockIcon,
LayerDiagonalIcon,
- CompletedStateIcon,
+ StateGroupIcon,
} from "components/icons";
import { StarIcon } from "@heroicons/react/24/outline";
+// components
+import { ViewIssueLabel } from "components/issues";
// helpers
import {
getDateRangeStatus,
@@ -383,8 +385,8 @@ export const ActiveCycleDetails: React.FC = () => {
{cycle.total_issues} issues
-
-
+
+
{cycle.completed_issues} issues
@@ -441,7 +443,10 @@ export const ActiveCycleDetails: React.FC = () => {
issues.map((issue) => (
+ router.push(`/${workspaceSlug}/projects/${projectId}/issues/${issue.id}`)
+ }
+ className="flex flex-wrap cursor-pointer rounded-md items-center justify-between gap-2 border border-custom-border-200 bg-custom-background-90 px-3 py-1.5"
>
@@ -472,29 +477,9 @@ export const ActiveCycleDetails: React.FC = () => {
: "border-orange-500/20 bg-orange-500/20 text-orange-500"
}`}
>
- {getPriorityIcon(issue.priority, "text-sm")}
+
- {issue.label_details.length > 0 ? (
-
- {issue.label_details.map((label) => (
-
-
- {label.name}
-
- ))}
-
- ) : (
- ""
- )}
+
{issue.assignees &&
issue.assignees.length > 0 &&
diff --git a/apps/app/components/cycles/active-cycle-stats.tsx b/web/components/cycles/active-cycle-stats.tsx
similarity index 100%
rename from apps/app/components/cycles/active-cycle-stats.tsx
rename to web/components/cycles/active-cycle-stats.tsx
diff --git a/apps/app/components/cycles/cycles-list/all-cycles-list.tsx b/web/components/cycles/cycles-list/all-cycles-list.tsx
similarity index 100%
rename from apps/app/components/cycles/cycles-list/all-cycles-list.tsx
rename to web/components/cycles/cycles-list/all-cycles-list.tsx
diff --git a/apps/app/components/cycles/cycles-list/completed-cycles-list.tsx b/web/components/cycles/cycles-list/completed-cycles-list.tsx
similarity index 100%
rename from apps/app/components/cycles/cycles-list/completed-cycles-list.tsx
rename to web/components/cycles/cycles-list/completed-cycles-list.tsx
diff --git a/apps/app/components/cycles/cycles-list/draft-cycles-list.tsx b/web/components/cycles/cycles-list/draft-cycles-list.tsx
similarity index 100%
rename from apps/app/components/cycles/cycles-list/draft-cycles-list.tsx
rename to web/components/cycles/cycles-list/draft-cycles-list.tsx
diff --git a/apps/app/components/cycles/cycles-list/index.ts b/web/components/cycles/cycles-list/index.ts
similarity index 100%
rename from apps/app/components/cycles/cycles-list/index.ts
rename to web/components/cycles/cycles-list/index.ts
diff --git a/apps/app/components/cycles/cycles-list/upcoming-cycles-list.tsx b/web/components/cycles/cycles-list/upcoming-cycles-list.tsx
similarity index 100%
rename from apps/app/components/cycles/cycles-list/upcoming-cycles-list.tsx
rename to web/components/cycles/cycles-list/upcoming-cycles-list.tsx
diff --git a/apps/app/components/cycles/cycles-view.tsx b/web/components/cycles/cycles-view.tsx
similarity index 100%
rename from apps/app/components/cycles/cycles-view.tsx
rename to web/components/cycles/cycles-view.tsx
diff --git a/apps/app/components/cycles/delete-cycle-modal.tsx b/web/components/cycles/delete-cycle-modal.tsx
similarity index 100%
rename from apps/app/components/cycles/delete-cycle-modal.tsx
rename to web/components/cycles/delete-cycle-modal.tsx
diff --git a/apps/app/components/cycles/form.tsx b/web/components/cycles/form.tsx
similarity index 100%
rename from apps/app/components/cycles/form.tsx
rename to web/components/cycles/form.tsx
diff --git a/apps/app/components/cycles/gantt-chart/blocks.tsx b/web/components/cycles/gantt-chart/blocks.tsx
similarity index 100%
rename from apps/app/components/cycles/gantt-chart/blocks.tsx
rename to web/components/cycles/gantt-chart/blocks.tsx
diff --git a/apps/app/components/cycles/gantt-chart/cycle-issues-layout.tsx b/web/components/cycles/gantt-chart/cycle-issues-layout.tsx
similarity index 78%
rename from apps/app/components/cycles/gantt-chart/cycle-issues-layout.tsx
rename to web/components/cycles/gantt-chart/cycle-issues-layout.tsx
index 7741432ce..c18bc9346 100644
--- a/apps/app/components/cycles/gantt-chart/cycle-issues-layout.tsx
+++ b/web/components/cycles/gantt-chart/cycle-issues-layout.tsx
@@ -5,6 +5,7 @@ import useIssuesView from "hooks/use-issues-view";
import useUser from "hooks/use-user";
import useGanttChartCycleIssues from "hooks/gantt-chart/cycle-issues-view";
import { updateGanttIssue } from "components/gantt-chart/hooks/block-update";
+import useProjectDetails from "hooks/use-project-details";
// components
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
@@ -18,6 +19,7 @@ export const CycleIssuesGanttChartView = () => {
const { orderBy } = useIssuesView();
const { user } = useUser();
+ const { projectDetails } = useProjectDetails();
const { ganttIssues, mutateGanttIssues } = useGanttChartCycleIssues(
workspaceSlug as string,
@@ -25,6 +27,8 @@ export const CycleIssuesGanttChartView = () => {
cycleId as string
);
+ const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
+
return (
{
}
SidebarBlockRender={IssueGanttSidebarBlock}
BlockRender={IssueGanttBlock}
- enableReorder={orderBy === "sort_order"}
+ enableBlockLeftResize={isAllowed}
+ enableBlockRightResize={isAllowed}
+ enableBlockMove={isAllowed}
+ enableReorder={orderBy === "sort_order" && isAllowed}
bottomSpacing
/>
diff --git a/apps/app/components/cycles/gantt-chart/cycles-list-layout.tsx b/web/components/cycles/gantt-chart/cycles-list-layout.tsx
similarity index 87%
rename from apps/app/components/cycles/gantt-chart/cycles-list-layout.tsx
rename to web/components/cycles/gantt-chart/cycles-list-layout.tsx
index a5b576bca..41e7a5444 100644
--- a/apps/app/components/cycles/gantt-chart/cycles-list-layout.tsx
+++ b/web/components/cycles/gantt-chart/cycles-list-layout.tsx
@@ -8,6 +8,7 @@ import { KeyedMutator } from "swr";
import cyclesService from "services/cycles.service";
// hooks
import useUser from "hooks/use-user";
+import useProjectDetails from "hooks/use-project-details";
// components
import { GanttChartRoot, IBlockUpdateData } from "components/gantt-chart";
import { CycleGanttBlock, CycleGanttSidebarBlock } from "components/cycles";
@@ -24,6 +25,7 @@ export const CyclesListGanttChartView: FC
= ({ cycles, mutateCycles }) =>
const { workspaceSlug } = router.query;
const { user } = useUser();
+ const { projectDetails } = useProjectDetails();
const handleCycleUpdate = (cycle: ICycle, payload: IBlockUpdateData) => {
if (!workspaceSlug || !user) return;
@@ -61,7 +63,9 @@ export const CyclesListGanttChartView: FC = ({ cycles, mutateCycles }) =>
const blockFormat = (blocks: ICycle[]) =>
blocks && blocks.length > 0
? blocks
- .filter((b) => b.start_date && b.end_date)
+ .filter(
+ (b) => b.start_date && b.end_date && new Date(b.start_date) <= new Date(b.end_date)
+ )
.map((block) => ({
data: block,
id: block.id,
@@ -71,6 +75,8 @@ export const CyclesListGanttChartView: FC = ({ cycles, mutateCycles }) =>
}))
: [];
+ const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
+
return (
= ({ cycles, mutateCycles }) =>
enableBlockLeftResize={false}
enableBlockRightResize={false}
enableBlockMove={false}
+ enableReorder={isAllowed}
/>
);
diff --git a/apps/app/components/cycles/gantt-chart/index.ts b/web/components/cycles/gantt-chart/index.ts
similarity index 100%
rename from apps/app/components/cycles/gantt-chart/index.ts
rename to web/components/cycles/gantt-chart/index.ts
diff --git a/apps/app/components/cycles/index.ts b/web/components/cycles/index.ts
similarity index 100%
rename from apps/app/components/cycles/index.ts
rename to web/components/cycles/index.ts
diff --git a/apps/app/components/cycles/modal.tsx b/web/components/cycles/modal.tsx
similarity index 100%
rename from apps/app/components/cycles/modal.tsx
rename to web/components/cycles/modal.tsx
diff --git a/apps/app/components/cycles/select.tsx b/web/components/cycles/select.tsx
similarity index 100%
rename from apps/app/components/cycles/select.tsx
rename to web/components/cycles/select.tsx
diff --git a/apps/app/components/cycles/sidebar.tsx b/web/components/cycles/sidebar.tsx
similarity index 100%
rename from apps/app/components/cycles/sidebar.tsx
rename to web/components/cycles/sidebar.tsx
diff --git a/apps/app/components/cycles/single-cycle-card.tsx b/web/components/cycles/single-cycle-card.tsx
similarity index 100%
rename from apps/app/components/cycles/single-cycle-card.tsx
rename to web/components/cycles/single-cycle-card.tsx
diff --git a/apps/app/components/cycles/single-cycle-list.tsx b/web/components/cycles/single-cycle-list.tsx
similarity index 100%
rename from apps/app/components/cycles/single-cycle-list.tsx
rename to web/components/cycles/single-cycle-list.tsx
diff --git a/apps/app/components/cycles/transfer-issues-modal.tsx b/web/components/cycles/transfer-issues-modal.tsx
similarity index 100%
rename from apps/app/components/cycles/transfer-issues-modal.tsx
rename to web/components/cycles/transfer-issues-modal.tsx
diff --git a/apps/app/components/cycles/transfer-issues.tsx b/web/components/cycles/transfer-issues.tsx
similarity index 100%
rename from apps/app/components/cycles/transfer-issues.tsx
rename to web/components/cycles/transfer-issues.tsx
diff --git a/apps/app/components/dnd/StrictModeDroppable.tsx b/web/components/dnd/StrictModeDroppable.tsx
similarity index 100%
rename from apps/app/components/dnd/StrictModeDroppable.tsx
rename to web/components/dnd/StrictModeDroppable.tsx
diff --git a/apps/app/components/emoji-icon-picker/emojis.json b/web/components/emoji-icon-picker/emojis.json
similarity index 100%
rename from apps/app/components/emoji-icon-picker/emojis.json
rename to web/components/emoji-icon-picker/emojis.json
diff --git a/apps/app/components/emoji-icon-picker/helpers.ts b/web/components/emoji-icon-picker/helpers.ts
similarity index 100%
rename from apps/app/components/emoji-icon-picker/helpers.ts
rename to web/components/emoji-icon-picker/helpers.ts
diff --git a/apps/app/components/emoji-icon-picker/icons.json b/web/components/emoji-icon-picker/icons.json
similarity index 100%
rename from apps/app/components/emoji-icon-picker/icons.json
rename to web/components/emoji-icon-picker/icons.json
diff --git a/apps/app/components/emoji-icon-picker/index.tsx b/web/components/emoji-icon-picker/index.tsx
similarity index 96%
rename from apps/app/components/emoji-icon-picker/index.tsx
rename to web/components/emoji-icon-picker/index.tsx
index ffe8b33d6..7af3bb74f 100644
--- a/apps/app/components/emoji-icon-picker/index.tsx
+++ b/web/components/emoji-icon-picker/index.tsx
@@ -23,7 +23,13 @@ const tabOptions = [
},
];
-const EmojiIconPicker: React.FC = ({ label, value, onChange, onIconColorChange }) => {
+const EmojiIconPicker: React.FC = ({
+ label,
+ value,
+ onChange,
+ onIconColorChange,
+ disabled = false,
+}) => {
const [isOpen, setIsOpen] = useState(false);
const [openColorPicker, setOpenColorPicker] = useState(false);
const [activeColor, setActiveColor] = useState("rgb(var(--color-text-200))");
@@ -40,7 +46,11 @@ const EmojiIconPicker: React.FC = ({ label, value, onChange, onIconColorC
return (
- setIsOpen((prev) => !prev)} className="outline-none">
+ setIsOpen((prev) => !prev)}
+ className="outline-none"
+ disabled={disabled}
+ >
{label}
void;
onIconColorChange?: (data: any) => void;
+ disabled?: boolean;
};
diff --git a/apps/app/components/estimates/create-update-estimate-modal.tsx b/web/components/estimates/create-update-estimate-modal.tsx
similarity index 100%
rename from apps/app/components/estimates/create-update-estimate-modal.tsx
rename to web/components/estimates/create-update-estimate-modal.tsx
diff --git a/apps/app/components/estimates/delete-estimate-modal.tsx b/web/components/estimates/delete-estimate-modal.tsx
similarity index 100%
rename from apps/app/components/estimates/delete-estimate-modal.tsx
rename to web/components/estimates/delete-estimate-modal.tsx
diff --git a/apps/app/components/estimates/index.tsx b/web/components/estimates/index.tsx
similarity index 100%
rename from apps/app/components/estimates/index.tsx
rename to web/components/estimates/index.tsx
diff --git a/apps/app/components/estimates/single-estimate.tsx b/web/components/estimates/single-estimate.tsx
similarity index 100%
rename from apps/app/components/estimates/single-estimate.tsx
rename to web/components/estimates/single-estimate.tsx
diff --git a/apps/app/components/exporter/export-modal.tsx b/web/components/exporter/export-modal.tsx
similarity index 100%
rename from apps/app/components/exporter/export-modal.tsx
rename to web/components/exporter/export-modal.tsx
diff --git a/apps/app/components/exporter/guide.tsx b/web/components/exporter/guide.tsx
similarity index 98%
rename from apps/app/components/exporter/guide.tsx
rename to web/components/exporter/guide.tsx
index dd6fab9dc..67b7c6d4d 100644
--- a/apps/app/components/exporter/guide.tsx
+++ b/web/components/exporter/guide.tsx
@@ -41,7 +41,7 @@ const IntegrationGuide = () => {
);
const handleCsvClose = () => {
- router.replace(`/plane/settings/exports`);
+ router.replace(`/${workspaceSlug?.toString()}/settings/exports`);
};
return (
diff --git a/apps/app/components/exporter/index.tsx b/web/components/exporter/index.tsx
similarity index 100%
rename from apps/app/components/exporter/index.tsx
rename to web/components/exporter/index.tsx
diff --git a/apps/app/components/exporter/single-export.tsx b/web/components/exporter/single-export.tsx
similarity index 100%
rename from apps/app/components/exporter/single-export.tsx
rename to web/components/exporter/single-export.tsx
diff --git a/apps/app/components/gantt-chart/blocks/blocks-display.tsx b/web/components/gantt-chart/blocks/blocks-display.tsx
similarity index 100%
rename from apps/app/components/gantt-chart/blocks/blocks-display.tsx
rename to web/components/gantt-chart/blocks/blocks-display.tsx
diff --git a/apps/app/components/gantt-chart/blocks/index.ts b/web/components/gantt-chart/blocks/index.ts
similarity index 100%
rename from apps/app/components/gantt-chart/blocks/index.ts
rename to web/components/gantt-chart/blocks/index.ts
diff --git a/apps/app/components/gantt-chart/chart/bi-week.tsx b/web/components/gantt-chart/chart/bi-week.tsx
similarity index 100%
rename from apps/app/components/gantt-chart/chart/bi-week.tsx
rename to web/components/gantt-chart/chart/bi-week.tsx
diff --git a/apps/app/components/gantt-chart/chart/day.tsx b/web/components/gantt-chart/chart/day.tsx
similarity index 100%
rename from apps/app/components/gantt-chart/chart/day.tsx
rename to web/components/gantt-chart/chart/day.tsx
diff --git a/apps/app/components/gantt-chart/chart/hours.tsx b/web/components/gantt-chart/chart/hours.tsx
similarity index 100%
rename from apps/app/components/gantt-chart/chart/hours.tsx
rename to web/components/gantt-chart/chart/hours.tsx
diff --git a/apps/app/components/gantt-chart/chart/index.tsx b/web/components/gantt-chart/chart/index.tsx
similarity index 100%
rename from apps/app/components/gantt-chart/chart/index.tsx
rename to web/components/gantt-chart/chart/index.tsx
diff --git a/apps/app/components/gantt-chart/chart/month.tsx b/web/components/gantt-chart/chart/month.tsx
similarity index 100%
rename from apps/app/components/gantt-chart/chart/month.tsx
rename to web/components/gantt-chart/chart/month.tsx
diff --git a/apps/app/components/gantt-chart/chart/quarter.tsx b/web/components/gantt-chart/chart/quarter.tsx
similarity index 100%
rename from apps/app/components/gantt-chart/chart/quarter.tsx
rename to web/components/gantt-chart/chart/quarter.tsx
diff --git a/apps/app/components/gantt-chart/chart/week.tsx b/web/components/gantt-chart/chart/week.tsx
similarity index 100%
rename from apps/app/components/gantt-chart/chart/week.tsx
rename to web/components/gantt-chart/chart/week.tsx
diff --git a/apps/app/components/gantt-chart/chart/year.tsx b/web/components/gantt-chart/chart/year.tsx
similarity index 100%
rename from apps/app/components/gantt-chart/chart/year.tsx
rename to web/components/gantt-chart/chart/year.tsx
diff --git a/apps/app/components/gantt-chart/contexts/index.tsx b/web/components/gantt-chart/contexts/index.tsx
similarity index 100%
rename from apps/app/components/gantt-chart/contexts/index.tsx
rename to web/components/gantt-chart/contexts/index.tsx
diff --git a/apps/app/components/gantt-chart/data/index.ts b/web/components/gantt-chart/data/index.ts
similarity index 100%
rename from apps/app/components/gantt-chart/data/index.ts
rename to web/components/gantt-chart/data/index.ts
diff --git a/web/components/gantt-chart/helpers/block-structure.tsx b/web/components/gantt-chart/helpers/block-structure.tsx
new file mode 100644
index 000000000..ea51c3b12
--- /dev/null
+++ b/web/components/gantt-chart/helpers/block-structure.tsx
@@ -0,0 +1,16 @@
+// types
+import { IIssue } from "types";
+import { IGanttBlock } from "components/gantt-chart";
+
+export const renderIssueBlocksStructure = (blocks: IIssue[]): IGanttBlock[] =>
+ blocks && blocks.length > 0
+ ? blocks
+ .filter((b) => new Date(b?.start_date ?? "") <= new Date(b?.target_date ?? ""))
+ .map((block) => ({
+ data: block,
+ id: block.id,
+ sort_order: block.sort_order,
+ start_date: new Date(block.start_date ?? ""),
+ target_date: new Date(block.target_date ?? ""),
+ }))
+ : [];
diff --git a/apps/app/components/gantt-chart/helpers/draggable.tsx b/web/components/gantt-chart/helpers/draggable.tsx
similarity index 96%
rename from apps/app/components/gantt-chart/helpers/draggable.tsx
rename to web/components/gantt-chart/helpers/draggable.tsx
index 20423ff59..b665bf5d3 100644
--- a/apps/app/components/gantt-chart/helpers/draggable.tsx
+++ b/web/components/gantt-chart/helpers/draggable.tsx
@@ -73,9 +73,11 @@ export const ChartDraggable: React.FC = ({
};
// handle block resize from the left end
- const handleBlockLeftResize = () => {
+ const handleBlockLeftResize = (e: React.MouseEvent) => {
if (!currentViewData || !resizableRef.current || !block.position) return;
+ if (e.button !== 0) return;
+
const resizableDiv = resizableRef.current;
const columnWidth = currentViewData.data.width;
@@ -126,9 +128,11 @@ export const ChartDraggable: React.FC = ({
};
// handle block resize from the right end
- const handleBlockRightResize = () => {
+ const handleBlockRightResize = (e: React.MouseEvent) => {
if (!currentViewData || !resizableRef.current || !block.position) return;
+ if (e.button !== 0) return;
+
const resizableDiv = resizableRef.current;
const columnWidth = currentViewData.data.width;
@@ -173,6 +177,8 @@ export const ChartDraggable: React.FC = ({
const handleBlockMove = (e: React.MouseEvent) => {
if (!enableBlockMove || !currentViewData || !resizableRef.current || !block.position) return;
+ if (e.button !== 0) return;
+
e.preventDefault();
e.stopPropagation();
@@ -266,7 +272,7 @@ export const ChartDraggable: React.FC = ({
{
dayData: weeks[date.getDay()],
weekNumber: getWeekNumberByDate(date),
title: `${weeks[date.getDay()].shortTitle} ${_day + 1}`,
- today: currentDate.getFullYear() === year && currentDate.getMonth() === month && currentDate.getDate() === (_day + 1) ? true : false,
+ today:
+ currentDate.getFullYear() === year &&
+ currentDate.getMonth() === month &&
+ currentDate.getDate() === _day + 1
+ ? true
+ : false,
});
});
@@ -180,7 +185,10 @@ export const generateMonthDataByYear = (
renderPayload.push(generateMonthDataByMonth(currentMonth, currentYear));
}
- const scrollWidth = ((renderPayload.map((monthData: any) => monthData.children.length)).reduce((partialSum: number, a: number) => partialSum + a, 0)) * monthPayload.data.width;
+ const scrollWidth =
+ renderPayload
+ .map((monthData: any) => monthData.children.length)
+ .reduce((partialSum: number, a: number) => partialSum + a, 0) * monthPayload.data.width;
return { state: renderState, payload: renderPayload, scrollWidth: scrollWidth };
-};
\ No newline at end of file
+};
diff --git a/apps/app/components/gantt-chart/views/helpers.ts b/web/components/gantt-chart/views/helpers.ts
similarity index 100%
rename from apps/app/components/gantt-chart/views/helpers.ts
rename to web/components/gantt-chart/views/helpers.ts
diff --git a/apps/app/components/gantt-chart/views/hours-view.ts b/web/components/gantt-chart/views/hours-view.ts
similarity index 93%
rename from apps/app/components/gantt-chart/views/hours-view.ts
rename to web/components/gantt-chart/views/hours-view.ts
index 67f369361..246ecd8b8 100644
--- a/apps/app/components/gantt-chart/views/hours-view.ts
+++ b/web/components/gantt-chart/views/hours-view.ts
@@ -72,7 +72,12 @@ export const getAllDaysInMonth = (month: number, year: number) => {
dayData: weeks[date.getDay()],
weekNumber: getWeekNumberByDate(date),
title: `${weeks[date.getDay()].shortTitle} ${_day + 1}`,
- today: currentDate.getFullYear() === year && currentDate.getMonth() === month && currentDate.getDate() === (_day + 1) ? true : false,
+ today:
+ currentDate.getFullYear() === year &&
+ currentDate.getMonth() === month &&
+ currentDate.getDate() === _day + 1
+ ? true
+ : false,
});
});
@@ -180,7 +185,10 @@ export const generateMonthDataByYear = (
renderPayload.push(generateMonthDataByMonth(currentMonth, currentYear));
}
- const scrollWidth = ((renderPayload.map((monthData: any) => monthData.children.length)).reduce((partialSum: number, a: number) => partialSum + a, 0)) * monthPayload.data.width;
+ const scrollWidth =
+ renderPayload
+ .map((monthData: any) => monthData.children.length)
+ .reduce((partialSum: number, a: number) => partialSum + a, 0) * monthPayload.data.width;
return { state: renderState, payload: renderPayload, scrollWidth: scrollWidth };
-};
\ No newline at end of file
+};
diff --git a/apps/app/components/gantt-chart/views/index.ts b/web/components/gantt-chart/views/index.ts
similarity index 100%
rename from apps/app/components/gantt-chart/views/index.ts
rename to web/components/gantt-chart/views/index.ts
diff --git a/apps/app/components/gantt-chart/views/month-view.ts b/web/components/gantt-chart/views/month-view.ts
similarity index 100%
rename from apps/app/components/gantt-chart/views/month-view.ts
rename to web/components/gantt-chart/views/month-view.ts
diff --git a/apps/app/components/gantt-chart/views/quater-view.ts b/web/components/gantt-chart/views/quater-view.ts
similarity index 100%
rename from apps/app/components/gantt-chart/views/quater-view.ts
rename to web/components/gantt-chart/views/quater-view.ts
diff --git a/apps/app/components/gantt-chart/views/week-view.ts b/web/components/gantt-chart/views/week-view.ts
similarity index 100%
rename from apps/app/components/gantt-chart/views/week-view.ts
rename to web/components/gantt-chart/views/week-view.ts
diff --git a/apps/app/components/gantt-chart/views/year-view.ts b/web/components/gantt-chart/views/year-view.ts
similarity index 100%
rename from apps/app/components/gantt-chart/views/year-view.ts
rename to web/components/gantt-chart/views/year-view.ts
diff --git a/apps/app/components/icons/alarm-clock-icon.tsx b/web/components/icons/alarm-clock-icon.tsx
similarity index 100%
rename from apps/app/components/icons/alarm-clock-icon.tsx
rename to web/components/icons/alarm-clock-icon.tsx
diff --git a/apps/app/components/icons/archive-icon.tsx b/web/components/icons/archive-icon.tsx
similarity index 100%
rename from apps/app/components/icons/archive-icon.tsx
rename to web/components/icons/archive-icon.tsx
diff --git a/apps/app/components/icons/arrow-right.tsx b/web/components/icons/arrow-right.tsx
similarity index 100%
rename from apps/app/components/icons/arrow-right.tsx
rename to web/components/icons/arrow-right.tsx
diff --git a/apps/app/components/icons/assignment-clipboard-icon.tsx b/web/components/icons/assignment-clipboard-icon.tsx
similarity index 100%
rename from apps/app/components/icons/assignment-clipboard-icon.tsx
rename to web/components/icons/assignment-clipboard-icon.tsx
diff --git a/apps/app/components/icons/attachment-icon.tsx b/web/components/icons/attachment-icon.tsx
similarity index 100%
rename from apps/app/components/icons/attachment-icon.tsx
rename to web/components/icons/attachment-icon.tsx
diff --git a/apps/app/components/icons/audio-file-icon.tsx b/web/components/icons/audio-file-icon.tsx
similarity index 78%
rename from apps/app/components/icons/audio-file-icon.tsx
rename to web/components/icons/audio-file-icon.tsx
index 6aff5d7a4..24ea55a23 100644
--- a/apps/app/components/icons/audio-file-icon.tsx
+++ b/web/components/icons/audio-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import AudioFileIcon from "public/attachment/audio-icon.png";
-export const AudioIcon: React.FC
= ({ width, height }) => (
+export const AudioIcon: React.FC = ({ width, height }) => (
);
diff --git a/apps/app/components/icons/bell-icon.tsx b/web/components/icons/bell-icon.tsx
similarity index 100%
rename from apps/app/components/icons/bell-icon.tsx
rename to web/components/icons/bell-icon.tsx
diff --git a/web/components/icons/blocked-icon.tsx b/web/components/icons/blocked-icon.tsx
new file mode 100644
index 000000000..b712f7698
--- /dev/null
+++ b/web/components/icons/blocked-icon.tsx
@@ -0,0 +1,25 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const BlockedIcon: React.FC = ({ width = "24", height = "24", className }) => (
+
+
+
+
+);
diff --git a/web/components/icons/blocker-icon.tsx b/web/components/icons/blocker-icon.tsx
new file mode 100644
index 000000000..b92fadaea
--- /dev/null
+++ b/web/components/icons/blocker-icon.tsx
@@ -0,0 +1,25 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const BlockerIcon: React.FC = ({ width = "24", height = "24", className }) => (
+
+
+
+
+);
diff --git a/web/components/icons/bolt-icon.tsx b/web/components/icons/bolt-icon.tsx
new file mode 100644
index 000000000..477d4e04e
--- /dev/null
+++ b/web/components/icons/bolt-icon.tsx
@@ -0,0 +1,16 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const BoltIcon: React.FC = ({ width = "24", height = "24", className }) => (
+
+
+
+);
diff --git a/apps/app/components/icons/calendar-after-icon.tsx b/web/components/icons/calendar-after-icon.tsx
similarity index 100%
rename from apps/app/components/icons/calendar-after-icon.tsx
rename to web/components/icons/calendar-after-icon.tsx
diff --git a/apps/app/components/icons/calendar-before-icon.tsx b/web/components/icons/calendar-before-icon.tsx
similarity index 100%
rename from apps/app/components/icons/calendar-before-icon.tsx
rename to web/components/icons/calendar-before-icon.tsx
diff --git a/apps/app/components/icons/calendar-month-icon.tsx b/web/components/icons/calendar-month-icon.tsx
similarity index 100%
rename from apps/app/components/icons/calendar-month-icon.tsx
rename to web/components/icons/calendar-month-icon.tsx
diff --git a/web/components/icons/cancel-icon.tsx b/web/components/icons/cancel-icon.tsx
new file mode 100644
index 000000000..a57425de1
--- /dev/null
+++ b/web/components/icons/cancel-icon.tsx
@@ -0,0 +1,16 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const CancelIcon: React.FC = ({ width, height, className }) => (
+
+
+
+);
diff --git a/apps/app/components/icons/check.tsx b/web/components/icons/check.tsx
similarity index 100%
rename from apps/app/components/icons/check.tsx
rename to web/components/icons/check.tsx
diff --git a/web/components/icons/clipboard-icon.tsx b/web/components/icons/clipboard-icon.tsx
new file mode 100644
index 000000000..a3feaf7af
--- /dev/null
+++ b/web/components/icons/clipboard-icon.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const ClipboardIcon: React.FC = ({ width = "24", height = "24", className }) => (
+
+
+
+);
diff --git a/apps/app/components/icons/clock-icon.tsx b/web/components/icons/clock-icon.tsx
similarity index 100%
rename from apps/app/components/icons/clock-icon.tsx
rename to web/components/icons/clock-icon.tsx
diff --git a/apps/app/components/icons/cloud-upload.tsx b/web/components/icons/cloud-upload.tsx
similarity index 100%
rename from apps/app/components/icons/cloud-upload.tsx
rename to web/components/icons/cloud-upload.tsx
diff --git a/apps/app/components/icons/cmd-icon.tsx b/web/components/icons/cmd-icon.tsx
similarity index 100%
rename from apps/app/components/icons/cmd-icon.tsx
rename to web/components/icons/cmd-icon.tsx
diff --git a/apps/app/components/icons/cog.tsx b/web/components/icons/cog.tsx
similarity index 100%
rename from apps/app/components/icons/cog.tsx
rename to web/components/icons/cog.tsx
diff --git a/apps/app/components/icons/color-pallette-icon.tsx b/web/components/icons/color-pallette-icon.tsx
similarity index 100%
rename from apps/app/components/icons/color-pallette-icon.tsx
rename to web/components/icons/color-pallette-icon.tsx
diff --git a/apps/app/components/icons/color-picker-icon.tsx b/web/components/icons/color-picker-icon.tsx
similarity index 100%
rename from apps/app/components/icons/color-picker-icon.tsx
rename to web/components/icons/color-picker-icon.tsx
diff --git a/apps/app/components/icons/command-icon.tsx b/web/components/icons/command-icon.tsx
similarity index 100%
rename from apps/app/components/icons/command-icon.tsx
rename to web/components/icons/command-icon.tsx
diff --git a/web/components/icons/comment-icon.tsx b/web/components/icons/comment-icon.tsx
new file mode 100644
index 000000000..8619abd34
--- /dev/null
+++ b/web/components/icons/comment-icon.tsx
@@ -0,0 +1,16 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const CommentIcon: React.FC = ({ width = "24", height = "24", className }) => (
+
+
+
+);
diff --git a/web/components/icons/completed-cycle-icon.tsx b/web/components/icons/completed-cycle-icon.tsx
new file mode 100644
index 000000000..77d30b24b
--- /dev/null
+++ b/web/components/icons/completed-cycle-icon.tsx
@@ -0,0 +1,17 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const CompletedCycleIcon: React.FC = ({
+ width = "24",
+ height = "24",
+ className,
+ color = "black",
+}) => (
+
+
+
+);
diff --git a/apps/app/components/icons/contrast-icon.tsx b/web/components/icons/contrast-icon.tsx
similarity index 100%
rename from apps/app/components/icons/contrast-icon.tsx
rename to web/components/icons/contrast-icon.tsx
diff --git a/apps/app/components/icons/css-file-icon.tsx b/web/components/icons/css-file-icon.tsx
similarity index 78%
rename from apps/app/components/icons/css-file-icon.tsx
rename to web/components/icons/css-file-icon.tsx
index 54b563d37..a753ead73 100644
--- a/apps/app/components/icons/css-file-icon.tsx
+++ b/web/components/icons/css-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import CssFileIcon from "public/attachment/css-icon.png";
-export const CssIcon: React.FC = ({ width, height }) => (
+export const CssIcon: React.FC = ({ width, height }) => (
);
diff --git a/apps/app/components/icons/csv-file-icon.tsx b/web/components/icons/csv-file-icon.tsx
similarity index 78%
rename from apps/app/components/icons/csv-file-icon.tsx
rename to web/components/icons/csv-file-icon.tsx
index 63f01205e..d25aca262 100644
--- a/apps/app/components/icons/csv-file-icon.tsx
+++ b/web/components/icons/csv-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import CSVFileIcon from "public/attachment/csv-icon.png";
-export const CsvIcon: React.FC = ({ width , height }) => (
+export const CsvIcon: React.FC = ({ width, height }) => (
);
diff --git a/web/components/icons/current-cycle-icon.tsx b/web/components/icons/current-cycle-icon.tsx
new file mode 100644
index 000000000..57b376780
--- /dev/null
+++ b/web/components/icons/current-cycle-icon.tsx
@@ -0,0 +1,17 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const CurrentCycleIcon: React.FC = ({
+ width = "24",
+ height = "24",
+ className,
+ color = "black",
+}) => (
+
+
+
+);
diff --git a/apps/app/components/icons/cycle-icon.tsx b/web/components/icons/cycle-icon.tsx
similarity index 100%
rename from apps/app/components/icons/cycle-icon.tsx
rename to web/components/icons/cycle-icon.tsx
diff --git a/apps/app/components/icons/default-file-icon.tsx b/web/components/icons/default-file-icon.tsx
similarity index 78%
rename from apps/app/components/icons/default-file-icon.tsx
rename to web/components/icons/default-file-icon.tsx
index 5323d8e07..3bc1948e3 100644
--- a/apps/app/components/icons/default-file-icon.tsx
+++ b/web/components/icons/default-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import DefaultFileIcon from "public/attachment/default-icon.png";
-export const DefaultIcon: React.FC = ({ width, height }) => (
+export const DefaultIcon: React.FC = ({ width, height }) => (
);
diff --git a/apps/app/components/icons/discord-icon.tsx b/web/components/icons/discord-icon.tsx
similarity index 100%
rename from apps/app/components/icons/discord-icon.tsx
rename to web/components/icons/discord-icon.tsx
diff --git a/apps/app/components/icons/doc-file-icon.tsx b/web/components/icons/doc-file-icon.tsx
similarity index 78%
rename from apps/app/components/icons/doc-file-icon.tsx
rename to web/components/icons/doc-file-icon.tsx
index 173d40df1..a4367ef7c 100644
--- a/apps/app/components/icons/doc-file-icon.tsx
+++ b/web/components/icons/doc-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import DocFileIcon from "public/attachment/doc-icon.png";
-export const DocIcon: React.FC = ({ width , height }) => (
+export const DocIcon: React.FC = ({ width, height }) => (
);
diff --git a/apps/app/components/icons/document-icon.tsx b/web/components/icons/document-icon.tsx
similarity index 82%
rename from apps/app/components/icons/document-icon.tsx
rename to web/components/icons/document-icon.tsx
index a9c599578..b84dd4c39 100644
--- a/apps/app/components/icons/document-icon.tsx
+++ b/web/components/icons/document-icon.tsx
@@ -2,17 +2,23 @@ import React from "react";
import type { Props } from "./types";
-export const DocumentIcon: React.FC = ({ width = "24", height = "24", className, color }) => (
-
+export const DocumentIcon: React.FC = ({
+ width = "24",
+ height = "24",
+ className,
+ color,
+}) => (
+
-
- );
+ d="M7.27051 14.792H12.7288C12.9094 14.792 13.0587 14.733 13.1768 14.6149C13.2948 14.4969 13.3538 14.3475 13.3538 14.167C13.3538 13.9864 13.2948 13.8371 13.1768 13.7191C13.0587 13.601 12.9094 13.542 12.7288 13.542H7.27051C7.08995 13.542 6.94065 13.601 6.82259 13.7191C6.70454 13.8371 6.64551 13.9864 6.64551 14.167C6.64551 14.3475 6.70454 14.4969 6.82259 14.6149C6.94065 14.733 7.08995 14.792 7.27051 14.792ZM7.27051 11.2503H12.7288C12.9094 11.2503 13.0587 11.1913 13.1768 11.0732C13.2948 10.9552 13.3538 10.8059 13.3538 10.6253C13.3538 10.4448 13.2948 10.2955 13.1768 10.1774C13.0587 10.0594 12.9094 10.0003 12.7288 10.0003H7.27051C7.08995 10.0003 6.94065 10.0594 6.82259 10.1774C6.70454 10.2955 6.64551 10.4448 6.64551 10.6253C6.64551 10.8059 6.70454 10.9552 6.82259 11.0732C6.94065 11.1913 7.08995 11.2503 7.27051 11.2503ZM4.58301 18.3337C4.24967 18.3337 3.95801 18.2087 3.70801 17.9587C3.45801 17.7087 3.33301 17.417 3.33301 17.0837V2.91699C3.33301 2.58366 3.45801 2.29199 3.70801 2.04199C3.95801 1.79199 4.24967 1.66699 4.58301 1.66699H11.583C11.7497 1.66699 11.9129 1.70171 12.0726 1.77116C12.2323 1.8406 12.3677 1.93088 12.4788 2.04199L16.2913 5.85449C16.4025 5.9656 16.4927 6.10102 16.5622 6.26074C16.6316 6.42046 16.6663 6.58366 16.6663 6.75033V17.0837C16.6663 17.417 16.5413 17.7087 16.2913 17.9587C16.0413 18.2087 15.7497 18.3337 15.4163 18.3337H4.58301ZM11.4788 6.16699V2.91699H4.58301V17.0837H15.4163V6.79199H12.1038C11.9233 6.79199 11.774 6.73296 11.6559 6.61491C11.5379 6.49685 11.4788 6.34755 11.4788 6.16699ZM4.58301 2.91699V6.79199V2.91699V17.0837V2.91699Z"
+ />
+
+);
diff --git a/web/components/icons/edit-icon.tsx b/web/components/icons/edit-icon.tsx
new file mode 100644
index 000000000..6b1ea2785
--- /dev/null
+++ b/web/components/icons/edit-icon.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const EditIcon: React.FC = ({ width, height, className }) => (
+
+
+
+);
diff --git a/web/components/icons/ellipsis-horizontal-icon.tsx b/web/components/icons/ellipsis-horizontal-icon.tsx
new file mode 100644
index 000000000..26979f9a5
--- /dev/null
+++ b/web/components/icons/ellipsis-horizontal-icon.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const EllipsisHorizontalIcon: React.FC = ({ width, height, className }) => (
+
+
+
+);
diff --git a/apps/app/components/icons/exclamation-icon.tsx b/web/components/icons/exclamation-icon.tsx
similarity index 100%
rename from apps/app/components/icons/exclamation-icon.tsx
rename to web/components/icons/exclamation-icon.tsx
diff --git a/apps/app/components/icons/external-link-icon.tsx b/web/components/icons/external-link-icon.tsx
similarity index 100%
rename from apps/app/components/icons/external-link-icon.tsx
rename to web/components/icons/external-link-icon.tsx
diff --git a/apps/app/components/icons/figma-file-icon.tsx b/web/components/icons/figma-file-icon.tsx
similarity index 78%
rename from apps/app/components/icons/figma-file-icon.tsx
rename to web/components/icons/figma-file-icon.tsx
index 7ff9f6ac0..fc7b74f73 100644
--- a/apps/app/components/icons/figma-file-icon.tsx
+++ b/web/components/icons/figma-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import FigmaFileIcon from "public/attachment/figma-icon.png";
-export const FigmaIcon: React.FC = ({ width , height }) => (
+export const FigmaIcon: React.FC = ({ width, height }) => (
);
diff --git a/apps/app/components/icons/github-icon.tsx b/web/components/icons/github-icon.tsx
similarity index 100%
rename from apps/app/components/icons/github-icon.tsx
rename to web/components/icons/github-icon.tsx
diff --git a/apps/app/components/icons/grid-view-icons.tsx b/web/components/icons/grid-view-icons.tsx
similarity index 100%
rename from apps/app/components/icons/grid-view-icons.tsx
rename to web/components/icons/grid-view-icons.tsx
diff --git a/apps/app/components/icons/heartbeat-icon.tsx b/web/components/icons/heartbeat-icon.tsx
similarity index 100%
rename from apps/app/components/icons/heartbeat-icon.tsx
rename to web/components/icons/heartbeat-icon.tsx
diff --git a/apps/app/components/icons/html-file-icon.tsx b/web/components/icons/html-file-icon.tsx
similarity index 78%
rename from apps/app/components/icons/html-file-icon.tsx
rename to web/components/icons/html-file-icon.tsx
index 9de4080b0..4eddb323b 100644
--- a/apps/app/components/icons/html-file-icon.tsx
+++ b/web/components/icons/html-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import HtmlFileIcon from "public/attachment/html-icon.png";
-export const HtmlIcon: React.FC = ({ width, height }) => (
+export const HtmlIcon: React.FC = ({ width, height }) => (
);
diff --git a/apps/app/components/icons/img-file-icon.tsx b/web/components/icons/img-file-icon.tsx
similarity index 78%
rename from apps/app/components/icons/img-file-icon.tsx
rename to web/components/icons/img-file-icon.tsx
index 1333957c1..0c58fa101 100644
--- a/apps/app/components/icons/img-file-icon.tsx
+++ b/web/components/icons/img-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import ImgFileIcon from "public/attachment/img-icon.png";
-export const ImgIcon: React.FC = ({ width , height }) => (
+export const ImgIcon: React.FC = ({ width, height }) => (
);
diff --git a/apps/app/components/icons/import-layers.tsx b/web/components/icons/import-layers.tsx
similarity index 100%
rename from apps/app/components/icons/import-layers.tsx
rename to web/components/icons/import-layers.tsx
diff --git a/apps/app/components/icons/inbox-icon.tsx b/web/components/icons/inbox-icon.tsx
similarity index 100%
rename from apps/app/components/icons/inbox-icon.tsx
rename to web/components/icons/inbox-icon.tsx
diff --git a/apps/app/components/icons/index.ts b/web/components/icons/index.ts
similarity index 91%
rename from apps/app/components/icons/index.ts
rename to web/components/icons/index.ts
index d3b311e40..d3be7f2a8 100644
--- a/apps/app/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/apps/app/components/icons/jpg-file-icon.tsx b/web/components/icons/jpg-file-icon.tsx
similarity index 78%
rename from apps/app/components/icons/jpg-file-icon.tsx
rename to web/components/icons/jpg-file-icon.tsx
index e88f0e47f..26d3af373 100644
--- a/apps/app/components/icons/jpg-file-icon.tsx
+++ b/web/components/icons/jpg-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import JpgFileIcon from "public/attachment/jpg-icon.png";
-export const JpgIcon: React.FC = ({ width, height }) => (
+export const JpgIcon: React.FC = ({ width, height }) => (
);
diff --git a/apps/app/components/icons/js-file-icon.tsx b/web/components/icons/js-file-icon.tsx
similarity index 97%
rename from apps/app/components/icons/js-file-icon.tsx
rename to web/components/icons/js-file-icon.tsx
index 9f879ba6b..67cfa05d4 100644
--- a/apps/app/components/icons/js-file-icon.tsx
+++ b/web/components/icons/js-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import JsFileIcon from "public/attachment/js-icon.png";
-export const JavaScriptIcon: React.FC = ({ width, height }) => (
+export const JavaScriptIcon: React.FC = ({ width, height }) => (
);
diff --git a/apps/app/components/icons/layer-diagonal-icon.tsx b/web/components/icons/layer-diagonal-icon.tsx
similarity index 100%
rename from apps/app/components/icons/layer-diagonal-icon.tsx
rename to web/components/icons/layer-diagonal-icon.tsx
diff --git a/web/components/icons/lock-icon.tsx b/web/components/icons/lock-icon.tsx
new file mode 100644
index 000000000..2892011df
--- /dev/null
+++ b/web/components/icons/lock-icon.tsx
@@ -0,0 +1,16 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const LockIcon: React.FC = ({ width = "24", height = "24", className }) => (
+
+
+
+);
diff --git a/web/components/icons/menu-icon.tsx b/web/components/icons/menu-icon.tsx
new file mode 100644
index 000000000..3b5e033d8
--- /dev/null
+++ b/web/components/icons/menu-icon.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const MenuIcon: React.FC = ({ width = "24", height = "24", className }) => (
+
+
+
+);
diff --git a/apps/app/components/icons/module/backlog.tsx b/web/components/icons/module/backlog.tsx
similarity index 100%
rename from apps/app/components/icons/module/backlog.tsx
rename to web/components/icons/module/backlog.tsx
diff --git a/apps/app/components/icons/module/cancelled.tsx b/web/components/icons/module/cancelled.tsx
similarity index 100%
rename from apps/app/components/icons/module/cancelled.tsx
rename to web/components/icons/module/cancelled.tsx
diff --git a/apps/app/components/icons/module/completed.tsx b/web/components/icons/module/completed.tsx
similarity index 100%
rename from apps/app/components/icons/module/completed.tsx
rename to web/components/icons/module/completed.tsx
diff --git a/apps/app/components/icons/module/in-progress.tsx b/web/components/icons/module/in-progress.tsx
similarity index 100%
rename from apps/app/components/icons/module/in-progress.tsx
rename to web/components/icons/module/in-progress.tsx
diff --git a/apps/app/components/icons/module/index.ts b/web/components/icons/module/index.ts
similarity index 100%
rename from apps/app/components/icons/module/index.ts
rename to web/components/icons/module/index.ts
diff --git a/apps/app/components/icons/module/module-status-icon.tsx b/web/components/icons/module/module-status-icon.tsx
similarity index 100%
rename from apps/app/components/icons/module/module-status-icon.tsx
rename to web/components/icons/module/module-status-icon.tsx
diff --git a/apps/app/components/icons/module/paused.tsx b/web/components/icons/module/paused.tsx
similarity index 100%
rename from apps/app/components/icons/module/paused.tsx
rename to web/components/icons/module/paused.tsx
diff --git a/apps/app/components/icons/module/planned.tsx b/web/components/icons/module/planned.tsx
similarity index 100%
rename from apps/app/components/icons/module/planned.tsx
rename to web/components/icons/module/planned.tsx
diff --git a/apps/app/components/icons/pdf-file-icon.tsx b/web/components/icons/pdf-file-icon.tsx
similarity index 78%
rename from apps/app/components/icons/pdf-file-icon.tsx
rename to web/components/icons/pdf-file-icon.tsx
index 5467f0812..cb2014ee0 100644
--- a/apps/app/components/icons/pdf-file-icon.tsx
+++ b/web/components/icons/pdf-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import PDFFileIcon from "public/attachment/pdf-icon.png";
-export const PdfIcon: React.FC = ({ width , height }) => (
+export const PdfIcon: React.FC = ({ width, height }) => (
);
diff --git a/apps/app/components/icons/pencil-scribble-icon.tsx b/web/components/icons/pencil-scribble-icon.tsx
similarity index 100%
rename from apps/app/components/icons/pencil-scribble-icon.tsx
rename to web/components/icons/pencil-scribble-icon.tsx
diff --git a/apps/app/components/icons/people-group-icon.tsx b/web/components/icons/people-group-icon.tsx
similarity index 100%
rename from apps/app/components/icons/people-group-icon.tsx
rename to web/components/icons/people-group-icon.tsx
diff --git a/apps/app/components/icons/person-running-icon.tsx b/web/components/icons/person-running-icon.tsx
similarity index 100%
rename from apps/app/components/icons/person-running-icon.tsx
rename to web/components/icons/person-running-icon.tsx
diff --git a/web/components/icons/plus-icon.tsx b/web/components/icons/plus-icon.tsx
new file mode 100644
index 000000000..25489a4fd
--- /dev/null
+++ b/web/components/icons/plus-icon.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const PlusIcon: React.FC = ({ width = "24", height = "24", className }) => (
+
+
+
+);
diff --git a/apps/app/components/icons/png-file-icon.tsx b/web/components/icons/png-file-icon.tsx
similarity index 78%
rename from apps/app/components/icons/png-file-icon.tsx
rename to web/components/icons/png-file-icon.tsx
index 21b5dc116..fb64ed824 100644
--- a/apps/app/components/icons/png-file-icon.tsx
+++ b/web/components/icons/png-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import PngFileIcon from "public/attachment/png-icon.png";
-export const PngIcon: React.FC = ({ width, height }) => (
+export const PngIcon: React.FC = ({ width, height }) => (
);
diff --git a/web/components/icons/priority-icon.tsx b/web/components/icons/priority-icon.tsx
new file mode 100644
index 000000000..8473e264b
--- /dev/null
+++ b/web/components/icons/priority-icon.tsx
@@ -0,0 +1,25 @@
+// 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";
+
+ 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/icons/question-mark-circle-icon.tsx b/web/components/icons/question-mark-circle-icon.tsx
new file mode 100644
index 000000000..f4abd903f
--- /dev/null
+++ b/web/components/icons/question-mark-circle-icon.tsx
@@ -0,0 +1,20 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const QuestionMarkCircleIcon: React.FC = ({
+ width = "24",
+ height = "24",
+ className,
+}) => (
+
+
+
+);
diff --git a/apps/app/components/icons/setting-icon.tsx b/web/components/icons/setting-icon.tsx
similarity index 100%
rename from apps/app/components/icons/setting-icon.tsx
rename to web/components/icons/setting-icon.tsx
diff --git a/apps/app/components/icons/sheet-file-icon.tsx b/web/components/icons/sheet-file-icon.tsx
similarity index 78%
rename from apps/app/components/icons/sheet-file-icon.tsx
rename to web/components/icons/sheet-file-icon.tsx
index 9e57ce71c..dd4eee8ec 100644
--- a/apps/app/components/icons/sheet-file-icon.tsx
+++ b/web/components/icons/sheet-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import SheetFileIcon from "public/attachment/excel-icon.png";
-export const SheetIcon: React.FC = ({ width, height }) => (
+export const SheetIcon: React.FC = ({ width, height }) => (
);
diff --git a/web/components/icons/signal-cellular-icon.tsx b/web/components/icons/signal-cellular-icon.tsx
new file mode 100644
index 000000000..bb7d108fe
--- /dev/null
+++ b/web/components/icons/signal-cellular-icon.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const SignalCellularIcon: React.FC = ({ width = "24", height = "24", className }) => (
+
+
+
+);
diff --git a/apps/app/components/icons/single-comment-icon.tsx b/web/components/icons/single-comment-icon.tsx
similarity index 100%
rename from apps/app/components/icons/single-comment-icon.tsx
rename to web/components/icons/single-comment-icon.tsx
diff --git a/apps/app/components/icons/sort-icon.tsx b/web/components/icons/sort-icon.tsx
similarity index 100%
rename from apps/app/components/icons/sort-icon.tsx
rename to web/components/icons/sort-icon.tsx
diff --git a/apps/app/components/icons/stacked-layers-horizontal-icon.tsx b/web/components/icons/stacked-layers-horizontal-icon.tsx
similarity index 100%
rename from apps/app/components/icons/stacked-layers-horizontal-icon.tsx
rename to web/components/icons/stacked-layers-horizontal-icon.tsx
diff --git a/apps/app/components/icons/stacked-layers-icon.tsx b/web/components/icons/stacked-layers-icon.tsx
similarity index 100%
rename from apps/app/components/icons/stacked-layers-icon.tsx
rename to web/components/icons/stacked-layers-icon.tsx
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/apps/app/components/icons/svg-file-icon.tsx b/web/components/icons/svg-file-icon.tsx
similarity index 78%
rename from apps/app/components/icons/svg-file-icon.tsx
rename to web/components/icons/svg-file-icon.tsx
index d04ae3167..043f41aeb 100644
--- a/apps/app/components/icons/svg-file-icon.tsx
+++ b/web/components/icons/svg-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import SvgFileIcon from "public/attachment/svg-icon.png";
-export const SvgIcon: React.FC = ({ width, height }) => (
+export const SvgIcon: React.FC = ({ width, height }) => (
);
diff --git a/web/components/icons/tag-icon.tsx b/web/components/icons/tag-icon.tsx
new file mode 100644
index 000000000..d907aabce
--- /dev/null
+++ b/web/components/icons/tag-icon.tsx
@@ -0,0 +1,24 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const TagIcon: React.FC = ({
+ width = "24",
+ height = "24",
+ className,
+ color = "black",
+}) => (
+
+
+
+);
diff --git a/apps/app/components/icons/target-icon.tsx b/web/components/icons/target-icon.tsx
similarity index 100%
rename from apps/app/components/icons/target-icon.tsx
rename to web/components/icons/target-icon.tsx
diff --git a/apps/app/components/icons/tick-mark-icon.tsx b/web/components/icons/tick-mark-icon.tsx
similarity index 100%
rename from apps/app/components/icons/tick-mark-icon.tsx
rename to web/components/icons/tick-mark-icon.tsx
diff --git a/web/components/icons/transfer-icon.tsx b/web/components/icons/transfer-icon.tsx
new file mode 100644
index 000000000..dfb3f8c05
--- /dev/null
+++ b/web/components/icons/transfer-icon.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const TransferIcon: React.FC = ({ width, height, className, color }) => (
+
+
+
+);
diff --git a/apps/app/components/icons/triangle-exclamation-icon.tsx b/web/components/icons/triangle-exclamation-icon.tsx
similarity index 100%
rename from apps/app/components/icons/triangle-exclamation-icon.tsx
rename to web/components/icons/triangle-exclamation-icon.tsx
diff --git a/web/components/icons/tune-icon.tsx b/web/components/icons/tune-icon.tsx
new file mode 100644
index 000000000..baa2dcd72
--- /dev/null
+++ b/web/components/icons/tune-icon.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const TuneIcon: React.FC = ({ width = "24", height = "24", className }) => (
+
+
+
+);
diff --git a/apps/app/components/icons/txt-file-icon.tsx b/web/components/icons/txt-file-icon.tsx
similarity index 78%
rename from apps/app/components/icons/txt-file-icon.tsx
rename to web/components/icons/txt-file-icon.tsx
index f0150a4cd..2fbfaee32 100644
--- a/apps/app/components/icons/txt-file-icon.tsx
+++ b/web/components/icons/txt-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import TxtFileIcon from "public/attachment/txt-icon.png";
-export const TxtIcon: React.FC = ({ width, height }) => (
+export const TxtIcon: React.FC = ({ width, height }) => (
);
diff --git a/apps/app/components/icons/types.d.ts b/web/components/icons/types.d.ts
similarity index 100%
rename from apps/app/components/icons/types.d.ts
rename to web/components/icons/types.d.ts
diff --git a/web/components/icons/upcoming-cycle-icon.tsx b/web/components/icons/upcoming-cycle-icon.tsx
new file mode 100644
index 000000000..e9bad7a42
--- /dev/null
+++ b/web/components/icons/upcoming-cycle-icon.tsx
@@ -0,0 +1,17 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const UpcomingCycleIcon: React.FC = ({
+ width = "24",
+ height = "24",
+ className,
+ color = "black",
+}) => (
+
+
+
+);
diff --git a/apps/app/components/icons/user-group-icon.tsx b/web/components/icons/user-group-icon.tsx
similarity index 100%
rename from apps/app/components/icons/user-group-icon.tsx
rename to web/components/icons/user-group-icon.tsx
diff --git a/web/components/icons/user-icon-circle.tsx b/web/components/icons/user-icon-circle.tsx
new file mode 100644
index 000000000..ffc88be3b
--- /dev/null
+++ b/web/components/icons/user-icon-circle.tsx
@@ -0,0 +1,16 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const UserCircleIcon: React.FC = ({ width = "24", height = "24", className }) => (
+
+
+
+);
diff --git a/web/components/icons/user-icon.tsx b/web/components/icons/user-icon.tsx
new file mode 100644
index 000000000..dedea1bae
--- /dev/null
+++ b/web/components/icons/user-icon.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+
+import type { Props } from "./types";
+
+export const UserIcon: React.FC = ({ width = "24", height = "24", className }) => (
+
+
+
+);
diff --git a/apps/app/components/icons/users.tsx b/web/components/icons/users.tsx
similarity index 100%
rename from apps/app/components/icons/users.tsx
rename to web/components/icons/users.tsx
diff --git a/apps/app/components/icons/video-file-icon.tsx b/web/components/icons/video-file-icon.tsx
similarity index 78%
rename from apps/app/components/icons/video-file-icon.tsx
rename to web/components/icons/video-file-icon.tsx
index 8deb7a80b..961aba1e6 100644
--- a/apps/app/components/icons/video-file-icon.tsx
+++ b/web/components/icons/video-file-icon.tsx
@@ -4,6 +4,6 @@ import Image from "next/image";
import type { Props } from "./types";
import VideoFileIcon from "public/attachment/video-icon.png";
-export const VideoIcon: React.FC = ({ width, height }) => (
+export const VideoIcon: React.FC = ({ width, height }) => (
);
diff --git a/apps/app/components/icons/view-list-icon.tsx b/web/components/icons/view-list-icon.tsx
similarity index 100%
rename from apps/app/components/icons/view-list-icon.tsx
rename to web/components/icons/view-list-icon.tsx
diff --git a/apps/app/components/icons/water-drop-icon.tsx b/web/components/icons/water-drop-icon.tsx
similarity index 100%
rename from apps/app/components/icons/water-drop-icon.tsx
rename to web/components/icons/water-drop-icon.tsx
diff --git a/apps/app/components/icons/x-mark-icon.tsx b/web/components/icons/x-mark-icon.tsx
similarity index 100%
rename from apps/app/components/icons/x-mark-icon.tsx
rename to web/components/icons/x-mark-icon.tsx
diff --git a/apps/app/components/inbox/accept-issue-modal.tsx b/web/components/inbox/accept-issue-modal.tsx
similarity index 100%
rename from apps/app/components/inbox/accept-issue-modal.tsx
rename to web/components/inbox/accept-issue-modal.tsx
diff --git a/apps/app/components/inbox/decline-issue-modal.tsx b/web/components/inbox/decline-issue-modal.tsx
similarity index 100%
rename from apps/app/components/inbox/decline-issue-modal.tsx
rename to web/components/inbox/decline-issue-modal.tsx
diff --git a/apps/app/components/inbox/delete-issue-modal.tsx b/web/components/inbox/delete-issue-modal.tsx
similarity index 100%
rename from apps/app/components/inbox/delete-issue-modal.tsx
rename to web/components/inbox/delete-issue-modal.tsx
diff --git a/apps/app/components/inbox/filters-dropdown.tsx b/web/components/inbox/filters-dropdown.tsx
similarity index 95%
rename from apps/app/components/inbox/filters-dropdown.tsx
rename to web/components/inbox/filters-dropdown.tsx
index 7bb601949..9220db899 100644
--- a/apps/app/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/apps/app/components/inbox/filters-list.tsx b/web/components/inbox/filters-list.tsx
similarity index 95%
rename from apps/app/components/inbox/filters-list.tsx
rename to web/components/inbox/filters-list.tsx
index 503c4ab04..7d07fb8d4 100644
--- a/apps/app/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)}
+
+
+
= ({ issueDetails }) => {
: null
);
- const handleCommentUpdate = async (comment: IIssueComment) => {
+ const handleCommentUpdate = async (commentId: string, data: Partial) => {
if (!workspaceSlug || !projectId || !inboxIssueId) return;
await issuesService
@@ -46,8 +46,8 @@ export const InboxIssueActivity: React.FC = ({ issueDetails }) => {
workspaceSlug as string,
projectId as string,
inboxIssueId as string,
- comment.id,
- comment,
+ commentId,
+ data,
user
)
.then(() => mutateIssueActivity());
diff --git a/apps/app/components/inbox/inbox-issue-card.tsx b/web/components/inbox/inbox-issue-card.tsx
similarity index 95%
rename from apps/app/components/inbox/inbox-issue-card.tsx
rename to web/components/inbox/inbox-issue-card.tsx
index 9cc8deb76..f23a4ca6e 100644
--- a/apps/app/components/inbox/inbox-issue-card.tsx
+++ b/web/components/inbox/inbox-issue-card.tsx
@@ -4,7 +4,7 @@ import Link from "next/link";
// ui
import { Tooltip } from "components/ui";
// icons
-import { getPriorityIcon } from "components/icons";
+import { PriorityIcon } from "components/icons";
import {
CalendarDaysIcon,
CheckCircleIcon,
@@ -65,10 +65,7 @@ export const InboxIssueCard: React.FC = (props) => {
: "border-custom-border-200"
}`}
>
- {getPriorityIcon(
- issue.priority && issue.priority !== "" ? issue.priority ?? "" : "None",
- "text-sm"
- )}
+
= {
name: "",
description_html: "",
estimate_point: null,
diff --git a/apps/app/components/inbox/index.ts b/web/components/inbox/index.ts
similarity index 100%
rename from apps/app/components/inbox/index.ts
rename to web/components/inbox/index.ts
diff --git a/apps/app/components/inbox/issues-list-sidebar.tsx b/web/components/inbox/issues-list-sidebar.tsx
similarity index 100%
rename from apps/app/components/inbox/issues-list-sidebar.tsx
rename to web/components/inbox/issues-list-sidebar.tsx
diff --git a/apps/app/components/inbox/select-duplicate.tsx b/web/components/inbox/select-duplicate.tsx
similarity index 100%
rename from apps/app/components/inbox/select-duplicate.tsx
rename to web/components/inbox/select-duplicate.tsx
diff --git a/apps/app/components/integration/delete-import-modal.tsx b/web/components/integration/delete-import-modal.tsx
similarity index 100%
rename from apps/app/components/integration/delete-import-modal.tsx
rename to web/components/integration/delete-import-modal.tsx
diff --git a/apps/app/components/integration/github/auth.tsx b/web/components/integration/github/auth.tsx
similarity index 100%
rename from apps/app/components/integration/github/auth.tsx
rename to web/components/integration/github/auth.tsx
diff --git a/apps/app/components/integration/github/import-configure.tsx b/web/components/integration/github/import-configure.tsx
similarity index 100%
rename from apps/app/components/integration/github/import-configure.tsx
rename to web/components/integration/github/import-configure.tsx
diff --git a/apps/app/components/integration/github/import-confirm.tsx b/web/components/integration/github/import-confirm.tsx
similarity index 100%
rename from apps/app/components/integration/github/import-confirm.tsx
rename to web/components/integration/github/import-confirm.tsx
diff --git a/apps/app/components/integration/github/import-data.tsx b/web/components/integration/github/import-data.tsx
similarity index 100%
rename from apps/app/components/integration/github/import-data.tsx
rename to web/components/integration/github/import-data.tsx
diff --git a/apps/app/components/integration/github/import-users.tsx b/web/components/integration/github/import-users.tsx
similarity index 100%
rename from apps/app/components/integration/github/import-users.tsx
rename to web/components/integration/github/import-users.tsx
diff --git a/apps/app/components/integration/github/index.ts b/web/components/integration/github/index.ts
similarity index 100%
rename from apps/app/components/integration/github/index.ts
rename to web/components/integration/github/index.ts
diff --git a/apps/app/components/integration/github/repo-details.tsx b/web/components/integration/github/repo-details.tsx
similarity index 100%
rename from apps/app/components/integration/github/repo-details.tsx
rename to web/components/integration/github/repo-details.tsx
diff --git a/apps/app/components/integration/github/root.tsx b/web/components/integration/github/root.tsx
similarity index 100%
rename from apps/app/components/integration/github/root.tsx
rename to web/components/integration/github/root.tsx
diff --git a/apps/app/components/integration/github/select-repository.tsx b/web/components/integration/github/select-repository.tsx
similarity index 100%
rename from apps/app/components/integration/github/select-repository.tsx
rename to web/components/integration/github/select-repository.tsx
diff --git a/apps/app/components/integration/github/single-user-select.tsx b/web/components/integration/github/single-user-select.tsx
similarity index 100%
rename from apps/app/components/integration/github/single-user-select.tsx
rename to web/components/integration/github/single-user-select.tsx
diff --git a/apps/app/components/integration/guide.tsx b/web/components/integration/guide.tsx
similarity index 100%
rename from apps/app/components/integration/guide.tsx
rename to web/components/integration/guide.tsx
diff --git a/apps/app/components/integration/index.ts b/web/components/integration/index.ts
similarity index 100%
rename from apps/app/components/integration/index.ts
rename to web/components/integration/index.ts
diff --git a/apps/app/components/integration/jira/confirm-import.tsx b/web/components/integration/jira/confirm-import.tsx
similarity index 100%
rename from apps/app/components/integration/jira/confirm-import.tsx
rename to web/components/integration/jira/confirm-import.tsx
diff --git a/apps/app/components/integration/jira/give-details.tsx b/web/components/integration/jira/give-details.tsx
similarity index 100%
rename from apps/app/components/integration/jira/give-details.tsx
rename to web/components/integration/jira/give-details.tsx
diff --git a/apps/app/components/integration/jira/import-users.tsx b/web/components/integration/jira/import-users.tsx
similarity index 100%
rename from apps/app/components/integration/jira/import-users.tsx
rename to web/components/integration/jira/import-users.tsx
diff --git a/apps/app/components/integration/jira/index.ts b/web/components/integration/jira/index.ts
similarity index 100%
rename from apps/app/components/integration/jira/index.ts
rename to web/components/integration/jira/index.ts
diff --git a/apps/app/components/integration/jira/jira-project-detail.tsx b/web/components/integration/jira/jira-project-detail.tsx
similarity index 99%
rename from apps/app/components/integration/jira/jira-project-detail.tsx
rename to web/components/integration/jira/jira-project-detail.tsx
index 88803727c..f651ad89c 100644
--- a/apps/app/components/integration/jira/jira-project-detail.tsx
+++ b/web/components/integration/jira/jira-project-detail.tsx
@@ -20,7 +20,7 @@ import { IJiraImporterForm, IJiraMetadata } from "types";
// components
import { Spinner, ToggleSwitch } from "components/ui";
-import type { IJiraIntegrationData, TJiraIntegrationSteps } from "./";
+import type { IJiraIntegrationData, TJiraIntegrationSteps } from ".";
type Props = {
setCurrentStep: React.Dispatch>;
diff --git a/apps/app/components/integration/jira/root.tsx b/web/components/integration/jira/root.tsx
similarity index 99%
rename from apps/app/components/integration/jira/root.tsx
rename to web/components/integration/jira/root.tsx
index b5c086431..451c23709 100644
--- a/apps/app/components/integration/jira/root.tsx
+++ b/web/components/integration/jira/root.tsx
@@ -31,7 +31,7 @@ import {
jiraFormDefaultValues,
TJiraIntegrationSteps,
IJiraIntegrationData,
-} from "./";
+} from ".";
import JiraLogo from "public/services/jira.png";
diff --git a/apps/app/components/integration/single-import.tsx b/web/components/integration/single-import.tsx
similarity index 100%
rename from apps/app/components/integration/single-import.tsx
rename to web/components/integration/single-import.tsx
diff --git a/apps/app/components/integration/single-integration-card.tsx b/web/components/integration/single-integration-card.tsx
similarity index 100%
rename from apps/app/components/integration/single-integration-card.tsx
rename to web/components/integration/single-integration-card.tsx
diff --git a/web/components/integration/slack/index.ts b/web/components/integration/slack/index.ts
new file mode 100644
index 000000000..4ea6cd1e4
--- /dev/null
+++ b/web/components/integration/slack/index.ts
@@ -0,0 +1 @@
+export * from "./select-channel";
diff --git a/apps/app/components/integration/slack/select-channel.tsx b/web/components/integration/slack/select-channel.tsx
similarity index 100%
rename from apps/app/components/integration/slack/select-channel.tsx
rename to web/components/integration/slack/select-channel.tsx
diff --git a/apps/app/components/issues/activity.tsx b/web/components/issues/activity.tsx
similarity index 96%
rename from apps/app/components/issues/activity.tsx
rename to web/components/issues/activity.tsx
index 5a82907f2..fe322afe9 100644
--- a/apps/app/components/issues/activity.tsx
+++ b/web/components/issues/activity.tsx
@@ -15,14 +15,16 @@ import { IIssueActivity, IIssueComment } from "types";
type Props = {
activity: IIssueActivity[] | undefined;
- handleCommentUpdate: (comment: IIssueComment) => Promise;
+ handleCommentUpdate: (commentId: string, data: Partial) => Promise;
handleCommentDelete: (commentId: string) => Promise;
+ showAccessSpecifier?: boolean;
};
export const IssueActivitySection: React.FC = ({
activity,
handleCommentUpdate,
handleCommentDelete,
+ showAccessSpecifier = false,
}) => {
const router = useRouter();
const { workspaceSlug } = router.query;
@@ -131,10 +133,11 @@ export const IssueActivitySection: React.FC = ({
return (
);
diff --git a/apps/app/components/issues/attachment/attachment-upload.tsx b/web/components/issues/attachment/attachment-upload.tsx
similarity index 100%
rename from apps/app/components/issues/attachment/attachment-upload.tsx
rename to web/components/issues/attachment/attachment-upload.tsx
diff --git a/apps/app/components/issues/attachment/attachments.tsx b/web/components/issues/attachment/attachments.tsx
similarity index 100%
rename from apps/app/components/issues/attachment/attachments.tsx
rename to web/components/issues/attachment/attachments.tsx
diff --git a/apps/app/components/issues/attachment/delete-attachment-modal.tsx b/web/components/issues/attachment/delete-attachment-modal.tsx
similarity index 100%
rename from apps/app/components/issues/attachment/delete-attachment-modal.tsx
rename to web/components/issues/attachment/delete-attachment-modal.tsx
diff --git a/apps/app/components/issues/attachment/index.ts b/web/components/issues/attachment/index.ts
similarity index 100%
rename from apps/app/components/issues/attachment/index.ts
rename to web/components/issues/attachment/index.ts
diff --git a/apps/app/components/issues/comment/add-comment.tsx b/web/components/issues/comment/add-comment.tsx
similarity index 100%
rename from apps/app/components/issues/comment/add-comment.tsx
rename to web/components/issues/comment/add-comment.tsx
diff --git a/apps/app/components/issues/comment/comment-card.tsx b/web/components/issues/comment/comment-card.tsx
similarity index 72%
rename from apps/app/components/issues/comment/comment-card.tsx
rename to web/components/issues/comment/comment-card.tsx
index 089aa9db9..3d3e43b39 100644
--- a/apps/app/components/issues/comment/comment-card.tsx
+++ b/web/components/issues/comment/comment-card.tsx
@@ -7,7 +7,7 @@ import { ChatBubbleLeftEllipsisIcon, CheckIcon, XMarkIcon } from "@heroicons/rea
// hooks
import useUser from "hooks/use-user";
// ui
-import { CustomMenu } from "components/ui";
+import { CustomMenu, Icon } from "components/ui";
import { CommentReaction } from "components/issues";
import { TipTapEditor } from "components/tiptap";
// helpers
@@ -16,17 +16,19 @@ import { timeAgo } from "helpers/date-time.helper";
import type { IIssueComment } from "types";
type Props = {
- workspaceSlug: string;
comment: IIssueComment;
- onSubmit: (comment: IIssueComment) => void;
handleCommentDeletion: (comment: string) => void;
+ onSubmit: (commentId: string, data: Partial) => void;
+ showAccessSpecifier?: boolean;
+ workspaceSlug: string;
};
export const CommentCard: React.FC = ({
comment,
- workspaceSlug,
- onSubmit,
handleCommentDeletion,
+ onSubmit,
+ showAccessSpecifier = false,
+ workspaceSlug,
}) => {
const { user } = useUser();
@@ -45,11 +47,11 @@ export const CommentCard: React.FC = ({
defaultValues: comment,
});
- const onEnter = (formData: IIssueComment) => {
+ const onEnter = (formData: Partial) => {
if (isSubmitting) return;
setIsEditing(false);
- onSubmit(formData);
+ onSubmit(comment.id, formData);
editorRef.current?.setEditorValue(formData.comment_html);
showEditorRef.current?.setEditorValue(formData.comment_html);
@@ -99,7 +101,7 @@ export const CommentCard: React.FC = ({
: comment.actor_detail.display_name}
- Commented {timeAgo(comment.created_at)}
+ commented {timeAgo(comment.created_at)}
@@ -137,7 +139,15 @@ export const CommentCard: React.FC
= ({
-
+
+ {showAccessSpecifier && (
+
+
+
+ )}
= ({
{user?.id === comment.actor && (
- setIsEditing(true)}>Edit
+ setIsEditing(true)}
+ className="flex items-center gap-1"
+ >
+
+ Edit comment
+
+ {showAccessSpecifier && (
+ <>
+ {comment.access === "INTERNAL" ? (
+ onSubmit(comment.id, { access: "EXTERNAL" })}
+ className="flex items-center gap-1"
+ >
+
+ Switch to public comment
+
+ ) : (
+ onSubmit(comment.id, { access: "INTERNAL" })}
+ className="flex items-center gap-1"
+ >
+
+ Switch to private comment
+
+ )}
+ >
+ )}
{
handleCommentDeletion(comment.id);
}}
+ className="flex items-center gap-1"
>
- Delete
+
+ Delete comment
)}
diff --git a/apps/app/components/issues/comment/comment-reaction.tsx b/web/components/issues/comment/comment-reaction.tsx
similarity index 100%
rename from apps/app/components/issues/comment/comment-reaction.tsx
rename to web/components/issues/comment/comment-reaction.tsx
diff --git a/apps/app/components/issues/comment/index.ts b/web/components/issues/comment/index.ts
similarity index 100%
rename from apps/app/components/issues/comment/index.ts
rename to web/components/issues/comment/index.ts
diff --git a/apps/app/components/issues/delete-issue-modal.tsx b/web/components/issues/delete-issue-modal.tsx
similarity index 97%
rename from apps/app/components/issues/delete-issue-modal.tsx
rename to web/components/issues/delete-issue-modal.tsx
index f46dae9aa..e9907973f 100644
--- a/apps/app/components/issues/delete-issue-modal.tsx
+++ b/web/components/issues/delete-issue-modal.tsx
@@ -34,9 +34,16 @@ type Props = {
handleClose: () => void;
data: IIssue | null;
user: ICurrentUserResponse | undefined;
+ onSubmit?: () => Promise
;
};
-export const DeleteIssueModal: React.FC = ({ isOpen, handleClose, data, user }) => {
+export const DeleteIssueModal: React.FC = ({
+ isOpen,
+ handleClose,
+ data,
+ user,
+ onSubmit,
+}) => {
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const router = useRouter();
@@ -116,6 +123,8 @@ export const DeleteIssueModal: React.FC = ({ isOpen, handleClose, data, u
else mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(data.project, params));
}
+ if (onSubmit) onSubmit();
+
handleClose();
setToastAlert({
title: "Success",
@@ -129,6 +138,7 @@ export const DeleteIssueModal: React.FC = ({ isOpen, handleClose, data, u
console.log(error);
setIsDeleteLoading(false);
});
+ if (onSubmit) await onSubmit();
};
const handleArchivedIssueDeletion = async () => {
diff --git a/apps/app/components/issues/description-form.tsx b/web/components/issues/description-form.tsx
similarity index 100%
rename from apps/app/components/issues/description-form.tsx
rename to web/components/issues/description-form.tsx
diff --git a/apps/app/components/issues/form.tsx b/web/components/issues/form.tsx
similarity index 100%
rename from apps/app/components/issues/form.tsx
rename to web/components/issues/form.tsx
diff --git a/apps/app/components/issues/gantt-chart/blocks.tsx b/web/components/issues/gantt-chart/blocks.tsx
similarity index 93%
rename from apps/app/components/issues/gantt-chart/blocks.tsx
rename to web/components/issues/gantt-chart/blocks.tsx
index 3ab7ea90b..0834e3e79 100644
--- a/apps/app/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/apps/app/components/issues/gantt-chart/index.ts b/web/components/issues/gantt-chart/index.ts
similarity index 100%
rename from apps/app/components/issues/gantt-chart/index.ts
rename to web/components/issues/gantt-chart/index.ts
diff --git a/apps/app/components/issues/gantt-chart/layout.tsx b/web/components/issues/gantt-chart/layout.tsx
similarity index 77%
rename from apps/app/components/issues/gantt-chart/layout.tsx
rename to web/components/issues/gantt-chart/layout.tsx
index a42d764d8..39e169a60 100644
--- a/apps/app/components/issues/gantt-chart/layout.tsx
+++ b/web/components/issues/gantt-chart/layout.tsx
@@ -5,6 +5,7 @@ import useIssuesView from "hooks/use-issues-view";
import useUser from "hooks/use-user";
import useGanttChartIssues from "hooks/gantt-chart/issue-view";
import { updateGanttIssue } from "components/gantt-chart/hooks/block-update";
+import useProjectDetails from "hooks/use-project-details";
// components
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
@@ -18,12 +19,15 @@ export const IssueGanttChartView = () => {
const { orderBy } = useIssuesView();
const { user } = useUser();
+ const { projectDetails } = useProjectDetails();
const { ganttIssues, mutateGanttIssues } = useGanttChartIssues(
workspaceSlug as string,
projectId as string
);
+ const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
+
return (
{
}
BlockRender={IssueGanttBlock}
SidebarBlockRender={IssueGanttSidebarBlock}
- enableReorder={orderBy === "sort_order"}
+ enableBlockLeftResize={isAllowed}
+ enableBlockRightResize={isAllowed}
+ enableBlockMove={isAllowed}
+ enableReorder={orderBy === "sort_order" && isAllowed}
bottomSpacing
/>
diff --git a/apps/app/components/issues/index.ts b/web/components/issues/index.ts
similarity index 100%
rename from apps/app/components/issues/index.ts
rename to web/components/issues/index.ts
diff --git a/apps/app/components/issues/issue-reaction.tsx b/web/components/issues/issue-reaction.tsx
similarity index 100%
rename from apps/app/components/issues/issue-reaction.tsx
rename to web/components/issues/issue-reaction.tsx
diff --git a/apps/app/components/issues/label.tsx b/web/components/issues/label.tsx
similarity index 79%
rename from apps/app/components/issues/label.tsx
rename to web/components/issues/label.tsx
index c5a48d0ad..75a08ba0f 100644
--- a/apps/app/components/issues/label.tsx
+++ b/web/components/issues/label.tsx
@@ -6,16 +6,16 @@ import { Tooltip } from "components/ui";
import { IIssue } from "types";
type Props = {
- issue: IIssue;
+ labelDetails: any[];
maxRender?: number;
};
-export const ViewIssueLabel: React.FC = ({ issue, maxRender = 1 }) => (
+export const ViewIssueLabel: React.FC = ({ labelDetails, maxRender = 1 }) => (
<>
- {issue.label_details.length > 0 ? (
- issue.label_details.length <= maxRender ? (
+ {labelDetails.length > 0 ? (
+ labelDetails.length <= maxRender ? (
<>
- {issue.label_details.map((label, index) => (
+ {labelDetails.map((label) => (
= ({ issue, maxRender = 1 }) => (
l.name).join(", ")}
+ tooltipContent={labelDetails.map((l) => l.name).join(", ")}
>
- {`${issue.label_details.length} Labels`}
+ {`${labelDetails.length} Labels`}
diff --git a/apps/app/components/issues/main-content.tsx b/web/components/issues/main-content.tsx
similarity index 97%
rename from apps/app/components/issues/main-content.tsx
rename to web/components/issues/main-content.tsx
index bab384523..b7b154ce2 100644
--- a/apps/app/components/issues/main-content.tsx
+++ b/web/components/issues/main-content.tsx
@@ -77,7 +77,7 @@ export const IssueMainContent: React.FC = ({
: null
);
- const handleCommentUpdate = async (comment: IIssueComment) => {
+ const handleCommentUpdate = async (commentId: string, data: Partial) => {
if (!workspaceSlug || !projectId || !issueId) return;
await issuesService
@@ -85,8 +85,8 @@ export const IssueMainContent: React.FC = ({
workspaceSlug as string,
projectId as string,
issueId as string,
- comment.id,
- comment,
+ commentId,
+ data,
user
)
.then(() => mutateIssueActivity());
@@ -222,6 +222,7 @@ export const IssueMainContent: React.FC = ({
activity={issueActivity}
handleCommentUpdate={handleCommentUpdate}
handleCommentDelete={handleCommentDelete}
+ showAccessSpecifier={projectDetails && projectDetails.is_deployed}
/>
= ({
if (cycleId) prePopulateData = { ...prePopulateData, cycle: cycleId as string };
if (moduleId) prePopulateData = { ...prePopulateData, module: moduleId as string };
- if (router.asPath.includes("my-issues"))
+ if (router.asPath.includes("my-issues") || router.asPath.includes("assigned"))
prePopulateData = {
...prePopulateData,
assignees: [...(prePopulateData?.assignees ?? []), user?.id ?? ""],
diff --git a/apps/app/components/issues/my-issues/index.ts b/web/components/issues/my-issues/index.ts
similarity index 100%
rename from apps/app/components/issues/my-issues/index.ts
rename to web/components/issues/my-issues/index.ts
diff --git a/apps/app/components/issues/my-issues/my-issues-select-filters.tsx b/web/components/issues/my-issues/my-issues-select-filters.tsx
similarity index 94%
rename from apps/app/components/issues/my-issues/my-issues-select-filters.tsx
rename to web/components/issues/my-issues/my-issues-select-filters.tsx
index 58cc63679..ce8e03797 100644
--- a/apps/app/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 { PriorityIcon, StateGroupIcon } 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
@@ -61,8 +61,10 @@ export const MyIssuesSelectFilters: React.FC = ({
setIsDateFilterModalOpen(false)}
+ isOpen={isDateFilterModalOpen}
+ onSelect={onSelect}
/>
)}
= ({
id: priority === null ? "null" : priority,
label: (
- {getPriorityIcon(priority)} {priority ?? "None"}
+
{priority ?? "None"}
),
value: {
@@ -102,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/apps/app/components/issues/my-issues/my-issues-view-options.tsx b/web/components/issues/my-issues/my-issues-view-options.tsx
similarity index 99%
rename from apps/app/components/issues/my-issues/my-issues-view-options.tsx
rename to web/components/issues/my-issues/my-issues-view-options.tsx
index 7c6a6fe44..d31f884dc 100644
--- a/apps/app/components/issues/my-issues/my-issues-view-options.tsx
+++ b/web/components/issues/my-issues/my-issues-view-options.tsx
@@ -123,7 +123,7 @@ export const MyIssuesViewOptions: React.FC = () => {
: "text-custom-sidebar-text-200"
}`}
>
- View
+ Display
diff --git a/apps/app/components/issues/my-issues/my-issues-view.tsx b/web/components/issues/my-issues/my-issues-view.tsx
similarity index 94%
rename from apps/app/components/issues/my-issues/my-issues-view.tsx
rename to web/components/issues/my-issues/my-issues-view.tsx
index ee38849cd..a66f4618b 100644
--- a/apps/app/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[];
@@ -209,6 +209,15 @@ export const MyIssuesView: React.FC = ({
Object.keys(filtersToDisplay).length > 0 &&
nullFilters.length !== Object.keys(filtersToDisplay).length;
+ const isSubscribedIssuesRoute = router.pathname.includes("subscribed");
+ const isMySubscribedIssues =
+ (filters.subscriber &&
+ filters.subscriber.length > 0 &&
+ router.pathname.includes("my-issues")) ??
+ false;
+
+ const disableAddIssueOption = isSubscribedIssuesRoute || isMySubscribedIssues;
+
return (
<>
= ({
isOpen={deleteIssueModal}
data={issueToDelete}
user={user}
+ onSubmit={async () => {
+ mutateMyIssues();
+ }}
/>
{areFiltersApplied && (
<>
@@ -288,6 +300,7 @@ export const MyIssuesView: React.FC = ({
handleIssueAction={handleIssueAction}
openIssuesListModal={openIssuesListModal ? openIssuesListModal : null}
removeIssue={null}
+ disableAddIssueOption={disableAddIssueOption}
trashBox={trashBox}
setTrashBox={setTrashBox}
viewProps={{
diff --git a/apps/app/components/issues/parent-issues-list-modal.tsx b/web/components/issues/parent-issues-list-modal.tsx
similarity index 99%
rename from apps/app/components/issues/parent-issues-list-modal.tsx
rename to web/components/issues/parent-issues-list-modal.tsx
index 62091511a..a29fa6521 100644
--- a/apps/app/components/issues/parent-issues-list-modal.tsx
+++ b/web/components/issues/parent-issues-list-modal.tsx
@@ -136,7 +136,7 @@ export const ParentIssuesListModal: React.FC = ({
onClick={() => setIsWorkspaceLevel((prevData) => !prevData)}
className="flex-shrink-0"
>
- workspace level
+ Workspace Level
diff --git a/apps/app/components/issues/peek-overview/full-screen-peek-view.tsx b/web/components/issues/peek-overview/full-screen-peek-view.tsx
similarity index 100%
rename from apps/app/components/issues/peek-overview/full-screen-peek-view.tsx
rename to web/components/issues/peek-overview/full-screen-peek-view.tsx
diff --git a/apps/app/components/issues/peek-overview/header.tsx b/web/components/issues/peek-overview/header.tsx
similarity index 100%
rename from apps/app/components/issues/peek-overview/header.tsx
rename to web/components/issues/peek-overview/header.tsx
diff --git a/apps/app/components/issues/peek-overview/index.ts b/web/components/issues/peek-overview/index.ts
similarity index 100%
rename from apps/app/components/issues/peek-overview/index.ts
rename to web/components/issues/peek-overview/index.ts
diff --git a/apps/app/components/issues/peek-overview/issue-activity.tsx b/web/components/issues/peek-overview/issue-activity.tsx
similarity index 81%
rename from apps/app/components/issues/peek-overview/issue-activity.tsx
rename to web/components/issues/peek-overview/issue-activity.tsx
index 975b01fb0..68e608dba 100644
--- a/apps/app/components/issues/peek-overview/issue-activity.tsx
+++ b/web/components/issues/peek-overview/issue-activity.tsx
@@ -5,6 +5,7 @@ import issuesService from "services/issues.service";
// hooks
import useUser from "hooks/use-user";
import useToast from "hooks/use-toast";
+import useProjectDetails from "hooks/use-project-details";
// components
import { AddComment, IssueActivitySection } from "components/issues";
// types
@@ -22,6 +23,7 @@ export const PeekOverviewIssueActivity: React.FC
= ({ workspaceSlug, issu
const { setToastAlert } = useToast();
const { user } = useUser();
+ const { projectDetails } = useProjectDetails();
const { data: issueActivity, mutate: mutateIssueActivity } = useSWR(
workspaceSlug && issue ? PROJECT_ISSUES_ACTIVITY(issue.id) : null,
@@ -30,18 +32,11 @@ export const PeekOverviewIssueActivity: React.FC = ({ workspaceSlug, issu
: null
);
- const handleCommentUpdate = async (comment: IIssueComment) => {
+ const handleCommentUpdate = async (commentId: string, data: Partial) => {
if (!workspaceSlug || !issue) return;
await issuesService
- .patchIssueComment(
- workspaceSlug as string,
- issue.project,
- issue.id,
- comment.id,
- comment,
- user
- )
+ .patchIssueComment(workspaceSlug as string, issue.project, issue.id, commentId, data, user)
.then(() => mutateIssueActivity());
};
@@ -80,9 +75,13 @@ export const PeekOverviewIssueActivity: React.FC = ({ workspaceSlug, issu
activity={issueActivity}
handleCommentUpdate={handleCommentUpdate}
handleCommentDelete={handleCommentDelete}
+ showAccessSpecifier={projectDetails && projectDetails.is_deployed}
/>
diff --git a/apps/app/components/issues/peek-overview/issue-details.tsx b/web/components/issues/peek-overview/issue-details.tsx
similarity index 100%
rename from apps/app/components/issues/peek-overview/issue-details.tsx
rename to web/components/issues/peek-overview/issue-details.tsx
diff --git a/apps/app/components/issues/peek-overview/issue-properties.tsx b/web/components/issues/peek-overview/issue-properties.tsx
similarity index 76%
rename from apps/app/components/issues/peek-overview/issue-properties.tsx
rename to web/components/issues/peek-overview/issue-properties.tsx
index 2c8b4d572..d001634fc 100644
--- a/apps/app/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";
@@ -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;
@@ -50,12 +50,9 @@ export const PeekOverviewIssueProperties: React.FC = ({
maxDate?.setDate(maxDate.getDate());
const handleCopyLink = () => {
- const originURL =
- typeof window !== "undefined" && window.location.origin ? window.location.origin : "";
+ const urlToCopy = window.location.href;
- copyTextToClipboard(
- `${originURL}/${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`
- ).then(() => {
+ copyTextToClipboard(urlToCopy).then(() => {
setToastAlert({
type: "success",
title: "Link copied!",
@@ -69,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}
@@ -103,7 +103,7 @@ export const PeekOverviewIssueProperties: React.FC
= ({
handleUpdateIssue({ assignees_list: val })}
disabled={readOnly}
/>
@@ -117,7 +117,7 @@ export const PeekOverviewIssueProperties: React.FC = ({
handleUpdateIssue({ priority: val })}
+ onChange={(val) => handleUpdateIssue({ priority: val })}
disabled={readOnly}
/>
@@ -128,23 +128,18 @@ export const PeekOverviewIssueProperties: React.FC = ({
Start date
- {issue.start_date ? (
-
- handleUpdateIssue({
- start_date: val,
- })
- }
- className="bg-custom-background-100"
- wrapperClassName="w-full"
- maxDate={maxDate ?? undefined}
- disabled={readOnly}
- />
- ) : (
- Empty
- )}
+
+ handleUpdateIssue({
+ start_date: val,
+ })
+ }
+ className="bg-custom-background-80 border-none"
+ maxDate={maxDate ?? undefined}
+ disabled={readOnly}
+ />
@@ -153,23 +148,18 @@ export const PeekOverviewIssueProperties: React.FC
= ({
Due date
- {issue.target_date ? (
-
- handleUpdateIssue({
- target_date: val,
- })
- }
- className="bg-custom-background-100"
- wrapperClassName="w-full"
- minDate={minDate ?? undefined}
- disabled={readOnly}
- />
- ) : (
- Empty
- )}
+
+ handleUpdateIssue({
+ target_date: val,
+ })
+ }
+ className="bg-custom-background-80 border-none"
+ minDate={minDate ?? undefined}
+ disabled={readOnly}
+ />
{/*
diff --git a/apps/app/components/issues/peek-overview/layout.tsx b/web/components/issues/peek-overview/layout.tsx
similarity index 63%
rename from apps/app/components/issues/peek-overview/layout.tsx
rename to web/components/issues/peek-overview/layout.tsx
index 50fa5df68..57bcb904c 100644
--- a/apps/app/components/issues/peek-overview/layout.tsx
+++ b/web/components/issues/peek-overview/layout.tsx
@@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react";
import { useRouter } from "next/router";
+import { mutate } from "swr";
// mobx
import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider";
@@ -10,9 +11,11 @@ import { Dialog, Transition } from "@headlessui/react";
// hooks
import useUser from "hooks/use-user";
// components
-import { FullScreenPeekView, SidePeekView } from "components/issues";
+import { DeleteIssueModal, FullScreenPeekView, SidePeekView } from "components/issues";
// types
import { IIssue } from "types";
+// fetch-keys
+import { PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys";
type Props = {
handleMutation: () => void;
@@ -28,6 +31,7 @@ export const IssuePeekOverview: React.FC
= observer(
const [isSidePeekOpen, setIsSidePeekOpen] = useState(false);
const [isModalPeekOpen, setIsModalPeekOpen] = useState(false);
const [peekOverviewMode, setPeekOverviewMode] = useState("side");
+ const [deleteIssueModal, setDeleteIssueModal] = useState(false);
const router = useRouter();
const { peekIssue } = router.query;
@@ -53,6 +57,7 @@ export const IssuePeekOverview: React.FC = observer(
if (!issue || !user) return;
await updateIssue(workspaceSlug, projectId, issue.id, formData, user);
+ mutate(PROJECT_ISSUES_ACTIVITY(issue.id));
handleMutation();
};
@@ -81,7 +86,6 @@ export const IssuePeekOverview: React.FC = observer(
setIsSidePeekOpen(false);
}
} else {
- console.log("Triggered");
setIsSidePeekOpen(false);
setIsModalPeekOpen(false);
}
@@ -89,33 +93,38 @@ export const IssuePeekOverview: React.FC = observer(
return (
<>
+ setDeleteIssueModal(false)}
+ data={issue ? { ...issue } : null}
+ onSubmit={handleDeleteIssue}
+ user={user}
+ />
-
-
-
-
- setPeekOverviewMode(mode)}
- workspaceSlug={workspaceSlug}
- />
-
-
-
+
+
+
+ setDeleteIssueModal(true)}
+ handleUpdateIssue={handleUpdateIssue}
+ issue={issue}
+ mode={peekOverviewMode}
+ readOnly={readOnly}
+ setMode={(mode) => setPeekOverviewMode(mode)}
+ workspaceSlug={workspaceSlug}
+ />
+
+
@@ -132,26 +141,26 @@ export const IssuePeekOverview: React.FC
= observer(
>
-
-
-
-
+
+
+
{peekOverviewMode === "modal" && (
setDeleteIssueModal(true)}
handleUpdateIssue={handleUpdateIssue}
issue={issue}
mode={peekOverviewMode}
@@ -163,7 +172,7 @@ export const IssuePeekOverview: React.FC = observer(
{peekOverviewMode === "full" && (
setDeleteIssueModal(true)}
handleUpdateIssue={handleUpdateIssue}
issue={issue}
mode={peekOverviewMode}
@@ -172,9 +181,9 @@ export const IssuePeekOverview: React.FC = observer(
workspaceSlug={workspaceSlug}
/>
)}
-
-
-
+
+
+
diff --git a/apps/app/components/issues/peek-overview/side-peek-view.tsx b/web/components/issues/peek-overview/side-peek-view.tsx
similarity index 100%
rename from apps/app/components/issues/peek-overview/side-peek-view.tsx
rename to web/components/issues/peek-overview/side-peek-view.tsx
diff --git a/apps/app/components/issues/select/assignee.tsx b/web/components/issues/select/assignee.tsx
similarity index 100%
rename from apps/app/components/issues/select/assignee.tsx
rename to web/components/issues/select/assignee.tsx
diff --git a/apps/app/components/issues/select/date.tsx b/web/components/issues/select/date.tsx
similarity index 100%
rename from apps/app/components/issues/select/date.tsx
rename to web/components/issues/select/date.tsx
diff --git a/apps/app/components/issues/select/estimate.tsx b/web/components/issues/select/estimate.tsx
similarity index 100%
rename from apps/app/components/issues/select/estimate.tsx
rename to web/components/issues/select/estimate.tsx
diff --git a/apps/app/components/issues/select/index.ts b/web/components/issues/select/index.ts
similarity index 100%
rename from apps/app/components/issues/select/index.ts
rename to web/components/issues/select/index.ts
diff --git a/apps/app/components/issues/select/label.tsx b/web/components/issues/select/label.tsx
similarity index 100%
rename from apps/app/components/issues/select/label.tsx
rename to web/components/issues/select/label.tsx
diff --git a/apps/app/components/issues/select/priority.tsx b/web/components/issues/select/priority.tsx
similarity index 73%
rename from apps/app/components/issues/select/priority.tsx
rename to web/components/issues/select/priority.tsx
index b734e6a90..6a2a07cbd 100644
--- a/apps/app/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/apps/app/components/issues/select/project.tsx b/web/components/issues/select/project.tsx
similarity index 100%
rename from apps/app/components/issues/select/project.tsx
rename to web/components/issues/select/project.tsx
diff --git a/apps/app/components/issues/select/state.tsx b/web/components/issues/select/state.tsx
similarity index 86%
rename from apps/app/components/issues/select/state.tsx
rename to web/components/issues/select/state.tsx
index d62daba76..22a4e6532 100644
--- a/apps/app/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/apps/app/components/issues/sidebar-select/assignee.tsx b/web/components/issues/sidebar-select/assignee.tsx
similarity index 91%
rename from apps/app/components/issues/sidebar-select/assignee.tsx
rename to web/components/issues/sidebar-select/assignee.tsx
index 61ece6f78..8b9872368 100644
--- a/apps/app/components/issues/sidebar-select/assignee.tsx
+++ b/web/components/issues/sidebar-select/assignee.tsx
@@ -51,7 +51,10 @@ export const SidebarAssigneeSelect: React.FC
= ({ value, onChange, disabl
{value.length} Assignees
) : (
-
+
No assignees
)}
diff --git a/apps/app/components/issues/sidebar-select/blocked.tsx b/web/components/issues/sidebar-select/blocked.tsx
similarity index 97%
rename from apps/app/components/issues/sidebar-select/blocked.tsx
rename to web/components/issues/sidebar-select/blocked.tsx
index fbe58b4b2..02cfd3b16 100644
--- a/apps/app/components/issues/sidebar-select/blocked.tsx
+++ b/web/components/issues/sidebar-select/blocked.tsx
@@ -124,7 +124,7 @@ export const SidebarBlockedSelect: React.FC = ({
setIsBlockedModalOpen(true)}
diff --git a/apps/app/components/issues/sidebar-select/blocker.tsx b/web/components/issues/sidebar-select/blocker.tsx
similarity index 97%
rename from apps/app/components/issues/sidebar-select/blocker.tsx
rename to web/components/issues/sidebar-select/blocker.tsx
index 49a6bc505..eb15e9ade 100644
--- a/apps/app/components/issues/sidebar-select/blocker.tsx
+++ b/web/components/issues/sidebar-select/blocker.tsx
@@ -126,7 +126,7 @@ export const SidebarBlockerSelect: React.FC = ({
setIsBlockerModalOpen(true)}
diff --git a/apps/app/components/issues/sidebar-select/cycle.tsx b/web/components/issues/sidebar-select/cycle.tsx
similarity index 80%
rename from apps/app/components/issues/sidebar-select/cycle.tsx
rename to web/components/issues/sidebar-select/cycle.tsx
index 3451be2c3..8fbfcf707 100644
--- a/apps/app/components/issues/sidebar-select/cycle.tsx
+++ b/web/components/issues/sidebar-select/cycle.tsx
@@ -62,23 +62,27 @@ export const SidebarCycleSelect: React.FC = ({
return (
-
+
-
- {issueCycle ? issueCycle.cycle_detail.name : "No cycle"}
-
-
-
+
+ {issueCycle ? issueCycle.cycle_detail.name : "No cycle"}
+
+
+
+
}
value={issueCycle ? issueCycle.cycle_detail.id : null}
onChange={(value: any) => {
diff --git a/apps/app/components/issues/sidebar-select/estimate.tsx b/web/components/issues/sidebar-select/estimate.tsx
similarity index 100%
rename from apps/app/components/issues/sidebar-select/estimate.tsx
rename to web/components/issues/sidebar-select/estimate.tsx
diff --git a/apps/app/components/issues/sidebar-select/index.ts b/web/components/issues/sidebar-select/index.ts
similarity index 100%
rename from apps/app/components/issues/sidebar-select/index.ts
rename to web/components/issues/sidebar-select/index.ts
diff --git a/apps/app/components/issues/sidebar-select/label.tsx b/web/components/issues/sidebar-select/label.tsx
similarity index 100%
rename from apps/app/components/issues/sidebar-select/label.tsx
rename to web/components/issues/sidebar-select/label.tsx
diff --git a/apps/app/components/issues/sidebar-select/module.tsx b/web/components/issues/sidebar-select/module.tsx
similarity index 78%
rename from apps/app/components/issues/sidebar-select/module.tsx
rename to web/components/issues/sidebar-select/module.tsx
index a183fe951..c9599bdf4 100644
--- a/apps/app/components/issues/sidebar-select/module.tsx
+++ b/web/components/issues/sidebar-select/module.tsx
@@ -56,27 +56,29 @@ export const SidebarModuleSelect: React.FC
= ({
return (
m.id === issueModule?.module)?.name ?? "No module"
- }`}
- >
-
+ m.id === issueModule?.module)?.name ?? "No module"
}`}
>
-
- {modules?.find((m) => m.id === issueModule?.module)?.name ?? "No module"}
-
-
-
+
+ {modules?.find((m) => m.id === issueModule?.module)?.name ?? "No module"}
+
+
+
+
}
value={issueModule ? issueModule.module_detail?.id : null}
onChange={(value: any) => {
diff --git a/apps/app/components/issues/sidebar-select/parent.tsx b/web/components/issues/sidebar-select/parent.tsx
similarity index 100%
rename from apps/app/components/issues/sidebar-select/parent.tsx
rename to web/components/issues/sidebar-select/parent.tsx
diff --git a/apps/app/components/issues/sidebar-select/priority.tsx b/web/components/issues/sidebar-select/priority.tsx
similarity index 76%
rename from apps/app/components/issues/sidebar-select/priority.tsx
rename to web/components/issues/sidebar-select/priority.tsx
index fd1c77f28..543f79707 100644
--- a/apps/app/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;
};
@@ -27,11 +29,11 @@ export const SidebarPrioritySelect: React.FC
= ({ value, onChange, disabl
? "border-yellow-500/20 bg-yellow-500/20 text-yellow-500"
: value === "low"
? "border-green-500/20 bg-green-500/20 text-green-500"
- : "bg-custom-background-80 border-custom-border-200"
+ : "bg-custom-background-80 border-custom-border-200 text-custom-text-200"
}`}
>
- {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/apps/app/components/issues/sidebar-select/state.tsx b/web/components/issues/sidebar-select/state.tsx
similarity index 85%
rename from apps/app/components/issues/sidebar-select/state.tsx
rename to web/components/issues/sidebar-select/state.tsx
index 5084c61bd..cf2cfe3b2 100644
--- a/apps/app/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/apps/app/components/issues/sidebar.tsx b/web/components/issues/sidebar.tsx
similarity index 99%
rename from apps/app/components/issues/sidebar.tsx
rename to web/components/issues/sidebar.tsx
index 4bdd30137..a33d17705 100644
--- a/apps/app/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/apps/app/components/issues/sub-issues-list.tsx b/web/components/issues/sub-issues-list.tsx
similarity index 100%
rename from apps/app/components/issues/sub-issues-list.tsx
rename to web/components/issues/sub-issues-list.tsx
diff --git a/apps/app/components/issues/view-select/assignee.tsx b/web/components/issues/view-select/assignee.tsx
similarity index 100%
rename from apps/app/components/issues/view-select/assignee.tsx
rename to web/components/issues/view-select/assignee.tsx
diff --git a/apps/app/components/issues/view-select/due-date.tsx b/web/components/issues/view-select/due-date.tsx
similarity index 100%
rename from apps/app/components/issues/view-select/due-date.tsx
rename to web/components/issues/view-select/due-date.tsx
diff --git a/apps/app/components/issues/view-select/estimate.tsx b/web/components/issues/view-select/estimate.tsx
similarity index 100%
rename from apps/app/components/issues/view-select/estimate.tsx
rename to web/components/issues/view-select/estimate.tsx
diff --git a/apps/app/components/issues/view-select/index.ts b/web/components/issues/view-select/index.ts
similarity index 100%
rename from apps/app/components/issues/view-select/index.ts
rename to web/components/issues/view-select/index.ts
diff --git a/apps/app/components/issues/view-select/label.tsx b/web/components/issues/view-select/label.tsx
similarity index 100%
rename from apps/app/components/issues/view-select/label.tsx
rename to web/components/issues/view-select/label.tsx
diff --git a/apps/app/components/issues/view-select/priority.tsx b/web/components/issues/view-select/priority.tsx
similarity index 83%
rename from apps/app/components/issues/view-select/priority.tsx
rename to web/components/issues/view-select/priority.tsx
index f9872729c..1bdbf3428 100644
--- a/apps/app/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/apps/app/components/issues/view-select/start-date.tsx b/web/components/issues/view-select/start-date.tsx
similarity index 100%
rename from apps/app/components/issues/view-select/start-date.tsx
rename to web/components/issues/view-select/start-date.tsx
diff --git a/apps/app/components/issues/view-select/state.tsx b/web/components/issues/view-select/state.tsx
similarity index 93%
rename from apps/app/components/issues/view-select/state.tsx
rename to web/components/issues/view-select/state.tsx
index 460a11272..08ca77d80 100644
--- a/apps/app/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/apps/app/components/labels/create-label-modal.tsx b/web/components/labels/create-label-modal.tsx
similarity index 100%
rename from apps/app/components/labels/create-label-modal.tsx
rename to web/components/labels/create-label-modal.tsx
diff --git a/apps/app/components/labels/create-update-label-inline.tsx b/web/components/labels/create-update-label-inline.tsx
similarity index 100%
rename from apps/app/components/labels/create-update-label-inline.tsx
rename to web/components/labels/create-update-label-inline.tsx
diff --git a/apps/app/components/labels/delete-label-modal.tsx b/web/components/labels/delete-label-modal.tsx
similarity index 100%
rename from apps/app/components/labels/delete-label-modal.tsx
rename to web/components/labels/delete-label-modal.tsx
diff --git a/apps/app/components/labels/index.ts b/web/components/labels/index.ts
similarity index 100%
rename from apps/app/components/labels/index.ts
rename to web/components/labels/index.ts
diff --git a/apps/app/components/labels/labels-list-modal.tsx b/web/components/labels/labels-list-modal.tsx
similarity index 100%
rename from apps/app/components/labels/labels-list-modal.tsx
rename to web/components/labels/labels-list-modal.tsx
diff --git a/apps/app/components/labels/single-label-group.tsx b/web/components/labels/single-label-group.tsx
similarity index 100%
rename from apps/app/components/labels/single-label-group.tsx
rename to web/components/labels/single-label-group.tsx
diff --git a/apps/app/components/labels/single-label.tsx b/web/components/labels/single-label.tsx
similarity index 100%
rename from apps/app/components/labels/single-label.tsx
rename to web/components/labels/single-label.tsx
diff --git a/apps/app/components/modules/delete-module-modal.tsx b/web/components/modules/delete-module-modal.tsx
similarity index 100%
rename from apps/app/components/modules/delete-module-modal.tsx
rename to web/components/modules/delete-module-modal.tsx
diff --git a/apps/app/components/modules/form.tsx b/web/components/modules/form.tsx
similarity index 100%
rename from apps/app/components/modules/form.tsx
rename to web/components/modules/form.tsx
diff --git a/apps/app/components/modules/gantt-chart/blocks.tsx b/web/components/modules/gantt-chart/blocks.tsx
similarity index 100%
rename from apps/app/components/modules/gantt-chart/blocks.tsx
rename to web/components/modules/gantt-chart/blocks.tsx
diff --git a/apps/app/components/modules/gantt-chart/index.ts b/web/components/modules/gantt-chart/index.ts
similarity index 100%
rename from apps/app/components/modules/gantt-chart/index.ts
rename to web/components/modules/gantt-chart/index.ts
diff --git a/apps/app/components/modules/gantt-chart/module-issues-layout.tsx b/web/components/modules/gantt-chart/module-issues-layout.tsx
similarity index 79%
rename from apps/app/components/modules/gantt-chart/module-issues-layout.tsx
rename to web/components/modules/gantt-chart/module-issues-layout.tsx
index 9c0b05078..c350232e9 100644
--- a/apps/app/components/modules/gantt-chart/module-issues-layout.tsx
+++ b/web/components/modules/gantt-chart/module-issues-layout.tsx
@@ -7,6 +7,7 @@ import useIssuesView from "hooks/use-issues-view";
import useUser from "hooks/use-user";
import useGanttChartModuleIssues from "hooks/gantt-chart/module-issues-view";
import { updateGanttIssue } from "components/gantt-chart/hooks/block-update";
+import useProjectDetails from "hooks/use-project-details";
// components
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
@@ -22,6 +23,7 @@ export const ModuleIssuesGanttChartView: FC = ({}) => {
const { orderBy } = useIssuesView();
const { user } = useUser();
+ const { projectDetails } = useProjectDetails();
const { ganttIssues, mutateGanttIssues } = useGanttChartModuleIssues(
workspaceSlug as string,
@@ -29,6 +31,8 @@ export const ModuleIssuesGanttChartView: FC = ({}) => {
moduleId as string
);
+ const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
+
return (
= ({}) => {
}
SidebarBlockRender={IssueGanttSidebarBlock}
BlockRender={IssueGanttBlock}
- enableReorder={orderBy === "sort_order"}
+ enableBlockLeftResize={isAllowed}
+ enableBlockRightResize={isAllowed}
+ enableBlockMove={isAllowed}
+ enableReorder={orderBy === "sort_order" && isAllowed}
bottomSpacing
/>
diff --git a/apps/app/components/modules/gantt-chart/modules-list-layout.tsx b/web/components/modules/gantt-chart/modules-list-layout.tsx
similarity index 83%
rename from apps/app/components/modules/gantt-chart/modules-list-layout.tsx
rename to web/components/modules/gantt-chart/modules-list-layout.tsx
index 70f493dde..b8ebd0185 100644
--- a/apps/app/components/modules/gantt-chart/modules-list-layout.tsx
+++ b/web/components/modules/gantt-chart/modules-list-layout.tsx
@@ -1,7 +1,6 @@
import { FC } from "react";
import { useRouter } from "next/router";
-import Link from "next/link";
import { KeyedMutator } from "swr";
@@ -9,6 +8,7 @@ import { KeyedMutator } from "swr";
import modulesService from "services/modules.service";
// hooks
import useUser from "hooks/use-user";
+import useProjectDetails from "hooks/use-project-details";
// components
import { GanttChartRoot, IBlockUpdateData } from "components/gantt-chart";
import { ModuleGanttBlock, ModuleGanttSidebarBlock } from "components/modules";
@@ -25,6 +25,7 @@ export const ModulesListGanttChartView: FC = ({ modules, mutateModules })
const { workspaceSlug } = router.query;
const { user } = useUser();
+ const { projectDetails } = useProjectDetails();
const handleModuleUpdate = (module: IModule, payload: IBlockUpdateData) => {
if (!workspaceSlug || !user) return;
@@ -68,7 +69,10 @@ export const ModulesListGanttChartView: FC = ({ modules, mutateModules })
const blockFormat = (blocks: IModule[]) =>
blocks && blocks.length > 0
? blocks
- .filter((b) => b.start_date && b.target_date)
+ .filter(
+ (b) =>
+ b.start_date && b.target_date && new Date(b.start_date) <= new Date(b.target_date)
+ )
.map((block) => ({
data: block,
id: block.id,
@@ -78,6 +82,8 @@ export const ModulesListGanttChartView: FC = ({ modules, mutateModules })
}))
: [];
+ const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
+
return (
= ({ modules, mutateModules })
blockUpdateHandler={(block, payload) => handleModuleUpdate(block, payload)}
SidebarBlockRender={ModuleGanttSidebarBlock}
BlockRender={ModuleGanttBlock}
+ enableBlockLeftResize={isAllowed}
+ enableBlockRightResize={isAllowed}
+ enableBlockMove={isAllowed}
+ enableReorder={isAllowed}
/>
);
diff --git a/apps/app/components/modules/index.ts b/web/components/modules/index.ts
similarity index 100%
rename from apps/app/components/modules/index.ts
rename to web/components/modules/index.ts
diff --git a/apps/app/components/modules/modal.tsx b/web/components/modules/modal.tsx
similarity index 100%
rename from apps/app/components/modules/modal.tsx
rename to web/components/modules/modal.tsx
diff --git a/apps/app/components/modules/select/index.ts b/web/components/modules/select/index.ts
similarity index 100%
rename from apps/app/components/modules/select/index.ts
rename to web/components/modules/select/index.ts
diff --git a/apps/app/components/modules/select/lead.tsx b/web/components/modules/select/lead.tsx
similarity index 100%
rename from apps/app/components/modules/select/lead.tsx
rename to web/components/modules/select/lead.tsx
diff --git a/apps/app/components/modules/select/members.tsx b/web/components/modules/select/members.tsx
similarity index 100%
rename from apps/app/components/modules/select/members.tsx
rename to web/components/modules/select/members.tsx
diff --git a/apps/app/components/modules/select/status.tsx b/web/components/modules/select/status.tsx
similarity index 100%
rename from apps/app/components/modules/select/status.tsx
rename to web/components/modules/select/status.tsx
diff --git a/apps/app/components/modules/sidebar-select/index.ts b/web/components/modules/sidebar-select/index.ts
similarity index 100%
rename from apps/app/components/modules/sidebar-select/index.ts
rename to web/components/modules/sidebar-select/index.ts
diff --git a/apps/app/components/modules/sidebar-select/select-lead.tsx b/web/components/modules/sidebar-select/select-lead.tsx
similarity index 100%
rename from apps/app/components/modules/sidebar-select/select-lead.tsx
rename to web/components/modules/sidebar-select/select-lead.tsx
diff --git a/apps/app/components/modules/sidebar-select/select-members.tsx b/web/components/modules/sidebar-select/select-members.tsx
similarity index 100%
rename from apps/app/components/modules/sidebar-select/select-members.tsx
rename to web/components/modules/sidebar-select/select-members.tsx
diff --git a/apps/app/components/modules/sidebar-select/select-status.tsx b/web/components/modules/sidebar-select/select-status.tsx
similarity index 100%
rename from apps/app/components/modules/sidebar-select/select-status.tsx
rename to web/components/modules/sidebar-select/select-status.tsx
diff --git a/apps/app/components/modules/sidebar.tsx b/web/components/modules/sidebar.tsx
similarity index 100%
rename from apps/app/components/modules/sidebar.tsx
rename to web/components/modules/sidebar.tsx
diff --git a/apps/app/components/modules/single-module-card.tsx b/web/components/modules/single-module-card.tsx
similarity index 100%
rename from apps/app/components/modules/single-module-card.tsx
rename to web/components/modules/single-module-card.tsx
diff --git a/apps/app/components/notifications/index.ts b/web/components/notifications/index.ts
similarity index 100%
rename from apps/app/components/notifications/index.ts
rename to web/components/notifications/index.ts
diff --git a/apps/app/components/notifications/notification-card.tsx b/web/components/notifications/notification-card.tsx
similarity index 99%
rename from apps/app/components/notifications/notification-card.tsx
rename to web/components/notifications/notification-card.tsx
index 9bb0715a8..29fe579a8 100644
--- a/apps/app/components/notifications/notification-card.tsx
+++ b/web/components/notifications/notification-card.tsx
@@ -210,7 +210,7 @@ export const NotificationCard: React.FC = (props) => {
{
+ menuButtonOnClick={(e: { stopPropagation: () => void }) => {
e.stopPropagation();
}}
customButton={
diff --git a/apps/app/components/notifications/notification-header.tsx b/web/components/notifications/notification-header.tsx
similarity index 100%
rename from apps/app/components/notifications/notification-header.tsx
rename to web/components/notifications/notification-header.tsx
diff --git a/apps/app/components/notifications/notification-popover.tsx b/web/components/notifications/notification-popover.tsx
similarity index 100%
rename from apps/app/components/notifications/notification-popover.tsx
rename to web/components/notifications/notification-popover.tsx
diff --git a/apps/app/components/notifications/select-snooze-till-modal.tsx b/web/components/notifications/select-snooze-till-modal.tsx
similarity index 100%
rename from apps/app/components/notifications/select-snooze-till-modal.tsx
rename to web/components/notifications/select-snooze-till-modal.tsx
diff --git a/apps/app/components/onboarding/index.ts b/web/components/onboarding/index.ts
similarity index 100%
rename from apps/app/components/onboarding/index.ts
rename to web/components/onboarding/index.ts
diff --git a/apps/app/components/onboarding/invite-members.tsx b/web/components/onboarding/invite-members.tsx
similarity index 100%
rename from apps/app/components/onboarding/invite-members.tsx
rename to web/components/onboarding/invite-members.tsx
diff --git a/apps/app/components/onboarding/join-workspaces.tsx b/web/components/onboarding/join-workspaces.tsx
similarity index 100%
rename from apps/app/components/onboarding/join-workspaces.tsx
rename to web/components/onboarding/join-workspaces.tsx
diff --git a/apps/app/components/onboarding/tour/index.ts b/web/components/onboarding/tour/index.ts
similarity index 100%
rename from apps/app/components/onboarding/tour/index.ts
rename to web/components/onboarding/tour/index.ts
diff --git a/apps/app/components/onboarding/tour/root.tsx b/web/components/onboarding/tour/root.tsx
similarity index 100%
rename from apps/app/components/onboarding/tour/root.tsx
rename to web/components/onboarding/tour/root.tsx
diff --git a/apps/app/components/onboarding/tour/sidebar.tsx b/web/components/onboarding/tour/sidebar.tsx
similarity index 100%
rename from apps/app/components/onboarding/tour/sidebar.tsx
rename to web/components/onboarding/tour/sidebar.tsx
diff --git a/apps/app/components/onboarding/user-details.tsx b/web/components/onboarding/user-details.tsx
similarity index 100%
rename from apps/app/components/onboarding/user-details.tsx
rename to web/components/onboarding/user-details.tsx
diff --git a/apps/app/components/onboarding/workspace.tsx b/web/components/onboarding/workspace.tsx
similarity index 100%
rename from apps/app/components/onboarding/workspace.tsx
rename to web/components/onboarding/workspace.tsx
diff --git a/apps/app/components/pages/create-block.tsx b/web/components/pages/create-block.tsx
similarity index 100%
rename from apps/app/components/pages/create-block.tsx
rename to web/components/pages/create-block.tsx
diff --git a/apps/app/components/pages/create-update-block-inline.tsx b/web/components/pages/create-update-block-inline.tsx
similarity index 100%
rename from apps/app/components/pages/create-update-block-inline.tsx
rename to web/components/pages/create-update-block-inline.tsx
diff --git a/apps/app/components/pages/create-update-page-modal.tsx b/web/components/pages/create-update-page-modal.tsx
similarity index 100%
rename from apps/app/components/pages/create-update-page-modal.tsx
rename to web/components/pages/create-update-page-modal.tsx
diff --git a/apps/app/components/pages/delete-page-modal.tsx b/web/components/pages/delete-page-modal.tsx
similarity index 100%
rename from apps/app/components/pages/delete-page-modal.tsx
rename to web/components/pages/delete-page-modal.tsx
diff --git a/apps/app/components/pages/index.ts b/web/components/pages/index.ts
similarity index 100%
rename from apps/app/components/pages/index.ts
rename to web/components/pages/index.ts
diff --git a/apps/app/components/pages/page-form.tsx b/web/components/pages/page-form.tsx
similarity index 100%
rename from apps/app/components/pages/page-form.tsx
rename to web/components/pages/page-form.tsx
diff --git a/apps/app/components/pages/pages-list/all-pages-list.tsx b/web/components/pages/pages-list/all-pages-list.tsx
similarity index 100%
rename from apps/app/components/pages/pages-list/all-pages-list.tsx
rename to web/components/pages/pages-list/all-pages-list.tsx
diff --git a/apps/app/components/pages/pages-list/favorite-pages-list.tsx b/web/components/pages/pages-list/favorite-pages-list.tsx
similarity index 100%
rename from apps/app/components/pages/pages-list/favorite-pages-list.tsx
rename to web/components/pages/pages-list/favorite-pages-list.tsx
diff --git a/apps/app/components/pages/pages-list/index.ts b/web/components/pages/pages-list/index.ts
similarity index 100%
rename from apps/app/components/pages/pages-list/index.ts
rename to web/components/pages/pages-list/index.ts
diff --git a/apps/app/components/pages/pages-list/my-pages-list.tsx b/web/components/pages/pages-list/my-pages-list.tsx
similarity index 100%
rename from apps/app/components/pages/pages-list/my-pages-list.tsx
rename to web/components/pages/pages-list/my-pages-list.tsx
diff --git a/apps/app/components/pages/pages-list/other-pages-list.tsx b/web/components/pages/pages-list/other-pages-list.tsx
similarity index 100%
rename from apps/app/components/pages/pages-list/other-pages-list.tsx
rename to web/components/pages/pages-list/other-pages-list.tsx
diff --git a/apps/app/components/pages/pages-list/recent-pages-list.tsx b/web/components/pages/pages-list/recent-pages-list.tsx
similarity index 100%
rename from apps/app/components/pages/pages-list/recent-pages-list.tsx
rename to web/components/pages/pages-list/recent-pages-list.tsx
diff --git a/apps/app/components/pages/pages-list/types.ts b/web/components/pages/pages-list/types.ts
similarity index 100%
rename from apps/app/components/pages/pages-list/types.ts
rename to web/components/pages/pages-list/types.ts
diff --git a/apps/app/components/pages/pages-view.tsx b/web/components/pages/pages-view.tsx
similarity index 100%
rename from apps/app/components/pages/pages-view.tsx
rename to web/components/pages/pages-view.tsx
diff --git a/apps/app/components/pages/single-page-block.tsx b/web/components/pages/single-page-block.tsx
similarity index 100%
rename from apps/app/components/pages/single-page-block.tsx
rename to web/components/pages/single-page-block.tsx
diff --git a/apps/app/components/pages/single-page-detailed-item.tsx b/web/components/pages/single-page-detailed-item.tsx
similarity index 100%
rename from apps/app/components/pages/single-page-detailed-item.tsx
rename to web/components/pages/single-page-detailed-item.tsx
diff --git a/apps/app/components/pages/single-page-list-item.tsx b/web/components/pages/single-page-list-item.tsx
similarity index 100%
rename from apps/app/components/pages/single-page-list-item.tsx
rename to web/components/pages/single-page-list-item.tsx
diff --git a/apps/app/components/profile/index.ts b/web/components/profile/index.ts
similarity index 100%
rename from apps/app/components/profile/index.ts
rename to web/components/profile/index.ts
diff --git a/apps/app/components/profile/navbar.tsx b/web/components/profile/navbar.tsx
similarity index 100%
rename from apps/app/components/profile/navbar.tsx
rename to web/components/profile/navbar.tsx
diff --git a/apps/app/components/profile/overview/activity.tsx b/web/components/profile/overview/activity.tsx
similarity index 100%
rename from apps/app/components/profile/overview/activity.tsx
rename to web/components/profile/overview/activity.tsx
diff --git a/apps/app/components/profile/overview/index.ts b/web/components/profile/overview/index.ts
similarity index 100%
rename from apps/app/components/profile/overview/index.ts
rename to web/components/profile/overview/index.ts
diff --git a/apps/app/components/profile/overview/priority-distribution.tsx b/web/components/profile/overview/priority-distribution.tsx
similarity index 100%
rename from apps/app/components/profile/overview/priority-distribution.tsx
rename to web/components/profile/overview/priority-distribution.tsx
diff --git a/apps/app/components/profile/overview/state-distribution.tsx b/web/components/profile/overview/state-distribution.tsx
similarity index 100%
rename from apps/app/components/profile/overview/state-distribution.tsx
rename to web/components/profile/overview/state-distribution.tsx
diff --git a/apps/app/components/profile/overview/stats.tsx b/web/components/profile/overview/stats.tsx
similarity index 100%
rename from apps/app/components/profile/overview/stats.tsx
rename to web/components/profile/overview/stats.tsx
diff --git a/apps/app/components/profile/overview/workload.tsx b/web/components/profile/overview/workload.tsx
similarity index 100%
rename from apps/app/components/profile/overview/workload.tsx
rename to web/components/profile/overview/workload.tsx
diff --git a/apps/app/components/profile/profile-issues-view-options.tsx b/web/components/profile/profile-issues-view-options.tsx
similarity index 99%
rename from apps/app/components/profile/profile-issues-view-options.tsx
rename to web/components/profile/profile-issues-view-options.tsx
index 38faf500b..4d59d6ffa 100644
--- a/apps/app/components/profile/profile-issues-view-options.tsx
+++ b/web/components/profile/profile-issues-view-options.tsx
@@ -149,7 +149,7 @@ export const ProfileIssuesViewOptions: React.FC = () => {
: "text-custom-sidebar-text-200"
}`}
>
- View
+ Display
diff --git a/apps/app/components/profile/profile-issues-view.tsx b/web/components/profile/profile-issues-view.tsx
similarity index 93%
rename from apps/app/components/profile/profile-issues-view.tsx
rename to web/components/profile/profile-issues-view.tsx
index 0449546fc..f4d75974e 100644
--- a/apps/app/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;
@@ -223,6 +223,15 @@ export const ProfileIssuesView = () => {
Object.keys(filtersToDisplay).length > 0 &&
nullFilters.length !== Object.keys(filtersToDisplay).length;
+ const isSubscribedIssuesRoute = router.pathname.includes("subscribed");
+ const isMySubscribedIssues =
+ (filters.subscriber &&
+ filters.subscriber.length > 0 &&
+ router.pathname.includes("my-issues")) ??
+ false;
+
+ const disableAddIssueOption = isSubscribedIssuesRoute || isMySubscribedIssues;
+
return (
<>
{
isOpen={deleteIssueModal}
data={issueToDelete}
user={user}
+ onSubmit={async () => {
+ mutateProfileIssues();
+ }}
/>
{areFiltersApplied && (
<>
@@ -289,6 +301,7 @@ export const ProfileIssuesView = () => {
handleIssueAction={handleIssueAction}
openIssuesListModal={null}
removeIssue={null}
+ disableAddIssueOption={disableAddIssueOption}
trashBox={trashBox}
setTrashBox={setTrashBox}
viewProps={{
diff --git a/apps/app/components/profile/sidebar.tsx b/web/components/profile/sidebar.tsx
similarity index 96%
rename from apps/app/components/profile/sidebar.tsx
rename to web/components/profile/sidebar.tsx
index a1236b397..59cc5528b 100644
--- a/apps/app/components/profile/sidebar.tsx
+++ b/web/components/profile/sidebar.tsx
@@ -14,7 +14,7 @@ import { Icon, Loader, Tooltip } from "components/ui";
// icons
import { EditOutlined } from "@mui/icons-material";
// helpers
-import { render12HourFormatTime, renderLongDetailDateFormat } from "helpers/date-time.helper";
+import { renderLongDetailDateFormat } from "helpers/date-time.helper";
import { renderEmoji } from "helpers/emoji.helper";
// fetch-keys
import { USER_PROFILE_PROJECT_SEGREGATION } from "constants/fetch-keys";
@@ -35,6 +35,16 @@ export const ProfileSidebar = () => {
: null
);
+ // Create a date object for the current time in the specified timezone
+ const currentTime = new Date();
+ const formatter = new Intl.DateTimeFormat("en-US", {
+ timeZone: userProjectsData?.user_data.user_timezone,
+ hour12: false, // Use 24-hour format
+ hour: "2-digit",
+ minute: "2-digit",
+ });
+ const timeString = formatter.format(currentTime);
+
const userDetails = [
{
label: "Joined on",
@@ -44,7 +54,7 @@ export const ProfileSidebar = () => {
label: "Timezone",
value: (
- {render12HourFormatTime(new Date())}{" "}
+ {timeString}{" "}
{userProjectsData?.user_data.user_timezone}
),
diff --git a/web/components/project/confirm-project-leave-modal.tsx b/web/components/project/confirm-project-leave-modal.tsx
new file mode 100644
index 000000000..7d6582869
--- /dev/null
+++ b/web/components/project/confirm-project-leave-modal.tsx
@@ -0,0 +1,211 @@
+import React from "react";
+// next imports
+import { useRouter } from "next/router";
+// react-hook-form
+import { Controller, useForm } from "react-hook-form";
+// headless ui
+import { Dialog, Transition } from "@headlessui/react";
+// icons
+import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
+// ui
+import { DangerButton, Input, SecondaryButton } from "components/ui";
+// fetch-keys
+import { PROJECTS_LIST } from "constants/fetch-keys";
+// mobx react lite
+import { observer } from "mobx-react-lite";
+// mobx store
+import { useMobxStore } from "lib/mobx/store-provider";
+import { RootStore } from "store/root";
+// hooks
+import useToast from "hooks/use-toast";
+import useUser from "hooks/use-user";
+import useProjects from "hooks/use-projects";
+// types
+import { IProject } from "types";
+
+type FormData = {
+ projectName: string;
+ confirmLeave: string;
+};
+
+const defaultValues: FormData = {
+ projectName: "",
+ confirmLeave: "",
+};
+
+export const ConfirmProjectLeaveModal: React.FC = observer(() => {
+ const router = useRouter();
+ const { workspaceSlug } = router.query;
+
+ const store: RootStore = useMobxStore();
+ const { project } = store;
+
+ const { user } = useUser();
+ const { mutateProjects } = useProjects();
+
+ const { setToastAlert } = useToast();
+
+ const {
+ control,
+ formState: { isSubmitting },
+ handleSubmit,
+ reset,
+ watch,
+ } = useForm({ defaultValues });
+
+ const handleClose = () => {
+ project.handleProjectLeaveModal(null);
+
+ reset({ ...defaultValues });
+ };
+
+ const onSubmit = async (data: any) => {
+ if (data) {
+ if (data.projectName === project?.projectLeaveDetails?.name) {
+ if (data.confirmLeave === "Leave Project") {
+ return project
+ .leaveProject(
+ project.projectLeaveDetails.workspaceSlug.toString(),
+ project.projectLeaveDetails.id.toString(),
+ user
+ )
+ .then((res) => {
+ mutateProjects();
+ handleClose();
+ router.push(`/${workspaceSlug}/projects`);
+ })
+ .catch((err) => {
+ setToastAlert({
+ type: "error",
+ title: "Error!",
+ message: "Something went wrong please try again later.",
+ });
+ });
+ } else {
+ setToastAlert({
+ type: "error",
+ title: "Error!",
+ message: "Please confirm leaving the project by typing the 'Leave Project'.",
+ });
+ }
+ } else {
+ setToastAlert({
+ type: "error",
+ title: "Error!",
+ message: "Please enter the project name as shown in the description.",
+ });
+ }
+ } else {
+ setToastAlert({
+ type: "error",
+ title: "Error!",
+ message: "Please fill all fields.",
+ });
+ }
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+});
diff --git a/apps/app/components/project/confirm-project-member-remove.tsx b/web/components/project/confirm-project-member-remove.tsx
similarity index 100%
rename from apps/app/components/project/confirm-project-member-remove.tsx
rename to web/components/project/confirm-project-member-remove.tsx
diff --git a/apps/app/components/project/create-project-modal.tsx b/web/components/project/create-project-modal.tsx
similarity index 100%
rename from apps/app/components/project/create-project-modal.tsx
rename to web/components/project/create-project-modal.tsx
diff --git a/apps/app/components/project/delete-project-modal.tsx b/web/components/project/delete-project-modal.tsx
similarity index 100%
rename from apps/app/components/project/delete-project-modal.tsx
rename to web/components/project/delete-project-modal.tsx
diff --git a/apps/app/components/project/index.ts b/web/components/project/index.ts
similarity index 74%
rename from apps/app/components/project/index.ts
rename to web/components/project/index.ts
index e5ece3955..494a04294 100644
--- a/apps/app/components/project/index.ts
+++ b/web/components/project/index.ts
@@ -1,7 +1,8 @@
export * from "./create-project-modal";
export * from "./delete-project-modal";
export * from "./sidebar-list";
-export * from "./settings-header"
+export * from "./settings-header";
export * from "./single-integration-card";
export * from "./single-project-card";
export * from "./single-sidebar-project";
+export * from "./confirm-project-leave-modal";
diff --git a/apps/app/components/project/join-project-modal.tsx b/web/components/project/join-project-modal.tsx
similarity index 100%
rename from apps/app/components/project/join-project-modal.tsx
rename to web/components/project/join-project-modal.tsx
diff --git a/apps/app/components/project/publish-project/modal.tsx b/web/components/project/publish-project/modal.tsx
similarity index 57%
rename from apps/app/components/project/publish-project/modal.tsx
rename to web/components/project/publish-project/modal.tsx
index b22a496f5..173a5242c 100644
--- a/apps/app/components/project/publish-project/modal.tsx
+++ b/web/components/project/publish-project/modal.tsx
@@ -6,7 +6,14 @@ import { Controller, useForm } from "react-hook-form";
// headless ui
import { Dialog, Transition } from "@headlessui/react";
// ui components
-import { ToggleSwitch, PrimaryButton, SecondaryButton, Icon, DangerButton } from "components/ui";
+import {
+ ToggleSwitch,
+ PrimaryButton,
+ SecondaryButton,
+ Icon,
+ DangerButton,
+ Loader,
+} from "components/ui";
import { CustomPopover } from "./popover";
// mobx react lite
import { observer } from "mobx-react-lite";
@@ -146,22 +153,14 @@ export const PublishProjectModal: React.FC = observer(() => {
const projectId = projectPublish.project_id;
return projectPublish
- .createProjectSettingsAsync(
- workspaceSlug.toString(),
- projectId?.toString() ?? "",
- payload,
- user
- )
- .then((response) => {
+ .publishProject(workspaceSlug.toString(), projectId?.toString() ?? "", payload, user)
+ .then((res) => {
mutateProjectDetails();
handleClose();
if (projectId) window.open(`${plane_deploy_url}/${workspaceSlug}/${projectId}`, "_blank");
- return response;
+ return res;
})
- .catch((error) => {
- console.error("error", error);
- return error;
- });
+ .catch((err) => err);
};
const handleUpdatePublishSettings = async (payload: IProjectPublishSettings) => {
@@ -199,7 +198,7 @@ export const PublishProjectModal: React.FC = observer(() => {
setIsUnpublishing(true);
projectPublish
- .deleteProjectSettingsAsync(
+ .unPublishProject(
workspaceSlug.toString(),
projectPublish.project_id as string,
publishId,
@@ -329,7 +328,7 @@ export const PublishProjectModal: React.FC = observer(() => {
{/* heading */}
Publish
- {watch("id") && (
+ {projectPublish.projectPublishSettings !== "not-initialized" && (
handleUnpublishProject(watch("id") ?? "")}
className="!px-2 !py-1.5"
@@ -341,137 +340,145 @@ export const PublishProjectModal: React.FC = observer(() => {
{/* content */}
-
-
-
- {`${plane_deploy_url}/${workspaceSlug}/${projectPublish.project_id}`}
-
-
-
-
-
+ {projectPublish.fetchSettingsLoader ? (
+
+
+
+
+
+
+ ) : (
+
+ {watch("id") && (
+ <>
+
+
+ {`${plane_deploy_url}/${workspaceSlug}/${projectPublish.project_id}`}
+
+
+
+
+
+
+
+
+
+
This project is live on web
+
+ >
+ )}
- {watch("id") && (
-
-
-
-
-
This project is live on web
-
- )}
-
-
-
-
Views
-
(
- 0
- ? viewOptions
- .filter((v) => value.includes(v.key))
- .map((v) => v.label)
- .join(", ")
- : ``
- }
- placeholder="Select views"
- >
- <>
- {viewOptions.map((option) => (
- {
- const _views =
- value.length > 0
- ? value.includes(option.key)
- ? value.filter((_o: string) => _o !== option.key)
- : [...value, option.key]
- : [option.key];
-
- if (_views.length === 0) return;
-
- onChange(_views);
- checkIfUpdateIsRequired();
- }}
- >
-
{option.label}
+
+
+
Views
+
(
+ 0
+ ? viewOptions
+ .filter((v) => value.includes(v.key))
+ .map((v) => v.label)
+ .join(", ")
+ : ``
+ }
+ placeholder="Select views"
+ >
+ <>
+ {viewOptions.map((option) => (
{
+ const _views =
+ value.length > 0
+ ? value.includes(option.key)
+ ? value.filter((_o: string) => _o !== option.key)
+ : [...value, option.key]
+ : [option.key];
+
+ if (_views.length === 0) return;
+
+ onChange(_views);
+ checkIfUpdateIsRequired();
+ }}
>
- {value.length > 0 && value.includes(option.key) && (
-
- )}
+
{option.label}
+
+ {value.length > 0 && value.includes(option.key) && (
+
+ )}
+
-
- ))}
- >
-
- )}
- />
-
+ ))}
+ >
+
+ )}
+ />
+
+
+
Allow comments
+
(
+ {
+ onChange(val);
+ checkIfUpdateIsRequired();
+ }}
+ size="sm"
+ />
+ )}
+ />
+
+
+
Allow reactions
+
(
+ {
+ onChange(val);
+ checkIfUpdateIsRequired();
+ }}
+ size="sm"
+ />
+ )}
+ />
+
+
+
Allow voting
+
(
+ {
+ onChange(val);
+ checkIfUpdateIsRequired();
+ }}
+ size="sm"
+ />
+ )}
+ />
+
-
-
Allow comments
-
(
- {
- onChange(val);
- checkIfUpdateIsRequired();
- }}
- size="sm"
- />
- )}
- />
-
-
-
Allow reactions
-
(
- {
- onChange(val);
- checkIfUpdateIsRequired();
- }}
- size="sm"
- />
- )}
- />
-
-
-
Allow voting
-
(
- {
- onChange(val);
- checkIfUpdateIsRequired();
- }}
- size="sm"
- />
- )}
- />
-
-
- {/*
+ {/*
Allow issue proposals
= observer(() => {
)}
/>
*/}
+
-
+ )}
{/* modal handlers */}
@@ -490,22 +498,24 @@ export const PublishProjectModal: React.FC
= observer(() => {
Anyone with the link can access
-
-
Cancel
- {watch("id") ? (
- <>
- {isUpdateRequired && (
-
- {isSubmitting ? "Updating..." : "Update settings"}
-
- )}
- >
- ) : (
-
- {isSubmitting ? "Publishing..." : "Publish"}
-
- )}
-
+ {!projectPublish.fetchSettingsLoader && (
+
+
Cancel
+ {watch("id") ? (
+ <>
+ {isUpdateRequired && (
+
+ {isSubmitting ? "Updating..." : "Update settings"}
+
+ )}
+ >
+ ) : (
+
+ {isSubmitting ? "Publishing..." : "Publish"}
+
+ )}
+
+ )}
diff --git a/apps/app/components/project/publish-project/popover.tsx b/web/components/project/publish-project/popover.tsx
similarity index 100%
rename from apps/app/components/project/publish-project/popover.tsx
rename to web/components/project/publish-project/popover.tsx
diff --git a/apps/app/components/project/send-project-invitation-modal.tsx b/web/components/project/send-project-invitation-modal.tsx
similarity index 97%
rename from apps/app/components/project/send-project-invitation-modal.tsx
rename to web/components/project/send-project-invitation-modal.tsx
index 414ef7a6c..b8f383f05 100644
--- a/apps/app/components/project/send-project-invitation-modal.tsx
+++ b/web/components/project/send-project-invitation-modal.tsx
@@ -85,7 +85,8 @@ const SendProjectInvitationModal: React.FC
= (props) => {
});
const uninvitedPeople = people?.filter((person) => {
- const isInvited = members?.find((member) => member.display_name === person.member.display_name);
+ const isInvited = members?.find((member) => member.memberId === person.member.id);
+
return !isInvited;
});
@@ -143,7 +144,7 @@ const SendProjectInvitationModal: React.FC = (props) => {
content: (
- {person.member.display_name}
+ {person.member.display_name} ({person.member.first_name + " " + person.member.last_name})
),
}));
@@ -218,7 +219,7 @@ const SendProjectInvitationModal: React.FC = (props) => {
}
) : (
- Select co-worker’s email
+ Select co-worker
)}
diff --git a/apps/app/components/project/settings-header.tsx b/web/components/project/settings-header.tsx
similarity index 100%
rename from apps/app/components/project/settings-header.tsx
rename to web/components/project/settings-header.tsx
diff --git a/apps/app/components/project/settings/single-label.tsx b/web/components/project/settings/single-label.tsx
similarity index 100%
rename from apps/app/components/project/settings/single-label.tsx
rename to web/components/project/settings/single-label.tsx
diff --git a/apps/app/components/project/sidebar-list.tsx b/web/components/project/sidebar-list.tsx
similarity index 97%
rename from apps/app/components/project/sidebar-list.tsx
rename to web/components/project/sidebar-list.tsx
index 0ab8f9bee..a46a97f04 100644
--- a/apps/app/components/project/sidebar-list.tsx
+++ b/web/components/project/sidebar-list.tsx
@@ -35,6 +35,7 @@ export const ProjectSidebarList: FC = () => {
const [isProjectModalOpen, setIsProjectModalOpen] = useState(false);
const [deleteProjectModal, setDeleteProjectModal] = useState(false);
const [projectToDelete, setProjectToDelete] = useState(null);
+ const [projectToLeaveId, setProjectToLeaveId] = useState(null);
// router
const [isScrolled, setIsScrolled] = useState(false);
@@ -217,6 +218,7 @@ export const ProjectSidebarList: FC = () => {
snapshot={snapshot}
handleDeleteProject={() => handleDeleteProject(project)}
handleCopyText={() => handleCopyText(project.id)}
+ handleProjectLeave={() => setProjectToLeaveId(project.id)}
shortContextMenu
/>
@@ -285,6 +287,7 @@ export const ProjectSidebarList: FC = () => {
provided={provided}
snapshot={snapshot}
handleDeleteProject={() => handleDeleteProject(project)}
+ handleProjectLeave={() => setProjectToLeaveId(project.id)}
handleCopyText={() => handleCopyText(project.id)}
/>
diff --git a/apps/app/components/project/single-integration-card.tsx b/web/components/project/single-integration-card.tsx
similarity index 100%
rename from apps/app/components/project/single-integration-card.tsx
rename to web/components/project/single-integration-card.tsx
diff --git a/apps/app/components/project/single-project-card.tsx b/web/components/project/single-project-card.tsx
similarity index 100%
rename from apps/app/components/project/single-project-card.tsx
rename to web/components/project/single-project-card.tsx
diff --git a/web/components/project/single-sidebar-project.tsx b/web/components/project/single-sidebar-project.tsx
new file mode 100644
index 000000000..ebc8bc974
--- /dev/null
+++ b/web/components/project/single-sidebar-project.tsx
@@ -0,0 +1,373 @@
+import Link from "next/link";
+import { useRouter } from "next/router";
+
+import { mutate } from "swr";
+
+// react-beautiful-dnd
+import { DraggableProvided, DraggableStateSnapshot } from "react-beautiful-dnd";
+// headless ui
+import { Disclosure, Transition } from "@headlessui/react";
+// services
+import projectService from "services/project.service";
+// hooks
+import useToast from "hooks/use-toast";
+// ui
+import { CustomMenu, Icon, Tooltip } from "components/ui";
+// icons
+import { EllipsisVerticalIcon, LinkIcon, StarIcon, TrashIcon } from "@heroicons/react/24/outline";
+import {
+ ArchiveOutlined,
+ ArticleOutlined,
+ ContrastOutlined,
+ DatasetOutlined,
+ ExpandMoreOutlined,
+ FilterNoneOutlined,
+ PhotoFilterOutlined,
+ SettingsOutlined,
+} from "@mui/icons-material";
+// helpers
+import { renderEmoji } from "helpers/emoji.helper";
+// types
+import { IProject } from "types";
+// fetch-keys
+import { PROJECTS_LIST } from "constants/fetch-keys";
+// mobx react lite
+import { observer } from "mobx-react-lite";
+// mobx store
+import { useMobxStore } from "lib/mobx/store-provider";
+import { RootStore } from "store/root";
+
+type Props = {
+ project: IProject;
+ sidebarCollapse: boolean;
+ provided?: DraggableProvided;
+ snapshot?: DraggableStateSnapshot;
+ handleDeleteProject: () => void;
+ handleCopyText: () => void;
+ handleProjectLeave: () => void;
+ shortContextMenu?: boolean;
+};
+
+const navigation = (workspaceSlug: string, projectId: string) => [
+ {
+ name: "Issues",
+ href: `/${workspaceSlug}/projects/${projectId}/issues`,
+ Icon: FilterNoneOutlined,
+ },
+ {
+ name: "Cycles",
+ href: `/${workspaceSlug}/projects/${projectId}/cycles`,
+ Icon: ContrastOutlined,
+ },
+ {
+ name: "Modules",
+ href: `/${workspaceSlug}/projects/${projectId}/modules`,
+ Icon: DatasetOutlined,
+ },
+ {
+ name: "Views",
+ href: `/${workspaceSlug}/projects/${projectId}/views`,
+ Icon: PhotoFilterOutlined,
+ },
+ {
+ name: "Pages",
+ href: `/${workspaceSlug}/projects/${projectId}/pages`,
+ Icon: ArticleOutlined,
+ },
+ {
+ name: "Settings",
+ href: `/${workspaceSlug}/projects/${projectId}/settings`,
+ Icon: SettingsOutlined,
+ },
+];
+
+export const SingleSidebarProject: React.FC
= observer((props) => {
+ const {
+ project,
+ sidebarCollapse,
+ provided,
+ snapshot,
+ handleDeleteProject,
+ handleCopyText,
+ handleProjectLeave,
+ shortContextMenu = false,
+ } = props;
+
+ const store: RootStore = useMobxStore();
+ const { projectPublish, project: projectStore } = store;
+
+ const router = useRouter();
+ const { workspaceSlug, projectId } = router.query;
+
+ const { setToastAlert } = useToast();
+
+ const isAdmin = project.member_role === 20;
+
+ const isViewerOrGuest = project.member_role === 10 || project.member_role === 5;
+
+ const handleAddToFavorites = () => {
+ if (!workspaceSlug) return;
+
+ mutate(
+ PROJECTS_LIST(workspaceSlug as string, { is_favorite: "all" }),
+ (prevData) =>
+ (prevData ?? []).map((p) => (p.id === project.id ? { ...p, is_favorite: true } : p)),
+ false
+ );
+
+ projectService
+ .addProjectToFavorites(workspaceSlug as string, {
+ project: project.id,
+ })
+ .catch(() =>
+ setToastAlert({
+ type: "error",
+ title: "Error!",
+ message: "Couldn't remove the project from favorites. Please try again.",
+ })
+ );
+ };
+
+ const handleRemoveFromFavorites = () => {
+ if (!workspaceSlug) return;
+
+ mutate(
+ PROJECTS_LIST(workspaceSlug as string, { is_favorite: "all" }),
+ (prevData) =>
+ (prevData ?? []).map((p) => (p.id === project.id ? { ...p, is_favorite: false } : p)),
+ false
+ );
+
+ projectService.removeProjectFromFavorites(workspaceSlug as string, project.id).catch(() =>
+ setToastAlert({
+ type: "error",
+ title: "Error!",
+ message: "Couldn't remove the project from favorites. Please try again.",
+ })
+ );
+ };
+
+ return (
+
+ {({ open }) => (
+ <>
+
+ {provided && (
+
+
+
+
+
+
+ )}
+
+
+
+ {project.emoji ? (
+
+ {renderEmoji(project.emoji)}
+
+ ) : project.icon_prop ? (
+
+ {renderEmoji(project.icon_prop)}
+
+ ) : (
+
+ {project?.name.charAt(0)}
+
+ )}
+
+ {!sidebarCollapse && (
+
+ {project.name}
+
+ )}
+
+ {!sidebarCollapse && (
+
+ )}
+
+
+
+ {!sidebarCollapse && (
+
+ {!shortContextMenu && isAdmin && (
+
+
+
+ Delete project
+
+
+ )}
+ {!project.is_favorite && (
+
+
+
+ Add to favorites
+
+
+ )}
+ {project.is_favorite && (
+
+
+
+ Remove from favorites
+
+
+ )}
+
+
+
+ Copy project link
+
+
+
+ {/* publish project settings */}
+ {isAdmin && (
+ projectPublish.handleProjectModal(project?.id)}
+ >
+
+
+
+
+
{project.is_deployed ? "Publish settings" : "Publish"}
+
+
+ )}
+
+ {project.archive_in > 0 && (
+
+ router.push(`/${workspaceSlug}/projects/${project?.id}/archived-issues/`)
+ }
+ >
+
+
+ )}
+ router.push(`/${workspaceSlug}/projects/${project?.id}/settings`)}
+ >
+
+
+ Settings
+
+
+
+ {/* leave project */}
+ {isViewerOrGuest && (
+
+ projectStore.handleProjectLeaveModal({
+ id: project?.id,
+ name: project?.name,
+ workspaceSlug: workspaceSlug as string,
+ })
+ }
+ >
+
+
+ Leave Project
+
+
+ )}
+
+ )}
+
+
+
+
+ {navigation(workspaceSlug as string, project?.id).map((item) => {
+ if (
+ (item.name === "Cycles" && !project.cycle_view) ||
+ (item.name === "Modules" && !project.module_view) ||
+ (item.name === "Views" && !project.issue_views_view) ||
+ (item.name === "Pages" && !project.page_view)
+ )
+ return;
+
+ return (
+
+
+
+
+
+ {!sidebarCollapse && item.name}
+
+
+
+
+ );
+ })}
+
+
+ >
+ )}
+
+ );
+});
diff --git a/apps/app/components/search-listbox/index.tsx b/web/components/search-listbox/index.tsx
similarity index 100%
rename from apps/app/components/search-listbox/index.tsx
rename to web/components/search-listbox/index.tsx
diff --git a/apps/app/components/search-listbox/types.d.ts b/web/components/search-listbox/types.d.ts
similarity index 100%
rename from apps/app/components/search-listbox/types.d.ts
rename to web/components/search-listbox/types.d.ts
diff --git a/apps/app/components/states/create-state-modal.tsx b/web/components/states/create-state-modal.tsx
similarity index 100%
rename from apps/app/components/states/create-state-modal.tsx
rename to web/components/states/create-state-modal.tsx
diff --git a/apps/app/components/states/create-update-state-inline.tsx b/web/components/states/create-update-state-inline.tsx
similarity index 100%
rename from apps/app/components/states/create-update-state-inline.tsx
rename to web/components/states/create-update-state-inline.tsx
diff --git a/apps/app/components/states/delete-state-modal.tsx b/web/components/states/delete-state-modal.tsx
similarity index 100%
rename from apps/app/components/states/delete-state-modal.tsx
rename to web/components/states/delete-state-modal.tsx
diff --git a/apps/app/components/states/index.ts b/web/components/states/index.ts
similarity index 100%
rename from apps/app/components/states/index.ts
rename to web/components/states/index.ts
diff --git a/apps/app/components/states/single-state.tsx b/web/components/states/single-state.tsx
similarity index 97%
rename from apps/app/components/states/single-state.tsx
rename to web/components/states/single-state.tsx
index 813afdc79..e5c1bf8dd 100644
--- a/apps/app/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/tiptap/bubble-menu/index.tsx b/web/components/tiptap/bubble-menu/index.tsx
new file mode 100644
index 000000000..217317ea1
--- /dev/null
+++ b/web/components/tiptap/bubble-menu/index.tsx
@@ -0,0 +1,121 @@
+import { BubbleMenu, BubbleMenuProps } from "@tiptap/react";
+import { FC, useState } from "react";
+import { BoldIcon, ItalicIcon, UnderlineIcon, StrikethroughIcon, CodeIcon } from "lucide-react";
+
+import { NodeSelector } from "./node-selector";
+import { LinkSelector } from "./link-selector";
+import { cn } from "../utils";
+
+export interface BubbleMenuItem {
+ name: string;
+ isActive: () => boolean;
+ command: () => void;
+ icon: typeof BoldIcon;
+}
+
+type EditorBubbleMenuProps = Omit
;
+
+export const EditorBubbleMenu: FC = (props: any) => {
+ const items: BubbleMenuItem[] = [
+ {
+ name: "bold",
+ isActive: () => props.editor?.isActive("bold"),
+ command: () => props.editor?.chain().focus().toggleBold().run(),
+ icon: BoldIcon,
+ },
+ {
+ name: "italic",
+ isActive: () => props.editor?.isActive("italic"),
+ command: () => props.editor?.chain().focus().toggleItalic().run(),
+ icon: ItalicIcon,
+ },
+ {
+ name: "underline",
+ isActive: () => props.editor?.isActive("underline"),
+ command: () => props.editor?.chain().focus().toggleUnderline().run(),
+ icon: UnderlineIcon,
+ },
+ {
+ name: "strike",
+ isActive: () => props.editor?.isActive("strike"),
+ command: () => props.editor?.chain().focus().toggleStrike().run(),
+ icon: StrikethroughIcon,
+ },
+ {
+ name: "code",
+ isActive: () => props.editor?.isActive("code"),
+ command: () => props.editor?.chain().focus().toggleCode().run(),
+ icon: CodeIcon,
+ },
+ ];
+
+ const bubbleMenuProps: EditorBubbleMenuProps = {
+ ...props,
+ shouldShow: ({ editor }) => {
+ if (!editor.isEditable) {
+ return false;
+ }
+ if (editor.isActive("image")) {
+ return false;
+ }
+ return editor.view.state.selection.content().size > 0;
+ },
+ tippyOptions: {
+ moveTransition: "transform 0.15s ease-out",
+ onHidden: () => {
+ setIsNodeSelectorOpen(false);
+ setIsLinkSelectorOpen(false);
+ },
+ },
+ };
+
+ const [isNodeSelectorOpen, setIsNodeSelectorOpen] = useState(false);
+ const [isLinkSelectorOpen, setIsLinkSelectorOpen] = useState(false);
+
+ return (
+
+ {!props.editor.isActive("table") && (
+ {
+ setIsNodeSelectorOpen(!isNodeSelectorOpen);
+ setIsLinkSelectorOpen(false);
+ }}
+ />
+ )}
+ {
+ setIsLinkSelectorOpen(!isLinkSelectorOpen);
+ setIsNodeSelectorOpen(false);
+ }}
+ />
+
+ {items.map((item, index) => (
+
+
+
+ ))}
+
+
+ );
+};
diff --git a/web/components/tiptap/bubble-menu/link-selector.tsx b/web/components/tiptap/bubble-menu/link-selector.tsx
new file mode 100644
index 000000000..559521db6
--- /dev/null
+++ b/web/components/tiptap/bubble-menu/link-selector.tsx
@@ -0,0 +1,92 @@
+import { Editor } from "@tiptap/core";
+import { Check, Trash } from "lucide-react";
+import { Dispatch, FC, SetStateAction, useCallback, useEffect, useRef } from "react";
+import { cn } from "../utils";
+import isValidHttpUrl from "./utils/link-validator";
+interface LinkSelectorProps {
+ editor: Editor;
+ isOpen: boolean;
+ setIsOpen: Dispatch>;
+}
+
+export const LinkSelector: FC = ({ editor, isOpen, setIsOpen }) => {
+ const inputRef = useRef(null);
+
+ const onLinkSubmit = useCallback(() => {
+ const input = inputRef.current;
+ const url = input?.value;
+ if (url && isValidHttpUrl(url)) {
+ editor.chain().focus().setLink({ href: url }).run();
+ setIsOpen(false);
+ }
+ }, [editor, inputRef, setIsOpen]);
+
+ useEffect(() => {
+ inputRef.current && inputRef.current?.focus();
+ });
+
+ return (
+
+
{
+ setIsOpen(!isOpen);
+ }}
+ >
+ ↗
+
+ Link
+
+
+ {isOpen && (
+
{
+ if (e.key === "Enter") {
+ e.preventDefault();
+ onLinkSubmit();
+ }
+ }}
+ >
+
+ {editor.getAttributes("link").href ? (
+ {
+ editor.chain().focus().unsetLink().run();
+ setIsOpen(false);
+ }}
+ >
+
+
+ ) : (
+ {
+ onLinkSubmit();
+ }}
+ >
+
+
+ )}
+
+ )}
+
+ );
+};
diff --git a/web/components/tiptap/bubble-menu/node-selector.tsx b/web/components/tiptap/bubble-menu/node-selector.tsx
new file mode 100644
index 000000000..34d40ec06
--- /dev/null
+++ b/web/components/tiptap/bubble-menu/node-selector.tsx
@@ -0,0 +1,130 @@
+import { Editor } from "@tiptap/core";
+import {
+ Check,
+ ChevronDown,
+ Heading1,
+ Heading2,
+ Heading3,
+ TextQuote,
+ ListOrdered,
+ TextIcon,
+ Code,
+ CheckSquare,
+} from "lucide-react";
+import { Dispatch, FC, SetStateAction } from "react";
+
+import { BubbleMenuItem } from ".";
+import { cn } from "../utils";
+
+interface NodeSelectorProps {
+ editor: Editor;
+ isOpen: boolean;
+ setIsOpen: Dispatch>;
+}
+
+export const NodeSelector: FC = ({ editor, isOpen, setIsOpen }) => {
+ const items: BubbleMenuItem[] = [
+ {
+ name: "Text",
+ icon: TextIcon,
+ command: () => editor.chain().focus().toggleNode("paragraph", "paragraph").run(),
+ isActive: () =>
+ editor.isActive("paragraph") &&
+ !editor.isActive("bulletList") &&
+ !editor.isActive("orderedList"),
+ },
+ {
+ name: "H1",
+ icon: Heading1,
+ command: () => editor.chain().focus().toggleHeading({ level: 1 }).run(),
+ isActive: () => editor.isActive("heading", { level: 1 }),
+ },
+ {
+ name: "H2",
+ icon: Heading2,
+ command: () => editor.chain().focus().toggleHeading({ level: 2 }).run(),
+ isActive: () => editor.isActive("heading", { level: 2 }),
+ },
+ {
+ name: "H3",
+ icon: Heading3,
+ command: () => editor.chain().focus().toggleHeading({ level: 3 }).run(),
+ isActive: () => editor.isActive("heading", { level: 3 }),
+ },
+ {
+ name: "To-do List",
+ icon: CheckSquare,
+ command: () => editor.chain().focus().toggleTaskList().run(),
+ isActive: () => editor.isActive("taskItem"),
+ },
+ {
+ name: "Bullet List",
+ icon: ListOrdered,
+ command: () => editor.chain().focus().toggleBulletList().run(),
+ isActive: () => editor.isActive("bulletList"),
+ },
+ {
+ name: "Numbered List",
+ icon: ListOrdered,
+ command: () => editor.chain().focus().toggleOrderedList().run(),
+ isActive: () => editor.isActive("orderedList"),
+ },
+ {
+ name: "Quote",
+ icon: TextQuote,
+ command: () =>
+ editor.chain().focus().toggleNode("paragraph", "paragraph").toggleBlockquote().run(),
+ isActive: () => editor.isActive("blockquote"),
+ },
+ {
+ name: "Code",
+ icon: Code,
+ command: () => editor.chain().focus().toggleCodeBlock().run(),
+ isActive: () => editor.isActive("codeBlock"),
+ },
+ ];
+
+ const activeItem = items.filter((item) => item.isActive()).pop() ?? {
+ name: "Multiple",
+ };
+
+ return (
+
+
setIsOpen(!isOpen)}
+ className="flex h-full items-center gap-1 whitespace-nowrap p-2 text-sm font-medium text-custom-text-300 hover:bg-custom-primary-100/5 active:bg-custom-primary-100/5"
+ >
+ {activeItem?.name}
+
+
+
+ {isOpen && (
+
+ {items.map((item, index) => (
+ {
+ item.command();
+ setIsOpen(false);
+ }}
+ className={cn(
+ "flex items-center justify-between rounded-sm px-2 py-1 text-sm text-custom-text-200 hover:bg-custom-primary-100/5 hover:text-custom-text-100",
+ { "bg-custom-primary-100/5 text-custom-text-100": activeItem.name === item.name }
+ )}
+ >
+
+ {activeItem.name === item.name && }
+
+ ))}
+
+ )}
+
+ );
+};
diff --git a/web/components/tiptap/bubble-menu/utils/link-validator.tsx b/web/components/tiptap/bubble-menu/utils/link-validator.tsx
new file mode 100644
index 000000000..9af366c02
--- /dev/null
+++ b/web/components/tiptap/bubble-menu/utils/link-validator.tsx
@@ -0,0 +1,11 @@
+export default function isValidHttpUrl(string: string): boolean {
+ let url;
+
+ try {
+ url = new URL(string);
+ } catch (_) {
+ return false;
+ }
+
+ return url.protocol === "http:" || url.protocol === "https:";
+}
diff --git a/web/components/tiptap/extensions/image-resize.tsx b/web/components/tiptap/extensions/image-resize.tsx
new file mode 100644
index 000000000..448b8811c
--- /dev/null
+++ b/web/components/tiptap/extensions/image-resize.tsx
@@ -0,0 +1,44 @@
+import { Editor } from "@tiptap/react";
+import Moveable from "react-moveable";
+
+export const ImageResizer = ({ editor }: { editor: Editor }) => {
+ const updateMediaSize = () => {
+ const imageInfo = document.querySelector(".ProseMirror-selectednode") as HTMLImageElement;
+ if (imageInfo) {
+ const selection = editor.state.selection;
+ editor.commands.setImage({
+ src: imageInfo.src,
+ width: Number(imageInfo.style.width.replace("px", "")),
+ height: Number(imageInfo.style.height.replace("px", "")),
+ } as any);
+ editor.commands.setNodeSelection(selection.from);
+ }
+ };
+
+ return (
+ <>
+ {
+ delta[0] && (target!.style.width = `${width}px`);
+ delta[1] && (target!.style.height = `${height}px`);
+ }}
+ onResizeEnd={() => {
+ updateMediaSize();
+ }}
+ scalable={true}
+ renderDirections={["w", "e"]}
+ onScale={({ target, transform }: any) => {
+ target!.style.transform = transform;
+ }}
+ />
+ >
+ );
+};
diff --git a/web/components/tiptap/extensions/index.tsx b/web/components/tiptap/extensions/index.tsx
new file mode 100644
index 000000000..f5dc11384
--- /dev/null
+++ b/web/components/tiptap/extensions/index.tsx
@@ -0,0 +1,153 @@
+import StarterKit from "@tiptap/starter-kit";
+import HorizontalRule from "@tiptap/extension-horizontal-rule";
+import TiptapLink from "@tiptap/extension-link";
+import Placeholder from "@tiptap/extension-placeholder";
+import TiptapUnderline from "@tiptap/extension-underline";
+import TextStyle from "@tiptap/extension-text-style";
+import { Color } from "@tiptap/extension-color";
+import TaskItem from "@tiptap/extension-task-item";
+import TaskList from "@tiptap/extension-task-list";
+import { Markdown } from "tiptap-markdown";
+import Highlight from "@tiptap/extension-highlight";
+import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
+import { lowlight } from "lowlight/lib/core";
+import SlashCommand from "../slash-command";
+import { InputRule } from "@tiptap/core";
+import Gapcursor from "@tiptap/extension-gapcursor";
+
+import ts from "highlight.js/lib/languages/typescript";
+
+import "highlight.js/styles/github-dark.css";
+import UniqueID from "@tiptap-pro/extension-unique-id";
+import UpdatedImage from "./updated-image";
+import isValidHttpUrl from "../bubble-menu/utils/link-validator";
+import { CustomTableCell } from "./table/table-cell";
+import { Table } from "./table/table";
+import { TableHeader } from "./table/table-header";
+import { TableRow } from "@tiptap/extension-table-row";
+
+lowlight.registerLanguage("ts", ts);
+
+export const TiptapExtensions = (
+ workspaceSlug: string,
+ setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
+) => [
+ StarterKit.configure({
+ bulletList: {
+ HTMLAttributes: {
+ class: "list-disc list-outside leading-3 -mt-2",
+ },
+ },
+ orderedList: {
+ HTMLAttributes: {
+ class: "list-decimal list-outside leading-3 -mt-2",
+ },
+ },
+ listItem: {
+ HTMLAttributes: {
+ class: "leading-normal -mb-2",
+ },
+ },
+ blockquote: {
+ HTMLAttributes: {
+ class: "border-l-4 border-custom-border-300",
+ },
+ },
+ code: {
+ HTMLAttributes: {
+ class:
+ "rounded-md bg-custom-primary-30 mx-1 px-1 py-1 font-mono font-medium text-custom-text-1000",
+ spellcheck: "false",
+ },
+ },
+ codeBlock: false,
+ horizontalRule: false,
+ dropcursor: {
+ color: "rgba(var(--color-text-100))",
+ width: 2,
+ },
+ gapcursor: false,
+ }),
+ CodeBlockLowlight.configure({
+ lowlight,
+ }),
+ HorizontalRule.extend({
+ addInputRules() {
+ return [
+ new InputRule({
+ find: /^(?:---|—-|___\s|\*\*\*\s)$/,
+ handler: ({ state, range, commands }) => {
+ commands.splitBlock();
+
+ const attributes = {};
+ const { tr } = state;
+ const start = range.from;
+ const end = range.to;
+ // @ts-ignore
+ tr.replaceWith(start - 1, end, this.type.create(attributes));
+ },
+ }),
+ ];
+ },
+ }).configure({
+ HTMLAttributes: {
+ class: "mb-6 border-t border-custom-border-300",
+ },
+ }),
+ Gapcursor,
+ TiptapLink.configure({
+ protocols: ["http", "https"],
+ validate: (url) => isValidHttpUrl(url),
+ HTMLAttributes: {
+ class:
+ "text-custom-primary-300 underline underline-offset-[3px] hover:text-custom-primary-500 transition-colors cursor-pointer",
+ },
+ }),
+ UpdatedImage.configure({
+ HTMLAttributes: {
+ class: "rounded-lg border border-custom-border-300",
+ },
+ }),
+ Placeholder.configure({
+ placeholder: ({ node }) => {
+ if (node.type.name === "heading") {
+ return `Heading ${node.attrs.level}`;
+ }
+ if (node.type.name === "image" || node.type.name === "table") {
+ return "";
+ }
+
+ return "Press '/' for commands...";
+ },
+ includeChildren: true,
+ }),
+ UniqueID.configure({
+ types: ["image"],
+ }),
+ SlashCommand(workspaceSlug, setIsSubmitting),
+ TiptapUnderline,
+ TextStyle,
+ Color,
+ Highlight.configure({
+ multicolor: true,
+ }),
+ TaskList.configure({
+ HTMLAttributes: {
+ class: "not-prose pl-2",
+ },
+ }),
+ TaskItem.configure({
+ HTMLAttributes: {
+ class: "flex items-start my-4",
+ },
+ nested: true,
+ }),
+ Markdown.configure({
+ html: true,
+ transformCopiedText: true,
+ }),
+ Table,
+ TableHeader,
+ CustomTableCell,
+ TableRow,
+ ];
diff --git a/web/components/tiptap/extensions/table/table-cell.ts b/web/components/tiptap/extensions/table/table-cell.ts
new file mode 100644
index 000000000..643cb8c64
--- /dev/null
+++ b/web/components/tiptap/extensions/table/table-cell.ts
@@ -0,0 +1,32 @@
+import { TableCell } from "@tiptap/extension-table-cell";
+
+export const CustomTableCell = TableCell.extend({
+ addAttributes() {
+ return {
+ ...this.parent?.(),
+ isHeader: {
+ default: false,
+ parseHTML: (element) => {
+ isHeader: element.tagName === "TD";
+ },
+ renderHTML: (attributes) => {
+ tag: attributes.isHeader ? "th" : "td";
+ },
+ },
+ };
+ },
+ renderHTML({ HTMLAttributes }) {
+ if (HTMLAttributes.isHeader) {
+ return [
+ "th",
+ {
+ ...HTMLAttributes,
+ class: `relative ${HTMLAttributes.class}`,
+ },
+ ["span", { class: "absolute top-0 right-0" }],
+ 0,
+ ];
+ }
+ return ["td", HTMLAttributes, 0];
+ },
+});
diff --git a/web/components/tiptap/extensions/table/table-header.ts b/web/components/tiptap/extensions/table/table-header.ts
new file mode 100644
index 000000000..f23aa93ef
--- /dev/null
+++ b/web/components/tiptap/extensions/table/table-header.ts
@@ -0,0 +1,7 @@
+import { TableHeader as BaseTableHeader } from "@tiptap/extension-table-header";
+
+const TableHeader = BaseTableHeader.extend({
+ content: "paragraph",
+});
+
+export { TableHeader };
diff --git a/web/components/tiptap/extensions/table/table.ts b/web/components/tiptap/extensions/table/table.ts
new file mode 100644
index 000000000..9b727bb51
--- /dev/null
+++ b/web/components/tiptap/extensions/table/table.ts
@@ -0,0 +1,9 @@
+import { Table as BaseTable } from "@tiptap/extension-table";
+
+const Table = BaseTable.configure({
+ resizable: true,
+ cellMinWidth: 100,
+ allowTableNodeSelection: true,
+});
+
+export { Table };
diff --git a/web/components/tiptap/extensions/updated-image.tsx b/web/components/tiptap/extensions/updated-image.tsx
new file mode 100644
index 000000000..b62050953
--- /dev/null
+++ b/web/components/tiptap/extensions/updated-image.tsx
@@ -0,0 +1,22 @@
+import Image from "@tiptap/extension-image";
+import TrackImageDeletionPlugin from "../plugins/delete-image";
+import UploadImagesPlugin from "../plugins/upload-image";
+
+const UpdatedImage = Image.extend({
+ addProseMirrorPlugins() {
+ return [UploadImagesPlugin(), TrackImageDeletionPlugin()];
+ },
+ addAttributes() {
+ return {
+ ...this.parent?.(),
+ width: {
+ default: "35%",
+ },
+ height: {
+ default: null,
+ },
+ };
+ },
+});
+
+export default UpdatedImage;
diff --git a/web/components/tiptap/index.tsx b/web/components/tiptap/index.tsx
new file mode 100644
index 000000000..84f691c35
--- /dev/null
+++ b/web/components/tiptap/index.tsx
@@ -0,0 +1,110 @@
+import { useImperativeHandle, useRef, forwardRef, useEffect } from "react";
+import { useEditor, EditorContent, Editor } from "@tiptap/react";
+import { useDebouncedCallback } from "use-debounce";
+// components
+import { EditorBubbleMenu } from "./bubble-menu";
+import { TiptapExtensions } from "./extensions";
+import { TiptapEditorProps } from "./props";
+import { ImageResizer } from "./extensions/image-resize";
+import { TableMenu } from "./table-menu";
+
+export interface ITipTapRichTextEditor {
+ value: string;
+ noBorder?: boolean;
+ borderOnFocus?: boolean;
+ customClassName?: string;
+ editorContentCustomClassNames?: string;
+ onChange?: (json: any, html: string) => void;
+ setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void;
+ setShouldShowAlert?: (showAlert: boolean) => void;
+ workspaceSlug: string;
+ editable?: boolean;
+ forwardedRef?: any;
+ debouncedUpdatesEnabled?: boolean;
+}
+
+const Tiptap = (props: ITipTapRichTextEditor) => {
+ const {
+ onChange,
+ debouncedUpdatesEnabled,
+ forwardedRef,
+ editable,
+ setIsSubmitting,
+ setShouldShowAlert,
+ editorContentCustomClassNames,
+ value,
+ noBorder,
+ workspaceSlug,
+ borderOnFocus,
+ customClassName,
+ } = props;
+
+ const editor = useEditor({
+ editable: editable ?? true,
+ editorProps: TiptapEditorProps(workspaceSlug, setIsSubmitting),
+ extensions: TiptapExtensions(workspaceSlug, setIsSubmitting),
+ content: value,
+ onUpdate: async ({ editor }) => {
+ // for instant feedback loop
+ setIsSubmitting?.("submitting");
+ setShouldShowAlert?.(true);
+ if (debouncedUpdatesEnabled) {
+ debouncedUpdates({ onChange, editor });
+ } else {
+ onChange?.(editor.getJSON(), editor.getHTML());
+ }
+ },
+ });
+
+ const editorRef: React.MutableRefObject = useRef(null);
+
+ useImperativeHandle(forwardedRef, () => ({
+ clearEditor: () => {
+ editorRef.current?.commands.clearContent();
+ },
+ setEditorValue: (content: string) => {
+ editorRef.current?.commands.setContent(content);
+ },
+ }));
+
+ const debouncedUpdates = useDebouncedCallback(async ({ onChange, editor }) => {
+ setTimeout(async () => {
+ if (onChange) {
+ onChange(editor.getJSON(), editor.getHTML());
+ }
+ }, 500);
+ }, 1000);
+
+ const editorClassNames = `relative w-full max-w-full sm:rounded-lg mt-2 p-3 relative focus:outline-none rounded-md
+ ${noBorder ? "" : "border border-custom-border-200"} ${
+ borderOnFocus ? "focus:border border-custom-border-300" : "focus:border-0"
+ } ${customClassName}`;
+
+ if (!editor) return null;
+ editorRef.current = editor;
+
+ return (
+ {
+ editor?.chain().focus().run();
+ }}
+ className={`tiptap-editor-container cursor-text ${editorClassNames}`}
+ >
+ {editor &&
}
+
+
+
+ {editor?.isActive("image") &&
}
+
+
+ );
+};
+
+const TipTapEditor = forwardRef((props, ref) => (
+
+));
+
+TipTapEditor.displayName = "TipTapEditor";
+
+export { TipTapEditor };
diff --git a/web/components/tiptap/plugins/delete-image.tsx b/web/components/tiptap/plugins/delete-image.tsx
new file mode 100644
index 000000000..fdf515ccc
--- /dev/null
+++ b/web/components/tiptap/plugins/delete-image.tsx
@@ -0,0 +1,68 @@
+import { EditorState, Plugin, PluginKey, Transaction } from "@tiptap/pm/state";
+import { Node as ProseMirrorNode } from "@tiptap/pm/model";
+import fileService from "services/file.service";
+
+const deleteKey = new PluginKey("delete-image");
+const IMAGE_NODE_TYPE = "image";
+
+interface ImageNode extends ProseMirrorNode {
+ attrs: {
+ src: string;
+ id: string;
+ };
+}
+
+const TrackImageDeletionPlugin = (): Plugin =>
+ new Plugin({
+ key: deleteKey,
+ appendTransaction: (transactions: readonly Transaction[], oldState: EditorState, newState: EditorState) => {
+ const newImageSources = new Set();
+ newState.doc.descendants((node) => {
+ if (node.type.name === IMAGE_NODE_TYPE) {
+ newImageSources.add(node.attrs.src);
+ }
+ });
+
+ transactions.forEach((transaction) => {
+ if (!transaction.docChanged) return;
+
+ const removedImages: ImageNode[] = [];
+
+ oldState.doc.descendants((oldNode, oldPos) => {
+ if (oldNode.type.name !== IMAGE_NODE_TYPE) return;
+ if (oldPos < 0 || oldPos > newState.doc.content.size) return;
+ if (!newState.doc.resolve(oldPos).parent) return;
+
+ const newNode = newState.doc.nodeAt(oldPos);
+
+ // Check if the node has been deleted or replaced
+ if (!newNode || newNode.type.name !== IMAGE_NODE_TYPE) {
+ if (!newImageSources.has(oldNode.attrs.src)) {
+ removedImages.push(oldNode as ImageNode);
+ }
+ }
+ });
+
+ removedImages.forEach(async (node) => {
+ const src = node.attrs.src;
+ await onNodeDeleted(src);
+ });
+ });
+
+ return null;
+ },
+ });
+
+export default TrackImageDeletionPlugin;
+
+async function onNodeDeleted(src: string): Promise {
+ try {
+ const assetUrlWithWorkspaceId = new URL(src).pathname.substring(1);
+ const resStatus = await fileService.deleteImage(assetUrlWithWorkspaceId);
+ if (resStatus === 204) {
+ console.log("Image deleted successfully");
+ }
+ } catch (error) {
+ console.error("Error deleting image: ", error);
+ }
+}
diff --git a/web/components/tiptap/plugins/upload-image.tsx b/web/components/tiptap/plugins/upload-image.tsx
new file mode 100644
index 000000000..bc0acdc54
--- /dev/null
+++ b/web/components/tiptap/plugins/upload-image.tsx
@@ -0,0 +1,127 @@
+import { EditorState, Plugin, PluginKey } from "@tiptap/pm/state";
+import { Decoration, DecorationSet, EditorView } from "@tiptap/pm/view";
+import fileService from "services/file.service";
+
+const uploadKey = new PluginKey("upload-image");
+
+const UploadImagesPlugin = () =>
+ new Plugin({
+ key: uploadKey,
+ state: {
+ init() {
+ return DecorationSet.empty;
+ },
+ apply(tr, set) {
+ set = set.map(tr.mapping, tr.doc);
+ // See if the transaction adds or removes any placeholders
+ const action = tr.getMeta(uploadKey);
+ if (action && action.add) {
+ const { id, pos, src } = action.add;
+
+ const placeholder = document.createElement("div");
+ placeholder.setAttribute("class", "img-placeholder");
+ const image = document.createElement("img");
+ image.setAttribute("class", "opacity-10 rounded-lg border border-custom-border-300");
+ image.src = src;
+ placeholder.appendChild(image);
+ const deco = Decoration.widget(pos + 1, placeholder, {
+ id,
+ });
+ set = set.add(tr.doc, [deco]);
+ } else if (action && action.remove) {
+ set = set.remove(set.find(undefined, undefined, (spec) => spec.id == action.remove.id));
+ }
+ return set;
+ },
+ },
+ props: {
+ decorations(state) {
+ return this.getState(state);
+ },
+ },
+ });
+
+export default UploadImagesPlugin;
+
+function findPlaceholder(state: EditorState, id: {}) {
+ const decos = uploadKey.getState(state);
+ const found = decos.find(
+ undefined,
+ undefined,
+ (spec: { id: number | undefined }) => spec.id == id
+ );
+ return found.length ? found[0].from : null;
+}
+
+export async function startImageUpload(
+ file: File,
+ view: EditorView,
+ pos: number,
+ workspaceSlug: string,
+ setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
+) {
+ if (!file.type.includes("image/")) {
+ return;
+ }
+
+ const id = {};
+
+ const tr = view.state.tr;
+ if (!tr.selection.empty) tr.deleteSelection();
+
+ const reader = new FileReader();
+ reader.readAsDataURL(file);
+ reader.onload = () => {
+ tr.setMeta(uploadKey, {
+ add: {
+ id,
+ pos,
+ src: reader.result,
+ },
+ });
+ view.dispatch(tr);
+ };
+
+ if (!workspaceSlug) {
+ return;
+ }
+ setIsSubmitting?.("submitting");
+ const src = await UploadImageHandler(file, workspaceSlug);
+ const { schema } = view.state;
+ pos = findPlaceholder(view.state, id);
+
+ if (pos == null) return;
+ const imageSrc = typeof src === "object" ? reader.result : src;
+
+ const node = schema.nodes.image.create({ src: imageSrc });
+ const transaction = view.state.tr
+ .replaceWith(pos, pos, node)
+ .setMeta(uploadKey, { remove: { id } });
+ view.dispatch(transaction);
+}
+
+const UploadImageHandler = (file: File, workspaceSlug: string): Promise => {
+ if (!workspaceSlug) {
+ return Promise.reject("Workspace slug is missing");
+ }
+ try {
+ const formData = new FormData();
+ formData.append("asset", file);
+ formData.append("attributes", JSON.stringify({}));
+
+ return new Promise(async (resolve, reject) => {
+ const imageUrl = await fileService
+ .uploadFile(workspaceSlug, formData)
+ .then((response) => response.asset);
+
+ const image = new Image();
+ image.src = imageUrl;
+ image.onload = () => {
+ resolve(imageUrl);
+ };
+ });
+ } catch (error) {
+ console.log(error);
+ return Promise.reject(error);
+ }
+};
diff --git a/web/components/tiptap/props.tsx b/web/components/tiptap/props.tsx
new file mode 100644
index 000000000..8233e3ab4
--- /dev/null
+++ b/web/components/tiptap/props.tsx
@@ -0,0 +1,69 @@
+import { EditorProps } from "@tiptap/pm/view";
+import { startImageUpload } from "./plugins/upload-image";
+import { findTableAncestor } from "./table-menu";
+
+export function TiptapEditorProps(
+ workspaceSlug: string,
+ setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
+): EditorProps {
+ return {
+ attributes: {
+ class: `prose prose-brand max-w-full prose-headings:font-display font-default focus:outline-none`,
+ },
+ handleDOMEvents: {
+ keydown: (_view, event) => {
+ // prevent default event listeners from firing when slash command is active
+ if (["ArrowUp", "ArrowDown", "Enter"].includes(event.key)) {
+ const slashCommand = document.querySelector("#slash-command");
+ if (slashCommand) {
+ return true;
+ }
+ }
+ },
+ },
+ handlePaste: (view, event) => {
+ if (typeof window !== "undefined") {
+ const selection: any = window?.getSelection();
+ if (selection.rangeCount !== 0) {
+ const range = selection.getRangeAt(0);
+ if (findTableAncestor(range.startContainer)) {
+ return;
+ }
+ }
+ }
+ if (event.clipboardData && event.clipboardData.files && event.clipboardData.files[0]) {
+ event.preventDefault();
+ const file = event.clipboardData.files[0];
+ const pos = view.state.selection.from;
+ startImageUpload(file, view, pos, workspaceSlug, setIsSubmitting);
+ return true;
+ }
+ return false;
+ },
+ handleDrop: (view, event, _slice, moved) => {
+ if (typeof window !== "undefined") {
+ const selection: any = window?.getSelection();
+ if (selection.rangeCount !== 0) {
+ const range = selection.getRangeAt(0);
+ if (findTableAncestor(range.startContainer)) {
+ return;
+ }
+ }
+ }
+ if (!moved && event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files[0]) {
+ event.preventDefault();
+ const file = event.dataTransfer.files[0];
+ const coordinates = view.posAtCoords({
+ left: event.clientX,
+ top: event.clientY,
+ });
+ // here we deduct 1 from the pos or else the image will create an extra node
+ if (coordinates) {
+ startImageUpload(file, view, coordinates.pos - 1, workspaceSlug, setIsSubmitting);
+ }
+ return true;
+ }
+ return false;
+ },
+ };
+}
diff --git a/web/components/tiptap/slash-command/index.tsx b/web/components/tiptap/slash-command/index.tsx
new file mode 100644
index 000000000..46bf5ea5a
--- /dev/null
+++ b/web/components/tiptap/slash-command/index.tsx
@@ -0,0 +1,365 @@
+import React, { useState, useEffect, useCallback, ReactNode, useRef, useLayoutEffect } from "react";
+import { Editor, Range, Extension } from "@tiptap/core";
+import Suggestion from "@tiptap/suggestion";
+import { ReactRenderer } from "@tiptap/react";
+import tippy from "tippy.js";
+import {
+ Heading1,
+ Heading2,
+ Heading3,
+ List,
+ ListOrdered,
+ Text,
+ TextQuote,
+ Code,
+ MinusSquare,
+ CheckSquare,
+ ImageIcon,
+ Table,
+} from "lucide-react";
+import { startImageUpload } from "../plugins/upload-image";
+import { cn } from "../utils";
+
+interface CommandItemProps {
+ title: string;
+ description: string;
+ icon: ReactNode;
+}
+
+interface CommandProps {
+ editor: Editor;
+ range: Range;
+}
+
+const Command = Extension.create({
+ name: "slash-command",
+ addOptions() {
+ return {
+ suggestion: {
+ char: "/",
+ command: ({ editor, range, props }: { editor: Editor; range: Range; props: any }) => {
+ props.command({ editor, range });
+ },
+ },
+ };
+ },
+ addProseMirrorPlugins() {
+ return [
+ Suggestion({
+ editor: this.editor,
+ allow({ editor }) {
+ return !editor.isActive("table");
+ },
+ ...this.options.suggestion,
+ }),
+ ];
+ },
+});
+
+const getSuggestionItems =
+ (
+ workspaceSlug: string,
+ setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
+ ) =>
+ ({ query }: { query: string }) =>
+ [
+ {
+ title: "Text",
+ description: "Just start typing with plain text.",
+ searchTerms: ["p", "paragraph"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").run();
+ },
+ },
+ {
+ title: "Heading 1",
+ description: "Big section heading.",
+ searchTerms: ["title", "big", "large"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 1 }).run();
+ },
+ },
+ {
+ title: "Heading 2",
+ description: "Medium section heading.",
+ searchTerms: ["subtitle", "medium"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 2 }).run();
+ },
+ },
+ {
+ title: "Heading 3",
+ description: "Small section heading.",
+ searchTerms: ["subtitle", "small"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).setNode("heading", { level: 3 }).run();
+ },
+ },
+ {
+ title: "To-do List",
+ description: "Track tasks with a to-do list.",
+ searchTerms: ["todo", "task", "list", "check", "checkbox"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).toggleTaskList().run();
+ },
+ },
+ {
+ title: "Bullet List",
+ description: "Create a simple bullet list.",
+ searchTerms: ["unordered", "point"],
+ icon:
,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).toggleBulletList().run();
+ },
+ },
+ {
+ title: "Divider",
+ description: "Visually divide blocks",
+ searchTerms: ["line", "divider", "horizontal", "rule", "separate"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).setHorizontalRule().run();
+ },
+ },
+ {
+ title: "Table",
+ description: "Create a Table",
+ searchTerms: ["table", "cell", "db", "data", "tabular"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor
+ .chain()
+ .focus()
+ .deleteRange(range)
+ .insertTable({ rows: 3, cols: 3, withHeaderRow: true })
+ .run();
+ },
+ },
+ {
+ title: "Numbered List",
+ description: "Create a list with numbering.",
+ searchTerms: ["ordered"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).toggleOrderedList().run();
+ },
+ },
+ {
+ title: "Quote",
+ description: "Capture a quote.",
+ searchTerms: ["blockquote"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) =>
+ editor
+ .chain()
+ .focus()
+ .deleteRange(range)
+ .toggleNode("paragraph", "paragraph")
+ .toggleBlockquote()
+ .run(),
+ },
+ {
+ title: "Code",
+ description: "Capture a code snippet.",
+ searchTerms: ["codeblock"],
+ icon:
,
+ command: ({ editor, range }: CommandProps) =>
+ editor.chain().focus().deleteRange(range).toggleCodeBlock().run(),
+ },
+ {
+ title: "Image",
+ description: "Upload an image from your computer.",
+ searchTerms: ["photo", "picture", "media"],
+ icon: ,
+ command: ({ editor, range }: CommandProps) => {
+ editor.chain().focus().deleteRange(range).run();
+ // upload image
+ const input = document.createElement("input");
+ input.type = "file";
+ input.accept = "image/*";
+ input.onchange = async () => {
+ if (input.files?.length) {
+ const file = input.files[0];
+ const pos = editor.view.state.selection.from;
+ startImageUpload(file, editor.view, pos, workspaceSlug, setIsSubmitting);
+ }
+ };
+ input.click();
+ },
+ },
+ ].filter((item) => {
+ if (typeof query === "string" && query.length > 0) {
+ const search = query.toLowerCase();
+ return (
+ item.title.toLowerCase().includes(search) ||
+ item.description.toLowerCase().includes(search) ||
+ (item.searchTerms && item.searchTerms.some((term: string) => term.includes(search)))
+ );
+ }
+ return true;
+ });
+
+export const updateScrollView = (container: HTMLElement, item: HTMLElement) => {
+ const containerHeight = container.offsetHeight;
+ const itemHeight = item ? item.offsetHeight : 0;
+
+ const top = item.offsetTop;
+ const bottom = top + itemHeight;
+
+ if (top < container.scrollTop) {
+ container.scrollTop -= container.scrollTop - top + 5;
+ } else if (bottom > containerHeight + container.scrollTop) {
+ container.scrollTop += bottom - containerHeight - container.scrollTop + 5;
+ }
+};
+
+const CommandList = ({
+ items,
+ command,
+}: {
+ items: CommandItemProps[];
+ command: any;
+ editor: any;
+ range: any;
+}) => {
+ const [selectedIndex, setSelectedIndex] = useState(0);
+
+ const selectItem = useCallback(
+ (index: number) => {
+ const item = items[index];
+ if (item) {
+ command(item);
+ }
+ },
+ [command, items]
+ );
+
+ useEffect(() => {
+ const navigationKeys = ["ArrowUp", "ArrowDown", "Enter"];
+ const onKeyDown = (e: KeyboardEvent) => {
+ if (navigationKeys.includes(e.key)) {
+ e.preventDefault();
+ if (e.key === "ArrowUp") {
+ setSelectedIndex((selectedIndex + items.length - 1) % items.length);
+ return true;
+ }
+ if (e.key === "ArrowDown") {
+ setSelectedIndex((selectedIndex + 1) % items.length);
+ return true;
+ }
+ if (e.key === "Enter") {
+ selectItem(selectedIndex);
+ return true;
+ }
+ return false;
+ }
+ };
+ document.addEventListener("keydown", onKeyDown);
+ return () => {
+ document.removeEventListener("keydown", onKeyDown);
+ };
+ }, [items, selectedIndex, setSelectedIndex, selectItem]);
+
+ useEffect(() => {
+ setSelectedIndex(0);
+ }, [items]);
+
+ const commandListContainer = useRef(null);
+
+ useLayoutEffect(() => {
+ const container = commandListContainer?.current;
+
+ const item = container?.children[selectedIndex] as HTMLElement;
+
+ if (item && container) updateScrollView(container, item);
+ }, [selectedIndex]);
+
+ return items.length > 0 ? (
+
+ {items.map((item: CommandItemProps, index: number) => (
+
selectItem(index)}
+ >
+
+
{item.title}
+
{item.description}
+
+
+ ))}
+
+ ) : null;
+};
+
+const renderItems = () => {
+ let component: ReactRenderer | null = null;
+ let popup: any | null = null;
+
+ return {
+ onStart: (props: { editor: Editor; clientRect: DOMRect }) => {
+ component = new ReactRenderer(CommandList, {
+ props,
+ editor: props.editor,
+ });
+
+ // @ts-ignore
+ popup = tippy("body", {
+ getReferenceClientRect: props.clientRect,
+ appendTo: () => document.querySelector("#tiptap-container"),
+ content: component.element,
+ showOnCreate: true,
+ interactive: true,
+ trigger: "manual",
+ placement: "bottom-start",
+ });
+ },
+ onUpdate: (props: { editor: Editor; clientRect: DOMRect }) => {
+ component?.updateProps(props);
+
+ popup &&
+ popup[0].setProps({
+ getReferenceClientRect: props.clientRect,
+ });
+ },
+ onKeyDown: (props: { event: KeyboardEvent }) => {
+ if (props.event.key === "Escape") {
+ popup?.[0].hide();
+
+ return true;
+ }
+
+ // @ts-ignore
+ return component?.ref?.onKeyDown(props);
+ },
+ onExit: () => {
+ popup?.[0].destroy();
+ component?.destroy();
+ },
+ };
+};
+
+export const SlashCommand = (
+ workspaceSlug: string,
+ setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
+) =>
+ Command.configure({
+ suggestion: {
+ items: getSuggestionItems(workspaceSlug, setIsSubmitting),
+ render: renderItems,
+ },
+ });
+
+export default SlashCommand;
diff --git a/web/components/tiptap/table-menu/InsertBottomTableIcon.tsx b/web/components/tiptap/table-menu/InsertBottomTableIcon.tsx
new file mode 100644
index 000000000..0e42ba648
--- /dev/null
+++ b/web/components/tiptap/table-menu/InsertBottomTableIcon.tsx
@@ -0,0 +1,16 @@
+const InsertBottomTableIcon = (props: any) => (
+
+
+
+);
+
+export default InsertBottomTableIcon;
diff --git a/web/components/tiptap/table-menu/InsertLeftTableIcon.tsx b/web/components/tiptap/table-menu/InsertLeftTableIcon.tsx
new file mode 100644
index 000000000..1fd75fe87
--- /dev/null
+++ b/web/components/tiptap/table-menu/InsertLeftTableIcon.tsx
@@ -0,0 +1,15 @@
+const InsertLeftTableIcon = (props: any) => (
+
+
+
+);
+export default InsertLeftTableIcon;
diff --git a/web/components/tiptap/table-menu/InsertRightTableIcon.tsx b/web/components/tiptap/table-menu/InsertRightTableIcon.tsx
new file mode 100644
index 000000000..1a6570969
--- /dev/null
+++ b/web/components/tiptap/table-menu/InsertRightTableIcon.tsx
@@ -0,0 +1,16 @@
+const InsertRightTableIcon = (props: any) => (
+
+
+
+);
+
+export default InsertRightTableIcon;
diff --git a/web/components/tiptap/table-menu/InsertTopTableIcon.tsx b/web/components/tiptap/table-menu/InsertTopTableIcon.tsx
new file mode 100644
index 000000000..8f04f4f61
--- /dev/null
+++ b/web/components/tiptap/table-menu/InsertTopTableIcon.tsx
@@ -0,0 +1,15 @@
+const InsertTopTableIcon = (props: any) => (
+
+
+
+);
+export default InsertTopTableIcon;
diff --git a/web/components/tiptap/table-menu/index.tsx b/web/components/tiptap/table-menu/index.tsx
new file mode 100644
index 000000000..94f9c0f8d
--- /dev/null
+++ b/web/components/tiptap/table-menu/index.tsx
@@ -0,0 +1,143 @@
+import { useState, useEffect } from "react";
+import { Rows, Columns, ToggleRight } from "lucide-react";
+import { cn } from "../utils";
+import { Tooltip } from "components/ui";
+import InsertLeftTableIcon from "./InsertLeftTableIcon";
+import InsertRightTableIcon from "./InsertRightTableIcon";
+import InsertTopTableIcon from "./InsertTopTableIcon";
+import InsertBottomTableIcon from "./InsertBottomTableIcon";
+
+interface TableMenuItem {
+ command: () => void;
+ icon: any;
+ key: string;
+ name: string;
+}
+
+export const findTableAncestor = (node: Node | null): HTMLTableElement | null => {
+ while (node !== null && node.nodeName !== "TABLE") {
+ node = node.parentNode;
+ }
+ return node as HTMLTableElement;
+};
+
+export const TableMenu = ({ editor }: { editor: any }) => {
+ const [tableLocation, setTableLocation] = useState({ bottom: 0, left: 0 });
+ const isOpen = editor?.isActive("table");
+
+ const items: TableMenuItem[] = [
+ {
+ command: () => editor.chain().focus().addColumnBefore().run(),
+ icon: InsertLeftTableIcon,
+ key: "insert-column-left",
+ name: "Insert 1 column left",
+ },
+ {
+ command: () => editor.chain().focus().addColumnAfter().run(),
+ icon: InsertRightTableIcon,
+ key: "insert-column-right",
+ name: "Insert 1 column right",
+ },
+ {
+ command: () => editor.chain().focus().addRowBefore().run(),
+ icon: InsertTopTableIcon,
+ key: "insert-row-above",
+ name: "Insert 1 row above",
+ },
+ {
+ command: () => editor.chain().focus().addRowAfter().run(),
+ icon: InsertBottomTableIcon,
+ key: "insert-row-below",
+ name: "Insert 1 row below",
+ },
+ {
+ command: () => editor.chain().focus().deleteColumn().run(),
+ icon: Columns,
+ key: "delete-column",
+ name: "Delete column",
+ },
+ {
+ command: () => editor.chain().focus().deleteRow().run(),
+ icon: Rows,
+ key: "delete-row",
+ name: "Delete row",
+ },
+ {
+ command: () => editor.chain().focus().toggleHeaderRow().run(),
+ icon: ToggleRight,
+ key: "toggle-header-row",
+ name: "Toggle header row",
+ },
+ ];
+
+ useEffect(() => {
+ if (!window) return;
+
+ const handleWindowClick = () => {
+ const selection: any = window?.getSelection();
+
+ if (selection.rangeCount !== 0) {
+ const range = selection.getRangeAt(0);
+ const tableNode = findTableAncestor(range.startContainer);
+
+ let parent = tableNode?.parentElement;
+
+ if (tableNode) {
+ const tableRect = tableNode.getBoundingClientRect();
+ const tableCenter = tableRect.left + tableRect.width / 2;
+ const menuWidth = 45;
+ const menuLeft = tableCenter - menuWidth / 2;
+ const tableBottom = tableRect.bottom;
+
+ setTableLocation({ bottom: tableBottom, left: menuLeft });
+
+ while (parent) {
+ if (!parent.classList.contains("disable-scroll"))
+ parent.classList.add("disable-scroll");
+ parent = parent.parentElement;
+ }
+ } else {
+ const scrollDisabledContainers = document.querySelectorAll(".disable-scroll");
+
+ scrollDisabledContainers.forEach((container) => {
+ container.classList.remove("disable-scroll");
+ });
+ }
+ }
+ };
+
+ window.addEventListener("click", handleWindowClick);
+
+ return () => {
+ window.removeEventListener("click", handleWindowClick);
+ };
+ }, [tableLocation, editor]);
+
+ return (
+
+ {items.map((item, index) => (
+
+
+
+
+
+ ))}
+
+ );
+};
diff --git a/web/components/tiptap/utils.ts b/web/components/tiptap/utils.ts
new file mode 100644
index 000000000..a5ef19350
--- /dev/null
+++ b/web/components/tiptap/utils.ts
@@ -0,0 +1,6 @@
+import { clsx, type ClassValue } from "clsx";
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
diff --git a/web/components/toast-alert/index.tsx b/web/components/toast-alert/index.tsx
new file mode 100644
index 000000000..5d0c0123c
--- /dev/null
+++ b/web/components/toast-alert/index.tsx
@@ -0,0 +1,67 @@
+import React from "react";
+// hooks
+import {
+ CheckCircleIcon,
+ ExclamationTriangleIcon,
+ InformationCircleIcon,
+ XCircleIcon,
+ XMarkIcon,
+} from "@heroicons/react/24/outline";
+import useToast from "hooks/use-toast";
+// icons
+
+const ToastAlerts = () => {
+ const { alerts, removeAlert } = useToast();
+
+ if (!alerts) return null;
+
+ return (
+
+ {alerts.map((alert) => (
+
+
+ removeAlert(alert.id)}
+ >
+ Dismiss
+
+
+
+
+
+
+ {alert.type === "success" ? (
+
+ ) : alert.type === "error" ? (
+
+ ) : alert.type === "warning" ? (
+
+ ) : (
+
+ )}
+
+
+
{alert.title}
+ {alert.message &&
{alert.message}
}
+
+
+
+
+ ))}
+
+ );
+};
+
+export default ToastAlerts;
diff --git a/apps/app/components/ui/avatar.tsx b/web/components/ui/avatar.tsx
similarity index 100%
rename from apps/app/components/ui/avatar.tsx
rename to web/components/ui/avatar.tsx
diff --git a/apps/app/components/ui/buttons/danger-button.tsx b/web/components/ui/buttons/danger-button.tsx
similarity index 100%
rename from apps/app/components/ui/buttons/danger-button.tsx
rename to web/components/ui/buttons/danger-button.tsx
diff --git a/apps/app/components/ui/buttons/index.ts b/web/components/ui/buttons/index.ts
similarity index 100%
rename from apps/app/components/ui/buttons/index.ts
rename to web/components/ui/buttons/index.ts
diff --git a/apps/app/components/ui/buttons/primary-button.tsx b/web/components/ui/buttons/primary-button.tsx
similarity index 100%
rename from apps/app/components/ui/buttons/primary-button.tsx
rename to web/components/ui/buttons/primary-button.tsx
diff --git a/apps/app/components/ui/buttons/secondary-button.tsx b/web/components/ui/buttons/secondary-button.tsx
similarity index 100%
rename from apps/app/components/ui/buttons/secondary-button.tsx
rename to web/components/ui/buttons/secondary-button.tsx
diff --git a/apps/app/components/ui/buttons/type.d.ts b/web/components/ui/buttons/type.d.ts
similarity index 100%
rename from apps/app/components/ui/buttons/type.d.ts
rename to web/components/ui/buttons/type.d.ts
diff --git a/apps/app/components/ui/circular-progress.tsx b/web/components/ui/circular-progress.tsx
similarity index 100%
rename from apps/app/components/ui/circular-progress.tsx
rename to web/components/ui/circular-progress.tsx
diff --git a/apps/app/components/ui/date.tsx b/web/components/ui/date.tsx
similarity index 100%
rename from apps/app/components/ui/date.tsx
rename to web/components/ui/date.tsx
diff --git a/apps/app/components/ui/datepicker.tsx b/web/components/ui/datepicker.tsx
similarity index 100%
rename from apps/app/components/ui/datepicker.tsx
rename to web/components/ui/datepicker.tsx
diff --git a/apps/app/components/ui/dropdowns/context-menu.tsx b/web/components/ui/dropdowns/context-menu.tsx
similarity index 100%
rename from apps/app/components/ui/dropdowns/context-menu.tsx
rename to web/components/ui/dropdowns/context-menu.tsx
diff --git a/apps/app/components/ui/dropdowns/custom-menu.tsx b/web/components/ui/dropdowns/custom-menu.tsx
similarity index 100%
rename from apps/app/components/ui/dropdowns/custom-menu.tsx
rename to web/components/ui/dropdowns/custom-menu.tsx
diff --git a/apps/app/components/ui/dropdowns/custom-search-select.tsx b/web/components/ui/dropdowns/custom-search-select.tsx
similarity index 100%
rename from apps/app/components/ui/dropdowns/custom-search-select.tsx
rename to web/components/ui/dropdowns/custom-search-select.tsx
diff --git a/apps/app/components/ui/dropdowns/custom-select.tsx b/web/components/ui/dropdowns/custom-select.tsx
similarity index 97%
rename from apps/app/components/ui/dropdowns/custom-select.tsx
rename to web/components/ui/dropdowns/custom-select.tsx
index 4e495a210..ae814dccb 100644
--- a/apps/app/components/ui/dropdowns/custom-select.tsx
+++ b/web/components/ui/dropdowns/custom-select.tsx
@@ -41,7 +41,7 @@ const CustomSelect = ({
>
<>
{customButton ? (
- {customButton}
+ {customButton}
) : (
= ({ data, noTooltip=false }) => {
+export const LinearProgressIndicator: React.FC = ({ data, noTooltip = false }) => {
const total = data.reduce((acc: any, cur: any) => acc + cur.value, 0);
let progress = 0;
@@ -17,12 +17,13 @@ export const LinearProgressIndicator: React.FC = ({ data, noTooltip=false
backgroundColor: item.color,
};
progress += item.value;
- if (noTooltip) return
- else return (
-
-
-
- );
+ if (noTooltip) return
;
+ else
+ return (
+
+
+
+ );
});
return (
diff --git a/web/components/ui/loader.tsx b/web/components/ui/loader.tsx
new file mode 100644
index 000000000..b9d13883a
--- /dev/null
+++ b/web/components/ui/loader.tsx
@@ -0,0 +1,25 @@
+import React from "react";
+
+type Props = {
+ children: React.ReactNode;
+ className?: string;
+};
+
+const Loader = ({ children, className = "" }: Props) => (
+
+ {children}
+
+);
+
+type ItemProps = {
+ height?: string;
+ width?: string;
+};
+
+const Item: React.FC = ({ height = "auto", width = "auto" }) => (
+
+);
+
+Loader.Item = Item;
+
+export { Loader };
diff --git a/apps/app/components/ui/markdown-to-component.tsx b/web/components/ui/markdown-to-component.tsx
similarity index 100%
rename from apps/app/components/ui/markdown-to-component.tsx
rename to web/components/ui/markdown-to-component.tsx
diff --git a/apps/app/components/ui/multi-level-dropdown.tsx b/web/components/ui/multi-level-dropdown.tsx
similarity index 100%
rename from apps/app/components/ui/multi-level-dropdown.tsx
rename to web/components/ui/multi-level-dropdown.tsx
diff --git a/apps/app/components/ui/multi-level-select.tsx b/web/components/ui/multi-level-select.tsx
similarity index 100%
rename from apps/app/components/ui/multi-level-select.tsx
rename to web/components/ui/multi-level-select.tsx
diff --git a/apps/app/components/ui/product-updates-modal.tsx b/web/components/ui/product-updates-modal.tsx
similarity index 100%
rename from apps/app/components/ui/product-updates-modal.tsx
rename to web/components/ui/product-updates-modal.tsx
diff --git a/apps/app/components/ui/profile-empty-state.tsx b/web/components/ui/profile-empty-state.tsx
similarity index 100%
rename from apps/app/components/ui/profile-empty-state.tsx
rename to web/components/ui/profile-empty-state.tsx
diff --git a/apps/app/components/ui/progress-bar.tsx b/web/components/ui/progress-bar.tsx
similarity index 100%
rename from apps/app/components/ui/progress-bar.tsx
rename to web/components/ui/progress-bar.tsx
diff --git a/apps/app/components/ui/range-datepicker.tsx b/web/components/ui/range-datepicker.tsx
similarity index 100%
rename from apps/app/components/ui/range-datepicker.tsx
rename to web/components/ui/range-datepicker.tsx
diff --git a/apps/app/components/ui/spinner.tsx b/web/components/ui/spinner.tsx
similarity index 100%
rename from apps/app/components/ui/spinner.tsx
rename to web/components/ui/spinner.tsx
diff --git a/apps/app/components/ui/text-area/index.tsx b/web/components/ui/text-area/index.tsx
similarity index 100%
rename from apps/app/components/ui/text-area/index.tsx
rename to web/components/ui/text-area/index.tsx
diff --git a/apps/app/components/ui/text-area/types.d.ts b/web/components/ui/text-area/types.d.ts
similarity index 100%
rename from apps/app/components/ui/text-area/types.d.ts
rename to web/components/ui/text-area/types.d.ts
diff --git a/apps/app/components/ui/toggle-switch.tsx b/web/components/ui/toggle-switch.tsx
similarity index 100%
rename from apps/app/components/ui/toggle-switch.tsx
rename to web/components/ui/toggle-switch.tsx
diff --git a/apps/app/components/ui/tooltip.tsx b/web/components/ui/tooltip.tsx
similarity index 100%
rename from apps/app/components/ui/tooltip.tsx
rename to web/components/ui/tooltip.tsx
diff --git a/apps/app/components/views/delete-view-modal.tsx b/web/components/views/delete-view-modal.tsx
similarity index 97%
rename from apps/app/components/views/delete-view-modal.tsx
rename to web/components/views/delete-view-modal.tsx
index 61c627430..c65f7ba29 100644
--- a/apps/app/components/views/delete-view-modal.tsx
+++ b/web/components/views/delete-view-modal.tsx
@@ -46,8 +46,9 @@ export const DeleteViewModal: React.FC = ({ isOpen, data, setIsOpen, user
await viewsService
.deleteView(workspaceSlug as string, projectId as string, data.id, user)
.then(() => {
- mutate(VIEWS_LIST(projectId as string), (views) =>
- views?.filter((view) => view.id !== data.id)
+ mutate(
+ VIEWS_LIST(projectId as string),
+ (views) => views?.filter((view) => view.id !== data.id)
);
handleClose();
diff --git a/apps/app/components/views/form.tsx b/web/components/views/form.tsx
similarity index 100%
rename from apps/app/components/views/form.tsx
rename to web/components/views/form.tsx
diff --git a/apps/app/components/views/gantt-chart.tsx b/web/components/views/gantt-chart.tsx
similarity index 78%
rename from apps/app/components/views/gantt-chart.tsx
rename to web/components/views/gantt-chart.tsx
index 36022f6fa..b25f034cd 100644
--- a/apps/app/components/views/gantt-chart.tsx
+++ b/web/components/views/gantt-chart.tsx
@@ -6,6 +6,7 @@ import { useRouter } from "next/router";
import useGanttChartViewIssues from "hooks/gantt-chart/view-issues-view";
import useUser from "hooks/use-user";
import { updateGanttIssue } from "components/gantt-chart/hooks/block-update";
+import useProjectDetails from "hooks/use-project-details";
// components
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
@@ -19,6 +20,7 @@ export const ViewIssuesGanttChartView: FC = ({}) => {
const { workspaceSlug, projectId, viewId } = router.query;
const { user } = useUser();
+ const { projectDetails } = useProjectDetails();
const { ganttIssues, mutateGanttIssues } = useGanttChartViewIssues(
workspaceSlug as string,
@@ -26,6 +28,8 @@ export const ViewIssuesGanttChartView: FC = ({}) => {
viewId as string
);
+ const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
+
return (
= ({}) => {
}
SidebarBlockRender={IssueGanttSidebarBlock}
BlockRender={IssueGanttBlock}
+ enableBlockLeftResize={isAllowed}
+ enableBlockRightResize={isAllowed}
+ enableBlockMove={isAllowed}
+ enableReorder={isAllowed}
/>
);
diff --git a/apps/app/components/views/index.ts b/web/components/views/index.ts
similarity index 100%
rename from apps/app/components/views/index.ts
rename to web/components/views/index.ts
diff --git a/apps/app/components/views/modal.tsx b/web/components/views/modal.tsx
similarity index 100%
rename from apps/app/components/views/modal.tsx
rename to web/components/views/modal.tsx
diff --git a/apps/app/components/views/select-filters.tsx b/web/components/views/select-filters.tsx
similarity index 95%
rename from apps/app/components/views/select-filters.tsx
rename to web/components/views/select-filters.tsx
index 7016afc00..52671f41f 100644
--- a/apps/app/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 { PriorityIcon, StateGroupIcon } from "components/icons";
// helpers
import { getStatesList } from "helpers/state.helper";
import { checkIfArraysHaveSameElements } from "helpers/array.helper";
@@ -78,8 +78,10 @@ export const SelectFilters: React.FC = ({
setIsDateFilterModalOpen(false)}
+ isOpen={isDateFilterModalOpen}
+ onSelect={onSelect}
/>
)}
= ({
id: priority === null ? "null" : priority,
label: (
- {getPriorityIcon(priority)} {priority ?? "None"}
+
+ {priority ?? "None"}
),
value: {
@@ -116,7 +119,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/apps/app/components/views/single-view-item.tsx b/web/components/views/single-view-item.tsx
similarity index 100%
rename from apps/app/components/views/single-view-item.tsx
rename to web/components/views/single-view-item.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/add-comment.tsx b/web/components/web-view/add-comment.tsx
new file mode 100644
index 000000000..b4f49d7be
--- /dev/null
+++ b/web/components/web-view/add-comment.tsx
@@ -0,0 +1,133 @@
+import React from "react";
+
+// next
+import { useRouter } from "next/router";
+
+// react-hook-form
+import { useForm, Controller } from "react-hook-form";
+
+// hooks
+import useProjectDetails from "hooks/use-project-details";
+
+// components
+import { TipTapEditor } from "components/tiptap";
+
+// icons
+import { Send } from "lucide-react";
+
+// ui
+import { Icon, SecondaryButton, Tooltip, PrimaryButton } from "components/ui";
+
+// types
+import type { IIssueComment } from "types";
+
+const defaultValues: Partial = {
+ access: "INTERNAL",
+ comment_html: "",
+};
+
+type Props = {
+ disabled?: boolean;
+ onSubmit: (data: IIssueComment) => Promise;
+};
+
+const commentAccess = [
+ {
+ icon: "lock",
+ key: "INTERNAL",
+ label: "Private",
+ },
+ {
+ icon: "public",
+ key: "EXTERNAL",
+ label: "Public",
+ },
+];
+
+export const AddComment: React.FC = ({ disabled = false, onSubmit }) => {
+ const editorRef = React.useRef(null);
+
+ const router = useRouter();
+ const { workspaceSlug } = router.query;
+
+ const { projectDetails } = useProjectDetails();
+
+ const showAccessSpecifier = projectDetails?.is_deployed;
+
+ const {
+ control,
+ formState: { isSubmitting },
+ handleSubmit,
+ reset,
+ } = useForm({ defaultValues });
+
+ const handleAddComment = async (formData: IIssueComment) => {
+ if (!formData.comment_html || isSubmitting) return;
+
+ await onSubmit(formData).then(() => {
+ reset(defaultValues);
+ editorRef.current?.clearEditor();
+ });
+ };
+
+ return (
+
+ );
+};
diff --git a/web/components/web-view/create-update-link-form.tsx b/web/components/web-view/create-update-link-form.tsx
new file mode 100644
index 000000000..fa1a33939
--- /dev/null
+++ b/web/components/web-view/create-update-link-form.tsx
@@ -0,0 +1,186 @@
+// react
+import React, { useEffect } from "react";
+
+// next
+import { useRouter } from "next/router";
+
+// swr
+import { mutate } from "swr";
+
+// react hooks form
+import { useForm } from "react-hook-form";
+
+// services
+import issuesService from "services/issues.service";
+
+// fetch keys
+import { ISSUE_DETAILS } from "constants/fetch-keys";
+
+// hooks
+import useToast from "hooks/use-toast";
+
+// ui
+import { PrimaryButton, Input } from "components/ui";
+
+// types
+import type { linkDetails, IIssueLink } from "types";
+
+type Props = {
+ isOpen: boolean;
+ data?: linkDetails;
+ links?: linkDetails[];
+ onSuccess: () => void;
+};
+
+export const CreateUpdateLinkForm: React.FC = (props) => {
+ const { isOpen, data, links, onSuccess } = props;
+
+ const router = useRouter();
+ const { workspaceSlug, projectId, issueId } = router.query;
+
+ const { setToastAlert } = useToast();
+
+ const {
+ register,
+ handleSubmit,
+ reset,
+ formState: { errors, isSubmitting },
+ } = useForm({
+ defaultValues: {
+ title: "",
+ url: "",
+ },
+ });
+
+ useEffect(() => {
+ if (!data) return;
+ reset({
+ title: data.title,
+ url: data.url,
+ });
+ }, [data, reset]);
+
+ useEffect(() => {
+ if (!isOpen)
+ reset({
+ title: "",
+ url: "",
+ });
+ }, [isOpen, reset]);
+
+ const onSubmit = async (formData: IIssueLink) => {
+ if (!workspaceSlug || !projectId || !issueId) return;
+
+ const payload = { metadata: {}, ...formData };
+
+ if (!data)
+ await issuesService
+ .createIssueLink(
+ workspaceSlug.toString(),
+ projectId.toString(),
+ issueId.toString(),
+ payload
+ )
+ .then(() => {
+ onSuccess();
+ mutate(ISSUE_DETAILS(issueId.toString()));
+ })
+ .catch((err) => {
+ if (err?.status === 400)
+ setToastAlert({
+ type: "error",
+ title: "Error!",
+ message: "This URL already exists for this issue.",
+ });
+ else
+ setToastAlert({
+ type: "error",
+ title: "Error!",
+ message: "Something went wrong. Please try again.",
+ });
+ });
+ else {
+ const updatedLinks = links?.map((l) =>
+ l.id === data.id
+ ? {
+ ...l,
+ title: formData.title,
+ url: formData.url,
+ }
+ : l
+ );
+
+ mutate(
+ ISSUE_DETAILS(issueId.toString()),
+ (prevData) => ({ ...prevData, issue_link: updatedLinks }),
+ false
+ );
+
+ await issuesService
+ .updateIssueLink(
+ workspaceSlug.toString(),
+ projectId.toString(),
+ issueId.toString(),
+ data!.id,
+ payload
+ )
+ .then(() => {
+ onSuccess();
+ mutate(ISSUE_DETAILS(issueId.toString()));
+ });
+ }
+ };
+
+ return (
+
+ );
+};
diff --git a/web/components/web-view/index.ts b/web/components/web-view/index.ts
new file mode 100644
index 000000000..915c891a9
--- /dev/null
+++ b/web/components/web-view/index.ts
@@ -0,0 +1,18 @@
+export * from "./web-view-modal";
+export * from "./select-state";
+export * from "./select-priority";
+export * from "./issue-web-view-form";
+export * from "./label";
+export * from "./sub-issues";
+export * from "./issue-attachments";
+export * from "./issue-properties-detail";
+export * from "./issue-link-list";
+export * from "./create-update-link-form";
+export * from "./issue-activity";
+export * from "./select-assignee";
+export * from "./select-estimate";
+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
new file mode 100644
index 000000000..4bd13eb5c
--- /dev/null
+++ b/web/components/web-view/issue-activity.tsx
@@ -0,0 +1,232 @@
+// react
+import React from "react";
+
+// next
+import { useRouter } from "next/router";
+
+// swr
+import useSWR, { mutate } from "swr";
+
+// fetch key
+import { PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys";
+
+// services
+import issuesService from "services/issues.service";
+
+// hooks
+import useUser from "hooks/use-user";
+
+// components
+import { CommentCard } from "components/issues/comment";
+import { Label, AddComment, ActivityMessage, ActivityIcon } from "components/web-view";
+
+// helpers
+import { timeAgo } from "helpers/date-time.helper";
+
+// ui
+import { Icon } from "components/ui";
+
+// types
+import type { IIssue, IIssueComment } from "types";
+
+type Props = {
+ allowed: boolean;
+ issueDetails: IIssue;
+};
+
+export const IssueActivity: React.FC = (props) => {
+ const { issueDetails, allowed } = props;
+
+ const router = useRouter();
+ const { workspaceSlug, projectId, issueId } = router.query;
+
+ const { user } = useUser();
+
+ const { data: issueActivities, mutate: mutateIssueActivity } = useSWR(
+ workspaceSlug && projectId && issueId ? PROJECT_ISSUES_ACTIVITY(issueId.toString()) : null,
+ workspaceSlug && projectId && issueId
+ ? () =>
+ issuesService.getIssueActivities(
+ workspaceSlug.toString(),
+ projectId.toString(),
+ issueId.toString()
+ )
+ : null
+ );
+
+ const handleCommentUpdate = async (comment: any) => {
+ if (!workspaceSlug || !projectId || !issueId) return;
+
+ await issuesService
+ .patchIssueComment(
+ workspaceSlug as string,
+ projectId as string,
+ issueId as string,
+ comment.id,
+ comment,
+ user
+ )
+ .then(() => mutateIssueActivity());
+ };
+
+ const handleCommentDelete = async (commentId: string) => {
+ if (!workspaceSlug || !projectId || !issueId) return;
+
+ mutateIssueActivity((prevData: any) => prevData?.filter((p: any) => p.id !== commentId), false);
+
+ await issuesService
+ .deleteIssueComment(
+ workspaceSlug as string,
+ projectId as string,
+ issueId as string,
+ commentId,
+ user
+ )
+ .then(() => mutateIssueActivity());
+ };
+
+ const handleAddComment = async (formData: IIssueComment) => {
+ if (!workspaceSlug || !issueDetails) return;
+
+ await issuesService
+ .createIssueComment(
+ workspaceSlug.toString(),
+ issueDetails.project,
+ issueDetails.id,
+ formData,
+ user
+ )
+ .then(() => {
+ mutate(PROJECT_ISSUES_ACTIVITY(issueDetails.id));
+ })
+ .catch(() =>
+ console.log(
+ "toast",
+ JSON.stringify({
+ type: "error",
+ title: "Error!",
+ message: "Comment could not be posted. Please try again.",
+ })
+ )
+ );
+ };
+
+ return (
+
+
Activity
+
+
+ {issueActivities?.map((activityItem, index) => {
+ // determines what type of action is performed
+ const message = activityItem.field ? (
+
+ ) : (
+ "created the issue."
+ );
+
+ if ("field" in activityItem && activityItem.field !== "updated_by") {
+ return (
+
+
+ {issueActivities.length > 1 && index !== issueActivities.length - 1 ? (
+
+ ) : null}
+
+
+
+
+
+ {activityItem.field ? (
+ activityItem.new_value === "restore" ? (
+
+ ) : (
+
+ )
+ ) : activityItem.actor_detail.avatar &&
+ activityItem.actor_detail.avatar !== "" ? (
+
+ ) : (
+
+ {activityItem.actor_detail.is_bot
+ ? activityItem.actor_detail.first_name.charAt(0)
+ : activityItem.actor_detail.display_name.charAt(0)}
+
+ )}
+
+
+
+
+
+
+ {activityItem.field === "archived_at" &&
+ activityItem.new_value !== "restore" ? (
+ Plane
+ ) : activityItem.actor_detail.is_bot ? (
+
+ {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}
+
+ )}{" "}
+ {message}{" "}
+
+ {timeAgo(activityItem.created_at)}
+
+
+
+
+
+
+ );
+ } else if ("comment_json" in activityItem)
+ return (
+
+
+
+ );
+ })}
+
+
+
+
+
+
+ );
+};
diff --git a/web/components/web-view/issue-attachments.tsx b/web/components/web-view/issue-attachments.tsx
new file mode 100644
index 000000000..ba4540318
--- /dev/null
+++ b/web/components/web-view/issue-attachments.tsx
@@ -0,0 +1,190 @@
+// react
+import React, { useState, useCallback } from "react";
+
+// next
+import Link from "next/link";
+import { useRouter } from "next/router";
+
+// swr
+import useSWR, { mutate } from "swr";
+
+// services
+import issuesService from "services/issues.service";
+
+// react dropzone
+import { useDropzone } from "react-dropzone";
+
+// fetch key
+import { ISSUE_ATTACHMENTS, PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys";
+
+// icons
+import { FileText, ChevronRight, X, Image as ImageIcon } from "lucide-react";
+
+// components
+import { Label, WebViewModal } from "components/web-view";
+import { DeleteAttachmentModal } from "components/issues";
+
+// types
+import type { IIssueAttachment } from "types";
+
+type Props = {
+ allowed: boolean;
+};
+
+const isImage = (fileName: string) => /\.(gif|jpe?g|tiff?|png|webp|bmp)$/i.test(fileName);
+
+export const IssueAttachments: React.FC = (props) => {
+ const { allowed } = props;
+
+ const router = useRouter();
+ const { workspaceSlug, projectId, issueId } = router.query;
+
+ const [isOpen, setIsOpen] = useState(false);
+ const [isLoading, setIsLoading] = useState(false);
+
+ const [deleteAttachment, setDeleteAttachment] = useState(null);
+ const [attachmentDeleteModal, setAttachmentDeleteModal] = useState(false);
+
+ const onDrop = useCallback(
+ (acceptedFiles: File[]) => {
+ if (!acceptedFiles[0] || !workspaceSlug) return;
+
+ const formData = new FormData();
+ formData.append("asset", acceptedFiles[0]);
+ formData.append(
+ "attributes",
+ JSON.stringify({
+ name: acceptedFiles[0].name,
+ size: acceptedFiles[0].size,
+ })
+ );
+ setIsLoading(true);
+
+ issuesService
+ .uploadIssueAttachment(
+ workspaceSlug as string,
+ projectId as string,
+ issueId as string,
+ formData
+ )
+ .then((res) => {
+ mutate(
+ ISSUE_ATTACHMENTS(issueId as string),
+ (prevData) => [res, ...(prevData ?? [])],
+ false
+ );
+ mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
+ console.log(
+ "toast",
+ JSON.stringify({
+ type: "success",
+ title: "Success!",
+ message: "File added successfully.",
+ })
+ );
+ setIsOpen(false);
+ setIsLoading(false);
+ })
+ .catch((err) => {
+ setIsLoading(false);
+ console.log(
+ "toast",
+ JSON.stringify({
+ type: "error",
+ title: "error!",
+ message: "Something went wrong. please check file type & size (max 5 MB)",
+ })
+ );
+ });
+ },
+ [issueId, projectId, workspaceSlug]
+ );
+
+ const { getRootProps, getInputProps } = useDropzone({
+ onDrop,
+ maxSize: 5 * 1024 * 1024,
+ disabled: !allowed || isLoading,
+ });
+
+ const { data: attachments } = useSWR(
+ workspaceSlug && projectId && issueId ? ISSUE_ATTACHMENTS(issueId as string) : null,
+ workspaceSlug && projectId && issueId
+ ? () =>
+ issuesService.getIssueAttachment(
+ workspaceSlug.toString(),
+ projectId.toString(),
+ issueId.toString()
+ )
+ : null
+ );
+
+ return (
+
+
+
+
setIsOpen(false)} modalTitle="Insert file">
+
+
+
+ {isLoading ? (
+
Uploading...
+ ) : (
+ <>
+
Upload
+
+ >
+ )}
+
+
+
+
+
Attachments
+
+ {attachments?.map((attachment) => (
+
+ ))}
+
setIsOpen(true)}
+ className="bg-custom-primary-100/10 border border-dotted rounded-[4px] border-custom-primary-100 text-center py-2 w-full text-custom-primary-100"
+ >
+ Click to upload file here
+
+
+
+ );
+};
diff --git a/web/components/web-view/issue-link-list.tsx b/web/components/web-view/issue-link-list.tsx
new file mode 100644
index 000000000..5f1da6a62
--- /dev/null
+++ b/web/components/web-view/issue-link-list.tsx
@@ -0,0 +1,138 @@
+// react
+import React, { useState } from "react";
+
+// next
+import Link from "next/link";
+import { useRouter } from "next/router";
+
+// swr
+import { mutate } from "swr";
+
+// services
+import issuesService from "services/issues.service";
+
+// icons
+// import { LinkIcon, PlusIcon, PencilIcon, TrashIcon } from "@heroicons/react/24/outline";
+import { Link as LinkIcon, Plus, Pencil, X } from "lucide-react";
+
+// components
+import { Label, WebViewModal, CreateUpdateLinkForm } from "components/web-view";
+
+// ui
+import { SecondaryButton } from "components/ui";
+
+// fetch keys
+import { ISSUE_DETAILS } from "constants/fetch-keys";
+
+// types
+import type { IIssue } from "types";
+
+type Props = {
+ allowed: boolean;
+ issueDetails: IIssue;
+};
+
+export const IssueLinks: React.FC = (props) => {
+ const { issueDetails, allowed } = props;
+
+ const links = issueDetails?.issue_link;
+
+ const [isOpen, setIsOpen] = useState(false);
+ const [selectedLink, setSelectedLink] = useState(null);
+
+ const router = useRouter();
+ const { workspaceSlug, projectId } = router.query;
+
+ const handleDeleteLink = async (linkId: string) => {
+ if (!workspaceSlug || !projectId || !issueDetails) return;
+
+ const updatedLinks = issueDetails.issue_link.filter((l) => l.id !== linkId);
+
+ mutate(
+ ISSUE_DETAILS(issueDetails.id),
+ (prevData) => ({ ...(prevData as IIssue), issue_link: updatedLinks }),
+ false
+ );
+
+ await issuesService
+ .deleteIssueLink(workspaceSlug as string, projectId as string, issueDetails.id, linkId)
+ .then((res) => {
+ mutate(ISSUE_DETAILS(issueDetails.id));
+ })
+ .catch((err) => {
+ console.log(err);
+ });
+ };
+
+ return (
+
+
{
+ setIsOpen(false);
+ setSelectedLink(null);
+ }}
+ modalTitle={selectedLink ? "Update Link" : "Add Link"}
+ >
+ {
+ setIsOpen(false);
+ setSelectedLink(null);
+ }}
+ data={links?.find((link) => link.id === selectedLink)}
+ />
+
+
+
Links
+
+ {links?.map((link) => (
+
+
+
+
+
+
+ {link.title}
+
+
+ {allowed && (
+
+
{
+ setIsOpen(true);
+ setSelectedLink(link.id);
+ }}
+ >
+
+
+
{
+ handleDeleteLink(link.id);
+ }}
+ >
+
+
+
+ )}
+
+ ))}
+
setIsOpen(true)}
+ className="w-full !py-2 text-custom-text-300 !text-base flex items-center justify-center"
+ >
+
+ Add
+
+
+
+ );
+};
diff --git a/web/components/web-view/issue-properties-detail.tsx b/web/components/web-view/issue-properties-detail.tsx
new file mode 100644
index 000000000..2fe0356f5
--- /dev/null
+++ b/web/components/web-view/issue-properties-detail.tsx
@@ -0,0 +1,355 @@
+// react
+import React, { useState } from "react";
+
+// next
+import { useRouter } from "next/router";
+
+// react hook forms
+import { Control, Controller, useWatch } from "react-hook-form";
+
+// icons
+import { BlockedIcon, BlockerIcon } from "components/icons";
+import { ChevronDown, PlayIcon, User, X, CalendarDays, LayoutGrid, Users } from "lucide-react";
+
+// hooks
+import useEstimateOption from "hooks/use-estimate-option";
+
+// ui
+import { SecondaryButton, CustomDatePicker } from "components/ui";
+
+// components
+import {
+ Label,
+ StateSelect,
+ PrioritySelect,
+ AssigneeSelect,
+ EstimateSelect,
+ ParentSelect,
+ BlockerSelect,
+} from "components/web-view";
+
+// types
+import type { IIssue } from "types";
+
+type Props = {
+ control: Control;
+ submitChanges: (data: Partial) => Promise;
+};
+
+export const IssuePropertiesDetail: React.FC = (props) => {
+ const { control, submitChanges } = props;
+
+ const blockerIssue = useWatch({
+ control,
+ name: "blocker_issues",
+ });
+
+ const blockedIssue = useWatch({
+ control,
+ name: "blocked_issues",
+ });
+
+ const startDate = useWatch({
+ control,
+ name: "start_date",
+ });
+
+ const router = useRouter();
+ const { workspaceSlug } = router.query;
+
+ const [isViewAllOpen, setIsViewAllOpen] = useState(false);
+
+ const { isEstimateActive } = useEstimateOption();
+
+ return (
+
+
Details
+
+
+
+
+ State
+
+
+ (
+ submitChanges({ state: val })}
+ />
+ )}
+ />
+
+
+
+
+
+
+
+
(
+ submitChanges({ priority: val })}
+ />
+ )}
+ />
+
+
+
+
+
+
+
+ Assignee
+
+
+
(
+ submitChanges({ assignees_list: [val] })}
+ />
+ )}
+ />
+
+
+
+ {isViewAllOpen && (
+ <>
+ {isEstimateActive && (
+
+
+
+
+ (
+ submitChanges({ estimate_point: val })}
+ />
+ )}
+ />
+
+
+
+ )}
+
+
+
+
+ Parent
+
+
+
(
+ submitChanges({ parent: val })}
+ />
+ )}
+ />
+
+
+
+
+
+
+
+
+ Blocking
+
+
+ (
+
+ submitChanges({
+ blocker_issues: val,
+ blockers_list: val?.map((i: any) => i.blocker_issue_detail?.id ?? ""),
+ })
+ }
+ />
+ )}
+ />
+
+
+ {blockerIssue &&
+ blockerIssue.map((issue) => (
+
+ ))}
+
+
+
+
+
+
+
+ Blocked by
+
+
+ (
+
+ submitChanges({
+ blocked_issues: val,
+ blocks_list: val?.map((i: any) => i.blocker_issue_detail?.id ?? ""),
+ })
+ }
+ />
+ )}
+ />
+
+
+ {blockedIssue &&
+ blockedIssue.map((issue) => (
+
+ ))}
+
+
+
+
+
+
+
+
+ Due date
+
+
+ (
+
+ submitChanges({
+ target_date: val,
+ })
+ }
+ className="border-transparent !shadow-none !w-[6.75rem]"
+ minDate={startDate ? new Date(startDate) : undefined}
+ />
+ )}
+ />
+
+
+
+
+ >
+ )}
+
+ setIsViewAllOpen((prev) => !prev)}
+ className="w-full flex justify-center items-center gap-1 !py-2"
+ >
+
+ {isViewAllOpen ? "View less" : "View all"}
+
+
+
+
+
+ );
+};
diff --git a/web/components/web-view/issue-web-view-form.tsx b/web/components/web-view/issue-web-view-form.tsx
new file mode 100644
index 000000000..ff9383fd0
--- /dev/null
+++ b/web/components/web-view/issue-web-view-form.tsx
@@ -0,0 +1,164 @@
+// react
+import React, { useCallback, useEffect, useState } from "react";
+
+// next
+import { useRouter } from "next/router";
+
+// react hook forms
+import { Controller } from "react-hook-form";
+
+// hooks
+
+import { useDebouncedCallback } from "use-debounce";
+import useReloadConfirmations from "hooks/use-reload-confirmation";
+
+// ui
+import { TextArea } from "components/ui";
+
+// components
+import { TipTapEditor } from "components/tiptap";
+import { Label } from "components/web-view";
+
+// types
+import type { IIssue } from "types";
+
+type Props = {
+ isAllowed: boolean;
+ issueDetails: IIssue;
+ submitChanges: (data: Partial) => Promise;
+ register: any;
+ control: any;
+ watch: any;
+ handleSubmit: any;
+};
+
+export const IssueWebViewForm: React.FC = (props) => {
+ const { isAllowed, issueDetails, submitChanges, register, control, watch, handleSubmit } = props;
+
+ const router = useRouter();
+ const { workspaceSlug } = router.query;
+
+ const [characterLimit, setCharacterLimit] = useState(false);
+ const [isSubmitting, setIsSubmitting] = useState<"submitting" | "submitted" | "saved">("saved");
+
+ const { setShowAlert } = useReloadConfirmations();
+
+ useEffect(() => {
+ if (isSubmitting === "submitted") {
+ setShowAlert(false);
+ setTimeout(async () => {
+ setIsSubmitting("saved");
+ }, 2000);
+ } else if (isSubmitting === "submitting") {
+ setShowAlert(true);
+ }
+ }, [isSubmitting, setShowAlert]);
+
+ const debouncedTitleSave = useDebouncedCallback(async () => {
+ setTimeout(async () => {
+ handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting("submitted"));
+ }, 500);
+ }, 1000);
+
+ const handleDescriptionFormSubmit = useCallback(
+ async (formData: Partial) => {
+ if (!formData?.name || formData?.name.length === 0 || formData?.name.length > 255) return;
+
+ await submitChanges({
+ name: formData.name ?? "",
+ description_html: formData.description_html ?? "
",
+ });
+ },
+ [submitChanges]
+ );
+
+ return (
+ <>
+
+
+
Description
+
+
{
+ if (!value) return <>>;
+
+ return (
+ "
+ : value
+ }
+ workspaceSlug={workspaceSlug!.toString()}
+ debouncedUpdatesEnabled={true}
+ setShouldShowAlert={setShowAlert}
+ setIsSubmitting={setIsSubmitting}
+ customClassName={
+ isAllowed ? "min-h-[150px] shadow-sm" : "!p-0 !pt-2 text-custom-text-200"
+ }
+ noBorder={!isAllowed}
+ onChange={(description: Object, description_html: string) => {
+ setShowAlert(true);
+ setIsSubmitting("submitting");
+ onChange(description_html);
+ handleSubmit(handleDescriptionFormSubmit)().finally(() =>
+ setIsSubmitting("submitted")
+ );
+ }}
+ editable={isAllowed}
+ />
+ );
+ }}
+ />
+
+ {isSubmitting === "submitting" ? "Saving..." : "Saved"}
+
+
+
+ >
+ );
+};
diff --git a/web/components/web-view/label.tsx b/web/components/web-view/label.tsx
new file mode 100644
index 000000000..6e59be4ad
--- /dev/null
+++ b/web/components/web-view/label.tsx
@@ -0,0 +1,7 @@
+export const Label: React.FC<
+ React.DetailedHTMLProps, HTMLLabelElement>
+> = (props) => (
+
+ {props.children}
+
+);
diff --git a/web/components/web-view/select-assignee.tsx b/web/components/web-view/select-assignee.tsx
new file mode 100644
index 000000000..27eae5db1
--- /dev/null
+++ b/web/components/web-view/select-assignee.tsx
@@ -0,0 +1,94 @@
+// react
+import React, { useState } from "react";
+
+// next
+import { useRouter } from "next/router";
+
+// swr
+import useSWR from "swr";
+
+// icons
+import { ChevronDown } from "lucide-react";
+
+// services
+import projectService from "services/project.service";
+
+// fetch key
+import { PROJECT_MEMBERS } from "constants/fetch-keys";
+
+// components
+import { Avatar } from "components/ui/avatar";
+import { WebViewModal } from "./web-view-modal";
+
+type Props = {
+ value: string[];
+ onChange: (value: any) => void;
+ disabled?: boolean;
+};
+
+export const AssigneeSelect: React.FC = (props) => {
+ const { value, onChange, disabled = false } = props;
+
+ const [isOpen, setIsOpen] = useState(false);
+
+ const router = useRouter();
+ const { workspaceSlug, projectId } = router.query;
+
+ const { data: members } = useSWR(
+ workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null,
+ workspaceSlug && projectId
+ ? () => projectService.projectMembers(workspaceSlug as string, projectId as string)
+ : null
+ );
+
+ const selectedAssignees = members?.filter((member) => value?.includes(member.member.id));
+
+ return (
+ <>
+ {
+ setIsOpen(false);
+ }}
+ >
+ ({
+ label: member.member.display_name,
+ value: member.member.id,
+ checked: value?.includes(member.member.id),
+ icon: ,
+ onClick: () => {
+ setIsOpen(false);
+ if (disabled) return;
+ onChange(member.member.id);
+ },
+ })) || []
+ }
+ />
+
+
+ setIsOpen(true)}
+ className={
+ "relative w-full px-2.5 py-0.5 text-base flex justify-between items-center gap-0.5 text-custom-text-100"
+ }
+ >
+ {value && value.length > 0 && Array.isArray(value) ? (
+
+
+
+ {selectedAssignees?.length} Assignees
+
+
+ ) : (
+ "No assignees"
+ )}
+
+
+ >
+ );
+};
diff --git a/web/components/web-view/select-blocked.tsx b/web/components/web-view/select-blocked.tsx
new file mode 100644
index 000000000..0056cad5c
--- /dev/null
+++ b/web/components/web-view/select-blocked.tsx
@@ -0,0 +1,87 @@
+// react
+import React, { useState } from "react";
+
+// next
+import { useRouter } from "next/router";
+
+// hooks
+import useToast from "hooks/use-toast";
+
+// icons
+import { ChevronDown } from "lucide-react";
+
+// components
+import { ExistingIssuesListModal } from "components/core";
+
+// types
+import { BlockeIssueDetail, ISearchIssueResponse } from "types";
+
+type Props = {
+ value: any;
+ onChange: (value: any) => void;
+ disabled?: boolean;
+};
+
+export const BlockedSelect: React.FC = (props) => {
+ const { value, onChange, disabled = false } = props;
+
+ const [isBlockedModalOpen, setIsBlockedModalOpen] = useState(false);
+
+ const router = useRouter();
+ const { issueId } = router.query;
+
+ const { setToastAlert } = useToast();
+
+ const onSubmit = async (data: ISearchIssueResponse[]) => {
+ if (data.length === 0) {
+ setToastAlert({
+ type: "error",
+ title: "Error!",
+ message: "Please select at least one issue.",
+ });
+
+ return;
+ }
+
+ const selectedIssues: { blocker_issue_detail: BlockeIssueDetail }[] = data.map((i) => ({
+ blocker_issue_detail: {
+ id: i.id,
+ name: i.name,
+ sequence_id: i.sequence_id,
+ project_detail: {
+ id: i.project_id,
+ identifier: i.project__identifier,
+ name: i.project__name,
+ },
+ },
+ }));
+
+ onChange([...(value || []), ...selectedIssues]);
+
+ setIsBlockedModalOpen(false);
+ };
+
+ return (
+ <>
+ setIsBlockedModalOpen(false)}
+ searchParams={{ blocker_blocked_by: true, issue_id: issueId!.toString() }}
+ handleOnSubmit={onSubmit}
+ workspaceLevelToggle
+ />
+
+ setIsBlockedModalOpen(true)}
+ className={
+ "relative w-full px-2.5 py-0.5 text-base flex justify-between items-center gap-0.5 text-custom-text-100"
+ }
+ >
+ Select issue
+
+
+ >
+ );
+};
diff --git a/web/components/web-view/select-blocker.tsx b/web/components/web-view/select-blocker.tsx
new file mode 100644
index 000000000..a46cdfcaa
--- /dev/null
+++ b/web/components/web-view/select-blocker.tsx
@@ -0,0 +1,87 @@
+// react
+import React, { useState } from "react";
+
+// next
+import { useRouter } from "next/router";
+
+// hooks
+import useToast from "hooks/use-toast";
+
+// icons
+import { ChevronDown } from "lucide-react";
+
+// components
+import { ExistingIssuesListModal } from "components/core";
+
+// types
+import { BlockeIssueDetail, ISearchIssueResponse } from "types";
+
+type Props = {
+ value: any;
+ onChange: (value: any) => void;
+ disabled?: boolean;
+};
+
+export const BlockerSelect: React.FC = (props) => {
+ const { value, onChange, disabled = false } = props;
+
+ const [isBlockerModalOpen, setIsBlockerModalOpen] = useState(false);
+
+ const router = useRouter();
+ const { issueId } = router.query;
+
+ const { setToastAlert } = useToast();
+
+ const onSubmit = async (data: ISearchIssueResponse[]) => {
+ if (data.length === 0) {
+ setToastAlert({
+ type: "error",
+ title: "Error!",
+ message: "Please select at least one issue.",
+ });
+
+ return;
+ }
+
+ const selectedIssues: { blocker_issue_detail: BlockeIssueDetail }[] = data.map((i) => ({
+ blocker_issue_detail: {
+ id: i.id,
+ name: i.name,
+ sequence_id: i.sequence_id,
+ project_detail: {
+ id: i.project_id,
+ identifier: i.project__identifier,
+ name: i.project__name,
+ },
+ },
+ }));
+
+ onChange([...(value || []), ...selectedIssues]);
+
+ setIsBlockerModalOpen(false);
+ };
+
+ return (
+ <>
+ setIsBlockerModalOpen(false)}
+ searchParams={{ blocker_blocked_by: true, issue_id: issueId!.toString() }}
+ handleOnSubmit={onSubmit}
+ workspaceLevelToggle
+ />
+
+ setIsBlockerModalOpen(true)}
+ className={
+ "relative w-full px-2.5 py-0.5 text-base flex justify-between items-center gap-0.5 text-custom-text-100"
+ }
+ >
+ Select issue
+
+
+ >
+ );
+};
diff --git a/web/components/web-view/select-estimate.tsx b/web/components/web-view/select-estimate.tsx
new file mode 100644
index 000000000..765e6187d
--- /dev/null
+++ b/web/components/web-view/select-estimate.tsx
@@ -0,0 +1,83 @@
+// react
+import React, { useState } from "react";
+
+// icons
+import { ChevronDown, PlayIcon } from "lucide-react";
+
+// hooks
+import useEstimateOption from "hooks/use-estimate-option";
+
+// components
+import { WebViewModal } from "./web-view-modal";
+
+type Props = {
+ value: any;
+ onChange: (value: any) => void;
+ disabled?: boolean;
+};
+
+export const EstimateSelect: React.FC = (props) => {
+ const { value, onChange, disabled = false } = props;
+
+ const [isOpen, setIsOpen] = useState(false);
+
+ const { estimatePoints } = useEstimateOption();
+
+ return (
+ <>
+ {
+ setIsOpen(false);
+ }}
+ >
+ {
+ setIsOpen(false);
+ if (disabled) return;
+ onChange(null);
+ },
+ icon: ,
+ },
+ ...estimatePoints?.map((point) => ({
+ label: point.value,
+ value: point.key,
+ checked: point.key === value,
+ icon: ,
+ onClick: () => {
+ setIsOpen(false);
+ if (disabled) return;
+ onChange(point.key);
+ },
+ })),
+ ]}
+ />
+
+
+ setIsOpen(true)}
+ className={
+ "relative w-full px-2.5 py-0.5 text-base flex justify-between items-center gap-0.5 text-custom-text-100"
+ }
+ >
+ {value ? (
+
+
+
{estimatePoints?.find((e) => e.key === value)?.value}
+
+ ) : (
+ "No estimate"
+ )}
+
+
+ >
+ );
+};
diff --git a/web/components/web-view/select-parent.tsx b/web/components/web-view/select-parent.tsx
new file mode 100644
index 000000000..e5975b7b5
--- /dev/null
+++ b/web/components/web-view/select-parent.tsx
@@ -0,0 +1,76 @@
+// react
+import React, { useState } from "react";
+
+// next
+import { useRouter } from "next/router";
+
+// swr
+import useSWR from "swr";
+
+// services
+import issuesService from "services/issues.service";
+
+// fetch key
+import { ISSUE_DETAILS } from "constants/fetch-keys";
+
+// components
+import { ParentIssuesListModal } from "components/issues";
+
+// types
+import { ISearchIssueResponse } from "types";
+
+type Props = {
+ value: string | null;
+ onChange: (value: any) => void;
+ disabled?: boolean;
+};
+
+export const ParentSelect: React.FC = (props) => {
+ const { value, onChange, disabled = false } = props;
+
+ const [isParentModalOpen, setIsParentModalOpen] = useState(false);
+ const [selectedParentIssue, setSelectedParentIssue] = useState(null);
+
+ const router = useRouter();
+ const { workspaceSlug, projectId, issueId } = router.query;
+
+ const { data: issueDetails } = useSWR(
+ workspaceSlug && projectId && issueId ? ISSUE_DETAILS(issueId.toString()) : null,
+ workspaceSlug && projectId && issueId
+ ? () =>
+ issuesService.retrieve(workspaceSlug.toString(), projectId.toString(), issueId.toString())
+ : null
+ );
+
+ return (
+ <>
+ setIsParentModalOpen(false)}
+ onChange={(issue) => {
+ onChange(issue.id);
+ setSelectedParentIssue(issue);
+ }}
+ issueId={issueId as string}
+ projectId={projectId as string}
+ />
+
+ setIsParentModalOpen(true)}
+ className={
+ "relative w-full px-2.5 py-0.5 text-base flex justify-between items-center gap-0.5 text-custom-text-100"
+ }
+ >
+ {selectedParentIssue && issueDetails?.parent ? (
+ `${selectedParentIssue.project__identifier}-${selectedParentIssue.sequence_id}`
+ ) : !selectedParentIssue && issueDetails?.parent ? (
+ `${issueDetails.parent_detail?.project_detail.identifier}-${issueDetails.parent_detail?.sequence_id}`
+ ) : (
+ Select issue
+ )}
+
+ >
+ );
+};
diff --git a/web/components/web-view/select-priority.tsx b/web/components/web-view/select-priority.tsx
new file mode 100644
index 000000000..ce7eef343
--- /dev/null
+++ b/web/components/web-view/select-priority.tsx
@@ -0,0 +1,85 @@
+// react
+import React, { useState } from "react";
+
+// icons
+import { ChevronDown } from "lucide-react";
+
+// constants
+import { PRIORITIES } from "constants/project";
+
+// components
+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: TIssuePriorities) => void;
+ disabled?: boolean;
+};
+
+export const PrioritySelect: React.FC = (props) => {
+ const { value, onChange, disabled = false } = props;
+
+ const [isOpen, setIsOpen] = useState(false);
+
+ return (
+ <>
+ {
+ setIsOpen(false);
+ }}
+ >
+ ({
+ label: priority ? capitalizeFirstLetter(priority) : "None",
+ value: priority,
+ checked: priority === value,
+ onClick: () => {
+ setIsOpen(false);
+ if (disabled) return;
+ onChange(priority);
+ },
+ icon: (
+
+
+
+ ),
+ })) || []
+ }
+ />
+
+
+ setIsOpen(true)}
+ className={
+ "relative w-full px-2.5 py-0.5 text-base flex justify-between items-center gap-0.5 text-custom-text-100"
+ }
+ >
+ {value ? capitalizeFirstLetter(value) : "None"}
+
+
+ >
+ );
+};
diff --git a/web/components/web-view/select-state.tsx b/web/components/web-view/select-state.tsx
new file mode 100644
index 000000000..c5bfa1257
--- /dev/null
+++ b/web/components/web-view/select-state.tsx
@@ -0,0 +1,89 @@
+// react
+import React, { useState } from "react";
+
+// next
+import { useRouter } from "next/router";
+
+// swr
+import useSWR from "swr";
+
+// icons
+import { ChevronDown } from "lucide-react";
+
+// services
+import stateService from "services/state.service";
+
+// fetch key
+import { STATES_LIST } from "constants/fetch-keys";
+
+// components
+import { StateGroupIcon } from "components/icons";
+import { WebViewModal } from "./web-view-modal";
+
+// helpers
+import { getStatesList } from "helpers/state.helper";
+
+type Props = {
+ value: any;
+ onChange: (value: any) => void;
+ disabled?: boolean;
+};
+
+export const StateSelect: React.FC = (props) => {
+ const { value, onChange, disabled = false } = props;
+
+ const [isOpen, setIsOpen] = useState(false);
+
+ const router = useRouter();
+ const { workspaceSlug, projectId } = router.query;
+
+ const { data: stateGroups } = useSWR(
+ workspaceSlug && projectId ? STATES_LIST(projectId as string) : null,
+ workspaceSlug && projectId
+ ? () => stateService.getStates(workspaceSlug as string, projectId as string)
+ : null
+ );
+ const states = getStatesList(stateGroups);
+
+ const selectedState = states?.find((s) => s.id === value);
+
+ return (
+ <>
+ {
+ setIsOpen(false);
+ }}
+ >
+ ({
+ label: state.name,
+ value: state.id,
+ checked: state.id === selectedState?.id,
+ icon: ,
+ onClick: () => {
+ setIsOpen(false);
+ if (disabled) return;
+ onChange(state.id);
+ },
+ })) || []
+ }
+ />
+
+
+ setIsOpen(true)}
+ className={
+ "relative w-full px-2.5 py-0.5 text-base flex justify-between items-center gap-0.5 text-custom-text-100"
+ }
+ >
+ {selectedState?.name || "Select a state"}
+
+
+ >
+ );
+};
diff --git a/web/components/web-view/sub-issues.tsx b/web/components/web-view/sub-issues.tsx
new file mode 100644
index 000000000..4299d9e3a
--- /dev/null
+++ b/web/components/web-view/sub-issues.tsx
@@ -0,0 +1,108 @@
+// react
+import React from "react";
+
+// next
+import { useRouter } from "next/router";
+
+// swr
+import useSWR, { mutate } from "swr";
+
+// icons
+import { X } from "lucide-react";
+
+// services
+import issuesService from "services/issues.service";
+
+// fetch key
+import { SUB_ISSUES } from "constants/fetch-keys";
+
+// hooks
+import useUser from "hooks/use-user";
+
+// ui
+import { Spinner } from "components/ui";
+import { IIssue } from "types";
+
+// components
+import { Label } from "components/web-view";
+
+type Props = {
+ issueDetails?: IIssue;
+};
+
+export const SubIssueList: React.FC = (props) => {
+ const { issueDetails } = props;
+
+ const router = useRouter();
+ const { workspaceSlug } = router.query;
+
+ const { user } = useUser();
+
+ const { data: subIssuesResponse } = useSWR(
+ workspaceSlug && issueDetails ? SUB_ISSUES(issueDetails.id) : null,
+ workspaceSlug && issueDetails
+ ? () =>
+ issuesService.subIssues(workspaceSlug as string, issueDetails.project, issueDetails.id)
+ : null
+ );
+
+ const handleSubIssueRemove = (issue: any) => {
+ if (!workspaceSlug || !issueDetails || !user) return;
+
+ mutate(
+ SUB_ISSUES(issueDetails.id),
+ (prevData) => {
+ if (!prevData) return prevData;
+
+ const stateDistribution = { ...prevData.state_distribution };
+
+ const issueGroup = issue.state_detail.group;
+ stateDistribution[issueGroup] = stateDistribution[issueGroup] - 1;
+
+ return {
+ state_distribution: stateDistribution,
+ sub_issues: prevData.sub_issues.filter((i: any) => i.id !== issue.id),
+ };
+ },
+ false
+ );
+
+ issuesService
+ .patchIssue(workspaceSlug.toString(), issue.project, issue.id, { parent: null }, user)
+ .finally(() => mutate(SUB_ISSUES(issueDetails.id)));
+ };
+
+ return (
+
+
Sub Issues
+
+ {!subIssuesResponse && (
+
+
+ Loading...
+
+ )}
+
+ {subIssuesResponse?.sub_issues.length === 0 && (
+
+ )}
+
+ {subIssuesResponse?.sub_issues?.map((subIssue) => (
+
+
+
+ {subIssue.project_detail.identifier}-{subIssue.sequence_id}
+
+
{subIssue.name}
+
+
handleSubIssueRemove(subIssue)}>
+
+
+
+ ))}
+
+
+ );
+};
diff --git a/web/components/web-view/web-view-modal.tsx b/web/components/web-view/web-view-modal.tsx
new file mode 100644
index 000000000..39769dfcd
--- /dev/null
+++ b/web/components/web-view/web-view-modal.tsx
@@ -0,0 +1,108 @@
+// react
+import React, { Fragment } from "react";
+
+// headless ui
+import { Transition, Dialog } from "@headlessui/react";
+
+// icons
+import { XMarkIcon } from "@heroicons/react/24/outline";
+
+type Props = {
+ isOpen: boolean;
+ onClose: () => void;
+ modalTitle: string;
+ children: React.ReactNode;
+};
+
+export const WebViewModal = (props: Props) => {
+ const { isOpen, onClose, modalTitle, children } = props;
+
+ const handleClose = () => {
+ onClose();
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ {modalTitle}
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+ );
+};
+
+type OptionsProps = {
+ options: Array<{
+ label: string;
+ value: string | null;
+ checked: boolean;
+ icon?: any;
+ onClick: () => void;
+ }>;
+};
+
+const Options: React.FC = ({ options }) => (
+
+ {options.map((option) => (
+
+
+
+
+ {option.icon}
+
+
{option.label}
+
+
+ ))}
+
+);
+
+WebViewModal.Options = Options;
+WebViewModal.Options.displayName = "WebViewModal.Options";
diff --git a/apps/app/components/workspace/activity-graph.tsx b/web/components/workspace/activity-graph.tsx
similarity index 100%
rename from apps/app/components/workspace/activity-graph.tsx
rename to web/components/workspace/activity-graph.tsx
diff --git a/apps/app/components/workspace/completed-issues-graph.tsx b/web/components/workspace/completed-issues-graph.tsx
similarity index 100%
rename from apps/app/components/workspace/completed-issues-graph.tsx
rename to web/components/workspace/completed-issues-graph.tsx
diff --git a/apps/app/components/workspace/confirm-workspace-member-remove.tsx b/web/components/workspace/confirm-workspace-member-remove.tsx
similarity index 100%
rename from apps/app/components/workspace/confirm-workspace-member-remove.tsx
rename to web/components/workspace/confirm-workspace-member-remove.tsx
diff --git a/apps/app/components/workspace/create-workspace-form.tsx b/web/components/workspace/create-workspace-form.tsx
similarity index 100%
rename from apps/app/components/workspace/create-workspace-form.tsx
rename to web/components/workspace/create-workspace-form.tsx
diff --git a/apps/app/components/workspace/delete-workspace-modal.tsx b/web/components/workspace/delete-workspace-modal.tsx
similarity index 97%
rename from apps/app/components/workspace/delete-workspace-modal.tsx
rename to web/components/workspace/delete-workspace-modal.tsx
index 7ba8c0eff..80cf08cd1 100644
--- a/apps/app/components/workspace/delete-workspace-modal.tsx
+++ b/web/components/workspace/delete-workspace-modal.tsx
@@ -68,8 +68,9 @@ export const DeleteWorkspaceModal: React.FC = ({ isOpen, data, onClose, u
router.push("/");
- mutate(USER_WORKSPACES, (prevData) =>
- prevData?.filter((workspace) => workspace.id !== data.id)
+ mutate(
+ USER_WORKSPACES,
+ (prevData) => prevData?.filter((workspace) => workspace.id !== data.id)
);
setToastAlert({
diff --git a/apps/app/components/workspace/help-section.tsx b/web/components/workspace/help-section.tsx
similarity index 100%
rename from apps/app/components/workspace/help-section.tsx
rename to web/components/workspace/help-section.tsx
diff --git a/apps/app/components/workspace/index.ts b/web/components/workspace/index.ts
similarity index 100%
rename from apps/app/components/workspace/index.ts
rename to web/components/workspace/index.ts
diff --git a/apps/app/components/workspace/issues-list.tsx b/web/components/workspace/issues-list.tsx
similarity index 100%
rename from apps/app/components/workspace/issues-list.tsx
rename to web/components/workspace/issues-list.tsx
diff --git a/apps/app/components/workspace/issues-pie-chart.tsx b/web/components/workspace/issues-pie-chart.tsx
similarity index 94%
rename from apps/app/components/workspace/issues-pie-chart.tsx
rename to web/components/workspace/issues-pie-chart.tsx
index 7d453d8a9..de1e199ff 100644
--- a/apps/app/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/components/workspace/issues-stats.tsx b/web/components/workspace/issues-stats.tsx
new file mode 100644
index 000000000..2c874d503
--- /dev/null
+++ b/web/components/workspace/issues-stats.tsx
@@ -0,0 +1,93 @@
+// components
+import { ActivityGraph } from "components/workspace";
+// ui
+import { Loader, Tooltip } from "components/ui";
+// icons
+import { InformationCircleIcon } from "@heroicons/react/24/outline";
+// types
+import { IUserWorkspaceDashboard } from "types";
+import { useRouter } from "next/router";
+
+type Props = {
+ data: IUserWorkspaceDashboard | undefined;
+};
+
+export const IssuesStats: React.FC = ({ data }) => {
+ const router = useRouter();
+ const { workspaceSlug } = router.query;
+ return (
+
+
+
+
+
Issues assigned to you
+
+ {data ? (
+ router.push(`/${workspaceSlug}/me/my-issues`)}
+ >
+ {data.assigned_issues_count}
+
+ ) : (
+
+
+
+ )}
+
+
+
+
Pending issues
+
+ {data ? (
+ data.pending_issues_count
+ ) : (
+
+
+
+ )}
+
+
+
+
+
+
Completed issues
+
+ {data ? (
+ data.completed_issues_count
+ ) : (
+
+
+
+ )}
+
+
+
+
Issues due by this week
+
+ {data ? (
+ data.issues_due_week_count
+ ) : (
+
+
+
+ )}
+
+
+
+
+
+
+ Activity Graph
+
+
+
+
+
+
+
+ );
+};
diff --git a/apps/app/components/workspace/send-workspace-invitation-modal.tsx b/web/components/workspace/send-workspace-invitation-modal.tsx
similarity index 100%
rename from apps/app/components/workspace/send-workspace-invitation-modal.tsx
rename to web/components/workspace/send-workspace-invitation-modal.tsx
diff --git a/apps/app/components/workspace/settings-header.tsx b/web/components/workspace/settings-header.tsx
similarity index 100%
rename from apps/app/components/workspace/settings-header.tsx
rename to web/components/workspace/settings-header.tsx
diff --git a/apps/app/components/workspace/sidebar-dropdown.tsx b/web/components/workspace/sidebar-dropdown.tsx
similarity index 100%
rename from apps/app/components/workspace/sidebar-dropdown.tsx
rename to web/components/workspace/sidebar-dropdown.tsx
diff --git a/apps/app/components/workspace/sidebar-menu.tsx b/web/components/workspace/sidebar-menu.tsx
similarity index 100%
rename from apps/app/components/workspace/sidebar-menu.tsx
rename to web/components/workspace/sidebar-menu.tsx
diff --git a/apps/app/components/workspace/sidebar-quick-action.tsx b/web/components/workspace/sidebar-quick-action.tsx
similarity index 100%
rename from apps/app/components/workspace/sidebar-quick-action.tsx
rename to web/components/workspace/sidebar-quick-action.tsx
diff --git a/apps/app/components/workspace/single-invitation.tsx b/web/components/workspace/single-invitation.tsx
similarity index 100%
rename from apps/app/components/workspace/single-invitation.tsx
rename to web/components/workspace/single-invitation.tsx
diff --git a/apps/app/constants/analytics.ts b/web/constants/analytics.ts
similarity index 100%
rename from apps/app/constants/analytics.ts
rename to web/constants/analytics.ts
diff --git a/apps/app/constants/calendar.ts b/web/constants/calendar.ts
similarity index 100%
rename from apps/app/constants/calendar.ts
rename to web/constants/calendar.ts
diff --git a/apps/app/constants/crisp.tsx b/web/constants/crisp.tsx
similarity index 100%
rename from apps/app/constants/crisp.tsx
rename to web/constants/crisp.tsx
diff --git a/apps/app/constants/fetch-keys.ts b/web/constants/fetch-keys.ts
similarity index 100%
rename from apps/app/constants/fetch-keys.ts
rename to web/constants/fetch-keys.ts
diff --git a/apps/app/constants/filters.ts b/web/constants/filters.ts
similarity index 100%
rename from apps/app/constants/filters.ts
rename to web/constants/filters.ts
diff --git a/apps/app/constants/graph.ts b/web/constants/graph.ts
similarity index 100%
rename from apps/app/constants/graph.ts
rename to web/constants/graph.ts
diff --git a/apps/app/constants/inbox.ts b/web/constants/inbox.ts
similarity index 100%
rename from apps/app/constants/inbox.ts
rename to web/constants/inbox.ts
diff --git a/apps/app/constants/issue.ts b/web/constants/issue.ts
similarity index 100%
rename from apps/app/constants/issue.ts
rename to web/constants/issue.ts
diff --git a/apps/app/constants/label.ts b/web/constants/label.ts
similarity index 100%
rename from apps/app/constants/label.ts
rename to web/constants/label.ts
diff --git a/apps/app/constants/module.ts b/web/constants/module.ts
similarity index 100%
rename from apps/app/constants/module.ts
rename to web/constants/module.ts
diff --git a/apps/app/constants/notification.ts b/web/constants/notification.ts
similarity index 100%
rename from apps/app/constants/notification.ts
rename to web/constants/notification.ts
diff --git a/apps/app/constants/project.ts b/web/constants/project.ts
similarity index 86%
rename from apps/app/constants/project.ts
rename to web/constants/project.ts
index 374ce26b9..1a366ead6 100644
--- a/apps/app/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/apps/app/constants/seo-variables.ts b/web/constants/seo-variables.ts
similarity index 100%
rename from apps/app/constants/seo-variables.ts
rename to web/constants/seo-variables.ts
diff --git a/apps/app/constants/spreadsheet.ts b/web/constants/spreadsheet.ts
similarity index 100%
rename from apps/app/constants/spreadsheet.ts
rename to web/constants/spreadsheet.ts
diff --git a/apps/app/constants/state.ts b/web/constants/state.ts
similarity index 68%
rename from apps/app/constants/state.ts
rename to web/constants/state.ts
index 735757822..13e8506ee 100644
--- a/apps/app/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/apps/app/constants/themes.ts b/web/constants/themes.ts
similarity index 100%
rename from apps/app/constants/themes.ts
rename to web/constants/themes.ts
diff --git a/apps/app/constants/timezones.ts b/web/constants/timezones.ts
similarity index 100%
rename from apps/app/constants/timezones.ts
rename to web/constants/timezones.ts
diff --git a/apps/app/constants/workspace.ts b/web/constants/workspace.ts
similarity index 100%
rename from apps/app/constants/workspace.ts
rename to web/constants/workspace.ts
diff --git a/apps/app/contexts/inbox-view-context.tsx b/web/contexts/inbox-view-context.tsx
similarity index 100%
rename from apps/app/contexts/inbox-view-context.tsx
rename to web/contexts/inbox-view-context.tsx
diff --git a/apps/app/contexts/issue-view.context.tsx b/web/contexts/issue-view.context.tsx
similarity index 100%
rename from apps/app/contexts/issue-view.context.tsx
rename to web/contexts/issue-view.context.tsx
diff --git a/apps/app/contexts/profile-issues-context.tsx b/web/contexts/profile-issues-context.tsx
similarity index 100%
rename from apps/app/contexts/profile-issues-context.tsx
rename to web/contexts/profile-issues-context.tsx
diff --git a/apps/app/contexts/project-member.context.tsx b/web/contexts/project-member.context.tsx
similarity index 100%
rename from apps/app/contexts/project-member.context.tsx
rename to web/contexts/project-member.context.tsx
diff --git a/apps/app/contexts/theme.context.tsx b/web/contexts/theme.context.tsx
similarity index 100%
rename from apps/app/contexts/theme.context.tsx
rename to web/contexts/theme.context.tsx
diff --git a/apps/app/contexts/toast.context.tsx b/web/contexts/toast.context.tsx
similarity index 100%
rename from apps/app/contexts/toast.context.tsx
rename to web/contexts/toast.context.tsx
diff --git a/apps/app/contexts/user-notification-context.tsx b/web/contexts/user-notification-context.tsx
similarity index 100%
rename from apps/app/contexts/user-notification-context.tsx
rename to web/contexts/user-notification-context.tsx
diff --git a/apps/app/contexts/user.context.tsx b/web/contexts/user.context.tsx
similarity index 100%
rename from apps/app/contexts/user.context.tsx
rename to web/contexts/user.context.tsx
diff --git a/apps/app/contexts/workspace-member.context.tsx b/web/contexts/workspace-member.context.tsx
similarity index 100%
rename from apps/app/contexts/workspace-member.context.tsx
rename to web/contexts/workspace-member.context.tsx
diff --git a/apps/app/contexts/workspace.context.tsx b/web/contexts/workspace.context.tsx
similarity index 100%
rename from apps/app/contexts/workspace.context.tsx
rename to web/contexts/workspace.context.tsx
diff --git a/apps/app/google.d.ts b/web/google.d.ts
similarity index 100%
rename from apps/app/google.d.ts
rename to web/google.d.ts
diff --git a/apps/app/helpers/analytics.helper.ts b/web/helpers/analytics.helper.ts
similarity index 93%
rename from apps/app/helpers/analytics.helper.ts
rename to web/helpers/analytics.helper.ts
index efc781794..08b763720 100644
--- a/apps/app/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();
diff --git a/apps/app/helpers/array.helper.ts b/web/helpers/array.helper.ts
similarity index 100%
rename from apps/app/helpers/array.helper.ts
rename to web/helpers/array.helper.ts
diff --git a/apps/app/helpers/attachment.helper.ts b/web/helpers/attachment.helper.ts
similarity index 100%
rename from apps/app/helpers/attachment.helper.ts
rename to web/helpers/attachment.helper.ts
diff --git a/apps/app/helpers/calendar.helper.ts b/web/helpers/calendar.helper.ts
similarity index 100%
rename from apps/app/helpers/calendar.helper.ts
rename to web/helpers/calendar.helper.ts
diff --git a/apps/app/helpers/color.helper.ts b/web/helpers/color.helper.ts
similarity index 100%
rename from apps/app/helpers/color.helper.ts
rename to web/helpers/color.helper.ts
diff --git a/apps/app/helpers/common.helper.ts b/web/helpers/common.helper.ts
similarity index 100%
rename from apps/app/helpers/common.helper.ts
rename to web/helpers/common.helper.ts
diff --git a/apps/app/helpers/date-time.helper.ts b/web/helpers/date-time.helper.ts
similarity index 100%
rename from apps/app/helpers/date-time.helper.ts
rename to web/helpers/date-time.helper.ts
diff --git a/web/helpers/emoji.helper.tsx b/web/helpers/emoji.helper.tsx
new file mode 100644
index 000000000..7c9f3cfcb
--- /dev/null
+++ b/web/helpers/emoji.helper.tsx
@@ -0,0 +1,56 @@
+export const getRandomEmoji = () => {
+ const emojis = [
+ "8986",
+ "9200",
+ "128204",
+ "127773",
+ "127891",
+ "127947",
+ "128076",
+ "128077",
+ "128187",
+ "128188",
+ "128512",
+ "128522",
+ "128578",
+ ];
+
+ return emojis[Math.floor(Math.random() * emojis.length)];
+};
+
+export const renderEmoji = (
+ emoji:
+ | string
+ | {
+ name: string;
+ color: string;
+ }
+) => {
+ if (!emoji) return;
+
+ if (typeof emoji === "object")
+ return (
+
+ {emoji.name}
+
+ );
+ else return isNaN(parseInt(emoji)) ? emoji : String.fromCodePoint(parseInt(emoji));
+};
+
+export const groupReactions: (reactions: any[], key: string) => { [key: string]: any[] } = (
+ reactions: any,
+ key: string
+) => {
+ const groupedReactions = reactions.reduce(
+ (acc: any, reaction: any) => {
+ if (!acc[reaction[key]]) {
+ acc[reaction[key]] = [];
+ }
+ acc[reaction[key]].push(reaction);
+ return acc;
+ },
+ {} as { [key: string]: any[] }
+ );
+
+ return groupedReactions;
+};
diff --git a/apps/app/helpers/graph.helper.ts b/web/helpers/graph.helper.ts
similarity index 100%
rename from apps/app/helpers/graph.helper.ts
rename to web/helpers/graph.helper.ts
diff --git a/apps/app/helpers/state.helper.ts b/web/helpers/state.helper.ts
similarity index 100%
rename from apps/app/helpers/state.helper.ts
rename to web/helpers/state.helper.ts
diff --git a/apps/app/helpers/string.helper.ts b/web/helpers/string.helper.ts
similarity index 100%
rename from apps/app/helpers/string.helper.ts
rename to web/helpers/string.helper.ts
diff --git a/apps/app/helpers/theme.helper.ts b/web/helpers/theme.helper.ts
similarity index 100%
rename from apps/app/helpers/theme.helper.ts
rename to web/helpers/theme.helper.ts
diff --git a/apps/app/hooks/gantt-chart/cycle-issues-view.tsx b/web/hooks/gantt-chart/cycle-issues-view.tsx
similarity index 100%
rename from apps/app/hooks/gantt-chart/cycle-issues-view.tsx
rename to web/hooks/gantt-chart/cycle-issues-view.tsx
diff --git a/apps/app/hooks/gantt-chart/issue-view.tsx b/web/hooks/gantt-chart/issue-view.tsx
similarity index 100%
rename from apps/app/hooks/gantt-chart/issue-view.tsx
rename to web/hooks/gantt-chart/issue-view.tsx
diff --git a/apps/app/hooks/gantt-chart/module-issues-view.tsx b/web/hooks/gantt-chart/module-issues-view.tsx
similarity index 100%
rename from apps/app/hooks/gantt-chart/module-issues-view.tsx
rename to web/hooks/gantt-chart/module-issues-view.tsx
diff --git a/apps/app/hooks/gantt-chart/view-issues-view.tsx b/web/hooks/gantt-chart/view-issues-view.tsx
similarity index 100%
rename from apps/app/hooks/gantt-chart/view-issues-view.tsx
rename to web/hooks/gantt-chart/view-issues-view.tsx
diff --git a/apps/app/hooks/my-issues/use-my-issues-filter.tsx b/web/hooks/my-issues/use-my-issues-filter.tsx
similarity index 100%
rename from apps/app/hooks/my-issues/use-my-issues-filter.tsx
rename to web/hooks/my-issues/use-my-issues-filter.tsx
diff --git a/apps/app/hooks/my-issues/use-my-issues.tsx b/web/hooks/my-issues/use-my-issues.tsx
similarity index 100%
rename from apps/app/hooks/my-issues/use-my-issues.tsx
rename to web/hooks/my-issues/use-my-issues.tsx
diff --git a/apps/app/hooks/use-calendar-issues-view.tsx b/web/hooks/use-calendar-issues-view.tsx
similarity index 100%
rename from apps/app/hooks/use-calendar-issues-view.tsx
rename to web/hooks/use-calendar-issues-view.tsx
diff --git a/apps/app/hooks/use-comment-reaction.tsx b/web/hooks/use-comment-reaction.tsx
similarity index 100%
rename from apps/app/hooks/use-comment-reaction.tsx
rename to web/hooks/use-comment-reaction.tsx
diff --git a/apps/app/hooks/use-debounce.tsx b/web/hooks/use-debounce.tsx
similarity index 100%
rename from apps/app/hooks/use-debounce.tsx
rename to web/hooks/use-debounce.tsx
diff --git a/apps/app/hooks/use-estimate-option.tsx b/web/hooks/use-estimate-option.tsx
similarity index 100%
rename from apps/app/hooks/use-estimate-option.tsx
rename to web/hooks/use-estimate-option.tsx
diff --git a/apps/app/hooks/use-inbox-view.tsx b/web/hooks/use-inbox-view.tsx
similarity index 100%
rename from apps/app/hooks/use-inbox-view.tsx
rename to web/hooks/use-inbox-view.tsx
diff --git a/apps/app/hooks/use-integration-popup.tsx b/web/hooks/use-integration-popup.tsx
similarity index 100%
rename from apps/app/hooks/use-integration-popup.tsx
rename to web/hooks/use-integration-popup.tsx
diff --git a/apps/app/hooks/use-issue-notification-subscription.tsx b/web/hooks/use-issue-notification-subscription.tsx
similarity index 100%
rename from apps/app/hooks/use-issue-notification-subscription.tsx
rename to web/hooks/use-issue-notification-subscription.tsx
diff --git a/apps/app/hooks/use-issue-properties.tsx b/web/hooks/use-issue-properties.tsx
similarity index 98%
rename from apps/app/hooks/use-issue-properties.tsx
rename to web/hooks/use-issue-properties.tsx
index d5d1072ce..6f4f093e0 100644
--- a/apps/app/hooks/use-issue-properties.tsx
+++ b/web/hooks/use-issue-properties.tsx
@@ -68,7 +68,7 @@ const useIssuesProperties = (workspaceSlug?: string, projectId?: string) => {
({
...prev,
properties: { ...prev?.properties, [key]: !prev?.properties?.[key] },
- } as IssuePriorities),
+ }) as IssuePriorities,
false
);
if (Object.keys(issueProperties).length > 0) {
diff --git a/apps/app/hooks/use-issue-reaction.tsx b/web/hooks/use-issue-reaction.tsx
similarity index 100%
rename from apps/app/hooks/use-issue-reaction.tsx
rename to web/hooks/use-issue-reaction.tsx
diff --git a/apps/app/hooks/use-issues-view.tsx b/web/hooks/use-issues-view.tsx
similarity index 100%
rename from apps/app/hooks/use-issues-view.tsx
rename to web/hooks/use-issues-view.tsx
diff --git a/apps/app/hooks/use-local-storage.tsx b/web/hooks/use-local-storage.tsx
similarity index 100%
rename from apps/app/hooks/use-local-storage.tsx
rename to web/hooks/use-local-storage.tsx
diff --git a/apps/app/hooks/use-outside-click-detector.tsx b/web/hooks/use-outside-click-detector.tsx
similarity index 100%
rename from apps/app/hooks/use-outside-click-detector.tsx
rename to web/hooks/use-outside-click-detector.tsx
diff --git a/apps/app/hooks/use-profile-issues.tsx b/web/hooks/use-profile-issues.tsx
similarity index 100%
rename from apps/app/hooks/use-profile-issues.tsx
rename to web/hooks/use-profile-issues.tsx
diff --git a/apps/app/hooks/use-project-details.tsx b/web/hooks/use-project-details.tsx
similarity index 100%
rename from apps/app/hooks/use-project-details.tsx
rename to web/hooks/use-project-details.tsx
diff --git a/apps/app/hooks/use-project-members.tsx b/web/hooks/use-project-members.tsx
similarity index 100%
rename from apps/app/hooks/use-project-members.tsx
rename to web/hooks/use-project-members.tsx
diff --git a/apps/app/hooks/use-projects.tsx b/web/hooks/use-projects.tsx
similarity index 100%
rename from apps/app/hooks/use-projects.tsx
rename to web/hooks/use-projects.tsx
diff --git a/apps/app/hooks/use-reload-confirmation.tsx b/web/hooks/use-reload-confirmation.tsx
similarity index 100%
rename from apps/app/hooks/use-reload-confirmation.tsx
rename to web/hooks/use-reload-confirmation.tsx
diff --git a/apps/app/hooks/use-spreadsheet-issues-view.tsx b/web/hooks/use-spreadsheet-issues-view.tsx
similarity index 100%
rename from apps/app/hooks/use-spreadsheet-issues-view.tsx
rename to web/hooks/use-spreadsheet-issues-view.tsx
diff --git a/apps/app/hooks/use-sub-issue.tsx b/web/hooks/use-sub-issue.tsx
similarity index 100%
rename from apps/app/hooks/use-sub-issue.tsx
rename to web/hooks/use-sub-issue.tsx
diff --git a/apps/app/hooks/use-theme.tsx b/web/hooks/use-theme.tsx
similarity index 100%
rename from apps/app/hooks/use-theme.tsx
rename to web/hooks/use-theme.tsx
diff --git a/web/hooks/use-timer.tsx b/web/hooks/use-timer.tsx
new file mode 100644
index 000000000..1edf4931a
--- /dev/null
+++ b/web/hooks/use-timer.tsx
@@ -0,0 +1,19 @@
+import { useState, useEffect } from "react";
+
+const TIMER = 30;
+
+const useTimer = (initialValue: number = TIMER) => {
+ const [timer, setTimer] = useState(initialValue);
+
+ useEffect(() => {
+ const interval = setInterval(() => {
+ setTimer((prev) => prev - 1);
+ }, 1000);
+
+ return () => clearInterval(interval);
+ }, []);
+
+ return { timer, setTimer };
+};
+
+export default useTimer;
diff --git a/web/hooks/use-toast.tsx b/web/hooks/use-toast.tsx
new file mode 100644
index 000000000..6de3c104c
--- /dev/null
+++ b/web/hooks/use-toast.tsx
@@ -0,0 +1,9 @@
+import { useContext } from "react";
+import { toastContext } from "contexts/toast.context";
+
+const useToast = () => {
+ const toastContextData = useContext(toastContext);
+ return toastContextData;
+};
+
+export default useToast;
diff --git a/apps/app/hooks/use-user-auth.tsx b/web/hooks/use-user-auth.tsx
similarity index 100%
rename from apps/app/hooks/use-user-auth.tsx
rename to web/hooks/use-user-auth.tsx
diff --git a/apps/app/hooks/use-user-notifications.tsx b/web/hooks/use-user-notifications.tsx
similarity index 99%
rename from apps/app/hooks/use-user-notifications.tsx
rename to web/hooks/use-user-notifications.tsx
index 5e6ea5d0b..5ddc9ddf5 100644
--- a/apps/app/hooks/use-user-notifications.tsx
+++ b/web/hooks/use-user-notifications.tsx
@@ -299,6 +299,7 @@ const useUserNotification = () => {
})
.finally(() => {
notificationMutate();
+ mutateNotificationCount();
});
};
diff --git a/apps/app/hooks/use-user.tsx b/web/hooks/use-user.tsx
similarity index 100%
rename from apps/app/hooks/use-user.tsx
rename to web/hooks/use-user.tsx
diff --git a/apps/app/hooks/use-workspace-details.tsx b/web/hooks/use-workspace-details.tsx
similarity index 100%
rename from apps/app/hooks/use-workspace-details.tsx
rename to web/hooks/use-workspace-details.tsx
diff --git a/apps/app/hooks/use-workspace-members.tsx b/web/hooks/use-workspace-members.tsx
similarity index 100%
rename from apps/app/hooks/use-workspace-members.tsx
rename to web/hooks/use-workspace-members.tsx
diff --git a/apps/app/hooks/use-workspaces.tsx b/web/hooks/use-workspaces.tsx
similarity index 100%
rename from apps/app/hooks/use-workspaces.tsx
rename to web/hooks/use-workspaces.tsx
diff --git a/apps/app/layouts/app-layout/app-header.tsx b/web/layouts/app-layout/app-header.tsx
similarity index 100%
rename from apps/app/layouts/app-layout/app-header.tsx
rename to web/layouts/app-layout/app-header.tsx
diff --git a/apps/app/layouts/app-layout/app-sidebar.tsx b/web/layouts/app-layout/app-sidebar.tsx
similarity index 88%
rename from apps/app/layouts/app-layout/app-sidebar.tsx
rename to web/layouts/app-layout/app-sidebar.tsx
index 9290c00c6..03ac72387 100644
--- a/apps/app/layouts/app-layout/app-sidebar.tsx
+++ b/web/layouts/app-layout/app-sidebar.tsx
@@ -9,6 +9,7 @@ import {
} from "components/workspace";
import { ProjectSidebarList } from "components/project";
import { PublishProjectModal } from "components/project/publish-project/modal";
+import { ConfirmProjectLeaveModal } from "components/project/confirm-project-leave-modal";
// mobx react lite
import { observer } from "mobx-react-lite";
// mobx store
@@ -38,7 +39,10 @@ const Sidebar: React.FC = observer(({ toggleSidebar, setToggleSide
+ {/* publish project modal */}
+ {/* project leave modal */}
+
);
});
diff --git a/apps/app/layouts/auth-layout/index.ts b/web/layouts/auth-layout/index.ts
similarity index 100%
rename from apps/app/layouts/auth-layout/index.ts
rename to web/layouts/auth-layout/index.ts
diff --git a/apps/app/layouts/auth-layout/project-authorization-wrapper.tsx b/web/layouts/auth-layout/project-authorization-wrapper.tsx
similarity index 100%
rename from apps/app/layouts/auth-layout/project-authorization-wrapper.tsx
rename to web/layouts/auth-layout/project-authorization-wrapper.tsx
diff --git a/apps/app/layouts/auth-layout/user-authorization-wrapper.tsx b/web/layouts/auth-layout/user-authorization-wrapper.tsx
similarity index 100%
rename from apps/app/layouts/auth-layout/user-authorization-wrapper.tsx
rename to web/layouts/auth-layout/user-authorization-wrapper.tsx
diff --git a/apps/app/layouts/auth-layout/workspace-authorization-wrapper.tsx b/web/layouts/auth-layout/workspace-authorization-wrapper.tsx
similarity index 100%
rename from apps/app/layouts/auth-layout/workspace-authorization-wrapper.tsx
rename to web/layouts/auth-layout/workspace-authorization-wrapper.tsx
diff --git a/apps/app/layouts/default-layout/index.tsx b/web/layouts/default-layout/index.tsx
similarity index 100%
rename from apps/app/layouts/default-layout/index.tsx
rename to web/layouts/default-layout/index.tsx
diff --git a/apps/app/layouts/profile-layout.tsx b/web/layouts/profile-layout.tsx
similarity index 100%
rename from apps/app/layouts/profile-layout.tsx
rename to web/layouts/profile-layout.tsx
diff --git a/apps/app/layouts/settings-navbar.tsx b/web/layouts/settings-navbar.tsx
similarity index 100%
rename from apps/app/layouts/settings-navbar.tsx
rename to web/layouts/settings-navbar.tsx
diff --git a/web/layouts/web-view-layout/index.tsx b/web/layouts/web-view-layout/index.tsx
new file mode 100644
index 000000000..8a58407c3
--- /dev/null
+++ b/web/layouts/web-view-layout/index.tsx
@@ -0,0 +1,64 @@
+// swr
+import useSWR from "swr";
+
+// services
+import userService from "services/user.service";
+
+// fetch keys
+import { CURRENT_USER } from "constants/fetch-keys";
+
+// icons
+import { AlertCircle } from "lucide-react";
+
+// ui
+import { Spinner } from "components/ui";
+
+type Props = {
+ children: React.ReactNode;
+ fullScreen?: boolean;
+};
+
+const getIfInWebview = (userAgent: NavigatorID["userAgent"]) => {
+ const safari = /safari/.test(userAgent);
+
+ if (safari) return false;
+ else if (/iphone|ipod|ipad/.test(userAgent) || userAgent.includes("wv")) return true;
+ else return false;
+};
+
+const useMobileDetect = () => {
+ const userAgent = typeof navigator === "undefined" ? "SSR" : navigator.userAgent;
+ return getIfInWebview(userAgent);
+};
+
+const WebViewLayout: React.FC
= ({ children, fullScreen = true }) => {
+ const { data: currentUser, error } = useSWR(CURRENT_USER, () => userService.currentUser());
+
+ const isWebview = useMobileDetect();
+
+ if (!currentUser && !error) {
+ return (
+
+
+
Loading your profile...
+
+
+
+ );
+ }
+
+ return (
+
+ {error || !isWebview ? (
+
+
+
You are not authorized to view this page.
+
+ ) : (
+ children
+ )}
+
+ );
+};
+
+export default WebViewLayout;
diff --git a/apps/app/lib/auth.ts b/web/lib/auth.ts
similarity index 100%
rename from apps/app/lib/auth.ts
rename to web/lib/auth.ts
diff --git a/apps/app/lib/cookie.ts b/web/lib/cookie.ts
similarity index 100%
rename from apps/app/lib/cookie.ts
rename to web/lib/cookie.ts
diff --git a/apps/app/lib/mobx/store-init.tsx b/web/lib/mobx/store-init.tsx
similarity index 100%
rename from apps/app/lib/mobx/store-init.tsx
rename to web/lib/mobx/store-init.tsx
diff --git a/apps/space/lib/mobx/store-provider.tsx b/web/lib/mobx/store-provider.tsx
similarity index 100%
rename from apps/space/lib/mobx/store-provider.tsx
rename to web/lib/mobx/store-provider.tsx
diff --git a/apps/app/lib/redirect.ts b/web/lib/redirect.ts
similarity index 100%
rename from apps/app/lib/redirect.ts
rename to web/lib/redirect.ts
diff --git a/apps/app/manifest.json b/web/manifest.json
similarity index 100%
rename from apps/app/manifest.json
rename to web/manifest.json
diff --git a/apps/app/next-env.d.ts b/web/next-env.d.ts
similarity index 100%
rename from apps/app/next-env.d.ts
rename to web/next-env.d.ts
diff --git a/apps/app/next.config.js b/web/next.config.js
similarity index 94%
rename from apps/app/next.config.js
rename to web/next.config.js
index 646504a54..b50066f86 100644
--- a/apps/app/next.config.js
+++ b/web/next.config.js
@@ -23,7 +23,7 @@ const nextConfig = {
output: "standalone",
experimental: {
// this includes files from the monorepo base two directories up
- outputFileTracingRoot: path.join(__dirname, "../../"),
+ outputFileTracingRoot: path.join(__dirname, "../"),
},
};
diff --git a/apps/app/package.json b/web/package.json
similarity index 99%
rename from apps/app/package.json
rename to web/package.json
index b9f3bf25e..1743e4b6c 100644
--- a/apps/app/package.json
+++ b/web/package.json
@@ -1,5 +1,5 @@
{
- "name": "app",
+ "name": "web",
"version": "0.1.0",
"private": true,
"scripts": {
diff --git a/apps/app/pages/404.tsx b/web/pages/404.tsx
similarity index 100%
rename from apps/app/pages/404.tsx
rename to web/pages/404.tsx
diff --git a/apps/app/pages/[workspaceSlug]/analytics.tsx b/web/pages/[workspaceSlug]/analytics.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/analytics.tsx
rename to web/pages/[workspaceSlug]/analytics.tsx
diff --git a/apps/app/pages/[workspaceSlug]/editor.tsx b/web/pages/[workspaceSlug]/editor.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/editor.tsx
rename to web/pages/[workspaceSlug]/editor.tsx
diff --git a/apps/app/pages/[workspaceSlug]/index.tsx b/web/pages/[workspaceSlug]/index.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/index.tsx
rename to web/pages/[workspaceSlug]/index.tsx
diff --git a/apps/app/pages/[workspaceSlug]/me/my-issues.tsx b/web/pages/[workspaceSlug]/me/my-issues.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/me/my-issues.tsx
rename to web/pages/[workspaceSlug]/me/my-issues.tsx
diff --git a/apps/app/pages/[workspaceSlug]/me/profile/activity.tsx b/web/pages/[workspaceSlug]/me/profile/activity.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/me/profile/activity.tsx
rename to web/pages/[workspaceSlug]/me/profile/activity.tsx
diff --git a/apps/app/pages/[workspaceSlug]/me/profile/index.tsx b/web/pages/[workspaceSlug]/me/profile/index.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/me/profile/index.tsx
rename to web/pages/[workspaceSlug]/me/profile/index.tsx
diff --git a/apps/app/pages/[workspaceSlug]/me/profile/preferences.tsx b/web/pages/[workspaceSlug]/me/profile/preferences.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/me/profile/preferences.tsx
rename to web/pages/[workspaceSlug]/me/profile/preferences.tsx
diff --git a/apps/app/pages/[workspaceSlug]/profile/[userId]/assigned.tsx b/web/pages/[workspaceSlug]/profile/[userId]/assigned.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/profile/[userId]/assigned.tsx
rename to web/pages/[workspaceSlug]/profile/[userId]/assigned.tsx
diff --git a/apps/app/pages/[workspaceSlug]/profile/[userId]/created.tsx b/web/pages/[workspaceSlug]/profile/[userId]/created.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/profile/[userId]/created.tsx
rename to web/pages/[workspaceSlug]/profile/[userId]/created.tsx
diff --git a/apps/app/pages/[workspaceSlug]/profile/[userId]/index.tsx b/web/pages/[workspaceSlug]/profile/[userId]/index.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/profile/[userId]/index.tsx
rename to web/pages/[workspaceSlug]/profile/[userId]/index.tsx
diff --git a/apps/app/pages/[workspaceSlug]/profile/[userId]/subscribed.tsx b/web/pages/[workspaceSlug]/profile/[userId]/subscribed.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/profile/[userId]/subscribed.tsx
rename to web/pages/[workspaceSlug]/profile/[userId]/subscribed.tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/archived-issues/[archivedIssueId].tsx b/web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/[archivedIssueId].tsx
similarity index 99%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/archived-issues/[archivedIssueId].tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/[archivedIssueId].tsx
index a48207db3..e4a1c37b2 100644
--- a/apps/app/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/apps/app/pages/[workspaceSlug]/projects/[projectId]/archived-issues/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/index.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/archived-issues/index.tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/index.tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx b/web/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/inbox/[inboxId].tsx b/web/pages/[workspaceSlug]/projects/[projectId]/inbox/[inboxId].tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/inbox/[inboxId].tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/inbox/[inboxId].tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx b/web/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx
similarity index 99%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx
index 916c0141e..c40f936de 100644
--- a/apps/app/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/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/issues/index.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/index.tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/issues/index.tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/modules/[moduleId].tsx b/web/pages/[workspaceSlug]/projects/[projectId]/modules/[moduleId].tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/modules/[moduleId].tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/modules/[moduleId].tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/modules/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/modules/index.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/modules/index.tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/modules/index.tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx b/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx
similarity index 99%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx
index 0502e9e87..d79bfb613 100644
--- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx
+++ b/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx
@@ -476,7 +476,7 @@ const SinglePage: NextPage = () => {
: "text-custom-sidebar-text-200"
}`}
>
- View
+ Display
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/pages/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/pages/index.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/pages/index.tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/pages/index.tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/control.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/control.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/control.tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/settings/control.tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/estimates.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/estimates.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/estimates.tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/settings/estimates.tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx
similarity index 86%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx
index 57bf4fa3c..a178e28fa 100644
--- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx
+++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx
@@ -187,7 +187,7 @@ const GeneralSettings: NextPage = () => {
/>
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/integrations.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/integrations.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/integrations.tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/settings/integrations.tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/labels.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/labels.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/labels.tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/settings/labels.tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/members.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/members.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/members.tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/settings/members.tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/views/[viewId].tsx b/web/pages/[workspaceSlug]/projects/[projectId]/views/[viewId].tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/views/[viewId].tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/views/[viewId].tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/views/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/views/index.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/[projectId]/views/index.tsx
rename to web/pages/[workspaceSlug]/projects/[projectId]/views/index.tsx
diff --git a/apps/app/pages/[workspaceSlug]/projects/index.tsx b/web/pages/[workspaceSlug]/projects/index.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/projects/index.tsx
rename to web/pages/[workspaceSlug]/projects/index.tsx
diff --git a/apps/app/pages/[workspaceSlug]/settings/billing.tsx b/web/pages/[workspaceSlug]/settings/billing.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/settings/billing.tsx
rename to web/pages/[workspaceSlug]/settings/billing.tsx
diff --git a/apps/app/pages/[workspaceSlug]/settings/exports.tsx b/web/pages/[workspaceSlug]/settings/exports.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/settings/exports.tsx
rename to web/pages/[workspaceSlug]/settings/exports.tsx
diff --git a/apps/app/pages/[workspaceSlug]/settings/imports.tsx b/web/pages/[workspaceSlug]/settings/imports.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/settings/imports.tsx
rename to web/pages/[workspaceSlug]/settings/imports.tsx
diff --git a/apps/app/pages/[workspaceSlug]/settings/index.tsx b/web/pages/[workspaceSlug]/settings/index.tsx
similarity index 82%
rename from apps/app/pages/[workspaceSlug]/settings/index.tsx
rename to web/pages/[workspaceSlug]/settings/index.tsx
index a254c7a49..bd7ea1bd9 100644
--- a/apps/app/pages/[workspaceSlug]/settings/index.tsx
+++ b/web/pages/[workspaceSlug]/settings/index.tsx
@@ -181,7 +181,7 @@ const WorkspaceSettings: NextPage = () => {
{activeWorkspace ? (
-
+
Logo
@@ -191,7 +191,11 @@ const WorkspaceSettings: NextPage = () => {
-
setIsImageUploadModalOpen(true)}>
+ setIsImageUploadModalOpen(true)}
+ disabled={!isAdmin}
+ >
{watch("logo") && watch("logo") !== null && watch("logo") !== "" ? (
{
)}
-
-
{
- setIsImageUploadModalOpen(true);
- }}
- >
- {isImageUploading ? "Uploading..." : "Upload"}
-
- {activeWorkspace.logo && activeWorkspace.logo !== "" && (
-
handleDelete(activeWorkspace.logo)}
- loading={isImageRemoving}
+ {isAdmin && (
+
+ {
+ setIsImageUploadModalOpen(true);
+ }}
>
- {isImageRemoving ? "Removing..." : "Remove"}
-
- )}
-
+ {isImageUploading ? "Uploading..." : "Upload"}
+
+ {activeWorkspace.logo && activeWorkspace.logo !== "" && (
+ handleDelete(activeWorkspace.logo)}
+ loading={isImageRemoving}
+ >
+ {isImageRemoving ? "Removing..." : "Remove"}
+
+ )}
+
+ )}
@@ -288,6 +294,7 @@ const WorkspaceSettings: NextPage = () => {
message: "Workspace name should not exceed 80 characters",
},
}}
+ disabled={!isAdmin}
/>
@@ -309,6 +316,7 @@ const WorkspaceSettings: NextPage = () => {
}
width="w-full"
input
+ disabled={!isAdmin}
>
{ORGANIZATION_SIZE?.map((item) => (
@@ -320,32 +328,35 @@ const WorkspaceSettings: NextPage = () => {
/>
-
-
- {isSubmitting ? "Updating..." : "Update Workspace"}
-
-
- {memberDetails?.role === 20 && (
-
-
-
Danger Zone
-
- The danger zone of the workspace delete page is a critical area that requires
- careful consideration and attention. When deleting a workspace, all of the data
- and resources within that workspace will be permanently removed and cannot be
- recovered.
-
+
+ {isAdmin && (
+ <>
+
+
+ {isSubmitting ? "Updating..." : "Update Workspace"}
+
-
-
setIsOpen(true)} outline>
- Delete the workspace
-
+
+
+
Danger Zone
+
+ The danger zone of the workspace delete page is a critical area that requires
+ careful consideration and attention. When deleting a workspace, all of the
+ data and resources within that workspace will be permanently removed and
+ cannot be recovered.
+
+
+
+ setIsOpen(true)} outline>
+ Delete the workspace
+
+
-
+ >
)}
) : (
diff --git a/apps/app/pages/[workspaceSlug]/settings/integrations.tsx b/web/pages/[workspaceSlug]/settings/integrations.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/settings/integrations.tsx
rename to web/pages/[workspaceSlug]/settings/integrations.tsx
diff --git a/apps/app/pages/[workspaceSlug]/settings/members.tsx b/web/pages/[workspaceSlug]/settings/members.tsx
similarity index 100%
rename from apps/app/pages/[workspaceSlug]/settings/members.tsx
rename to web/pages/[workspaceSlug]/settings/members.tsx
diff --git a/apps/app/pages/_app.tsx b/web/pages/_app.tsx
similarity index 100%
rename from apps/app/pages/_app.tsx
rename to web/pages/_app.tsx
diff --git a/apps/app/pages/_document.tsx b/web/pages/_document.tsx
similarity index 100%
rename from apps/app/pages/_document.tsx
rename to web/pages/_document.tsx
diff --git a/apps/app/pages/_error.tsx b/web/pages/_error.tsx
similarity index 100%
rename from apps/app/pages/_error.tsx
rename to web/pages/_error.tsx
diff --git a/apps/app/pages/api/slack-redirect.ts b/web/pages/api/slack-redirect.ts
similarity index 94%
rename from apps/app/pages/api/slack-redirect.ts
rename to web/pages/api/slack-redirect.ts
index e4a220bd5..d9382f055 100644
--- a/apps/app/pages/api/slack-redirect.ts
+++ b/web/pages/api/slack-redirect.ts
@@ -18,6 +18,6 @@ export default async function handleSlackAuthorize(req: NextApiRequest, res: Nex
});
// if (response?.data?.ok)
- res.status(200).json(response.data);
+ res.status(200).json(response.data);
// else res.status(404).json(response.data);
}
diff --git a/apps/app/pages/api/track-event.ts b/web/pages/api/track-event.ts
similarity index 100%
rename from apps/app/pages/api/track-event.ts
rename to web/pages/api/track-event.ts
diff --git a/apps/app/pages/api/unsplash.ts b/web/pages/api/unsplash.ts
similarity index 100%
rename from apps/app/pages/api/unsplash.ts
rename to web/pages/api/unsplash.ts
diff --git a/apps/app/pages/create-workspace.tsx b/web/pages/create-workspace.tsx
similarity index 100%
rename from apps/app/pages/create-workspace.tsx
rename to web/pages/create-workspace.tsx
diff --git a/apps/app/pages/error.tsx b/web/pages/error.tsx
similarity index 100%
rename from apps/app/pages/error.tsx
rename to web/pages/error.tsx
diff --git a/apps/app/pages/index.tsx b/web/pages/index.tsx
similarity index 100%
rename from apps/app/pages/index.tsx
rename to web/pages/index.tsx
diff --git a/apps/app/pages/installations/[provider]/index.tsx b/web/pages/installations/[provider]/index.tsx
similarity index 69%
rename from apps/app/pages/installations/[provider]/index.tsx
rename to web/pages/installations/[provider]/index.tsx
index 2becb1f88..ad5b5a284 100644
--- a/apps/app/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;
diff --git a/apps/app/pages/invitations.tsx b/web/pages/invitations.tsx
similarity index 100%
rename from apps/app/pages/invitations.tsx
rename to web/pages/invitations.tsx
diff --git a/web/pages/m/[workspaceSlug]/editor.tsx b/web/pages/m/[workspaceSlug]/editor.tsx
new file mode 100644
index 000000000..2bfac63b8
--- /dev/null
+++ b/web/pages/m/[workspaceSlug]/editor.tsx
@@ -0,0 +1,99 @@
+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 } = useForm({
+ defaultValues: {
+ data: "",
+ data_html: "",
+ },
+ });
+
+ useEffect(() => {
+ setIsLoading(true);
+ if (!router?.query?.["editable"]) return;
+ setIsLoading(false);
+ const data_html = Cookies.get("data_html");
+ setValue("data_html", data_html ?? "");
+ }, [isEditable, setValue, router]);
+
+ 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;
diff --git a/web/pages/m/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx b/web/pages/m/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx
new file mode 100644
index 000000000..ede258c73
--- /dev/null
+++ b/web/pages/m/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx
@@ -0,0 +1,175 @@
+// react
+import React, { useCallback, useEffect } from "react";
+
+// next
+import { useRouter } from "next/router";
+
+// swr
+import useSWR, { mutate } from "swr";
+
+// react hook forms
+import { useForm } from "react-hook-form";
+
+// services
+import issuesService from "services/issues.service";
+
+// fetch key
+import { ISSUE_DETAILS, PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys";
+
+// hooks
+import useUser from "hooks/use-user";
+import useProjectMembers from "hooks/use-project-members";
+
+// layouts
+import WebViewLayout from "layouts/web-view-layout";
+
+// ui
+import { Spinner } from "components/ui";
+
+// components
+import {
+ IssueWebViewForm,
+ SubIssueList,
+ IssueAttachments,
+ IssuePropertiesDetail,
+ IssueLinks,
+ IssueActivity,
+} from "components/web-view";
+
+// types
+import type { IIssue } from "types";
+
+const MobileWebViewIssueDetail = () => {
+ const router = useRouter();
+ const { workspaceSlug, projectId, issueId } = router.query;
+
+ const memberRole = useProjectMembers(
+ workspaceSlug as string,
+ projectId as string,
+ !!workspaceSlug && !!projectId
+ );
+
+ const isAllowed = Boolean(memberRole.isMember || memberRole.isOwner);
+
+ const { user } = useUser();
+
+ const { register, control, reset, handleSubmit, watch } = useForm
({
+ defaultValues: {
+ name: "",
+ description: "",
+ description_html: "",
+ state: "",
+ },
+ });
+
+ const {
+ data: issueDetails,
+ mutate: mutateIssueDetails,
+ error,
+ } = useSWR(
+ workspaceSlug && projectId && issueId ? ISSUE_DETAILS(issueId.toString()) : null,
+ workspaceSlug && projectId && issueId
+ ? () =>
+ issuesService.retrieve(workspaceSlug.toString(), projectId.toString(), issueId.toString())
+ : null
+ );
+
+ useEffect(() => {
+ if (!issueDetails) return;
+ reset({
+ ...issueDetails,
+ name: issueDetails.name,
+ description: issueDetails.description,
+ description_html: issueDetails.description_html,
+ state: issueDetails.state,
+ assignees_list:
+ issueDetails.assignees_list ?? issueDetails.assignee_details?.map((user) => user.id),
+ labels_list: issueDetails.labels_list ?? issueDetails.labels,
+ labels: issueDetails.labels_list ?? issueDetails.labels,
+ });
+ }, [issueDetails, reset]);
+
+ const submitChanges = useCallback(
+ async (formData: Partial) => {
+ if (!workspaceSlug || !projectId || !issueId) return;
+
+ mutate(
+ ISSUE_DETAILS(issueId.toString()),
+ (prevData) => {
+ if (!prevData) return prevData;
+
+ return {
+ ...prevData,
+ ...formData,
+ };
+ },
+ false
+ );
+
+ const payload: Partial = {
+ ...formData,
+ };
+
+ delete payload.blocker_issues;
+ delete payload.blocked_issues;
+
+ await issuesService
+ .patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
+ .then(() => {
+ mutateIssueDetails();
+ mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
+ })
+ .catch((e) => {
+ console.error(e);
+ });
+ },
+ [workspaceSlug, issueId, projectId, mutateIssueDetails, user]
+ );
+
+ if (!error && !issueDetails)
+ return (
+
+
+
+ );
+
+ if (error)
+ return (
+
+ {error?.response?.data || "Something went wrong"}
+
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default MobileWebViewIssueDetail;
diff --git a/apps/app/pages/magic-sign-in.tsx b/web/pages/magic-sign-in.tsx
similarity index 100%
rename from apps/app/pages/magic-sign-in.tsx
rename to web/pages/magic-sign-in.tsx
diff --git a/apps/app/pages/onboarding.tsx b/web/pages/onboarding.tsx
similarity index 100%
rename from apps/app/pages/onboarding.tsx
rename to web/pages/onboarding.tsx
diff --git a/apps/app/pages/reset-password.tsx b/web/pages/reset-password.tsx
similarity index 100%
rename from apps/app/pages/reset-password.tsx
rename to web/pages/reset-password.tsx
diff --git a/apps/app/pages/sign-up.tsx b/web/pages/sign-up.tsx
similarity index 100%
rename from apps/app/pages/sign-up.tsx
rename to web/pages/sign-up.tsx
diff --git a/apps/app/pages/workspace-member-invitation.tsx b/web/pages/workspace-member-invitation.tsx
similarity index 100%
rename from apps/app/pages/workspace-member-invitation.tsx
rename to web/pages/workspace-member-invitation.tsx
diff --git a/apps/space/postcss.config.js b/web/postcss.config.js
similarity index 72%
rename from apps/space/postcss.config.js
rename to web/postcss.config.js
index 12a703d90..cbfea5ea2 100644
--- a/apps/space/postcss.config.js
+++ b/web/postcss.config.js
@@ -1,5 +1,6 @@
module.exports = {
plugins: {
+ "tailwindcss/nesting": {},
tailwindcss: {},
autoprefixer: {},
},
diff --git a/apps/space/public/404.svg b/web/public/404.svg
similarity index 100%
rename from apps/space/public/404.svg
rename to web/public/404.svg
diff --git a/apps/app/public/animated-icons/uploading.json b/web/public/animated-icons/uploading.json
similarity index 100%
rename from apps/app/public/animated-icons/uploading.json
rename to web/public/animated-icons/uploading.json
diff --git a/apps/app/public/attachment/audio-icon.png b/web/public/attachment/audio-icon.png
similarity index 100%
rename from apps/app/public/attachment/audio-icon.png
rename to web/public/attachment/audio-icon.png
diff --git a/apps/app/public/attachment/css-icon.png b/web/public/attachment/css-icon.png
similarity index 100%
rename from apps/app/public/attachment/css-icon.png
rename to web/public/attachment/css-icon.png
diff --git a/apps/app/public/attachment/csv-icon.png b/web/public/attachment/csv-icon.png
similarity index 100%
rename from apps/app/public/attachment/csv-icon.png
rename to web/public/attachment/csv-icon.png
diff --git a/apps/app/public/attachment/default-icon.png b/web/public/attachment/default-icon.png
similarity index 100%
rename from apps/app/public/attachment/default-icon.png
rename to web/public/attachment/default-icon.png
diff --git a/apps/app/public/attachment/doc-icon.png b/web/public/attachment/doc-icon.png
similarity index 100%
rename from apps/app/public/attachment/doc-icon.png
rename to web/public/attachment/doc-icon.png
diff --git a/apps/app/public/attachment/excel-icon.png b/web/public/attachment/excel-icon.png
similarity index 100%
rename from apps/app/public/attachment/excel-icon.png
rename to web/public/attachment/excel-icon.png
diff --git a/apps/app/public/attachment/figma-icon.png b/web/public/attachment/figma-icon.png
similarity index 100%
rename from apps/app/public/attachment/figma-icon.png
rename to web/public/attachment/figma-icon.png
diff --git a/apps/app/public/attachment/html-icon.png b/web/public/attachment/html-icon.png
similarity index 100%
rename from apps/app/public/attachment/html-icon.png
rename to web/public/attachment/html-icon.png
diff --git a/apps/app/public/attachment/img-icon.png b/web/public/attachment/img-icon.png
similarity index 100%
rename from apps/app/public/attachment/img-icon.png
rename to web/public/attachment/img-icon.png
diff --git a/apps/app/public/attachment/jpg-icon.png b/web/public/attachment/jpg-icon.png
similarity index 100%
rename from apps/app/public/attachment/jpg-icon.png
rename to web/public/attachment/jpg-icon.png
diff --git a/apps/app/public/attachment/js-icon.png b/web/public/attachment/js-icon.png
similarity index 100%
rename from apps/app/public/attachment/js-icon.png
rename to web/public/attachment/js-icon.png
diff --git a/apps/app/public/attachment/pdf-icon.png b/web/public/attachment/pdf-icon.png
similarity index 100%
rename from apps/app/public/attachment/pdf-icon.png
rename to web/public/attachment/pdf-icon.png
diff --git a/apps/app/public/attachment/png-icon.png b/web/public/attachment/png-icon.png
similarity index 100%
rename from apps/app/public/attachment/png-icon.png
rename to web/public/attachment/png-icon.png
diff --git a/apps/app/public/attachment/svg-icon.png b/web/public/attachment/svg-icon.png
similarity index 100%
rename from apps/app/public/attachment/svg-icon.png
rename to web/public/attachment/svg-icon.png
diff --git a/apps/app/public/attachment/txt-icon.png b/web/public/attachment/txt-icon.png
similarity index 100%
rename from apps/app/public/attachment/txt-icon.png
rename to web/public/attachment/txt-icon.png
diff --git a/apps/app/public/attachment/video-icon.png b/web/public/attachment/video-icon.png
similarity index 100%
rename from apps/app/public/attachment/video-icon.png
rename to web/public/attachment/video-icon.png
diff --git a/apps/app/public/auth/project-not-authorized.svg b/web/public/auth/project-not-authorized.svg
similarity index 100%
rename from apps/app/public/auth/project-not-authorized.svg
rename to web/public/auth/project-not-authorized.svg
diff --git a/apps/app/public/auth/workspace-not-authorized.svg b/web/public/auth/workspace-not-authorized.svg
similarity index 100%
rename from apps/app/public/auth/workspace-not-authorized.svg
rename to web/public/auth/workspace-not-authorized.svg
diff --git a/apps/app/public/empty-state/analytics.svg b/web/public/empty-state/analytics.svg
similarity index 100%
rename from apps/app/public/empty-state/analytics.svg
rename to web/public/empty-state/analytics.svg
diff --git a/apps/app/public/empty-state/cycle.svg b/web/public/empty-state/cycle.svg
similarity index 100%
rename from apps/app/public/empty-state/cycle.svg
rename to web/public/empty-state/cycle.svg
diff --git a/apps/app/public/empty-state/dashboard.svg b/web/public/empty-state/dashboard.svg
similarity index 100%
rename from apps/app/public/empty-state/dashboard.svg
rename to web/public/empty-state/dashboard.svg
diff --git a/apps/app/public/empty-state/empty_bar_graph.svg b/web/public/empty-state/empty_bar_graph.svg
similarity index 100%
rename from apps/app/public/empty-state/empty_bar_graph.svg
rename to web/public/empty-state/empty_bar_graph.svg
diff --git a/apps/app/public/empty-state/empty_graph.svg b/web/public/empty-state/empty_graph.svg
similarity index 100%
rename from apps/app/public/empty-state/empty_graph.svg
rename to web/public/empty-state/empty_graph.svg
diff --git a/apps/app/public/empty-state/empty_users.svg b/web/public/empty-state/empty_users.svg
similarity index 100%
rename from apps/app/public/empty-state/empty_users.svg
rename to web/public/empty-state/empty_users.svg
diff --git a/apps/app/public/empty-state/estimate.svg b/web/public/empty-state/estimate.svg
similarity index 100%
rename from apps/app/public/empty-state/estimate.svg
rename to web/public/empty-state/estimate.svg
diff --git a/apps/app/public/empty-state/integration.svg b/web/public/empty-state/integration.svg
similarity index 100%
rename from apps/app/public/empty-state/integration.svg
rename to web/public/empty-state/integration.svg
diff --git a/apps/app/public/empty-state/invitation.svg b/web/public/empty-state/invitation.svg
similarity index 100%
rename from apps/app/public/empty-state/invitation.svg
rename to web/public/empty-state/invitation.svg
diff --git a/apps/app/public/empty-state/issue-archive.svg b/web/public/empty-state/issue-archive.svg
similarity index 100%
rename from apps/app/public/empty-state/issue-archive.svg
rename to web/public/empty-state/issue-archive.svg
diff --git a/apps/app/public/empty-state/issue.svg b/web/public/empty-state/issue.svg
similarity index 100%
rename from apps/app/public/empty-state/issue.svg
rename to web/public/empty-state/issue.svg
diff --git a/apps/app/public/empty-state/label.svg b/web/public/empty-state/label.svg
similarity index 100%
rename from apps/app/public/empty-state/label.svg
rename to web/public/empty-state/label.svg
diff --git a/apps/app/public/empty-state/module.svg b/web/public/empty-state/module.svg
similarity index 100%
rename from apps/app/public/empty-state/module.svg
rename to web/public/empty-state/module.svg
diff --git a/apps/app/public/empty-state/my-issues.svg b/web/public/empty-state/my-issues.svg
similarity index 100%
rename from apps/app/public/empty-state/my-issues.svg
rename to web/public/empty-state/my-issues.svg
diff --git a/apps/app/public/empty-state/notification.svg b/web/public/empty-state/notification.svg
similarity index 100%
rename from apps/app/public/empty-state/notification.svg
rename to web/public/empty-state/notification.svg
diff --git a/apps/app/public/empty-state/page.svg b/web/public/empty-state/page.svg
similarity index 100%
rename from apps/app/public/empty-state/page.svg
rename to web/public/empty-state/page.svg
diff --git a/apps/app/public/empty-state/project.svg b/web/public/empty-state/project.svg
similarity index 100%
rename from apps/app/public/empty-state/project.svg
rename to web/public/empty-state/project.svg
diff --git a/apps/app/public/empty-state/recent_activity.svg b/web/public/empty-state/recent_activity.svg
similarity index 100%
rename from apps/app/public/empty-state/recent_activity.svg
rename to web/public/empty-state/recent_activity.svg
diff --git a/apps/app/public/empty-state/state_graph.svg b/web/public/empty-state/state_graph.svg
similarity index 100%
rename from apps/app/public/empty-state/state_graph.svg
rename to web/public/empty-state/state_graph.svg
diff --git a/apps/app/public/empty-state/view.svg b/web/public/empty-state/view.svg
similarity index 100%
rename from apps/app/public/empty-state/view.svg
rename to web/public/empty-state/view.svg
diff --git a/web/public/favicon/android-chrome-192x192.png b/web/public/favicon/android-chrome-192x192.png
new file mode 100644
index 000000000..62e95acfc
Binary files /dev/null and b/web/public/favicon/android-chrome-192x192.png differ
diff --git a/web/public/favicon/android-chrome-512x512.png b/web/public/favicon/android-chrome-512x512.png
new file mode 100644
index 000000000..41400832b
Binary files /dev/null and b/web/public/favicon/android-chrome-512x512.png differ
diff --git a/web/public/favicon/apple-touch-icon.png b/web/public/favicon/apple-touch-icon.png
new file mode 100644
index 000000000..5273d4951
Binary files /dev/null and b/web/public/favicon/apple-touch-icon.png differ
diff --git a/web/public/favicon/favicon-16x16.png b/web/public/favicon/favicon-16x16.png
new file mode 100644
index 000000000..8ddbd49c0
Binary files /dev/null and b/web/public/favicon/favicon-16x16.png differ
diff --git a/web/public/favicon/favicon-32x32.png b/web/public/favicon/favicon-32x32.png
new file mode 100644
index 000000000..80cbe7a68
Binary files /dev/null and b/web/public/favicon/favicon-32x32.png differ
diff --git a/web/public/favicon/favicon.ico b/web/public/favicon/favicon.ico
new file mode 100644
index 000000000..9094a07c7
Binary files /dev/null and b/web/public/favicon/favicon.ico differ
diff --git a/web/public/favicon/site.webmanifest b/web/public/favicon/site.webmanifest
new file mode 100644
index 000000000..45dc8a206
--- /dev/null
+++ b/web/public/favicon/site.webmanifest
@@ -0,0 +1 @@
+{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
\ No newline at end of file
diff --git a/apps/app/public/logos/github-black.png b/web/public/logos/github-black.png
similarity index 100%
rename from apps/app/public/logos/github-black.png
rename to web/public/logos/github-black.png
diff --git a/apps/app/public/logos/github-square.png b/web/public/logos/github-square.png
similarity index 100%
rename from apps/app/public/logos/github-square.png
rename to web/public/logos/github-square.png
diff --git a/apps/app/public/logos/github-white.png b/web/public/logos/github-white.png
similarity index 100%
rename from apps/app/public/logos/github-white.png
rename to web/public/logos/github-white.png
diff --git a/apps/app/public/mac-command.svg b/web/public/mac-command.svg
similarity index 100%
rename from apps/app/public/mac-command.svg
rename to web/public/mac-command.svg
diff --git a/apps/app/public/onboarding/cycles.svg b/web/public/onboarding/cycles.svg
similarity index 100%
rename from apps/app/public/onboarding/cycles.svg
rename to web/public/onboarding/cycles.svg
diff --git a/apps/app/public/onboarding/cycles.webp b/web/public/onboarding/cycles.webp
similarity index 100%
rename from apps/app/public/onboarding/cycles.webp
rename to web/public/onboarding/cycles.webp
diff --git a/apps/app/public/onboarding/issues.svg b/web/public/onboarding/issues.svg
similarity index 100%
rename from apps/app/public/onboarding/issues.svg
rename to web/public/onboarding/issues.svg
diff --git a/apps/app/public/onboarding/issues.webp b/web/public/onboarding/issues.webp
similarity index 100%
rename from apps/app/public/onboarding/issues.webp
rename to web/public/onboarding/issues.webp
diff --git a/apps/app/public/onboarding/modules.svg b/web/public/onboarding/modules.svg
similarity index 100%
rename from apps/app/public/onboarding/modules.svg
rename to web/public/onboarding/modules.svg
diff --git a/apps/app/public/onboarding/modules.webp b/web/public/onboarding/modules.webp
similarity index 100%
rename from apps/app/public/onboarding/modules.webp
rename to web/public/onboarding/modules.webp
diff --git a/apps/app/public/onboarding/pages.svg b/web/public/onboarding/pages.svg
similarity index 100%
rename from apps/app/public/onboarding/pages.svg
rename to web/public/onboarding/pages.svg
diff --git a/apps/app/public/onboarding/pages.webp b/web/public/onboarding/pages.webp
similarity index 100%
rename from apps/app/public/onboarding/pages.webp
rename to web/public/onboarding/pages.webp
diff --git a/apps/app/public/onboarding/views.svg b/web/public/onboarding/views.svg
similarity index 100%
rename from apps/app/public/onboarding/views.svg
rename to web/public/onboarding/views.svg
diff --git a/apps/app/public/onboarding/views.webp b/web/public/onboarding/views.webp
similarity index 100%
rename from apps/app/public/onboarding/views.webp
rename to web/public/onboarding/views.webp
diff --git a/web/public/plane-logos/black-horizontal-with-blue-logo.svg b/web/public/plane-logos/black-horizontal-with-blue-logo.svg
new file mode 100644
index 000000000..ae79919fc
--- /dev/null
+++ b/web/public/plane-logos/black-horizontal-with-blue-logo.svg
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/public/plane-logos/blue-without-text.png b/web/public/plane-logos/blue-without-text.png
new file mode 100644
index 000000000..ea94aec79
Binary files /dev/null and b/web/public/plane-logos/blue-without-text.png differ
diff --git a/web/public/plane-logos/white-horizontal-with-blue-logo.svg b/web/public/plane-logos/white-horizontal-with-blue-logo.svg
new file mode 100644
index 000000000..1f09cc34a
--- /dev/null
+++ b/web/public/plane-logos/white-horizontal-with-blue-logo.svg
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/public/plane-logos/white-horizontal.svg b/web/public/plane-logos/white-horizontal.svg
new file mode 100644
index 000000000..13e2dbb9f
--- /dev/null
+++ b/web/public/plane-logos/white-horizontal.svg
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/app/public/services/csv.svg b/web/public/services/csv.svg
similarity index 100%
rename from apps/app/public/services/csv.svg
rename to web/public/services/csv.svg
diff --git a/apps/app/public/services/excel.svg b/web/public/services/excel.svg
similarity index 100%
rename from apps/app/public/services/excel.svg
rename to web/public/services/excel.svg
diff --git a/apps/app/public/services/github.png b/web/public/services/github.png
similarity index 100%
rename from apps/app/public/services/github.png
rename to web/public/services/github.png
diff --git a/apps/app/public/services/jira.png b/web/public/services/jira.png
similarity index 100%
rename from apps/app/public/services/jira.png
rename to web/public/services/jira.png
diff --git a/apps/app/public/services/json.svg b/web/public/services/json.svg
similarity index 100%
rename from apps/app/public/services/json.svg
rename to web/public/services/json.svg
diff --git a/apps/app/public/services/slack.png b/web/public/services/slack.png
similarity index 100%
rename from apps/app/public/services/slack.png
rename to web/public/services/slack.png
diff --git a/apps/app/public/site.webmanifest.json b/web/public/site.webmanifest.json
similarity index 100%
rename from apps/app/public/site.webmanifest.json
rename to web/public/site.webmanifest.json
diff --git a/apps/app/public/sw.js b/web/public/sw.js
similarity index 100%
rename from apps/app/public/sw.js
rename to web/public/sw.js
diff --git a/apps/app/public/sw.js.map b/web/public/sw.js.map
similarity index 100%
rename from apps/app/public/sw.js.map
rename to web/public/sw.js.map
diff --git a/apps/app/public/user.png b/web/public/user.png
similarity index 100%
rename from apps/app/public/user.png
rename to web/public/user.png
diff --git a/apps/app/public/workbox-7805bd61.js b/web/public/workbox-7805bd61.js
similarity index 100%
rename from apps/app/public/workbox-7805bd61.js
rename to web/public/workbox-7805bd61.js
diff --git a/apps/app/public/workbox-7805bd61.js.map b/web/public/workbox-7805bd61.js.map
similarity index 100%
rename from apps/app/public/workbox-7805bd61.js.map
rename to web/public/workbox-7805bd61.js.map
diff --git a/apps/app/sentry.client.config.js b/web/sentry.client.config.js
similarity index 100%
rename from apps/app/sentry.client.config.js
rename to web/sentry.client.config.js
diff --git a/apps/app/sentry.edge.config.js b/web/sentry.edge.config.js
similarity index 100%
rename from apps/app/sentry.edge.config.js
rename to web/sentry.edge.config.js
diff --git a/apps/app/sentry.properties b/web/sentry.properties
similarity index 100%
rename from apps/app/sentry.properties
rename to web/sentry.properties
diff --git a/apps/app/sentry.server.config.js b/web/sentry.server.config.js
similarity index 100%
rename from apps/app/sentry.server.config.js
rename to web/sentry.server.config.js
diff --git a/apps/app/services/ai.service.ts b/web/services/ai.service.ts
similarity index 100%
rename from apps/app/services/ai.service.ts
rename to web/services/ai.service.ts
diff --git a/apps/app/services/analytics.service.ts b/web/services/analytics.service.ts
similarity index 100%
rename from apps/app/services/analytics.service.ts
rename to web/services/analytics.service.ts
diff --git a/apps/app/services/api.service.ts b/web/services/api.service.ts
similarity index 95%
rename from apps/app/services/api.service.ts
rename to web/services/api.service.ts
index 361fea03e..c71c75ba8 100644
--- a/apps/app/services/api.service.ts
+++ b/web/services/api.service.ts
@@ -8,11 +8,19 @@ const nonValidatedRoutes = [
"/reset-password",
"/workspace-member-invitation",
"/sign-up",
+ "/m/",
];
const validateRouteCheck = (route: string): boolean => {
let validationToggle = false;
- const routeCheck = nonValidatedRoutes.find((_route: string) => _route === route);
+
+ let routeCheck = false;
+ nonValidatedRoutes.forEach((_route: string) => {
+ if (route.includes(_route)) {
+ routeCheck = true;
+ }
+ });
+
if (routeCheck) validationToggle = true;
return validationToggle;
};
diff --git a/apps/app/services/app-installations.service.ts b/web/services/app-installations.service.ts
similarity index 77%
rename from apps/app/services/app-installations.service.ts
rename to web/services/app-installations.service.ts
index 8ee04dcfe..dea6fa421 100644
--- a/apps/app/services/app-installations.service.ts
+++ b/web/services/app-installations.service.ts
@@ -17,7 +17,12 @@ class AppInstallationsService extends APIService {
});
}
- async addSlackChannel(workspaceSlug: string, projectId: string, integrationId: string | null | undefined, data: any): Promise {
+ async addSlackChannel(
+ workspaceSlug: string,
+ projectId: string,
+ integrationId: string | null | undefined,
+ data: any
+ ): Promise {
return this.post(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/workspace-integrations/${integrationId}/project-slack-sync/`,
data
@@ -28,7 +33,11 @@ class AppInstallationsService extends APIService {
});
}
- async getSlackChannelDetail(workspaceSlug: string, projectId: string, integrationId: string | null | undefined): Promise {
+ async getSlackChannelDetail(
+ workspaceSlug: string,
+ projectId: string,
+ integrationId: string | null | undefined
+ ): Promise {
return this.get(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/workspace-integrations/${integrationId}/project-slack-sync/`
)
@@ -38,7 +47,12 @@ class AppInstallationsService extends APIService {
});
}
- async removeSlackChannel(workspaceSlug: string, projectId: string, integrationId: string | null | undefined, slackSyncId: string | undefined): Promise {
+ async removeSlackChannel(
+ workspaceSlug: string,
+ projectId: string,
+ integrationId: string | null | undefined,
+ slackSyncId: string | undefined
+ ): Promise {
return this.delete(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/workspace-integrations/${integrationId}/project-slack-sync/${slackSyncId}`
)
diff --git a/apps/app/services/authentication.service.ts b/web/services/authentication.service.ts
similarity index 100%
rename from apps/app/services/authentication.service.ts
rename to web/services/authentication.service.ts
diff --git a/apps/app/services/cycles.service.ts b/web/services/cycles.service.ts
similarity index 100%
rename from apps/app/services/cycles.service.ts
rename to web/services/cycles.service.ts
diff --git a/apps/app/services/estimates.service.ts b/web/services/estimates.service.ts
similarity index 100%
rename from apps/app/services/estimates.service.ts
rename to web/services/estimates.service.ts
diff --git a/apps/app/services/file.service.ts b/web/services/file.service.ts
similarity index 100%
rename from apps/app/services/file.service.ts
rename to web/services/file.service.ts
diff --git a/apps/app/services/inbox.service.ts b/web/services/inbox.service.ts
similarity index 100%
rename from apps/app/services/inbox.service.ts
rename to web/services/inbox.service.ts
diff --git a/apps/app/services/integration/csv.services.ts b/web/services/integration/csv.services.ts
similarity index 100%
rename from apps/app/services/integration/csv.services.ts
rename to web/services/integration/csv.services.ts
diff --git a/apps/app/services/integration/github.service.ts b/web/services/integration/github.service.ts
similarity index 100%
rename from apps/app/services/integration/github.service.ts
rename to web/services/integration/github.service.ts
diff --git a/apps/app/services/integration/index.ts b/web/services/integration/index.ts
similarity index 100%
rename from apps/app/services/integration/index.ts
rename to web/services/integration/index.ts
diff --git a/apps/app/services/integration/jira.service.ts b/web/services/integration/jira.service.ts
similarity index 100%
rename from apps/app/services/integration/jira.service.ts
rename to web/services/integration/jira.service.ts
diff --git a/apps/app/services/issues.service.ts b/web/services/issues.service.ts
similarity index 99%
rename from apps/app/services/issues.service.ts
rename to web/services/issues.service.ts
index b8875e6c5..af5d722e3 100644
--- a/apps/app/services/issues.service.ts
+++ b/web/services/issues.service.ts
@@ -204,7 +204,7 @@ class ProjectIssuesServices extends APIService {
projectId: string,
issueId: string,
commentId: string,
- data: IIssueComment,
+ data: Partial,
user: ICurrentUserResponse | undefined
): Promise {
return this.patch(
diff --git a/apps/app/services/modules.service.ts b/web/services/modules.service.ts
similarity index 98%
rename from apps/app/services/modules.service.ts
rename to web/services/modules.service.ts
index c70066a1e..0e3b5cfe2 100644
--- a/apps/app/services/modules.service.ts
+++ b/web/services/modules.service.ts
@@ -221,17 +221,16 @@ class ProjectIssuesServices extends APIService {
metadata: any;
title: string;
url: string;
- },
-
+ }
): Promise {
return this.patch(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-links/${linkId}/`,
data
)
- .then((response) => response?.data)
- .catch((error) => {
- throw error?.response;
- });
+ .then((response) => response?.data)
+ .catch((error) => {
+ throw error?.response;
+ });
}
async deleteModuleLink(
diff --git a/apps/app/services/notifications.service.ts b/web/services/notifications.service.ts
similarity index 100%
rename from apps/app/services/notifications.service.ts
rename to web/services/notifications.service.ts
diff --git a/apps/app/services/pages.service.ts b/web/services/pages.service.ts
similarity index 100%
rename from apps/app/services/pages.service.ts
rename to web/services/pages.service.ts
diff --git a/apps/app/services/project-publish.service.ts b/web/services/project-publish.service.ts
similarity index 100%
rename from apps/app/services/project-publish.service.ts
rename to web/services/project-publish.service.ts
diff --git a/apps/app/services/project.service.ts b/web/services/project.service.ts
similarity index 94%
rename from apps/app/services/project.service.ts
rename to web/services/project.service.ts
index 961333bee..0c2712c56 100644
--- a/apps/app/services/project.service.ts
+++ b/web/services/project.service.ts
@@ -21,7 +21,7 @@ const { NEXT_PUBLIC_API_BASE_URL } = process.env;
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
-class ProjectServices extends APIService {
+export class ProjectServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
}
@@ -142,6 +142,30 @@ class ProjectServices extends APIService {
});
}
+ async leaveProject(
+ workspaceSlug: string,
+ projectId: string,
+ user: ICurrentUserResponse
+ ): Promise {
+ return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/leave/`)
+ .then((response) => {
+ if (trackEvent)
+ trackEventServices.trackProjectEvent(
+ "PROJECT_MEMBER_LEAVE",
+ {
+ workspaceSlug,
+ projectId,
+ ...response?.data,
+ },
+ user
+ );
+ return response?.data;
+ })
+ .catch((error) => {
+ throw error?.response?.data;
+ });
+ }
+
async joinProjects(data: any): Promise {
return this.post("/api/users/me/invitations/projects/", data)
.then((response) => response?.data)
diff --git a/apps/app/services/reaction.service.ts b/web/services/reaction.service.ts
similarity index 100%
rename from apps/app/services/reaction.service.ts
rename to web/services/reaction.service.ts
diff --git a/apps/app/services/state.service.ts b/web/services/state.service.ts
similarity index 100%
rename from apps/app/services/state.service.ts
rename to web/services/state.service.ts
diff --git a/apps/app/services/track-event.service.ts b/web/services/track-event.service.ts
similarity index 99%
rename from apps/app/services/track-event.service.ts
rename to web/services/track-event.service.ts
index f55a6f366..c59242f50 100644
--- a/apps/app/services/track-event.service.ts
+++ b/web/services/track-event.service.ts
@@ -35,7 +35,8 @@ type ProjectEventType =
| "CREATE_PROJECT"
| "UPDATE_PROJECT"
| "DELETE_PROJECT"
- | "PROJECT_MEMBER_INVITE";
+ | "PROJECT_MEMBER_INVITE"
+ | "PROJECT_MEMBER_LEAVE";
type IssueEventType = "ISSUE_CREATE" | "ISSUE_UPDATE" | "ISSUE_DELETE";
@@ -163,7 +164,11 @@ class TrackEventServices extends APIService {
user: ICurrentUserResponse | undefined
): Promise {
let payload: any;
- if (eventName !== "DELETE_PROJECT" && eventName !== "PROJECT_MEMBER_INVITE")
+ if (
+ eventName !== "DELETE_PROJECT" &&
+ eventName !== "PROJECT_MEMBER_INVITE" &&
+ eventName !== "PROJECT_MEMBER_LEAVE"
+ )
payload = {
workspaceId: data?.workspace_detail?.id,
workspaceName: data?.workspace_detail?.name,
diff --git a/apps/app/services/user.service.ts b/web/services/user.service.ts
similarity index 100%
rename from apps/app/services/user.service.ts
rename to web/services/user.service.ts
diff --git a/apps/app/services/views.service.ts b/web/services/views.service.ts
similarity index 100%
rename from apps/app/services/views.service.ts
rename to web/services/views.service.ts
diff --git a/apps/app/services/web-waitlist.service.ts b/web/services/web-waitlist.service.ts
similarity index 100%
rename from apps/app/services/web-waitlist.service.ts
rename to web/services/web-waitlist.service.ts
diff --git a/apps/app/services/workspace.service.ts b/web/services/workspace.service.ts
similarity index 100%
rename from apps/app/services/workspace.service.ts
rename to web/services/workspace.service.ts
diff --git a/apps/app/store/issues.ts b/web/store/issues.ts
similarity index 94%
rename from apps/app/store/issues.ts
rename to web/store/issues.ts
index 538c5e2a9..286d98534 100644
--- a/apps/app/store/issues.ts
+++ b/web/store/issues.ts
@@ -116,11 +116,12 @@ class IssuesStore {
const originalIssue = { ...this.issues[issueId] };
// immediately update the issue in the store
- const updatedIssue = { ...originalIssue, ...issueForm };
+ const updatedIssue = { ...this.issues[issueId], ...issueForm };
+ if (updatedIssue.assignees_list) updatedIssue.assignees = updatedIssue.assignees_list;
try {
runInAction(() => {
- this.issues[issueId] = updatedIssue;
+ this.issues[issueId] = { ...updatedIssue };
});
// make a patch request to update the issue
diff --git a/apps/app/store/project-publish.tsx b/web/store/project-publish.tsx
similarity index 87%
rename from apps/app/store/project-publish.tsx
rename to web/store/project-publish.tsx
index ffc45f546..b8c6f0dbe 100644
--- a/apps/app/store/project-publish.tsx
+++ b/web/store/project-publish.tsx
@@ -21,7 +21,8 @@ export interface IProjectPublishSettings {
}
export interface IProjectPublishStore {
- loader: boolean;
+ generalLoader: boolean;
+ fetchSettingsLoader: boolean;
error: any | null;
projectPublishModal: boolean;
@@ -35,7 +36,7 @@ export interface IProjectPublishStore {
project_slug: string,
user: any
) => Promise;
- createProjectSettingsAsync: (
+ publishProject: (
workspace_slug: string,
project_slug: string,
data: IProjectPublishSettings,
@@ -48,7 +49,7 @@ export interface IProjectPublishStore {
data: IProjectPublishSettings,
user: any
) => Promise;
- deleteProjectSettingsAsync: (
+ unPublishProject: (
workspace_slug: string,
project_slug: string,
project_publish_id: string,
@@ -57,7 +58,8 @@ export interface IProjectPublishStore {
}
class ProjectPublishStore implements IProjectPublishStore {
- loader: boolean = false;
+ generalLoader: boolean = false;
+ fetchSettingsLoader: boolean = false;
error: any | null = null;
projectPublishModal: boolean = false;
@@ -72,7 +74,8 @@ class ProjectPublishStore implements IProjectPublishStore {
constructor(_rootStore: RootStore) {
makeObservable(this, {
// observable
- loader: observable,
+ generalLoader: observable,
+ fetchSettingsLoader: observable,
error: observable,
projectPublishModal: observable,
@@ -80,6 +83,10 @@ class ProjectPublishStore implements IProjectPublishStore {
projectPublishSettings: observable.ref,
// action
handleProjectModal: action,
+ getProjectSettingsAsync: action,
+ publishProject: action,
+ updateProjectSettingsAsync: action,
+ unPublishProject: action,
// computed
});
@@ -100,7 +107,7 @@ class ProjectPublishStore implements IProjectPublishStore {
getProjectSettingsAsync = async (workspace_slug: string, project_slug: string, user: any) => {
try {
- this.loader = true;
+ this.fetchSettingsLoader = true;
this.error = null;
const response = await this.projectPublishService.getProjectSettingsAsync(
@@ -128,30 +135,30 @@ class ProjectPublishStore implements IProjectPublishStore {
runInAction(() => {
this.projectPublishSettings = _projectPublishSettings;
- this.loader = false;
+ this.fetchSettingsLoader = false;
this.error = null;
});
} else {
this.projectPublishSettings = "not-initialized";
- this.loader = false;
+ this.fetchSettingsLoader = false;
this.error = null;
}
return response;
} catch (error) {
- this.loader = false;
+ this.fetchSettingsLoader = false;
this.error = error;
return error;
}
};
- createProjectSettingsAsync = async (
+ publishProject = async (
workspace_slug: string,
project_slug: string,
data: IProjectPublishSettings,
user: any
) => {
try {
- this.loader = true;
+ this.generalLoader = true;
this.error = null;
const response = await this.projectPublishService.createProjectSettingsAsync(
@@ -174,14 +181,14 @@ class ProjectPublishStore implements IProjectPublishStore {
runInAction(() => {
this.projectPublishSettings = _projectPublishSettings;
- this.loader = false;
+ this.generalLoader = false;
this.error = null;
});
return response;
}
} catch (error) {
- this.loader = false;
+ this.generalLoader = false;
this.error = error;
return error;
}
@@ -195,7 +202,7 @@ class ProjectPublishStore implements IProjectPublishStore {
user: any
) => {
try {
- this.loader = true;
+ this.generalLoader = true;
this.error = null;
const response = await this.projectPublishService.updateProjectSettingsAsync(
@@ -219,27 +226,27 @@ class ProjectPublishStore implements IProjectPublishStore {
runInAction(() => {
this.projectPublishSettings = _projectPublishSettings;
- this.loader = false;
+ this.generalLoader = false;
this.error = null;
});
return response;
}
} catch (error) {
- this.loader = false;
+ this.generalLoader = false;
this.error = error;
return error;
}
};
- deleteProjectSettingsAsync = async (
+ unPublishProject = async (
workspace_slug: string,
project_slug: string,
project_publish_id: string,
user: any
) => {
try {
- this.loader = true;
+ this.generalLoader = true;
this.error = null;
const response = await this.projectPublishService.deleteProjectSettingsAsync(
@@ -251,13 +258,13 @@ class ProjectPublishStore implements IProjectPublishStore {
runInAction(() => {
this.projectPublishSettings = "not-initialized";
- this.loader = false;
+ this.generalLoader = false;
this.error = null;
});
return response;
} catch (error) {
- this.loader = false;
+ this.generalLoader = false;
this.error = error;
return error;
}
diff --git a/web/store/project.ts b/web/store/project.ts
new file mode 100644
index 000000000..0fe842dad
--- /dev/null
+++ b/web/store/project.ts
@@ -0,0 +1,86 @@
+import { observable, action, computed, makeObservable, runInAction } from "mobx";
+// types
+import { RootStore } from "./root";
+// services
+import { ProjectServices } from "services/project.service";
+
+export interface IProject {
+ id: string;
+ name: string;
+ workspaceSlug: string;
+}
+
+export interface IProjectStore {
+ loader: boolean;
+ error: any | null;
+
+ projectLeaveModal: boolean;
+ projectLeaveDetails: IProject | any;
+
+ handleProjectLeaveModal: (project: IProject | null) => void;
+
+ leaveProject: (workspace_slug: string, project_slug: string, user: any) => Promise;
+}
+
+class ProjectStore implements IProjectStore {
+ loader: boolean = false;
+ error: any | null = null;
+
+ projectLeaveModal: boolean = false;
+ projectLeaveDetails: IProject | null = null;
+
+ // root store
+ rootStore;
+ // service
+ projectService;
+
+ constructor(_rootStore: RootStore) {
+ makeObservable(this, {
+ // observable
+ loader: observable,
+ error: observable,
+
+ projectLeaveModal: observable,
+ projectLeaveDetails: observable.ref,
+ // action
+ handleProjectLeaveModal: action,
+ leaveProject: action,
+ // computed
+ });
+
+ this.rootStore = _rootStore;
+ this.projectService = new ProjectServices();
+ }
+
+ handleProjectLeaveModal = (project: IProject | null = null) => {
+ if (project && project?.id) {
+ this.projectLeaveModal = !this.projectLeaveModal;
+ this.projectLeaveDetails = project;
+ } else {
+ this.projectLeaveModal = !this.projectLeaveModal;
+ this.projectLeaveDetails = null;
+ }
+ };
+
+ leaveProject = async (workspace_slug: string, project_slug: string, user: any) => {
+ try {
+ this.loader = true;
+ this.error = null;
+
+ const response = await this.projectService.leaveProject(workspace_slug, project_slug, user);
+
+ runInAction(() => {
+ this.loader = false;
+ this.error = null;
+ });
+
+ return response;
+ } catch (error) {
+ this.loader = false;
+ this.error = error;
+ return error;
+ }
+ };
+}
+
+export default ProjectStore;
diff --git a/apps/app/store/root.ts b/web/store/root.ts
similarity index 83%
rename from apps/app/store/root.ts
rename to web/store/root.ts
index 40dd62fe6..ce0bdfad5 100644
--- a/apps/app/store/root.ts
+++ b/web/store/root.ts
@@ -3,20 +3,23 @@ import { enableStaticRendering } from "mobx-react-lite";
// store imports
import UserStore from "./user";
import ThemeStore from "./theme";
-import IssuesStore from "./issues";
+import ProjectStore, { IProjectStore } from "./project";
import ProjectPublishStore, { IProjectPublishStore } from "./project-publish";
+import IssuesStore from "./issues";
enableStaticRendering(typeof window === "undefined");
export class RootStore {
user;
theme;
+ project: IProjectStore;
projectPublish: IProjectPublishStore;
issues: IssuesStore;
constructor() {
this.user = new UserStore(this);
this.theme = new ThemeStore(this);
+ this.project = new ProjectStore(this);
this.projectPublish = new ProjectPublishStore(this);
this.issues = new IssuesStore(this);
}
diff --git a/apps/app/store/theme.ts b/web/store/theme.ts
similarity index 100%
rename from apps/app/store/theme.ts
rename to web/store/theme.ts
diff --git a/apps/app/store/user.ts b/web/store/user.ts
similarity index 100%
rename from apps/app/store/user.ts
rename to web/store/user.ts
diff --git a/apps/app/styles/command-pallette.css b/web/styles/command-pallette.css
similarity index 100%
rename from apps/app/styles/command-pallette.css
rename to web/styles/command-pallette.css
diff --git a/web/styles/editor.css b/web/styles/editor.css
new file mode 100644
index 000000000..9da250dd1
--- /dev/null
+++ b/web/styles/editor.css
@@ -0,0 +1,231 @@
+.ProseMirror p.is-editor-empty:first-child::before {
+ content: attr(data-placeholder);
+ float: left;
+ color: rgb(var(--color-text-400));
+ pointer-events: none;
+ height: 0;
+}
+
+.ProseMirror .is-empty::before {
+ content: attr(data-placeholder);
+ float: left;
+ color: rgb(var(--color-text-400));
+ pointer-events: none;
+ height: 0;
+}
+
+/* Custom image styles */
+
+.ProseMirror img {
+ transition: filter 0.1s ease-in-out;
+
+ &:hover {
+ cursor: pointer;
+ filter: brightness(90%);
+ }
+
+ &.ProseMirror-selectednode {
+ outline: 3px solid #5abbf7;
+ filter: brightness(90%);
+ }
+}
+
+.ProseMirror-gapcursor:after {
+ border-top: 1px solid rgb(var(--color-text-100)) !important;
+}
+
+/* Custom TODO list checkboxes – shoutout to this awesome tutorial: https://moderncss.dev/pure-css-custom-checkbox-style/ */
+
+ul[data-type="taskList"] li > label {
+ margin-right: 0.2rem;
+ user-select: none;
+}
+
+@media screen and (max-width: 768px) {
+ ul[data-type="taskList"] li > label {
+ margin-right: 0.5rem;
+ }
+}
+
+ul[data-type="taskList"] li > label input[type="checkbox"] {
+ -webkit-appearance: none;
+ appearance: none;
+ background-color: rgb(var(--color-background-100));
+ margin: 0;
+ cursor: pointer;
+ width: 1.2rem;
+ height: 1.2rem;
+ position: relative;
+ border: 2px solid rgb(var(--color-text-100));
+ margin-right: 0.3rem;
+ display: grid;
+ place-content: center;
+
+ &:hover {
+ background-color: rgb(var(--color-background-80));
+ }
+
+ &:active {
+ background-color: rgb(var(--color-background-90));
+ }
+
+ &::before {
+ content: "";
+ width: 0.65em;
+ height: 0.65em;
+ transform: scale(0);
+ transition: 120ms transform ease-in-out;
+ box-shadow: inset 1em 1em;
+ transform-origin: center;
+ clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
+ }
+
+ &:checked::before {
+ transform: scale(1);
+ }
+}
+
+ul[data-type="taskList"] li[data-checked="true"] > div > p {
+ color: rgb(var(--color-text-200));
+ text-decoration: line-through;
+ text-decoration-thickness: 2px;
+}
+
+/* Overwrite tippy-box original max-width */
+
+.tippy-box {
+ max-width: 400px !important;
+}
+
+.ProseMirror {
+ position: relative;
+ word-wrap: break-word;
+ white-space: pre-wrap;
+ -moz-tab-size: 4;
+ tab-size: 4;
+ -webkit-user-select: text;
+ -moz-user-select: text;
+ -ms-user-select: text;
+ user-select: text;
+ outline: none;
+ cursor: text;
+ line-height: 1.2;
+ font-family: inherit;
+ font-size: 14px;
+ color: inherit;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ appearance: textfield;
+ -webkit-appearance: textfield;
+ -moz-appearance: textfield;
+}
+
+.fadeIn {
+ opacity: 1;
+ transition: opacity 0.3s ease-in;
+}
+
+.fadeOut {
+ opacity: 0;
+ transition: opacity 0.2s ease-out;
+}
+
+.img-placeholder {
+ position: relative;
+ width: 35%;
+
+ &:before {
+ content: "";
+ box-sizing: border-box;
+ position: absolute;
+ top: 50%;
+ left: 45%;
+ width: 20px;
+ height: 20px;
+ border-radius: 50%;
+ border: 3px solid rgba(var(--color-text-200));
+ border-top-color: rgba(var(--color-text-800));
+ animation: spinning 0.6s linear infinite;
+ }
+}
+
+@keyframes spinning {
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+#tiptap-container {
+ table {
+ border-collapse: collapse;
+ table-layout: fixed;
+ margin: 0;
+ border: 1px solid rgb(var(--color-border-200));
+ width: 100%;
+
+ td,
+ th {
+ min-width: 1em;
+ border: 1px solid rgb(var(--color-border-200));
+ padding: 10px 15px;
+ vertical-align: top;
+ box-sizing: border-box;
+ position: relative;
+ transition: background-color 0.3s ease;
+
+ > * {
+ margin-bottom: 0;
+ }
+ }
+
+ th {
+ font-weight: bold;
+ text-align: left;
+ background-color: rgb(var(--color-primary-100));
+ }
+
+ td:hover {
+ background-color: rgba(var(--color-primary-300), 0.1);
+ }
+
+ .selectedCell:after {
+ z-index: 2;
+ position: absolute;
+ content: "";
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ background-color: rgba(var(--color-primary-300), 0.1);
+ pointer-events: none;
+ }
+
+ .column-resize-handle {
+ position: absolute;
+ right: -2px;
+ top: 0;
+ bottom: -2px;
+ width: 2px;
+ background-color: rgb(var(--color-primary-400));
+ pointer-events: none;
+ }
+ }
+}
+
+.tableWrapper {
+ overflow-x: auto;
+}
+
+.resize-cursor {
+ cursor: ew-resize;
+ cursor: col-resize;
+}
+
+.ProseMirror table * p {
+ padding: 0px 1px;
+ margin: 6px 2px;
+}
+
+.ProseMirror table * .is-empty::before {
+ opacity: 0;
+}
diff --git a/apps/app/styles/globals.css b/web/styles/globals.css
similarity index 100%
rename from apps/app/styles/globals.css
rename to web/styles/globals.css
diff --git a/apps/app/styles/nprogress.css b/web/styles/nprogress.css
similarity index 100%
rename from apps/app/styles/nprogress.css
rename to web/styles/nprogress.css
diff --git a/apps/app/styles/react-datepicker.css b/web/styles/react-datepicker.css
similarity index 100%
rename from apps/app/styles/react-datepicker.css
rename to web/styles/react-datepicker.css
diff --git a/apps/app/tailwind.config.js b/web/tailwind.config.js
similarity index 100%
rename from apps/app/tailwind.config.js
rename to web/tailwind.config.js
diff --git a/web/tsconfig.json b/web/tsconfig.json
new file mode 100644
index 000000000..63c95575d
--- /dev/null
+++ b/web/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "extends": "tsconfig/nextjs.json",
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
+ "exclude": ["node_modules"],
+ "compilerOptions": {
+ "baseUrl": ".",
+ "jsx": "preserve"
+ }
+}
diff --git a/apps/app/types/ai.d.ts b/web/types/ai.d.ts
similarity index 100%
rename from apps/app/types/ai.d.ts
rename to web/types/ai.d.ts
diff --git a/apps/app/types/analytics.d.ts b/web/types/analytics.d.ts
similarity index 100%
rename from apps/app/types/analytics.d.ts
rename to web/types/analytics.d.ts
diff --git a/apps/app/types/calendar.ts b/web/types/calendar.ts
similarity index 100%
rename from apps/app/types/calendar.ts
rename to web/types/calendar.ts
diff --git a/apps/app/types/cycles.d.ts b/web/types/cycles.d.ts
similarity index 100%
rename from apps/app/types/cycles.d.ts
rename to web/types/cycles.d.ts
diff --git a/apps/app/types/estimate.d.ts b/web/types/estimate.d.ts
similarity index 100%
rename from apps/app/types/estimate.d.ts
rename to web/types/estimate.d.ts
diff --git a/apps/app/types/importer/github-importer.d.ts b/web/types/importer/github-importer.d.ts
similarity index 100%
rename from apps/app/types/importer/github-importer.d.ts
rename to web/types/importer/github-importer.d.ts
diff --git a/apps/app/types/importer/index.ts b/web/types/importer/index.ts
similarity index 100%
rename from apps/app/types/importer/index.ts
rename to web/types/importer/index.ts
diff --git a/apps/app/types/importer/jira-importer.d.ts b/web/types/importer/jira-importer.d.ts
similarity index 100%
rename from apps/app/types/importer/jira-importer.d.ts
rename to web/types/importer/jira-importer.d.ts
diff --git a/apps/app/types/inbox.d.ts b/web/types/inbox.d.ts
similarity index 100%
rename from apps/app/types/inbox.d.ts
rename to web/types/inbox.d.ts
diff --git a/apps/app/types/index.d.ts b/web/types/index.d.ts
similarity index 99%
rename from apps/app/types/index.d.ts
rename to web/types/index.d.ts
index 8c9592917..dbd314826 100644
--- a/apps/app/types/index.d.ts
+++ b/web/types/index.d.ts
@@ -19,7 +19,6 @@ export * from "./notifications";
export * from "./waitlist";
export * from "./reaction";
-
export type NestedKeyOf = {
[Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends object
? ObjectType[Key] extends { pop: any; push: any }
diff --git a/apps/app/types/integration.d.ts b/web/types/integration.d.ts
similarity index 100%
rename from apps/app/types/integration.d.ts
rename to web/types/integration.d.ts
diff --git a/apps/app/types/issues.d.ts b/web/types/issues.d.ts
similarity index 98%
rename from apps/app/types/issues.d.ts
rename to web/types/issues.d.ts
index 93e1598f3..cdc0a391a 100644
--- a/apps/app/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;
diff --git a/apps/app/types/modules.d.ts b/web/types/modules.d.ts
similarity index 100%
rename from apps/app/types/modules.d.ts
rename to web/types/modules.d.ts
diff --git a/apps/app/types/notifications.d.ts b/web/types/notifications.d.ts
similarity index 100%
rename from apps/app/types/notifications.d.ts
rename to web/types/notifications.d.ts
diff --git a/apps/app/types/pages.d.ts b/web/types/pages.d.ts
similarity index 100%
rename from apps/app/types/pages.d.ts
rename to web/types/pages.d.ts
diff --git a/apps/app/types/projects.d.ts b/web/types/projects.d.ts
similarity index 99%
rename from apps/app/types/projects.d.ts
rename to web/types/projects.d.ts
index 78ef4d953..590fe5023 100644
--- a/apps/app/types/projects.d.ts
+++ b/web/types/projects.d.ts
@@ -8,7 +8,7 @@ import type {
TIssueOrderByOptions,
TIssueViewOptions,
TStateGroups,
-} from "./";
+} from ".";
export interface IProject {
archive_in: number;
diff --git a/apps/app/types/reaction.d.ts b/web/types/reaction.d.ts
similarity index 100%
rename from apps/app/types/reaction.d.ts
rename to web/types/reaction.d.ts
diff --git a/apps/app/types/state.d.ts b/web/types/state.d.ts
similarity index 100%
rename from apps/app/types/state.d.ts
rename to web/types/state.d.ts
diff --git a/apps/app/types/users.d.ts b/web/types/users.d.ts
similarity index 99%
rename from apps/app/types/users.d.ts
rename to web/types/users.d.ts
index 55c95e5f3..8440922d1 100644
--- a/apps/app/types/users.d.ts
+++ b/web/types/users.d.ts
@@ -7,7 +7,7 @@ import {
NestedKeyOf,
Properties,
TStateGroups,
-} from "./";
+} from ".";
export interface IUser {
avatar: string;
diff --git a/apps/app/types/views.d.ts b/web/types/views.d.ts
similarity index 100%
rename from apps/app/types/views.d.ts
rename to web/types/views.d.ts
diff --git a/apps/app/types/waitlist.d.ts b/web/types/waitlist.d.ts
similarity index 100%
rename from apps/app/types/waitlist.d.ts
rename to web/types/waitlist.d.ts
diff --git a/apps/app/types/workspace.d.ts b/web/types/workspace.d.ts
similarity index 100%
rename from apps/app/types/workspace.d.ts
rename to web/types/workspace.d.ts
diff --git a/yarn.lock b/yarn.lock
index 3eafeb5b9..1aa8e5bde 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -37,37 +37,37 @@
"@babel/highlight" "^7.10.4"
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.22.10", "@babel/code-frame@^7.22.5":
- version "7.22.10"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.10.tgz#1c20e612b768fefa75f6e90d6ecb86329247f0a3"
- integrity sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==
+ version "7.22.13"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e"
+ integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==
dependencies:
- "@babel/highlight" "^7.22.10"
+ "@babel/highlight" "^7.22.13"
chalk "^2.4.2"
-"@babel/compat-data@^7.22.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9":
+"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9":
version "7.22.9"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730"
integrity sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==
"@babel/core@^7.11.1":
- version "7.22.10"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.10.tgz#aad442c7bcd1582252cb4576747ace35bc122f35"
- integrity sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.11.tgz#8033acaa2aa24c3f814edaaa057f3ce0ba559c24"
+ integrity sha512-lh7RJrtPdhibbxndr6/xx0w8+CVlY5FJZiaSz908Fpy+G0xkBFTvwLcKJFF4PJxVfGhVWNebikpWGnOoC71juQ==
dependencies:
"@ampproject/remapping" "^2.2.0"
"@babel/code-frame" "^7.22.10"
"@babel/generator" "^7.22.10"
"@babel/helper-compilation-targets" "^7.22.10"
"@babel/helper-module-transforms" "^7.22.9"
- "@babel/helpers" "^7.22.10"
- "@babel/parser" "^7.22.10"
+ "@babel/helpers" "^7.22.11"
+ "@babel/parser" "^7.22.11"
"@babel/template" "^7.22.5"
- "@babel/traverse" "^7.22.10"
- "@babel/types" "^7.22.10"
+ "@babel/traverse" "^7.22.11"
+ "@babel/types" "^7.22.11"
convert-source-map "^1.7.0"
debug "^4.1.0"
gensync "^1.0.0-beta.2"
- json5 "^2.2.2"
+ json5 "^2.2.3"
semver "^6.3.1"
"@babel/generator@^7.22.10":
@@ -105,10 +105,10 @@
lru-cache "^5.1.1"
semver "^6.3.1"
-"@babel/helper-create-class-features-plugin@^7.22.5":
- version "7.22.10"
- resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.10.tgz#dd2612d59eac45588021ac3d6fa976d08f4e95a3"
- integrity sha512-5IBb77txKYQPpOEdUdIhBx8VrZyDCQ+H82H0+5dX1TmuscP5vJKEE3cKurjtIw/vFwzbVH48VweE78kVDBrqjA==
+"@babel/helper-create-class-features-plugin@^7.22.11", "@babel/helper-create-class-features-plugin@^7.22.5":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.11.tgz#4078686740459eeb4af3494a273ac09148dfb213"
+ integrity sha512-y1grdYL4WzmUDBRGK0pDbIoFd7UZKoDurDzWEoNMYoj1EL+foGRQNyPWDcC+YyegN5y1DUsFFmzjGijB3nSVAQ==
dependencies:
"@babel/helper-annotate-as-pure" "^7.22.5"
"@babel/helper-environment-visitor" "^7.22.5"
@@ -260,28 +260,28 @@
"@babel/template" "^7.22.5"
"@babel/types" "^7.22.10"
-"@babel/helpers@^7.22.10":
- version "7.22.10"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.10.tgz#ae6005c539dfbcb5cd71fb51bfc8a52ba63bc37a"
- integrity sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==
+"@babel/helpers@^7.22.11":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.11.tgz#b02f5d5f2d7abc21ab59eeed80de410ba70b056a"
+ integrity sha512-vyOXC8PBWaGc5h7GMsNx68OH33cypkEDJCHvYVVgVbbxJDROYVtexSk0gK5iCF1xNjRIN2s8ai7hwkWDq5szWg==
dependencies:
"@babel/template" "^7.22.5"
- "@babel/traverse" "^7.22.10"
- "@babel/types" "^7.22.10"
+ "@babel/traverse" "^7.22.11"
+ "@babel/types" "^7.22.11"
-"@babel/highlight@^7.10.4", "@babel/highlight@^7.22.10":
- version "7.22.10"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.10.tgz#02a3f6d8c1cb4521b2fd0ab0da8f4739936137d7"
- integrity sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==
+"@babel/highlight@^7.10.4", "@babel/highlight@^7.22.13":
+ version "7.22.13"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.13.tgz#9cda839e5d3be9ca9e8c26b6dd69e7548f0cbf16"
+ integrity sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==
dependencies:
"@babel/helper-validator-identifier" "^7.22.5"
chalk "^2.4.2"
js-tokens "^4.0.0"
-"@babel/parser@^7.22.10", "@babel/parser@^7.22.5":
- version "7.22.10"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.10.tgz#e37634f9a12a1716136c44624ef54283cabd3f55"
- integrity sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==
+"@babel/parser@^7.22.11", "@babel/parser@^7.22.5":
+ version "7.22.14"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.14.tgz#c7de58e8de106e88efca42ce17f0033209dfd245"
+ integrity sha512-1KucTHgOvaw/LzCVrEOAyXkr9rQlp0A1HiHRYnSUE9dmb8PvPW7o5sscg+5169r54n3vGlbx6GevTE/Iw/P3AQ==
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5":
version "7.22.5"
@@ -438,10 +438,10 @@
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
-"@babel/plugin-transform-async-generator-functions@^7.22.10":
- version "7.22.10"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.10.tgz#45946cd17f915b10e65c29b8ed18a0a50fc648c8"
- integrity sha512-eueE8lvKVzq5wIObKK/7dvoeKJ+xc6TvRn6aysIjS6pSCeLy7S/eVi7pEQknZqyqvzaNKdDtem8nUNTBgDVR2g==
+"@babel/plugin-transform-async-generator-functions@^7.22.11":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.11.tgz#dbe3b1ff5a52e2e5edc4b19a60d325a675ed2649"
+ integrity sha512-0pAlmeRJn6wU84zzZsEOx1JV1Jf8fqO9ok7wofIJwUnplYo247dcd24P+cMJht7ts9xkzdtB0EPHmOb7F+KzXw==
dependencies:
"@babel/helper-environment-visitor" "^7.22.5"
"@babel/helper-plugin-utils" "^7.22.5"
@@ -479,12 +479,12 @@
"@babel/helper-create-class-features-plugin" "^7.22.5"
"@babel/helper-plugin-utils" "^7.22.5"
-"@babel/plugin-transform-class-static-block@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.5.tgz#3e40c46f048403472d6f4183116d5e46b1bff5ba"
- integrity sha512-SPToJ5eYZLxlnp1UzdARpOGeC2GbHvr9d/UV0EukuVx8atktg194oe+C5BqQ8jRTkgLRVOPYeXRSBg1IlMoVRA==
+"@babel/plugin-transform-class-static-block@^7.22.11":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz#dc8cc6e498f55692ac6b4b89e56d87cec766c974"
+ integrity sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==
dependencies:
- "@babel/helper-create-class-features-plugin" "^7.22.5"
+ "@babel/helper-create-class-features-plugin" "^7.22.11"
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-class-static-block" "^7.14.5"
@@ -533,10 +533,10 @@
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
-"@babel/plugin-transform-dynamic-import@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.5.tgz#d6908a8916a810468c4edff73b5b75bda6ad393e"
- integrity sha512-0MC3ppTB1AMxd8fXjSrbPa7LT9hrImt+/fcj+Pg5YMD7UQyWp/02+JWpdnCymmsXwIx5Z+sYn1bwCn4ZJNvhqQ==
+"@babel/plugin-transform-dynamic-import@^7.22.11":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz#2c7722d2a5c01839eaf31518c6ff96d408e447aa"
+ integrity sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-dynamic-import" "^7.8.3"
@@ -549,10 +549,10 @@
"@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.5"
"@babel/helper-plugin-utils" "^7.22.5"
-"@babel/plugin-transform-export-namespace-from@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.5.tgz#57c41cb1d0613d22f548fddd8b288eedb9973a5b"
- integrity sha512-X4hhm7FRnPgd4nDA4b/5V280xCx6oL7Oob5+9qVS5C13Zq4bh1qq7LU0GgRU6b5dBWBvhGaXYVB4AcN6+ol6vg==
+"@babel/plugin-transform-export-namespace-from@^7.22.11":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz#b3c84c8f19880b6c7440108f8929caf6056db26c"
+ integrity sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-export-namespace-from" "^7.8.3"
@@ -573,10 +573,10 @@
"@babel/helper-function-name" "^7.22.5"
"@babel/helper-plugin-utils" "^7.22.5"
-"@babel/plugin-transform-json-strings@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz#14b64352fdf7e1f737eed68de1a1468bd2a77ec0"
- integrity sha512-DuCRB7fu8MyTLbEQd1ew3R85nx/88yMoqo2uPSjevMj3yoN7CDM8jkgrY0wmVxfJZyJ/B9fE1iq7EQppWQmR5A==
+"@babel/plugin-transform-json-strings@^7.22.11":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz#689a34e1eed1928a40954e37f74509f48af67835"
+ integrity sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-json-strings" "^7.8.3"
@@ -588,10 +588,10 @@
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
-"@babel/plugin-transform-logical-assignment-operators@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.5.tgz#66ae5f068fd5a9a5dc570df16f56c2a8462a9d6c"
- integrity sha512-MQQOUW1KL8X0cDWfbwYP+TbVbZm16QmQXJQ+vndPtH/BoO0lOKpVoEDMI7+PskYxH+IiE0tS8xZye0qr1lGzSA==
+"@babel/plugin-transform-logical-assignment-operators@^7.22.11":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz#24c522a61688bde045b7d9bc3c2597a4d948fc9c"
+ integrity sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
@@ -611,22 +611,22 @@
"@babel/helper-module-transforms" "^7.22.5"
"@babel/helper-plugin-utils" "^7.22.5"
-"@babel/plugin-transform-modules-commonjs@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz#7d9875908d19b8c0536085af7b053fd5bd651bfa"
- integrity sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==
+"@babel/plugin-transform-modules-commonjs@^7.22.11":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.11.tgz#d7991d3abad199c03b68ee66a64f216c47ffdfae"
+ integrity sha512-o2+bg7GDS60cJMgz9jWqRUsWkMzLCxp+jFDeDUT5sjRlAxcJWZ2ylNdI7QQ2+CH5hWu7OnN+Cv3htt7AkSf96g==
dependencies:
- "@babel/helper-module-transforms" "^7.22.5"
+ "@babel/helper-module-transforms" "^7.22.9"
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/helper-simple-access" "^7.22.5"
-"@babel/plugin-transform-modules-systemjs@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz#18c31410b5e579a0092638f95c896c2a98a5d496"
- integrity sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ==
+"@babel/plugin-transform-modules-systemjs@^7.22.11":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.11.tgz#3386be5875d316493b517207e8f1931d93154bb1"
+ integrity sha512-rIqHmHoMEOhI3VkVf5jQ15l539KrwhzqcBO6wdCNWPWc/JWt9ILNYNUssbRpeq0qWns8svuw8LnMNCvWBIJ8wA==
dependencies:
"@babel/helper-hoist-variables" "^7.22.5"
- "@babel/helper-module-transforms" "^7.22.5"
+ "@babel/helper-module-transforms" "^7.22.9"
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/helper-validator-identifier" "^7.22.5"
@@ -653,29 +653,29 @@
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
-"@babel/plugin-transform-nullish-coalescing-operator@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.5.tgz#f8872c65776e0b552e0849d7596cddd416c3e381"
- integrity sha512-6CF8g6z1dNYZ/VXok5uYkkBBICHZPiGEl7oDnAx2Mt1hlHVHOSIKWJaXHjQJA5VB43KZnXZDIexMchY4y2PGdA==
+"@babel/plugin-transform-nullish-coalescing-operator@^7.22.11":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz#debef6c8ba795f5ac67cd861a81b744c5d38d9fc"
+ integrity sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
-"@babel/plugin-transform-numeric-separator@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.5.tgz#57226a2ed9e512b9b446517ab6fa2d17abb83f58"
- integrity sha512-NbslED1/6M+sXiwwtcAB/nieypGw02Ejf4KtDeMkCEpP6gWFMX1wI9WKYua+4oBneCCEmulOkRpwywypVZzs/g==
+"@babel/plugin-transform-numeric-separator@^7.22.11":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz#498d77dc45a6c6db74bb829c02a01c1d719cbfbd"
+ integrity sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-numeric-separator" "^7.10.4"
-"@babel/plugin-transform-object-rest-spread@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.5.tgz#9686dc3447df4753b0b2a2fae7e8bc33cdc1f2e1"
- integrity sha512-Kk3lyDmEslH9DnvCDA1s1kkd3YWQITiBOHngOtDL9Pt6BZjzqb6hiOlb8VfjiiQJ2unmegBqZu0rx5RxJb5vmQ==
+"@babel/plugin-transform-object-rest-spread@^7.22.11":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.11.tgz#dbbb06ce783cd994a8f430d8cefa553e9b42ca62"
+ integrity sha512-nX8cPFa6+UmbepISvlf5jhQyaC7ASs/7UxHmMkuJ/k5xSHvDPPaibMo+v3TXwU/Pjqhep/nFNpd3zn4YR59pnw==
dependencies:
- "@babel/compat-data" "^7.22.5"
- "@babel/helper-compilation-targets" "^7.22.5"
+ "@babel/compat-data" "^7.22.9"
+ "@babel/helper-compilation-targets" "^7.22.10"
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-object-rest-spread" "^7.8.3"
"@babel/plugin-transform-parameters" "^7.22.5"
@@ -688,18 +688,18 @@
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/helper-replace-supers" "^7.22.5"
-"@babel/plugin-transform-optional-catch-binding@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.5.tgz#842080be3076703be0eaf32ead6ac8174edee333"
- integrity sha512-pH8orJahy+hzZje5b8e2QIlBWQvGpelS76C63Z+jhZKsmzfNaPQ+LaW6dcJ9bxTpo1mtXbgHwy765Ro3jftmUg==
+"@babel/plugin-transform-optional-catch-binding@^7.22.11":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz#461cc4f578a127bb055527b3e77404cad38c08e0"
+ integrity sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
-"@babel/plugin-transform-optional-chaining@^7.22.10", "@babel/plugin-transform-optional-chaining@^7.22.5":
- version "7.22.10"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.10.tgz#076d28a7e074392e840d4ae587d83445bac0372a"
- integrity sha512-MMkQqZAZ+MGj+jGTG3OTuhKeBpNcO+0oCEbrGNEaOmiEn+1MzRyQlYsruGiU8RTK3zV6XwrVJTmwiDOyYK6J9g==
+"@babel/plugin-transform-optional-chaining@^7.22.12", "@babel/plugin-transform-optional-chaining@^7.22.5":
+ version "7.22.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.12.tgz#d7ebf6a88cd2f4d307b0e000ab630acd8124b333"
+ integrity sha512-7XXCVqZtyFWqjDsYDY4T45w4mlx1rf7aOgkc/Ww76xkgBiOlmjPkx36PBLHa1k1rwWvVgYMPsbuVnIamx2ZQJw==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
@@ -720,13 +720,13 @@
"@babel/helper-create-class-features-plugin" "^7.22.5"
"@babel/helper-plugin-utils" "^7.22.5"
-"@babel/plugin-transform-private-property-in-object@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.5.tgz#07a77f28cbb251546a43d175a1dda4cf3ef83e32"
- integrity sha512-/9xnaTTJcVoBtSSmrVyhtSvO3kbqS2ODoh2juEU72c3aYonNF0OMGiaz2gjukyKM2wBBYJP38S4JiE0Wfb5VMQ==
+"@babel/plugin-transform-private-property-in-object@^7.22.11":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz#ad45c4fc440e9cb84c718ed0906d96cf40f9a4e1"
+ integrity sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==
dependencies:
"@babel/helper-annotate-as-pure" "^7.22.5"
- "@babel/helper-create-class-features-plugin" "^7.22.5"
+ "@babel/helper-create-class-features-plugin" "^7.22.11"
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-private-property-in-object" "^7.14.5"
@@ -820,9 +820,9 @@
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/preset-env@^7.11.0":
- version "7.22.10"
- resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.22.10.tgz#3263b9fe2c8823d191d28e61eac60a79f9ce8a0f"
- integrity sha512-riHpLb1drNkpLlocmSyEg4oYJIQFeXAK/d7rI6mbD0XsvoTOOweXDmQPG/ErxsEhWk3rl3Q/3F6RFQlVFS8m0A==
+ version "7.22.14"
+ resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.22.14.tgz#1cbb468d899f64fa71c53446f13b7ff8c0005cc1"
+ integrity sha512-daodMIoVo+ol/g+//c/AH+szBkFj4STQUikvBijRGL72Ph+w+AMTSh55DUETe8KJlPlDT1k/mp7NBfOuiWmoig==
dependencies:
"@babel/compat-data" "^7.22.9"
"@babel/helper-compilation-targets" "^7.22.10"
@@ -850,41 +850,41 @@
"@babel/plugin-syntax-top-level-await" "^7.14.5"
"@babel/plugin-syntax-unicode-sets-regex" "^7.18.6"
"@babel/plugin-transform-arrow-functions" "^7.22.5"
- "@babel/plugin-transform-async-generator-functions" "^7.22.10"
+ "@babel/plugin-transform-async-generator-functions" "^7.22.11"
"@babel/plugin-transform-async-to-generator" "^7.22.5"
"@babel/plugin-transform-block-scoped-functions" "^7.22.5"
"@babel/plugin-transform-block-scoping" "^7.22.10"
"@babel/plugin-transform-class-properties" "^7.22.5"
- "@babel/plugin-transform-class-static-block" "^7.22.5"
+ "@babel/plugin-transform-class-static-block" "^7.22.11"
"@babel/plugin-transform-classes" "^7.22.6"
"@babel/plugin-transform-computed-properties" "^7.22.5"
"@babel/plugin-transform-destructuring" "^7.22.10"
"@babel/plugin-transform-dotall-regex" "^7.22.5"
"@babel/plugin-transform-duplicate-keys" "^7.22.5"
- "@babel/plugin-transform-dynamic-import" "^7.22.5"
+ "@babel/plugin-transform-dynamic-import" "^7.22.11"
"@babel/plugin-transform-exponentiation-operator" "^7.22.5"
- "@babel/plugin-transform-export-namespace-from" "^7.22.5"
+ "@babel/plugin-transform-export-namespace-from" "^7.22.11"
"@babel/plugin-transform-for-of" "^7.22.5"
"@babel/plugin-transform-function-name" "^7.22.5"
- "@babel/plugin-transform-json-strings" "^7.22.5"
+ "@babel/plugin-transform-json-strings" "^7.22.11"
"@babel/plugin-transform-literals" "^7.22.5"
- "@babel/plugin-transform-logical-assignment-operators" "^7.22.5"
+ "@babel/plugin-transform-logical-assignment-operators" "^7.22.11"
"@babel/plugin-transform-member-expression-literals" "^7.22.5"
"@babel/plugin-transform-modules-amd" "^7.22.5"
- "@babel/plugin-transform-modules-commonjs" "^7.22.5"
- "@babel/plugin-transform-modules-systemjs" "^7.22.5"
+ "@babel/plugin-transform-modules-commonjs" "^7.22.11"
+ "@babel/plugin-transform-modules-systemjs" "^7.22.11"
"@babel/plugin-transform-modules-umd" "^7.22.5"
"@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5"
"@babel/plugin-transform-new-target" "^7.22.5"
- "@babel/plugin-transform-nullish-coalescing-operator" "^7.22.5"
- "@babel/plugin-transform-numeric-separator" "^7.22.5"
- "@babel/plugin-transform-object-rest-spread" "^7.22.5"
+ "@babel/plugin-transform-nullish-coalescing-operator" "^7.22.11"
+ "@babel/plugin-transform-numeric-separator" "^7.22.11"
+ "@babel/plugin-transform-object-rest-spread" "^7.22.11"
"@babel/plugin-transform-object-super" "^7.22.5"
- "@babel/plugin-transform-optional-catch-binding" "^7.22.5"
- "@babel/plugin-transform-optional-chaining" "^7.22.10"
+ "@babel/plugin-transform-optional-catch-binding" "^7.22.11"
+ "@babel/plugin-transform-optional-chaining" "^7.22.12"
"@babel/plugin-transform-parameters" "^7.22.5"
"@babel/plugin-transform-private-methods" "^7.22.5"
- "@babel/plugin-transform-private-property-in-object" "^7.22.5"
+ "@babel/plugin-transform-private-property-in-object" "^7.22.11"
"@babel/plugin-transform-property-literals" "^7.22.5"
"@babel/plugin-transform-regenerator" "^7.22.10"
"@babel/plugin-transform-reserved-words" "^7.22.5"
@@ -898,7 +898,7 @@
"@babel/plugin-transform-unicode-regex" "^7.22.5"
"@babel/plugin-transform-unicode-sets-regex" "^7.22.5"
"@babel/preset-modules" "0.1.6-no-external-plugins"
- "@babel/types" "^7.22.10"
+ "@babel/types" "^7.22.11"
babel-plugin-polyfill-corejs2 "^0.4.5"
babel-plugin-polyfill-corejs3 "^0.8.3"
babel-plugin-polyfill-regenerator "^0.5.2"
@@ -919,10 +919,10 @@
resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
-"@babel/runtime@^7.1.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
- version "7.22.10"
- resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.10.tgz#ae3e9631fd947cb7e3610d3e9d8fef5f76696682"
- integrity sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==
+"@babel/runtime@^7.1.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.10", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.11.tgz#7a9ba3bbe406ad6f9e8dd4da2ece453eb23a77a4"
+ integrity sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==
dependencies:
regenerator-runtime "^0.14.0"
@@ -935,10 +935,10 @@
"@babel/parser" "^7.22.5"
"@babel/types" "^7.22.5"
-"@babel/traverse@^7.22.10":
- version "7.22.10"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.10.tgz#20252acb240e746d27c2e82b4484f199cf8141aa"
- integrity sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==
+"@babel/traverse@^7.22.11":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.11.tgz#71ebb3af7a05ff97280b83f05f8865ac94b2027c"
+ integrity sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ==
dependencies:
"@babel/code-frame" "^7.22.10"
"@babel/generator" "^7.22.10"
@@ -946,15 +946,15 @@
"@babel/helper-function-name" "^7.22.5"
"@babel/helper-hoist-variables" "^7.22.5"
"@babel/helper-split-export-declaration" "^7.22.6"
- "@babel/parser" "^7.22.10"
- "@babel/types" "^7.22.10"
+ "@babel/parser" "^7.22.11"
+ "@babel/types" "^7.22.11"
debug "^4.1.0"
globals "^11.1.0"
-"@babel/types@^7.22.10", "@babel/types@^7.22.5", "@babel/types@^7.4.4":
- version "7.22.10"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.10.tgz#4a9e76446048f2c66982d1a989dd12b8a2d2dc03"
- integrity sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==
+"@babel/types@^7.22.10", "@babel/types@^7.22.11", "@babel/types@^7.22.5", "@babel/types@^7.4.4":
+ version "7.22.11"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.11.tgz#0e65a6a1d4d9cbaa892b2213f6159485fe632ea2"
+ integrity sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==
dependencies:
"@babel/helper-string-parser" "^7.22.5"
"@babel/helper-validator-identifier" "^7.22.5"
@@ -1155,9 +1155,9 @@
eslint-visitor-keys "^3.3.0"
"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1":
- version "4.6.2"
- resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.6.2.tgz#1816b5f6948029c5eaacb0703b850ee0cb37d8f8"
- integrity sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==
+ version "4.8.0"
+ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.8.0.tgz#11195513186f68d42fbf449f9a7136b2c0c92005"
+ integrity sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==
"@eslint/eslintrc@^0.4.3":
version "0.4.3"
@@ -1204,15 +1204,42 @@
minimatch "^3.1.2"
strip-json-comments "^3.1.1"
-"@eslint/js@^8.47.0":
- version "8.47.0"
- resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.47.0.tgz#5478fdf443ff8158f9de171c704ae45308696c7d"
- integrity sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==
+"@eslint/js@8.48.0":
+ version "8.48.0"
+ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.48.0.tgz#642633964e217905436033a2bd08bf322849b7fb"
+ integrity sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==
+
+"@floating-ui/core@^1.4.1":
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.4.1.tgz#0d633f4b76052668afb932492ac452f7ebe97f17"
+ integrity sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ==
+ dependencies:
+ "@floating-ui/utils" "^0.1.1"
+
+"@floating-ui/dom@^1.5.1":
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.5.1.tgz#88b70defd002fe851f17b4a25efb2d3c04d7a8d7"
+ integrity sha512-KwvVcPSXg6mQygvA1TjbN/gh///36kKtllIF8SUm0qpFj8+rvYrpvlYdL1JoA71SHpDqgSSdGOSoQ0Mp3uY5aw==
+ dependencies:
+ "@floating-ui/core" "^1.4.1"
+ "@floating-ui/utils" "^0.1.1"
+
+"@floating-ui/react-dom@^2.0.1":
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.0.2.tgz#fab244d64db08e6bed7be4b5fcce65315ef44d20"
+ integrity sha512-5qhlDvjaLmAst/rKb3VdlCinwTF4EYMiVxuuc/HVUjs46W0zgtbMmAZ1UTsDrRTxRmUEzl92mOtWbeeXL26lSQ==
+ dependencies:
+ "@floating-ui/dom" "^1.5.1"
+
+"@floating-ui/utils@^0.1.1":
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.1.1.tgz#1a5b1959a528e374e8037c4396c3e825d6cf4a83"
+ integrity sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw==
"@headlessui/react@^1.7.13", "@headlessui/react@^1.7.3":
- version "1.7.16"
- resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.16.tgz#9c458c9c4dbb708258c9e8da3fe5363f915f7b11"
- integrity sha512-2MphIAZdSUacZBT6EXk8AJkj+EuvaaJbtCyHTJrPsz8inhzCl7qeNPI1uk1AUvCgWylVtdN8cVVmnhUDPxPy3g==
+ version "1.7.17"
+ resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.17.tgz#a0ec23af21b527c030967245fd99776aa7352bc6"
+ integrity sha512-4am+tzvkqDSSgiwrsEpGWqgGo9dz8qU5M3znCkC4PgkpY4HcCZzEDEvozltGGGHIKl9jbXbZPSH5TWn4sWJdow==
dependencies:
client-only "^0.0.1"
@@ -1222,9 +1249,9 @@
integrity sha512-7TyMjRrZZMBPa+/5Y8lN0iyvUU/01PeMGX2+RE7cQWpEUIcb4QotzUObFkJDejj/HUH4qjP/eQ0gzzKs2f+6Yw==
"@humanwhocodes/config-array@^0.11.10", "@humanwhocodes/config-array@^0.11.8":
- version "0.11.10"
- resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2"
- integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==
+ version "0.11.11"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.11.tgz#88a04c570dbbc7dd943e4712429c3df09bc32844"
+ integrity sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==
dependencies:
"@humanwhocodes/object-schema" "^1.2.1"
debug "^4.1.1"
@@ -1320,43 +1347,44 @@
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
-"@mui/base@5.0.0-beta.10":
- version "5.0.0-beta.10"
- resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.10.tgz#b9a2de21c7de45aa4275c7ecf5aa803ecc236ba6"
- integrity sha512-moTAhGwFfQffj7hsu61FnqcGqVcd53A1CrOhnskM9TF0Uh2rnLDMCuar4JRUWWpaJofAfQEbQBBFPadFQLI4PA==
+"@mui/base@5.0.0-beta.13":
+ version "5.0.0-beta.13"
+ resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.13.tgz#3bae94c39752546d84a67d4ca73486b7c4923a89"
+ integrity sha512-uC0l97pBspfDAp+iz2cJq8YZ8Sd9i73V77+WzUiOAckIVEyCm5dyVDZCCO2/phmzckVEeZCGcytybkjMQuhPQw==
dependencies:
- "@babel/runtime" "^7.22.6"
+ "@babel/runtime" "^7.22.10"
"@emotion/is-prop-valid" "^1.2.1"
+ "@floating-ui/react-dom" "^2.0.1"
"@mui/types" "^7.2.4"
- "@mui/utils" "^5.14.4"
+ "@mui/utils" "^5.14.7"
"@popperjs/core" "^2.11.8"
clsx "^2.0.0"
prop-types "^15.8.1"
react-is "^18.2.0"
-"@mui/core-downloads-tracker@^5.14.4":
- version "5.14.4"
- resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.4.tgz#a517265647ee9660170107d68905db5e400576c5"
- integrity sha512-pW2XghSi3hpYKX57Wu0SCWMTSpzvXZmmucj3TcOJWaCiFt4xr05w2gcwBZi36dAp9uvd9//9N51qbblmnD+GPg==
+"@mui/core-downloads-tracker@^5.14.7":
+ version "5.14.7"
+ resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.7.tgz#95bed2487bf59632125a13b8eb8f4c21e460afec"
+ integrity sha512-sCWTUNElBPgB30iLvWe3PU7SIlTKZNf6/E/sko85iHVeHCM6WPkDw+y89CrZYjhFNmPqt2fIQM/pZu+rP2lFLA==
-"@mui/icons-material@^5.14.1":
- version "5.14.3"
- resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.14.3.tgz#26a84d52ab2fceea2856adf7a139527b3a51ae90"
- integrity sha512-XkxWPhageu1OPUm2LWjo5XqeQ0t2xfGe8EiLkRW9oz2LHMMZmijvCxulhgquUVTF1DnoSh+3KoDLSsoAFtVNVw==
+"@mui/icons-material@^5.14.1", "@mui/icons-material@^5.14.7":
+ version "5.14.7"
+ resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.14.7.tgz#d7f6bd188fe38adf35c89d9343b8a529c2306383"
+ integrity sha512-mWp4DwMa8c1Gx9yOEtPgxM4b+e6hAbtZyzfSubdBwrnEE6G5D2rbAJ5MB+If6kfI48JaYaJ5j8+zAdmZLuZc0A==
dependencies:
- "@babel/runtime" "^7.22.6"
+ "@babel/runtime" "^7.22.10"
"@mui/material@^5.14.1":
- version "5.14.4"
- resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.14.4.tgz#9d4d1834a929a4acc59e550e34ca64c0fd60b3a6"
- integrity sha512-2XUV3KyRC07BQPPzEgd+ss3x/ezXtHeKtOGCMCNmx3MauZojPYUpSwFkE0fYgYCD9dMQMVG4DY/VF38P0KShsg==
+ version "5.14.7"
+ resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.14.7.tgz#6c2c0de8a625562f789e1bb33cb4cfc8cf20bdb0"
+ integrity sha512-jIZj9F7zMv6IlyaYDVv5M2Kp20jIX8c0kzuwteySHS/A0IvPVyomQEPtWc51MCbpDNCqzwoZUp3rQtA2lI8k7A==
dependencies:
- "@babel/runtime" "^7.22.6"
- "@mui/base" "5.0.0-beta.10"
- "@mui/core-downloads-tracker" "^5.14.4"
- "@mui/system" "^5.14.4"
+ "@babel/runtime" "^7.22.10"
+ "@mui/base" "5.0.0-beta.13"
+ "@mui/core-downloads-tracker" "^5.14.7"
+ "@mui/system" "^5.14.7"
"@mui/types" "^7.2.4"
- "@mui/utils" "^5.14.4"
+ "@mui/utils" "^5.14.7"
"@types/react-transition-group" "^4.4.6"
clsx "^2.0.0"
csstype "^3.1.2"
@@ -1364,35 +1392,35 @@
react-is "^18.2.0"
react-transition-group "^4.4.5"
-"@mui/private-theming@^5.14.4":
- version "5.14.4"
- resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.14.4.tgz#0ec5510da05047f94984344360c7f457f3a0e19e"
- integrity sha512-ISXsHDiQ3z1XA4IuKn+iXDWvDjcz/UcQBiFZqtdoIsEBt8CB7wgdQf3LwcwqO81dl5ofg/vNQBEnXuKfZHrnYA==
+"@mui/private-theming@^5.14.7":
+ version "5.14.7"
+ resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.14.7.tgz#c9fec31e59bf66b12959e724b0e8ec3bb4a3d923"
+ integrity sha512-Y86+hmDnJab2Ka42PgxKpK3oL7EiacbeeX3X/lG9LGO0wSc45wZjHeTfIlVSkkUCkexiMKEJp5NlSjZhr27NRQ==
dependencies:
- "@babel/runtime" "^7.22.6"
- "@mui/utils" "^5.14.4"
+ "@babel/runtime" "^7.22.10"
+ "@mui/utils" "^5.14.7"
prop-types "^15.8.1"
-"@mui/styled-engine@^5.13.2":
- version "5.13.2"
- resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.13.2.tgz#c87bd61c0ab8086d34828b6defe97c02bcd642ef"
- integrity sha512-VCYCU6xVtXOrIN8lcbuPmoG+u7FYuOERG++fpY74hPpEWkyFQG97F+/XfTQVYzlR2m7nPjnwVUgATcTCMEaMvw==
+"@mui/styled-engine@^5.14.7":
+ version "5.14.7"
+ resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.14.7.tgz#aaacec6c87bcc9a180b2da062c613213af10f2e3"
+ integrity sha512-hKBETEDsIAkL8/mBwPiQj/vw28OeIhMXC3Tvj4J2bb9snxAKpiZioR1PwqP+6P41twsC/GKBd0Vr9oaWYaHuMg==
dependencies:
- "@babel/runtime" "^7.21.0"
+ "@babel/runtime" "^7.22.10"
"@emotion/cache" "^11.11.0"
csstype "^3.1.2"
prop-types "^15.8.1"
-"@mui/system@^5.14.4":
- version "5.14.4"
- resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.14.4.tgz#306a2fdd41ab6f4912ea689316f834db8461bb86"
- integrity sha512-oPgfWS97QNfHcDBapdkZIs4G5i85BJt69Hp6wbXF6s7vi3Evcmhdk8AbCRW6n0sX4vTj8oe0mh0RIm1G2A1KDA==
+"@mui/system@^5.14.7":
+ version "5.14.7"
+ resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.14.7.tgz#b08e23f9151d38186ab12dd618906abd4d73d203"
+ integrity sha512-jeZtHglc+Pi6qjGoopT6O4RqYXVBMqHVOsjMGP0hxGSSPm1T4gsAu7jU8eqGx9YwwjvvJ0eotTjFqw7iJ6qE2Q==
dependencies:
- "@babel/runtime" "^7.22.6"
- "@mui/private-theming" "^5.14.4"
- "@mui/styled-engine" "^5.13.2"
+ "@babel/runtime" "^7.22.10"
+ "@mui/private-theming" "^5.14.7"
+ "@mui/styled-engine" "^5.14.7"
"@mui/types" "^7.2.4"
- "@mui/utils" "^5.14.4"
+ "@mui/utils" "^5.14.7"
clsx "^2.0.0"
csstype "^3.1.2"
prop-types "^15.8.1"
@@ -1402,12 +1430,12 @@
resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.4.tgz#b6fade19323b754c5c6de679a38f068fd50b9328"
integrity sha512-LBcwa8rN84bKF+f5sDyku42w1NTxaPgPyYKODsh01U1fVstTClbUoSA96oyRBnSNyEiAVjKm6Gwx9vjR+xyqHA==
-"@mui/utils@^5.14.4":
- version "5.14.4"
- resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.14.4.tgz#498cc2b08e46776c1e4327bfd8c23ad2f5890bc6"
- integrity sha512-4ANV0txPD3x0IcTCSEHKDWnsutg1K3m6Vz5IckkbLXVYu17oOZCVUdOKsb/txUmaCd0v0PmSRe5PW+Mlvns5dQ==
+"@mui/utils@^5.14.7":
+ version "5.14.7"
+ resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.14.7.tgz#3677bcabe032f1185e151f57d8c1a166df3ae0a1"
+ integrity sha512-RtheP/aBoPogVdi8vj8Vo2IFnRa4mZVmnD0RGlVZ49yF60rZs+xP4/KbpIrTr83xVs34QmHQ2aQ+IX7I0a0dDw==
dependencies:
- "@babel/runtime" "^7.22.6"
+ "@babel/runtime" "^7.22.10"
"@types/prop-types" "^15.7.5"
"@types/react-is" "^18.2.1"
prop-types "^15.8.1"
@@ -1418,11 +1446,6 @@
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.3.2.tgz#fb819366771f5721e9438ca3a42ad18684f0949b"
integrity sha512-upwtMaHxlv/udAWGq0kE+rg8huwmcxQPsKZFhS1R5iVO323mvxEBe1YrSXe1awLbg9sTIuEHbgxjLLt7JbeuAQ==
-"@next/env@13.4.16":
- version "13.4.16"
- resolved "https://registry.yarnpkg.com/@next/env/-/env-13.4.16.tgz#382b565b35a2a69bd0e6b50f74c7b95f0c4b1097"
- integrity sha512-pCU0sJBqdfKP9mwDadxvZd+eLz3fZrTlmmDHY12Hdpl3DD0vy8ou5HWKVfG0zZS6tqhL4wnQqRbspdY5nqa7MA==
-
"@next/eslint-plugin-next@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.2.2.tgz#b4a22c06b6454068b54cc44502168d90fbb29a6d"
@@ -1459,21 +1482,11 @@
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.2.tgz#97c532d35c66ce6b6941ae24b5b8b267b9b0d0d8"
integrity sha512-PTUfe1ZrwjsiuTmr3bOM9lsoy5DCmfYsLOUF9ZVhtbi5MNJVmUTy4VZ06GfrvnCO5hGCr48z3vpFE9QZ0qLcPw==
-"@next/swc-darwin-arm64@13.4.16":
- version "13.4.16"
- resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.16.tgz#ed6a342f95e5f21213fdadbceb65b40ae678cee0"
- integrity sha512-Rl6i1uUq0ciRa3VfEpw6GnWAJTSKo9oM2OrkGXPsm7rMxdd2FR5NkKc0C9xzFCI4+QtmBviWBdF2m3ur3Nqstw==
-
"@next/swc-darwin-x64@12.3.2":
version "12.3.2"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.2.tgz#e0cb4ff4b11faaff3a891bd1d18ed72f71e30ebe"
integrity sha512-1HkjmS9awwlaeEY8Y01nRSNkSv3y+qnC/mjMPe/W66hEh3QKa/LQHqHeS7NOdEs19B2mhZ7w+EgMRXdLQ0Su8w==
-"@next/swc-darwin-x64@13.4.16":
- version "13.4.16"
- resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.16.tgz#36c16066a1a3ef8211e84a6a5d72bef15826b291"
- integrity sha512-o1vIKYbZORyDmTrPV1hApt9NLyWrS5vr2p5hhLGpOnkBY1cz6DAXjv8Lgan8t6X87+83F0EUDlu7klN8ieZ06A==
-
"@next/swc-freebsd-x64@12.3.2":
version "12.3.2"
resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.2.tgz#d7b93dd344cb67d1969565d0796c7b7d0217fccf"
@@ -1489,71 +1502,36 @@
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.2.tgz#26df7d7cdc18cf413f12a408179ee4ac315f383a"
integrity sha512-T9GCFyOIb4S3acA9LqflUYD+QZ94iZketHCqKdoO0Nx0OCHIgGJV5rotDe8TDXwh/goYpIfyHU4j1qqw4w4VnA==
-"@next/swc-linux-arm64-gnu@13.4.16":
- version "13.4.16"
- resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.16.tgz#a5b5500737f07e3aa7f184014d8df7973420df26"
- integrity sha512-JRyAl8lCfyTng4zoOmE6hNI2f1MFUr7JyTYCHl1RxX42H4a5LMwJhDVQ7a9tmDZ/yj+0hpBn+Aan+d6lA3v0UQ==
-
"@next/swc-linux-arm64-musl@12.3.2":
version "12.3.2"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.2.tgz#fd42232a6b10d9f9a4f71433d59c280a4532d06f"
integrity sha512-hxNVZS6L3c2z3l9EH2GP0MGQ9exu6O8cohYNZyqC9WUl6C03sEn8xzDH1y+NgD3fVurvYkGU5F0PDddJJLfDIw==
-"@next/swc-linux-arm64-musl@13.4.16":
- version "13.4.16"
- resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.16.tgz#381b7662c5b10ed5750dce41dd57841aa0713e77"
- integrity sha512-9gqVqNzUMWbUDgDiND18xoUqhwSm2gmksqXgCU0qaOKt6oAjWz8cWYjgpPVD0WICKFylEY/gvPEP1fMZDVFZ/g==
-
"@next/swc-linux-x64-gnu@12.3.2":
version "12.3.2"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.2.tgz#5307579e3d8fbdb03adbe6cfc915b51548e0a103"
integrity sha512-fCPkLuwDwY8/QeXxciJJjDHG09liZym/Bhb4A+RLFQ877wUkwFsNWDUTSdUx0YXlYK/1gf67BKauqKkOKp6CYw==
-"@next/swc-linux-x64-gnu@13.4.16":
- version "13.4.16"
- resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.16.tgz#6e0b0eab1c316506950aeb4a09a5ea5c38edabe7"
- integrity sha512-KcQGwchAKmZVPa8i5PLTxvTs1/rcFnSltfpTm803Tr/BtBV3AxCkHLfhtoyVtVzx/kl/oue8oS+DSmbepQKwhw==
-
"@next/swc-linux-x64-musl@12.3.2":
version "12.3.2"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.2.tgz#d5cb920a825a8dc80ffba8a6b797fb845af0b84c"
integrity sha512-o+GifBIQ2K+/MEFxHsxUZoU3bsuVFLXZYWd3idimFHiVdDCVYiKsY6mYMmKDlucX+9xRyOCkKL9Tjf+3tuXJpw==
-"@next/swc-linux-x64-musl@13.4.16":
- version "13.4.16"
- resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.16.tgz#36b84e4509168a5cadf9dfd728c239002d4311fe"
- integrity sha512-2RbMZNxYnJmW8EPHVBsGZPq5zqWAyBOc/YFxq/jIQ/Yn3RMFZ1dZVCjtIcsiaKmgh7mjA/W0ApbumutHNxRqqQ==
-
"@next/swc-win32-arm64-msvc@12.3.2":
version "12.3.2"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.2.tgz#2a0d619e5bc0cec17ed093afd1ca6b1c37c2690c"
integrity sha512-crii66irzGGMSUR0L8r9+A06eTv7FTXqw4rgzJ33M79EwQJOdpY7RVKXLQMurUhniEeQEEOfamiEdPIi/qxisw==
-"@next/swc-win32-arm64-msvc@13.4.16":
- version "13.4.16"
- resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.16.tgz#52d36f909ccdefa2761617b6d4e9ae65f99880a9"
- integrity sha512-thDcGonELN7edUKzjzlHrdoKkm7y8IAdItQpRvvMxNUXa4d9r0ElofhTZj5emR7AiXft17hpen+QAkcWpqG7Jg==
-
"@next/swc-win32-ia32-msvc@12.3.2":
version "12.3.2"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.2.tgz#769bef60d0d678c3d7606a4dc7fee018d6199227"
integrity sha512-5hRUSvn3MdQ4nVRu1rmKxq5YJzpTtZfaC/NyGw6wa4NSF1noUn/pdQGUr+I5Qz3CZkd1gZzzC0eaXQHlrk0E2g==
-"@next/swc-win32-ia32-msvc@13.4.16":
- version "13.4.16"
- resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.16.tgz#a9cb0556d19c33fbb39ac9bef195fd490d6c7673"
- integrity sha512-f7SE1Mo4JAchUWl0LQsbtySR9xCa+x55C0taetjUApKtcLR3AgAjASrrP+oE1inmLmw573qRnE1eZN8YJfEBQw==
-
"@next/swc-win32-x64-msvc@12.3.2":
version "12.3.2"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.2.tgz#45beb4b9d28e6dd6abf63cab1c5b92dc84323a6b"
integrity sha512-tpQJYUH+TzPMIsdVl9fH8uDg47iwiNjKY+8e9da3dXqlkztKzjSw0OwSADoqh3KrifplXeKSta+BBGLdBqg3sg==
-"@next/swc-win32-x64-msvc@13.4.16":
- version "13.4.16"
- resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.16.tgz#79a151d94583e03992c80df3d3e7f7686390ddac"
- integrity sha512-WamDZm1M/OEM4QLce3lOmD1XdLEl37zYZwlmOLhmF7qYJ2G6oYm9+ejZVv+LakQIsIuXhSpVlOvrxIAHqwRkPQ==
-
"@nivo/annotations@0.80.0":
version "0.80.0"
resolved "https://registry.yarnpkg.com/@nivo/annotations/-/annotations-0.80.0.tgz#127e4801fff7370dcfb9acfe1e335781dd65cfd5"
@@ -2011,9 +1989,9 @@
picomatch "^2.2.2"
"@rollup/pluginutils@^5.0.1":
- version "5.0.3"
- resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.3.tgz#183126d69aeb1cfa23401d5a71cb4b8c16c4a4e0"
- integrity sha512-hfllNN4a80rwNQ9QCxhxuHCGHMAvabXqxNdaChUSSadMre7t4iEUI6fFAhBOn/eIYTgYVhBv7vCLsAJ4u3lf3g==
+ version "5.0.4"
+ resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.4.tgz#74f808f9053d33bafec0cc98e7b835c9667d32ba"
+ integrity sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==
dependencies:
"@types/estree" "^1.0.0"
estree-walker "^2.0.2"
@@ -2046,26 +2024,26 @@
dependencies:
"@daybrush/utils" "^1.4.0"
-"@sentry-internal/tracing@7.63.0":
- version "7.63.0"
- resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.63.0.tgz#58903b2205456034611cc5bc1b5b2479275f89c7"
- integrity sha512-Fxpc53p6NGvLSURg3iRvZA0k10K9yfeVhtczvJnpX30POBuV41wxpkLHkb68fjksirjEma1K3Ut1iLOEEDpPQg==
+"@sentry-internal/tracing@7.66.0":
+ version "7.66.0"
+ resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.66.0.tgz#45ea607917d55a5bcaa3229341387ff6ed9b3a2b"
+ integrity sha512-3vCgC2hC3T45pn53yTDVcRpHoJTBxelDPPZVsipAbZnoOVPkj7n6dNfDhj3I3kwWCBPahPkXmE+R4xViR8VqJg==
dependencies:
- "@sentry/core" "7.63.0"
- "@sentry/types" "7.63.0"
- "@sentry/utils" "7.63.0"
+ "@sentry/core" "7.66.0"
+ "@sentry/types" "7.66.0"
+ "@sentry/utils" "7.66.0"
tslib "^2.4.1 || ^1.9.3"
-"@sentry/browser@7.63.0":
- version "7.63.0"
- resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.63.0.tgz#d7eee4be7bfff015f050bca83cafb111dc13d40d"
- integrity sha512-P1Iw/2281C/7CUCRsN4jgXvjMNKnrwKqxRg7JqN8eVeCDPMpOeEPHNJ6YatEXdVLTKVn0JB7L63Q1prhFr8+SQ==
+"@sentry/browser@7.66.0":
+ version "7.66.0"
+ resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.66.0.tgz#9aa3078f8914d2f8acb4ad9fc7b2011c80e357f5"
+ integrity sha512-rW037rf8jkhyykG38+HUdwkRCKHJEMM5NkCqPIO5zuuxfLKukKdI2rbvgJ93s3/9UfsTuDFcKFL1u43mCn6sDw==
dependencies:
- "@sentry-internal/tracing" "7.63.0"
- "@sentry/core" "7.63.0"
- "@sentry/replay" "7.63.0"
- "@sentry/types" "7.63.0"
- "@sentry/utils" "7.63.0"
+ "@sentry-internal/tracing" "7.66.0"
+ "@sentry/core" "7.66.0"
+ "@sentry/replay" "7.66.0"
+ "@sentry/types" "7.66.0"
+ "@sentry/utils" "7.66.0"
tslib "^2.4.1 || ^1.9.3"
"@sentry/cli@^1.74.6":
@@ -2080,88 +2058,88 @@
proxy-from-env "^1.1.0"
which "^2.0.2"
-"@sentry/core@7.63.0":
- version "7.63.0"
- resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.63.0.tgz#8c38da6ef3a1de6e364463a09bc703b196ecbba4"
- integrity sha512-13Ljiq8hv6ieCkO+Am99/PljYJO5ynKT/hRQrWgGy9IIEgUr8sV3fW+1W6K4/3MCeOJou0HsiGBjOD1mASItVg==
+"@sentry/core@7.66.0":
+ version "7.66.0"
+ resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.66.0.tgz#8968f2a9e641d33e3750a8e24d1d39953680c4f2"
+ integrity sha512-WMAEPN86NeCJ1IT48Lqiz4MS5gdDjBwP4M63XP4msZn9aujSf2Qb6My5uT87AJr9zBtgk8MyJsuHr35F0P3q1w==
dependencies:
- "@sentry/types" "7.63.0"
- "@sentry/utils" "7.63.0"
+ "@sentry/types" "7.66.0"
+ "@sentry/utils" "7.66.0"
tslib "^2.4.1 || ^1.9.3"
-"@sentry/integrations@7.63.0":
- version "7.63.0"
- resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.63.0.tgz#bf4268b524670fdbc290dc489de0069143b499c6"
- integrity sha512-+P8GNqFZNH/yS/KPbvUfUDERneoRNUrqp9ayvvp8aq4cTtrBdM72CYgI21oG6cti42SSM1VDLYZomTV3ElPzSg==
+"@sentry/integrations@7.66.0":
+ version "7.66.0"
+ resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.66.0.tgz#297d13fd2f567b0eba7faaa3727301db586b398a"
+ integrity sha512-2PNEnihG9e9Rjbz205+A4BYtFcS2XdgwsN6obAU6Yir7VIbskwZXxx87lKZuz6S53sOWPHleC7uvUBjL+Q6vYg==
dependencies:
- "@sentry/types" "7.63.0"
- "@sentry/utils" "7.63.0"
+ "@sentry/types" "7.66.0"
+ "@sentry/utils" "7.66.0"
localforage "^1.8.1"
tslib "^2.4.1 || ^1.9.3"
"@sentry/nextjs@^7.36.0":
- version "7.63.0"
- resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-7.63.0.tgz#79bca799d451e1570c7873474e295660218cadea"
- integrity sha512-pf1kEt2oqxe84+DdmGkI6BEe1KMUcUFU4PZKg5GRFY7e2ZqHoS8hTJF5rBkScqVlQoXDTiGpfI+vU8Ie3snUcQ==
+ version "7.66.0"
+ resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-7.66.0.tgz#4ee5a8dc99ed930d2957ac7e287918ff3ba31e87"
+ integrity sha512-CJwl3/rIJRR1isqWjGEE8CYiNUndvRksp7l0/75tfe4JoKTk+XS3tXcXVZyyXh34GU5San1c46ctiyodaGGIeg==
dependencies:
"@rollup/plugin-commonjs" "24.0.0"
- "@sentry/core" "7.63.0"
- "@sentry/integrations" "7.63.0"
- "@sentry/node" "7.63.0"
- "@sentry/react" "7.63.0"
- "@sentry/types" "7.63.0"
- "@sentry/utils" "7.63.0"
+ "@sentry/core" "7.66.0"
+ "@sentry/integrations" "7.66.0"
+ "@sentry/node" "7.66.0"
+ "@sentry/react" "7.66.0"
+ "@sentry/types" "7.66.0"
+ "@sentry/utils" "7.66.0"
"@sentry/webpack-plugin" "1.20.0"
chalk "3.0.0"
rollup "2.78.0"
stacktrace-parser "^0.1.10"
tslib "^2.4.1 || ^1.9.3"
-"@sentry/node@7.63.0":
- version "7.63.0"
- resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.63.0.tgz#38508a440c04c0e98d00f5a1855e5448ee70c8d6"
- integrity sha512-tSMyfQNbfjX1w8vJDZtvWeaD4QQ/Z4zVW/TLXfL/JZFIIksPgDZmqLdF+NJS4bSGTU5JiHiUh4pYhME4mHgNBQ==
+"@sentry/node@7.66.0":
+ version "7.66.0"
+ resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.66.0.tgz#d3e08471e1ecae28d3cd0ba3c18487ecb2449881"
+ integrity sha512-PxqIqLr4Sh5xcDfECiBQ4PuZ7v8yTgLhaRkruWrZPYxQrcJFPkwbFkw/IskzVnhT2VwXUmeWEIlRMQKBJ0t83A==
dependencies:
- "@sentry-internal/tracing" "7.63.0"
- "@sentry/core" "7.63.0"
- "@sentry/types" "7.63.0"
- "@sentry/utils" "7.63.0"
+ "@sentry-internal/tracing" "7.66.0"
+ "@sentry/core" "7.66.0"
+ "@sentry/types" "7.66.0"
+ "@sentry/utils" "7.66.0"
cookie "^0.4.1"
https-proxy-agent "^5.0.0"
lru_map "^0.3.3"
tslib "^2.4.1 || ^1.9.3"
-"@sentry/react@7.63.0":
- version "7.63.0"
- resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.63.0.tgz#6d318191e13ccf7ebba4897d7258b4ea3bcf6c51"
- integrity sha512-KFRjgADVE4aMI7gJmGnoSz65ZErQlz9xRB3vETWSyNOLprWXuQLPPtcDEn39BROtsDG4pLyYFaSDiD7o0+DyjQ==
+"@sentry/react@7.66.0":
+ version "7.66.0"
+ resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.66.0.tgz#5f4d52a47b97e4daad0a2729ec6c88c0b29f0186"
+ integrity sha512-TC7kCkLoo+Klp9uywdV6tg8DDyn1CrTdndJghO6PoGz6sCa9k+t7K+z4E7MlgDoh3wiZwS2G2zhkT/xVeDRvJA==
dependencies:
- "@sentry/browser" "7.63.0"
- "@sentry/types" "7.63.0"
- "@sentry/utils" "7.63.0"
+ "@sentry/browser" "7.66.0"
+ "@sentry/types" "7.66.0"
+ "@sentry/utils" "7.66.0"
hoist-non-react-statics "^3.3.2"
tslib "^2.4.1 || ^1.9.3"
-"@sentry/replay@7.63.0":
- version "7.63.0"
- resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.63.0.tgz#989ae32ea028a5eca323786cc07294fedb1f0d45"
- integrity sha512-ikeFVojuP9oDF103blZcj0Vvb4S50dV54BESMrMW2lYBoMMjvOd7AdL+iDHjn1OL05/mv1C6Oc8MovmvdjILVA==
+"@sentry/replay@7.66.0":
+ version "7.66.0"
+ resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.66.0.tgz#5469144192824e7688c475ed29586a8cce6606f6"
+ integrity sha512-5Y2SlVTOFTo3uIycv0mRneBakQtLgWkOnsJaC5LB0Ip0TqVKiMCbQ578vvXp+yvRj4LcS1gNd98xTTNojBoQNg==
dependencies:
- "@sentry/core" "7.63.0"
- "@sentry/types" "7.63.0"
- "@sentry/utils" "7.63.0"
+ "@sentry/core" "7.66.0"
+ "@sentry/types" "7.66.0"
+ "@sentry/utils" "7.66.0"
-"@sentry/types@7.63.0":
- version "7.63.0"
- resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.63.0.tgz#8032029fee6f70e04b667646626a674b03e2f79b"
- integrity sha512-pZNwJVW7RqNLGuTUAhoygt0c9zmc0js10eANAz0MstygJRhQI1tqPDuiELVdujPrbeL+IFKF+7NvRDAydR2Niw==
+"@sentry/types@7.66.0":
+ version "7.66.0"
+ resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.66.0.tgz#4ec290cc6a3dd2024a61a0bffb468cedb409f7fb"
+ integrity sha512-uUMSoSiar6JhuD8p7ON/Ddp4JYvrVd2RpwXJRPH1A4H4Bd4DVt1mKJy1OLG6HdeQv39XyhB1lPZckKJg4tATPw==
-"@sentry/utils@7.63.0":
- version "7.63.0"
- resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.63.0.tgz#7c598553b4dbb6e3740dc96bc7f112ec32edbe69"
- integrity sha512-7FQv1RYAwnuTuarruP+1+Jd6YQuN7i/Y7KltwPMVEwU7j5mzYQaexLr/Jz1XIdR2KYVdkbXQyP8jj8BmA6u9Jw==
+"@sentry/utils@7.66.0":
+ version "7.66.0"
+ resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.66.0.tgz#2e37c96610f26bc79ac064fca4222ea91fece68d"
+ integrity sha512-9GYUVgXjK66uXXcLXVMXVzlptqMtq1eJENCuDeezQiEFrNA71KkLDg00wESp+LL+bl3wpVTBApArpbF6UEG5hQ==
dependencies:
- "@sentry/types" "7.63.0"
+ "@sentry/types" "7.66.0"
tslib "^2.4.1 || ^1.9.3"
"@sentry/webpack-plugin@1.20.0":
@@ -2189,13 +2167,6 @@
dependencies:
tslib "^2.4.0"
-"@swc/helpers@0.5.1":
- version "0.5.1"
- resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.1.tgz#e9031491aa3f26bfcc974a67f48bd456c8a5357a"
- integrity sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==
- dependencies:
- tslib "^2.4.0"
-
"@tailwindcss/typography@^0.5.9":
version "0.5.9"
resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.9.tgz#027e4b0674929daaf7c921c900beee80dbad93e8"
@@ -2207,152 +2178,147 @@
postcss-selector-parser "6.0.10"
"@tiptap-pro/extension-unique-id@^2.1.0":
- version "2.1.0"
- resolved "https://registry.tiptap.dev/@tiptap-pro%2fextension-unique-id/-/extension-unique-id-2.1.0.tgz#7f5e7cc2d068eff11531e2b8c894ddf13c8d41d8"
- integrity sha512-RdkDqFV0adN/NXJ31I64mD3VmoGhQfNMmOyF5X92fbIymHaonAGzDeoXoindd+6MUUd6e3cm75x5VQLdsddG4Q==
+ version "2.2.1"
+ resolved "https://registry.tiptap.dev/@tiptap-pro%2fextension-unique-id/-/extension-unique-id-2.2.1.tgz#656803254760314d4e1b453dc5b75c86023048a6"
+ integrity sha512-B0GNLrWDVcfhbUOOi/lJfow6I4Y8xwJYXnSlhAENnGgOGERjinY1J5nZaR5dDMu1chcJYqAt3I7vkVLA/UMwmQ==
dependencies:
uuid "^8.3.2"
-"@tiptap/core@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.4.tgz#0a2047150ae537e75f96841a603699526f7b4ec5"
- integrity sha512-2YOMjRqoBGEP4YGgYpuPuBBJHMeqKOhLnS0WVwjVP84zOmMgZ7A8M6ILC9Xr7Q/qHZCvyBGWOSsI7+3HsEzzYQ==
+"@tiptap/core@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.1.7.tgz#9823a3712d176849cfd281dd8229ad0719c9eb9e"
+ integrity sha512-1pqTwlTnwTKQSNQmmTWhs2lwdvd+hFFNFZnrRAfvZhQZA6qPmPmKMNTcYmK38Tn4axKth6mhBamzTJgMZFI7ng==
-"@tiptap/extension-blockquote@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.0.4.tgz#1e87f8f157573deec65b54d8a8b5568d79066a86"
- integrity sha512-z5qfuLi04OgCBI6/odzB2vhulT/wpjymYOnON65vLXGZZbUw4cbPloykhqgWvQp+LzKH+HBhl4fz53d5CgnbOA==
+"@tiptap/extension-blockquote@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.1.7.tgz#fe25ec1dedd1f7e3eb1a851a6ac8738ca4691a17"
+ integrity sha512-oAsUU1c0DDZKHwK7/uCtYpnTUQt0o3w+SsJSv4S2vlSHidiFl9gCQGozUQ/Alzc7GO1Y95rOscL28DJXgXESQg==
-"@tiptap/extension-bold@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.4.tgz#debba8b0d957fe0b6943354834d8f1f0f8c0695c"
- integrity sha512-CWSQy1uWkVsen8HUsqhm+oEIxJrCiCENABUbhaVcJL/MqhnP4Trrh1B6O00Yfoc0XToPRRibDaHMFs4A3MSO0g==
+"@tiptap/extension-bold@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.1.7.tgz#c5d89284235d75c2e65745b50a5c0681be1cbab6"
+ integrity sha512-GZV2D91WENkWd1W29vM4kyGWObcxOKQrY8MuCvTdxni1kobEc/LPZzQ1XiQmiNTvXTMcBz5ckLpezdjASV1dNg==
-"@tiptap/extension-bubble-menu@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.4.tgz#f9dde09d3984e9879b1fe13d3e8c1859f0779ef5"
- integrity sha512-+cRZwj0YINNNDElSAiX1pvY2K98S2j9MQW2dXV5oLqsJhqGPZsKxVo8I1u7ZtqUla3QE1V18RYPAzVgTiMRkBg==
+"@tiptap/extension-bubble-menu@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.1.7.tgz#62616c9ee456c8413ad6c120757978266052a1a0"
+ integrity sha512-VcwwUgiG17TEDZda1JBbyKCHLIBTu8B2OAzYrnd4ZqeRs5KTVAB279o/TVjsLVgEfC+c7IWwhhaPPMoXn/lJ3g==
dependencies:
tippy.js "^6.3.7"
-"@tiptap/extension-bullet-list@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.4.tgz#d192767d39e45253c5e9d974e949f271e09c72d7"
- integrity sha512-JSZKBVTaKSuLl5fR4EKE4dOINOrgeRHYA25Vj6cWjgdvpTw5ef7vcUdn9yP4JwTmLRI+VnnMlYL3rqigU3iZNg==
+"@tiptap/extension-bullet-list@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.1.7.tgz#3a7356824a931122314a6bd73b5f9d8a8a313791"
+ integrity sha512-BReix1wkGNH12DSWGnWPKNu4do92Avh98aLkRS1o1V1Y49/+YGMYtfBXB9obq40o0WqKvk4MoM+rhKbfEc44Gg==
"@tiptap/extension-code-block-lowlight@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.4.tgz#e641f08d2ea77271722e848c6efa819b63638b1a"
- integrity sha512-fKM/4MY9R75IJJVt7P+aD+GX3yzzL6oHo1dn4hNFJlYp2x5+yH6kneaqKcTglVicBCGc8Ks6wJLEZTxxG35MOA==
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.1.7.tgz#713dad4324c9ce25c66768fc4cfdb514ecea21c7"
+ integrity sha512-GOmpe3bwjlhMC79vFICInkJwaHx5dTiKQCTzdjZ5qRsvKgk/0YTrmWaN+w+JW5BBUaChj8IrgAPy7VZ20l7GKQ==
-"@tiptap/extension-code-block@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.4.tgz#d551ee7c13fef379bbbad298f1be757d1125cd54"
- integrity sha512-In2tV3rgm/MznVF0N7qYsYugPWSzhZHaCRCWcFKNvllMExpo91bUWvk+hXaIhhPxvuqGIVezjybwrYuU3bJW0g==
+"@tiptap/extension-code-block@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.1.7.tgz#c087c22c305f3c87645228ad32f32595dde7f2a2"
+ integrity sha512-uiasfWCIQuk34vGoIENqAJOHf9m3hAkcELnb9T6+uNxA3O7PUZQqBVN/27oEipj7j15pqua50D6C1jql9kFe0g==
-"@tiptap/extension-code@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.0.4.tgz#6952d402e7372dd2d129e962bf9bd54d68ee6183"
- integrity sha512-HuwJSJkipZf4hkns9witv1CABNIPiB9C8lgAQXK4xJKcoUQChcnljEL+PQ2NqeEeMTEeV3nG3A/0QafH0pgTgg==
+"@tiptap/extension-code@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.1.7.tgz#bad3b1aedc23123a2094f8810801edb0c13acbff"
+ integrity sha512-g0IA6Q6DFZE0AEOMXAV1mktl/XzIO3s1h/haPIKZ8GNes522qhBr9FYc5OUPQCCbgYjL7soTGzxA/W5Jk3f2AQ==
"@tiptap/extension-color@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-color/-/extension-color-2.0.4.tgz#564265c2bcadd268e6b5745d2a06571744cb4090"
- integrity sha512-7Eb5Gk9v3sj2i1Q8dfqmpnc5aDPC/t0ZEsSLRi4C6SNo1nBeUxteXzpzxWwYjTvK+Um40STR89Z6PY14FIYXSA==
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-color/-/extension-color-2.1.7.tgz#7f436aed2f41087d8de6af6a4dd4cb7d964354dd"
+ integrity sha512-NLspH5taSpZP60rXJjDKu8AP9VDd+dlqz4guxvijtuPEePw87Fzidxx9w6X0uYQfx1O0xdPFq3UodlDz591scA==
-"@tiptap/extension-document@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-document/-/extension-document-2.0.4.tgz#f94e6da23a7d93a8ea34c6767d4e2e31f5ab8849"
- integrity sha512-mCj2fAhnNhIHttPSqfTPSSTGwClGaPYvhT56Ij/Pi4iCrWjPXzC4XnIkIHSS34qS2tJN4XJzr/z7lm3NeLkF1w==
+"@tiptap/extension-document@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-document/-/extension-document-2.1.7.tgz#5e1d56e899fdca8ebfad1b7cb358d5ace664b851"
+ integrity sha512-tZyoPPmvzti7PEnyulXomEtINd/Oi2S84uOt6gw7DTCnDq5bF5sn1IfN8Icqp9t4jDwyLXy2TL0Zg/sR0a2Ibg==
-"@tiptap/extension-dropcursor@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-2.0.4.tgz#f4a7542866c9100fee8e78eca5eebefff58989ca"
- integrity sha512-1OmKBv/E+nJo2vsosvu8KwFiBB+gZM1pY61qc7JbwEKHSYAxUFHfvLkIA0IQ53Z0DHMrFSKgWmHEcbnqtGevCA==
+"@tiptap/extension-dropcursor@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-2.1.7.tgz#a3f79b7453579f36f326852b16e421601e881a28"
+ integrity sha512-hNk2BuLnNSXlGOQphlzdpFKCKo7uHUFjWuBfzF1S9FMAQgcN7eTia+cCClmXABYfVLW4fT14PC1KiuGjxi9MuA==
-"@tiptap/extension-floating-menu@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.4.tgz#82f12c2415b7ddbfd782a03b100f717e9905bab0"
- integrity sha512-0YRE738k+kNKuSHhAb3jj9ZQ7Kda78RYRr+cX2jrQVueIMKebPIY07eBt6JcKmob9V9vcNn9qLtBfmygfcPUQg==
+"@tiptap/extension-floating-menu@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.1.7.tgz#fe2def740b3136d38101634ae60d2fec5468c57e"
+ integrity sha512-K0bO7JKHAvgLM5MkhNgoYcD6SB0Z2tNIFhZHs5SCTuhg7dwduMSM3pC6QBrJGUk99DGsKuMPYQn3c2oG7MLbyQ==
dependencies:
tippy.js "^6.3.7"
-"@tiptap/extension-gapcursor@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.4.tgz#c100a792fd41535ad6382aa8133d0d9c0b2cb2b8"
- integrity sha512-VxmKfBQjSSu1mNvHlydA4dJW/zawGKyqmnryiFNcUV9s+/HWLR5i9SiUl4wJM/B8sG8cQxClne5/LrCAeGNYuA==
-
"@tiptap/extension-gapcursor@^2.1.7":
version "2.1.7"
resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.1.7.tgz#5c0303ba37b4c066f3a3c5835fd0b298f0d3e919"
integrity sha512-7eoInzzk1sssoD3RMkwFC86U15Ja4ANve+8wIC+xhN4R3Oe3PY3lFbp1GQxCmaJj8b3rtjNKIQZ2zO0PH58afA==
-"@tiptap/extension-hard-break@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.4.tgz#a4f70fa9a473270f7ec89f20a14b9122af5657bc"
- integrity sha512-4j8BZa6diuoRytWoIc7j25EYWWut5TZDLbb+OVURdkHnsF8B8zeNTo55W40CdwSaSyTtXtxbTIldV80ShQarGQ==
+"@tiptap/extension-hard-break@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.1.7.tgz#1cd783adfe2788d41614f8851b8d7a52ec027cce"
+ integrity sha512-6gFXXlCGAdXjy27BW29q4yfCQPAEFd18k7zRTnbd4aE/zIWUtLqdiTfI3kotUMab9Tt9/z1BRmCbEUxRsf1Nww==
-"@tiptap/extension-heading@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.4.tgz#5372e346c5d69cfa0060d7238d1a0bf440442f6f"
- integrity sha512-EfitUbew5ljH3xVlBXAxqqcJ4rjv15b8379LYOV6KQCf+Y1wY0gy9Q8wXSnrsAagqrvqipja4Ihn3OZeyIM+CA==
+"@tiptap/extension-heading@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.1.7.tgz#26d16227eab95b1f381e977f7aa1685f493c6fb5"
+ integrity sha512-jMeTqtq3kbMFtMvUb3SeIt4FFM3W+b6TAw5H4Qd6z3gYsAU3GahRK67MtbJfPmznUkZfimrqW9VCaBezScfrsQ==
"@tiptap/extension-highlight@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-highlight/-/extension-highlight-2.0.4.tgz#5d54232ac573d0b04c3e705ca38f207fb6cf7270"
- integrity sha512-z1hcpf0eHHdaBE0pewXiNIu+QBodw4IAbZykTXMaY1xCsbYWfOJxeIb5o+CEG5HBsmaoJrCYenQw71xzgV0hKA==
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-highlight/-/extension-highlight-2.1.7.tgz#0f9434eedfdcb95a22ca5b6f601d13f4343a7e5c"
+ integrity sha512-3EXrnf1BQSdOe/iqzcTIr5Tf0NOhPQ+y1B9nMi/40v3MD8WzRBLaqj0lvpwO7xMAdgxm6IiL/XFYU41n9yFl/Q==
-"@tiptap/extension-history@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-history/-/extension-history-2.0.4.tgz#761a9c4b2a875817acc73137660552bd49e94fca"
- integrity sha512-3GAUszn1xZx3vniHMiX9BSKmfvb5QOb0oSLXInN+hx80CgJDIHqIFuhx2dyV9I/HWpa0cTxaLWj64kfDzb1JVg==
+"@tiptap/extension-history@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-history/-/extension-history-2.1.7.tgz#baa566875ef1278c5dd8821970362d85348b266c"
+ integrity sha512-8SIEKSImrIkqJThym1bPD13sC4/76UrG+piQ30xKQU4B7zUFCbutvrwYuQHSRvaEt8BPdTv2LWIK+wBkIgbWVA==
-"@tiptap/extension-horizontal-rule@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.4.tgz#6988dd63fb00ca144feb1baac84142782e8ebe38"
- integrity sha512-OMx2ImQseKbSUjPbbRCuYGOJshxYedh9giWAqwgWWokhYkH4nGxXn5m7+Laj+1wLre4bnWgHWVY4wMGniEj3aw==
+"@tiptap/extension-horizontal-rule@^2.0.4", "@tiptap/extension-horizontal-rule@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.1.7.tgz#7c21bc4917e4ced9382e81626e0f0068b224bfbb"
+ integrity sha512-hJupsDxDVmjmKI/Ewl/gtiyUx52Y3wRUhT8dCXNOA5eldmPXN23E2Fa2BC8XB47dyc5pubyNcLuqaLeaZ5hedw==
"@tiptap/extension-image@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.0.4.tgz#a41d5ca246bd41dd293194e359a80cb97f477ab3"
- integrity sha512-5iQ96pt9xppM8sWzwhGgc99PPoYPQuokTaCXAQKDI0Y1CFCjZ+/duUG3al1VUMpBXsjJw3/RVO1+7CEhRTd3mA==
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.1.7.tgz#597129fb072f6b0014c980892c367a283077f564"
+ integrity sha512-aWa/NPMc1U9Z6xuV0gk1O1nk4H7BAwQMwqXWdvUQCJhmW5+LJPdEiKvt3P6j+ClIN7sdyokZCgr6eGr817qTLA==
-"@tiptap/extension-italic@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.4.tgz#4c6d0938542e4f7276f9dd18db395c040f76dcd8"
- integrity sha512-C/6+qs4Jh8xERRP0wcOopA1+emK8MOkBE4RQx5NbPnT2iCpERP0GlmHBFQIjaYPctZgKFHxsCfRnneS5Xe76+A==
+"@tiptap/extension-italic@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.1.7.tgz#d077683597d4282ae272c48b313d768d71985b67"
+ integrity sha512-7e37f+OFqisdY19nWIthbSNHMJy4+4dec06rUICPrkiuFaADj5HjUQr0dyWpL/LkZh92Wf/rWgp4V/lEwon3jA==
"@tiptap/extension-link@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.0.4.tgz#2899f9060ca722f11bd10ceb572ceb5178f111d6"
- integrity sha512-CliImI1hmC+J6wHxqgz9P4wMjoNSSgm3fnNHsx5z0Bn6JRA4Evh2E3KZAdMaE8xCTx89rKxMYNbamZf4VLSoqQ==
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.1.7.tgz#2705c212d105ccf411d505e334ece4a723971ee4"
+ integrity sha512-NDfoMCkThng1B530pMg5y69+eWoghZXK2uCntrJH7Rs8jNeGMyt9wGIOd7N8ZYz0oJ2ZYKzZjS0RANdBDS17DA==
dependencies:
linkifyjs "^4.1.0"
-"@tiptap/extension-list-item@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.0.4.tgz#8ca7c9959a07bf94602f8957d784d526568f2069"
- integrity sha512-tSkbLgRo1QMNDJttWs9FeRywkuy5T2HdLKKfUcUNzT3s0q5AqIJl7VyimsBL4A6MUfN1qQMZCMHB4pM9Mkluww==
+"@tiptap/extension-list-item@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.1.7.tgz#dc24045e445d0f91baec9b113f711dc90c6682ac"
+ integrity sha512-hd/E4qQopBXWa6kdFY19qFVgqj4fzdPgAnzdXJ2XW7bC6O2CusmHphRRZ5FBsuspYTN/6/fv0i0jK9rSGlsEyA==
-"@tiptap/extension-ordered-list@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.4.tgz#e3e220e9c15114b07c952c32fa58e96601db6bd7"
- integrity sha512-Kfg+8k9p4iJCUKP/yIa18LfUpl9trURSMP/HX3/yQTz9Ul1vDrjxeFjSE5uWNvupcXRAM24js+aYrCmV7zpU+Q==
+"@tiptap/extension-ordered-list@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.1.7.tgz#72d9ddc432ecf0fd19c8acd3c6b44f5358d8e0d0"
+ integrity sha512-3XIXqbZmYkNzF+8PQ2jcCOCj0lpC3y9HGM/+joPIunhiUiktrIgpbUDv2E1Gq5lJHYqthIeujniI2dB85tkwJQ==
-"@tiptap/extension-paragraph@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.0.4.tgz#9cffa3f8a980349ca068b1b3c12596bf5f3aef0f"
- integrity sha512-nDxpopi9WigVqpfi8nU3B0fWYB14EMvKIkutNZo8wJvKGTZufNI8hw66wupIx/jZH1gFxEa5dHerw6aSYuWjgQ==
+"@tiptap/extension-paragraph@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.1.7.tgz#76408706f0037a510a384b86780bd50c6e8ffeea"
+ integrity sha512-cLqX27hNrXrwZCKrIW8OC3rW2+MT8hhS37+cdqOxZo5hUqQ9EF/puwS0w8uUZ7B3awX9Jm1QZDMjjERLkcmobw==
"@tiptap/extension-placeholder@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-placeholder/-/extension-placeholder-2.0.4.tgz#74259783757c59751d78fcdd1aade7e928809187"
- integrity sha512-Y8hjUYBGTbytgrsplSZdHGciqbuVHQX+h0JcuvVaIlAy1kR7hmbxJLqL8tNa7qLtTqo2MfS2942OtSv85JOCzA==
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-placeholder/-/extension-placeholder-2.1.7.tgz#8477cf5116c89f0f75e8e2e3b8528e146a7f0f24"
+ integrity sha512-IiBoItYYNS7hb/zmPitw3w6Cylmp9qX+zW+QKe3lDkCNPeKxyQr86AnVLcQYOuXg62cLV9dp+4azZzHoz9SOcg==
-"@tiptap/extension-strike@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.0.4.tgz#13286dcf8780c55610ed65b24238b8395a5be824"
- integrity sha512-Men7LK6N/Dh3/G4/z2Z9WkDHM2Gxx1XyxYix2ZMf5CnqY37SeDNUnGDqit65pdIN3Y/TQnOZTkKSBilSAtXfJA==
+"@tiptap/extension-strike@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.1.7.tgz#b7b7f49254f1de22416b1415ca88a2a20edd0627"
+ integrity sha512-ONLXYnuZGM2EoGcxkyvJSDMBeAp7K6l83UXkK9TSj+VpEEDdeV7m8mJs8/vACJjJxD5HMN61+EPgU7VTEukQCA==
"@tiptap/extension-table-cell@^2.1.6":
version "2.1.7"
@@ -2375,34 +2341,34 @@
integrity sha512-nlKs35vTQOFW9lfw76S7kJvqVJAfHUlz1muQgWT0gNUlKJYINMXjUIg4Wcx8LTaITCCkp0lMGrLETGRNI+RyxA==
"@tiptap/extension-task-item@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-task-item/-/extension-task-item-2.0.4.tgz#71f46d35ac629ca10c5c23d4ad170007338a436e"
- integrity sha512-0FfYWrOslDzzN7Ehnt3yBekOSH45tiB/3gzFRvGdLBUv0PiYQolUpyfHGsdNzeKYuWLF1yiacJkCeLgNDgCLDw==
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-task-item/-/extension-task-item-2.1.7.tgz#384a55308f3524f36388560486a2508a4b3c5413"
+ integrity sha512-4wFLZmhYqr87SEI/Qgk3FiH+qfp6IOmuYVhpL5zGLa6p+ytUdmPH3+zOaD1rthn5JiRU9KwYWFvTo2f+/O0NAg==
"@tiptap/extension-task-list@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-task-list/-/extension-task-list-2.0.4.tgz#69b2b23d1e757044c05f3d7dcbd30194c71f9324"
- integrity sha512-3RGoEgGJdWpGf8aWl7O7+jnnvfpF0or2YHYYvJv13t5G4dNIS9E7QXT3/rU9QtHNYkbcJYFjHligIFuBTAhZNg==
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-task-list/-/extension-task-list-2.1.7.tgz#abaad3a7b964e58dac6b96b08000a50a06a071b4"
+ integrity sha512-eerV8pbGuYoFji6arWk+LBsIfURXPWNSLi1ZCuPfXP6N8sAV3fNT+VDm6RlGQwadQNae7rnibNClk67+55h9Zg==
"@tiptap/extension-text-style@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-text-style/-/extension-text-style-2.0.4.tgz#4ba3fd6b204badc43ac6a00285315fe868f07e52"
- integrity sha512-HQk8c7HasDdeAJxlHrztkgprxocZecZVUMlvPvFAhkq8E/5+nfmr/Gm9qudiStEARZrIYBATNA2PbnQuIGMx3A==
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-text-style/-/extension-text-style-2.1.7.tgz#57f5dc5b223a855e782f24e09dc7fc53d9bd4b00"
+ integrity sha512-0QhEMDiDqMpyBGRt6o4GvbN9cUibZe4LT9e0ujarT6ElSe2fbtwGPnXSXApUtgHDDwHw95M5ZVxX/H5cjyjw1g==
-"@tiptap/extension-text@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.4.tgz#318b0105491a5976d220871dccabe6c4d2cbeedd"
- integrity sha512-i8/VFlVZh7TkAI49KKX5JmC0tM8RGwyg5zUpozxYbLdCOv07AkJt+E1fLJty9mqH4Y5HJMNnyNxsuZ9Ol/ySRA==
+"@tiptap/extension-text@^2.1.7":
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.1.7.tgz#071053ab0a8804a3bce36d1488a603b7446dff4e"
+ integrity sha512-3xaMMMNydLgoS+o+yOvaZF04ui9spJwJZl8VyYgcJKVGGLGRlWHrireXN5/OqXG2jLb/jWqXVx5idppQjX+PMA==
"@tiptap/extension-underline@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-underline/-/extension-underline-2.0.4.tgz#c1e5df75a4c9f2d9e691d48438ee0894f8bb01f1"
- integrity sha512-Hvhy3iV5dWs0SFTww6sIzyQSSgVzcQuiozhDs11iP+gvFjK7ejg86KZ8wAVvyCi9K3bOMhohsw1Q2b8JSnIxcg==
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-underline/-/extension-underline-2.1.7.tgz#ab815645770f7d2013ac69327975837b4937c8df"
+ integrity sha512-mL95afyEJvg+C2yrTVn7QltfyE9ja1+94+OUkRBbB8PN3N6HvfSL4K/QSqecOLQ38bSQm/6ZGPkBLDkDGhGPdw==
"@tiptap/pm@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/pm/-/pm-2.0.4.tgz#c3df31a29120e1e3334f8f063df23ccb1ace7851"
- integrity sha512-DNgxntpEaiW7ciW0BTNTL0TFqAreZTrAROWakI4XaYRAyi5H9NfZW8jmwGwMBkoZ1KB3pfy+jT/Bisy4okEQGQ==
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/pm/-/pm-2.1.7.tgz#91e1b87d4ddbddca3cfe46e3c052b0072e4e1d97"
+ integrity sha512-RBVb/k9OjmClwdVl7fpekFgUsLAm1U+5I4w1qA2tj7L/hSPOuPzaEHwCqDYe0b2PR5dd8h0nylS9qXuXVlfwfQ==
dependencies:
prosemirror-changeset "^2.2.0"
prosemirror-collab "^1.3.0"
@@ -2424,42 +2390,42 @@
prosemirror-view "^1.28.2"
"@tiptap/react@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/react/-/react-2.0.4.tgz#b879faeabd67859254d594eafe0f8232f5d78116"
- integrity sha512-NcrZL4Tu3+1Xfj/us5AOD7+kJhwYo2XViOB2iRRnfwS80PUtiLWDis6o3ngMGot/jBWzaMn4gofXnMWHtFdIAw==
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/react/-/react-2.1.7.tgz#0c5a5407bcb398ff75234dd9c7a3f8878d943088"
+ integrity sha512-jCs5z/rXZ7mEOTPcJ+r/OSTtLOGBahS7D3xDu3pRX4P0wtWHlprsdptxxlWjkBHLav01XXJ+OtGZTfhWBio1QQ==
dependencies:
- "@tiptap/extension-bubble-menu" "^2.0.4"
- "@tiptap/extension-floating-menu" "^2.0.4"
+ "@tiptap/extension-bubble-menu" "^2.1.7"
+ "@tiptap/extension-floating-menu" "^2.1.7"
"@tiptap/starter-kit@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/starter-kit/-/starter-kit-2.0.4.tgz#20456eb4a4ae0ac8d5bf2ac5e9771b3c617c51a6"
- integrity sha512-9WtVXhujyp5cOlE7qlcQMFr0FEx3Cvo1isvfQGzhKKPzXa3rR7FT8bnOFsten31/Ia/uwvGXAvRDQy24YfHdNA==
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/starter-kit/-/starter-kit-2.1.7.tgz#a33a7928b7051ac9cd89d1798745f9855b7b72d9"
+ integrity sha512-z2cmJRSC7ImaTGWrHv+xws9y1wIG0OCPosBYpmpwlEfA3JG3axWFmVRJlWnsQV4eSMi3QY3vaPgBAnrR4IxRhQ==
dependencies:
- "@tiptap/core" "^2.0.4"
- "@tiptap/extension-blockquote" "^2.0.4"
- "@tiptap/extension-bold" "^2.0.4"
- "@tiptap/extension-bullet-list" "^2.0.4"
- "@tiptap/extension-code" "^2.0.4"
- "@tiptap/extension-code-block" "^2.0.4"
- "@tiptap/extension-document" "^2.0.4"
- "@tiptap/extension-dropcursor" "^2.0.4"
- "@tiptap/extension-gapcursor" "^2.0.4"
- "@tiptap/extension-hard-break" "^2.0.4"
- "@tiptap/extension-heading" "^2.0.4"
- "@tiptap/extension-history" "^2.0.4"
- "@tiptap/extension-horizontal-rule" "^2.0.4"
- "@tiptap/extension-italic" "^2.0.4"
- "@tiptap/extension-list-item" "^2.0.4"
- "@tiptap/extension-ordered-list" "^2.0.4"
- "@tiptap/extension-paragraph" "^2.0.4"
- "@tiptap/extension-strike" "^2.0.4"
- "@tiptap/extension-text" "^2.0.4"
+ "@tiptap/core" "^2.1.7"
+ "@tiptap/extension-blockquote" "^2.1.7"
+ "@tiptap/extension-bold" "^2.1.7"
+ "@tiptap/extension-bullet-list" "^2.1.7"
+ "@tiptap/extension-code" "^2.1.7"
+ "@tiptap/extension-code-block" "^2.1.7"
+ "@tiptap/extension-document" "^2.1.7"
+ "@tiptap/extension-dropcursor" "^2.1.7"
+ "@tiptap/extension-gapcursor" "^2.1.7"
+ "@tiptap/extension-hard-break" "^2.1.7"
+ "@tiptap/extension-heading" "^2.1.7"
+ "@tiptap/extension-history" "^2.1.7"
+ "@tiptap/extension-horizontal-rule" "^2.1.7"
+ "@tiptap/extension-italic" "^2.1.7"
+ "@tiptap/extension-list-item" "^2.1.7"
+ "@tiptap/extension-ordered-list" "^2.1.7"
+ "@tiptap/extension-paragraph" "^2.1.7"
+ "@tiptap/extension-strike" "^2.1.7"
+ "@tiptap/extension-text" "^2.1.7"
"@tiptap/suggestion@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@tiptap/suggestion/-/suggestion-2.0.4.tgz#08e6c47a723200d02238d845cb09684c481f0066"
- integrity sha512-C5LGGjH8VFET34V7vKkqlwpSzrPl+7oAcj9h+P3jvJQ076iYpmpnMtz6dNLSFGKpHp5mtyl4RoJzh7lTvlfyiA==
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/@tiptap/suggestion/-/suggestion-2.1.7.tgz#ac88deef2ade8d836ca9084c276cc9d64c6e604a"
+ integrity sha512-FKlXFMWf9rCnNJQsUfeX6WpS2VUs2O98ENkyhfV8ehCB7X5+57mkkxJxl/88SMbjZL+FbWPBKLaiOvsXfIUoww==
"@types/debug@^4.0.0":
version "4.1.8"
@@ -2522,9 +2488,9 @@
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
"@types/linkify-it@*":
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-3.0.2.tgz#fd2cd2edbaa7eaac7e7f3c1748b52a19143846c9"
- integrity sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-3.0.3.tgz#15a0712296c5041733c79efe233ba17ae5a7587b"
+ integrity sha512-pTjcqY9E4nOI55Wgpz7eiI8+LzdYnw3qxXCfHyBDdPbYvbyLgWLJGh8EdPvqawwMK1Uo1794AUkkR38Fr0g+2g==
"@types/lodash.debounce@^4.0.7":
version "4.0.7"
@@ -2569,9 +2535,9 @@
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
"@types/node@*":
- version "20.5.0"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.0.tgz#7fc8636d5f1aaa3b21e6245e97d56b7f56702313"
- integrity sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==
+ version "20.5.8"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.8.tgz#fb171fd22d37ca6e2ea97fde88e6a13ee14bc327"
+ integrity sha512-eajsR9aeljqNhK028VG0Wuw+OaY5LLxYmxeoXynIoE6jannr9/Ucd1LL0hSSoafk5LTYG+FfqsyGt81Q6Zkybw==
"@types/node@18.0.6":
version "18.0.6"
@@ -2662,9 +2628,9 @@
"@types/react" "*"
"@types/react-redux@^7.1.20":
- version "7.1.25"
- resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.25.tgz#de841631205b24f9dfb4967dd4a7901e048f9a88"
- integrity sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==
+ version "7.1.26"
+ resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.26.tgz#84149f5614e40274bb70fcbe8f7cae6267d548b1"
+ integrity sha512-UKPo7Cm7rswYU6PH6CmTNCRv5NYF3HrgKuHEYTK8g/3czYLrUux50gQ2pkxc9c7ZpQZi+PNhgmI8oNIRoiVIxg==
dependencies:
"@types/hoist-non-react-statics" "^3.3.0"
"@types/react" "*"
@@ -2679,9 +2645,9 @@
"@types/react" "*"
"@types/react@*", "@types/react@^18.0.17":
- version "18.2.20"
- resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.20.tgz#1605557a83df5c8a2cc4eeb743b3dfc0eb6aaeb2"
- integrity sha512-WKNtmsLWJM/3D5mG4U84cysVY31ivmyw85dE84fOCk5Hx78wezB/XEjVPWl2JTZ5FkEeaTJf+VgUAUn3PE7Isw==
+ version "18.2.21"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.21.tgz#774c37fd01b522d0b91aed04811b58e4e0514ed9"
+ integrity sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
@@ -2725,9 +2691,9 @@
integrity sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==
"@types/semver@^7.3.12":
- version "7.5.0"
- resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a"
- integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==
+ version "7.5.1"
+ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.1.tgz#0480eeb7221eb9bc398ad7432c9d7e14b1a5a367"
+ integrity sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==
"@types/throttle-debounce@^2.1.0":
version "2.1.0"
@@ -2740,9 +2706,9 @@
integrity sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==
"@types/unist@^2", "@types/unist@^2.0.0":
- version "2.0.7"
- resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.7.tgz#5b06ad6894b236a1d2bd6b2f07850ca5c59cf4d6"
- integrity sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==
+ version "2.0.8"
+ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.8.tgz#bb197b9639aa1a04cf464a617fe800cccd92ad5c"
+ integrity sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw==
"@types/uuid@^8.3.4":
version "8.3.4"
@@ -2750,9 +2716,9 @@
integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==
"@types/uuid@^9.0.1":
- version "9.0.2"
- resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.2.tgz#ede1d1b1e451548d44919dc226253e32a6952c4b"
- integrity sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==
+ version "9.0.3"
+ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.3.tgz#6cdd939b4316b4f81625de9f06028d848c4a1533"
+ integrity sha512-taHQQH/3ZyI3zP8M/puluDEIEvtQHVYcC6y3N8ijFtAd28+Ey/G4sg1u2gB01S8MwybLOKAp9/yCMu/uR5l3Ug==
"@typescript-eslint/eslint-plugin@^5.48.2", "@typescript-eslint/eslint-plugin@^5.51.0":
version "5.62.0"
@@ -2990,15 +2956,15 @@ array-uniq@^1.0.1:
integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==
array.prototype.findlastindex@^1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz#bc229aef98f6bd0533a2bc61ff95209875526c9b"
- integrity sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz#b37598438f97b579166940814e2c0493a4f50207"
+ integrity sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.4"
- es-abstract "^1.20.4"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
es-shim-unscopables "^1.0.0"
- get-intrinsic "^1.1.3"
+ get-intrinsic "^1.2.1"
array.prototype.flat@^1.3.1:
version "1.3.1"
@@ -3058,6 +3024,13 @@ async@^3.2.3:
resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
+asynciterator.prototype@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz#8c5df0514936cdd133604dfcc9d3fb93f09b2b62"
+ integrity sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==
+ dependencies:
+ has-symbols "^1.0.3"
+
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
@@ -3096,9 +3069,9 @@ axe-core@^4.6.2:
integrity sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==
axios@^1.1.3, axios@^1.3.4:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f"
- integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.0.tgz#f02e4af823e2e46a9768cfc74691fdd0517ea267"
+ integrity sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==
dependencies:
follow-redirects "^1.15.0"
form-data "^4.0.0"
@@ -3243,13 +3216,6 @@ builtin-modules@^3.1.0:
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6"
integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==
-busboy@1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
- integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
- dependencies:
- streamsearch "^1.1.0"
-
call-bind@^1.0.0, call-bind@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
@@ -3277,9 +3243,9 @@ camelcase-css@^2.0.1:
integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001517, caniuse-lite@^1.0.30001520:
- version "1.0.30001520"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001520.tgz#62e2b7a1c7b35269594cf296a80bdf8cb9565006"
- integrity sha512-tahF5O9EiiTzwTUqAeFjIZbn4Dnqxzz7ktrgGlMYNLH43Ul26IgTMH/zvL3DG0lZxBYnlT04axvInszUsZULdA==
+ version "1.0.30001525"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001525.tgz#d2e8fdec6116ffa36284ca2c33ef6d53612fe1c8"
+ integrity sha512-/3z+wB4icFt3r0USMwxujAqRvaD/B7rvGTsKhbhSQErVrJvkZCLhgNLJxU8MevahQVH6hCU9FsHdNUFbiwmE7Q==
capital-case@^1.0.4:
version "1.0.4"
@@ -3375,7 +3341,7 @@ clean-webpack-plugin@^4.0.0:
dependencies:
del "^4.1.1"
-client-only@0.0.1, client-only@^0.0.1:
+client-only@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
@@ -3500,11 +3466,11 @@ cookie@^0.5.0:
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
core-js-compat@^3.31.0:
- version "3.32.0"
- resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.32.0.tgz#f41574b6893ab15ddb0ac1693681bd56c8550a90"
- integrity sha512-7a9a3D1k4UCVKnLhrgALyFcP7YCsLOQIxPd0dKjf/6GuPcgyiGP70ewWdCGrSK7evyhymi0qO4EqCmSJofDeYw==
+ version "3.32.1"
+ resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.32.1.tgz#55f9a7d297c0761a8eb1d31b593e0f5b6ffae964"
+ integrity sha512-GSvKDv4wE0bPnQtjklV101juQ85g6H3rm5PDP20mqlS5j0kXF3pP97YvAu5hl+uFHqMictp3b2VxOHljWMAtuA==
dependencies:
- browserslist "^4.21.9"
+ browserslist "^4.21.10"
cosmiconfig@^7.0.0:
version "7.1.0"
@@ -3847,9 +3813,9 @@ ejs@^3.1.6:
jake "^10.8.5"
electron-to-chromium@^1.4.477:
- version "1.4.490"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.490.tgz#d99286f6e915667fa18ea4554def1aa60eb4d5f1"
- integrity sha512-6s7NVJz+sATdYnIwhdshx/N/9O6rvMxmhVoDSDFdj6iA45gHR8EQje70+RYsF4GeB+k0IeNSBnP7yG9ZXJFr7A==
+ version "1.4.508"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.508.tgz#5641ff2f5ba11df4bd960fe6a2f9f70aa8b9af96"
+ integrity sha512-FFa8QKjQK/A5QuFr2167myhMesGrhlOBD+3cYNxO9/S4XzHEXesyTD/1/xF644gC8buFPz3ca6G1LOQD0tZrrg==
emoji-regex@^8.0.0:
version "8.0.0"
@@ -3901,7 +3867,7 @@ error-ex@^1.3.1:
dependencies:
is-arrayish "^0.2.1"
-es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2:
+es-abstract@^1.20.4, es-abstract@^1.22.1:
version "1.22.1"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.1.tgz#8b4e5fc5cefd7f1660f0f8e1a52900dfbc9d9ccc"
integrity sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==
@@ -3946,6 +3912,26 @@ es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2:
unbox-primitive "^1.0.2"
which-typed-array "^1.1.10"
+es-iterator-helpers@^1.0.12:
+ version "1.0.14"
+ resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.14.tgz#19cd7903697d97e21198f3293b55e8985791c365"
+ integrity sha512-JgtVnwiuoRuzLvqelrvN3Xu7H9bu2ap/kQ2CrM62iidP8SKuD99rWU3CJy++s7IVL2qb/AjXPGR/E7i9ngd/Cw==
+ dependencies:
+ asynciterator.prototype "^1.0.0"
+ call-bind "^1.0.2"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
+ es-set-tostringtag "^2.0.1"
+ function-bind "^1.1.1"
+ get-intrinsic "^1.2.1"
+ globalthis "^1.0.3"
+ has-property-descriptors "^1.0.0"
+ has-proto "^1.0.1"
+ has-symbols "^1.0.3"
+ internal-slot "^1.0.5"
+ iterator.prototype "^1.1.0"
+ safe-array-concat "^1.0.0"
+
es-set-tostringtag@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8"
@@ -4037,11 +4023,11 @@ eslint-config-prettier@^8.3.0:
integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==
eslint-config-turbo@latest:
- version "1.10.12"
- resolved "https://registry.yarnpkg.com/eslint-config-turbo/-/eslint-config-turbo-1.10.12.tgz#5868252d6833dd2b5cab4414751ed31ebe2177c3"
- integrity sha512-z3jfh+D7UGYlzMWGh+Kqz++hf8LOE96q3o5R8X4HTjmxaBWlLAWG+0Ounr38h+JLR2TJno0hU9zfzoPNkR9BdA==
+ version "1.10.13"
+ resolved "https://registry.yarnpkg.com/eslint-config-turbo/-/eslint-config-turbo-1.10.13.tgz#3743def3c76e27c3969c16222137f5bd913a10e2"
+ integrity sha512-Ffa0SxkRCPMtfUX/HDanEqsWoLwZTQTAXO9W4IsOtycb2MzJDrVcLmoFW5sMwCrg7gjqbrC4ZJoD+1SPPzIVqg==
dependencies:
- eslint-plugin-turbo "1.10.12"
+ eslint-plugin-turbo "1.10.13"
eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.7:
version "0.3.9"
@@ -4084,9 +4070,9 @@ eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0:
debug "^3.2.7"
eslint-plugin-import@^2.26.0:
- version "2.28.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.28.0.tgz#8d66d6925117b06c4018d491ae84469eb3cb1005"
- integrity sha512-B8s/n+ZluN7sxj9eUf7/pRFERX0r5bnFA2dCaLHy2ZeaQEAz0k+ZZkFWRFHJAqxfxQDx6KLv9LeIki7cFdwW+Q==
+ version "2.28.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz#63b8b5b3c409bfc75ebaf8fb206b07ab435482c4"
+ integrity sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==
dependencies:
array-includes "^3.1.6"
array.prototype.findlastindex "^1.2.2"
@@ -4097,13 +4083,12 @@ eslint-plugin-import@^2.26.0:
eslint-import-resolver-node "^0.3.7"
eslint-module-utils "^2.8.0"
has "^1.0.3"
- is-core-module "^2.12.1"
+ is-core-module "^2.13.0"
is-glob "^4.0.3"
minimatch "^3.1.2"
object.fromentries "^2.0.6"
object.groupby "^1.0.0"
object.values "^1.1.6"
- resolve "^1.22.3"
semver "^6.3.1"
tsconfig-paths "^3.14.2"
@@ -4155,14 +4140,15 @@ eslint-plugin-react@7.31.8:
string.prototype.matchall "^4.0.7"
eslint-plugin-react@^7.29.4, eslint-plugin-react@^7.31.7:
- version "7.33.1"
- resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.1.tgz#bc27cccf860ae45413a4a4150bf0977345c1ceab"
- integrity sha512-L093k0WAMvr6VhNwReB8VgOq5s2LesZmrpPdKz/kZElQDzqS7G7+DnKoqT+w4JwuiGeAhAvHO0fvy0Eyk4ejDA==
+ version "7.33.2"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz#69ee09443ffc583927eafe86ffebb470ee737608"
+ integrity sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==
dependencies:
array-includes "^3.1.6"
array.prototype.flatmap "^1.3.1"
array.prototype.tosorted "^1.1.1"
doctrine "^2.1.0"
+ es-iterator-helpers "^1.0.12"
estraverse "^5.3.0"
jsx-ast-utils "^2.4.1 || ^3.0.0"
minimatch "^3.1.2"
@@ -4175,10 +4161,10 @@ eslint-plugin-react@^7.29.4, eslint-plugin-react@^7.31.7:
semver "^6.3.1"
string.prototype.matchall "^4.0.8"
-eslint-plugin-turbo@1.10.12:
- version "1.10.12"
- resolved "https://registry.yarnpkg.com/eslint-plugin-turbo/-/eslint-plugin-turbo-1.10.12.tgz#3f95884faf35b56e0855d939585fa6cd457bb128"
- integrity sha512-uNbdj+ohZaYo4tFJ6dStRXu2FZigwulR1b3URPXe0Q8YaE7thuekKNP+54CHtZPH9Zey9dmDx5btAQl9mfzGOw==
+eslint-plugin-turbo@1.10.13:
+ version "1.10.13"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-turbo/-/eslint-plugin-turbo-1.10.13.tgz#d2c14c7e733ee1462c94d79dce29d75f42ced275"
+ integrity sha512-el4AAmn0zXmvHEyp1h0IQMfse10Vy8g5Vbg4IU3+vD9CSj5sDbX07iFVt8sCKg7og9Q5FAa9mXzlCf7t4vYgzg==
dependencies:
dotenv "16.0.3"
@@ -4319,14 +4305,14 @@ eslint@^7.23.0, eslint@^7.32.0:
v8-compile-cache "^2.0.3"
eslint@^8.31.0:
- version "8.47.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.47.0.tgz#c95f9b935463fb4fad7005e626c7621052e90806"
- integrity sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==
+ version "8.48.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.48.0.tgz#bf9998ba520063907ba7bfe4c480dc8be03c2155"
+ integrity sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==
dependencies:
"@eslint-community/eslint-utils" "^4.2.0"
"@eslint-community/regexpp" "^4.6.1"
"@eslint/eslintrc" "^2.1.2"
- "@eslint/js" "^8.47.0"
+ "@eslint/js" "8.48.0"
"@humanwhocodes/config-array" "^0.11.10"
"@humanwhocodes/module-importer" "^1.0.1"
"@nodelib/fs.walk" "^1.2.8"
@@ -4439,9 +4425,9 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-fifo@^1.1.0, fast-fifo@^1.2.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.0.tgz#03e381bcbfb29932d7c3afde6e15e83e05ab4d8b"
- integrity sha512-IgfweLvEpwyA4WgiQe9Nx6VV2QkML2NkvZnk1oKnIzXgXdWxuhF7zw4DvLTPZJn6PIUneiAXPF24QmoEqHTjyw==
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c"
+ integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==
fast-glob@^3.2.12, fast-glob@^3.2.9, fast-glob@^3.3.1:
version "3.3.1"
@@ -4485,6 +4471,14 @@ file-entry-cache@^6.0.1:
dependencies:
flat-cache "^3.0.4"
+file-loader@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d"
+ integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==
+ dependencies:
+ loader-utils "^2.0.0"
+ schema-utils "^3.0.0"
+
file-selector@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/file-selector/-/file-selector-0.6.0.tgz#fa0a8d9007b829504db4d07dd4de0310b65287dc"
@@ -4537,14 +4531,15 @@ find-up@^5.0.0:
path-exists "^4.0.0"
flat-cache@^3.0.4:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
- integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.1.0.tgz#0e54ab4a1a60fe87e2946b6b00657f1c99e1af3f"
+ integrity sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==
dependencies:
- flatted "^3.1.0"
+ flatted "^3.2.7"
+ keyv "^4.5.3"
rimraf "^3.0.2"
-flatted@^3.1.0:
+flatted@^3.2.7:
version "3.2.7"
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
@@ -4576,9 +4571,9 @@ format@^0.2.0:
integrity sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==
fraction.js@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
- integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
+ version "4.3.6"
+ resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.6.tgz#e9e3acec6c9a28cf7bc36cbe35eea4ceb2c5c92d"
+ integrity sha512-n2aZ9tNfYDwaHhvFTkhFErqOMIb8uyzSQ+vGJBjZyanAKZVbGUQ1sngfk9FdkBw7G26O7AgNjLcecLffD1c7eg==
framework-utils@^1.1.0:
version "1.1.0"
@@ -4606,9 +4601,9 @@ fs.realpath@^1.0.0:
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
fsevents@~2.3.2:
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
- integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
+ integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
function-bind@^1.1.1:
version "1.1.1"
@@ -4616,21 +4611,21 @@ function-bind@^1.1.1:
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
function.prototype.name@^1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621"
- integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd"
+ integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.3"
- es-abstract "^1.19.0"
- functions-have-names "^1.2.2"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
+ functions-have-names "^1.2.3"
functional-red-black-tree@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==
-functions-have-names@^1.2.2, functions-have-names@^1.2.3:
+functions-have-names@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
@@ -4702,11 +4697,6 @@ glob-parent@^6.0.2:
dependencies:
is-glob "^4.0.3"
-glob-to-regexp@^0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
- integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
-
glob@7.1.6:
version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
@@ -4803,7 +4793,7 @@ gopd@^1.0.1:
dependencies:
get-intrinsic "^1.1.3"
-graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
+graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
version "4.2.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
@@ -4902,6 +4892,11 @@ https-proxy-agent@^5.0.0:
agent-base "6"
debug "4"
+husky@^8.0.3:
+ version "8.0.3"
+ resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184"
+ integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==
+
idb@^7.0.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b"
@@ -4963,7 +4958,7 @@ inline-style-parser@0.1.1:
resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1"
integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==
-internal-slot@^1.0.3, internal-slot@^1.0.5:
+internal-slot@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986"
integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==
@@ -5011,6 +5006,13 @@ is-arrayish@^0.3.1:
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
+is-async-function@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646"
+ integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
is-bigint@^1.0.1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
@@ -5043,14 +5045,14 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7:
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
-is-core-module@^2.11.0, is-core-module@^2.12.1, is-core-module@^2.13.0, is-core-module@^2.9.0:
+is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.9.0:
version "2.13.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db"
integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==
dependencies:
has "^1.0.3"
-is-date-object@^1.0.1:
+is-date-object@^1.0.1, is-date-object@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==
@@ -5069,11 +5071,25 @@ is-extglob@^2.1.1:
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+is-finalizationregistry@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6"
+ integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==
+ dependencies:
+ call-bind "^1.0.2"
+
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+is-generator-function@^1.0.10:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72"
+ integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
@@ -5081,6 +5097,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
dependencies:
is-extglob "^2.1.1"
+is-map@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127"
+ integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==
+
is-module@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
@@ -5164,6 +5185,11 @@ is-regexp@^1.0.0:
resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==
+is-set@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec"
+ integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==
+
is-shared-array-buffer@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79"
@@ -5197,6 +5223,11 @@ is-typed-array@^1.1.10, is-typed-array@^1.1.9:
dependencies:
which-typed-array "^1.1.11"
+is-weakmap@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2"
+ integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==
+
is-weakref@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
@@ -5204,6 +5235,14 @@ is-weakref@^1.0.2:
dependencies:
call-bind "^1.0.2"
+is-weakset@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.2.tgz#4569d67a747a1ce5a994dfd4ef6dcea76e7c0a1d"
+ integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.1.1"
+
isarray@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
@@ -5219,6 +5258,16 @@ isobject@^3.0.1:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==
+iterator.prototype@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.1.tgz#ab5b790e23ec00658f5974e032a2b05188bd3a5c"
+ integrity sha512-9E+nePc8C9cnQldmNl6bgpTY6zI4OPRZd97fhJ/iVZ1GifIUDVV5F6x1nEDqpe8KaMEZGT4xgrwKQDxXnjOIZQ==
+ dependencies:
+ define-properties "^1.2.0"
+ get-intrinsic "^1.2.1"
+ has-symbols "^1.0.3"
+ reflect.getprototypeof "^1.0.3"
+
jake@^10.8.5:
version "10.8.7"
resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.7.tgz#63a32821177940c33f356e0ba44ff9d34e1c7d8f"
@@ -5248,9 +5297,9 @@ jest-worker@^27.4.5:
supports-color "^8.0.0"
jiti@^1.18.2:
- version "1.19.1"
- resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.19.1.tgz#fa99e4b76a23053e0e7cde098efe1704a14c16f1"
- integrity sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==
+ version "1.19.3"
+ resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.19.3.tgz#ef554f76465b3c2b222dc077834a71f0d4a37569"
+ integrity sha512-5eEbBDQT/jF1xg6l36P+mWGGoH9Spuy0PCdSr2dtWRDGC6ph/w9ZCL4lmESW8f8F7MwT3XKescfP0wnZWAKL9w==
js-cookie@^3.0.1:
version "3.0.5"
@@ -5292,6 +5341,11 @@ jsesc@~0.5.0:
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==
+json-buffer@3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
+ integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
+
json-parse-even-better-errors@^2.3.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
@@ -5324,7 +5378,7 @@ json5@^1.0.2:
dependencies:
minimist "^1.2.0"
-json5@^2.1.2, json5@^2.2.0, json5@^2.2.2:
+json5@^2.1.2, json5@^2.2.0, json5@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
@@ -5368,6 +5422,13 @@ keycon@^1.2.0:
"@scena/event-emitter" "^1.0.2"
keycode "^2.2.0"
+keyv@^4.5.3:
+ version "4.5.3"
+ resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25"
+ integrity sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==
+ dependencies:
+ json-buffer "3.0.1"
+
kleur@^4.0.3:
version "4.1.5"
resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780"
@@ -5866,7 +5927,7 @@ mime-db@1.52.0:
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
-mime-types@^2.1.12:
+mime-types@^2.1.12, mime-types@^2.1.27:
version "2.1.35"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
@@ -5910,16 +5971,16 @@ mkdirp@^0.5.5:
minimist "^1.2.6"
mobx-react-lite@^4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-4.0.3.tgz#f7aa5ac3be558ca19a53b2929d9599679769c2a8"
- integrity sha512-wEE1oT5zvDdvplG4HnRrFgPwg5GFVVrEtl42Er85k23zeu3om8H8wbDPgdbQP88zAihVsik6xJfw6VnzUl8fQw==
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-4.0.4.tgz#eee3c55dfa6841365d5a7764971c456db12570fb"
+ integrity sha512-68uNYvQC/5Dazs3sIBv+bnpzRwcWde8y4ujHiLizhq8yeQtJ2tlNUGSh4r40gyE5M0utACIofBDsAj2hplcovQ==
dependencies:
use-sync-external-store "^1.2.0"
mobx@^6.10.0:
- version "6.10.0"
- resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.10.0.tgz#3537680fe98d45232cc19cc8f76280bd8bb6b0b7"
- integrity sha512-WMbVpCMFtolbB8swQ5E2YRrU+Yu8iLozCVx3CdGjbBKlP7dFiCSuiG06uea3JCFN5DnvtAX7+G5Bp82e2xu0ww==
+ version "6.10.2"
+ resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.10.2.tgz#96e123deef140750360ca9a5b02a8b91fbffd4d9"
+ integrity sha512-B1UGC3ieK3boCjnMEcZSwxqRDMdzX65H/8zOHbuTY8ZhvrIjTUoLRR2TP2bPqIgYRfb3+dUigu8yMZufNjn0LQ==
mri@^1.1.0:
version "1.2.0"
@@ -5965,6 +6026,14 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
+next-images@^1.8.5:
+ version "1.8.5"
+ resolved "https://registry.yarnpkg.com/next-images/-/next-images-1.8.5.tgz#2eb5535bb1d6c58a5c4e03bc3be6c72c8a053a45"
+ integrity sha512-YLBERp92v+Nu2EVxI9+wa32KRuxyxTC8ItbiHUWVPlatUoTl0yRqsNtP39c2vYv27VRvY4LlYcUGjNRBSMUIZA==
+ dependencies:
+ file-loader "^6.2.0"
+ url-loader "^4.1.0"
+
next-pwa@^5.6.0:
version "5.6.0"
resolved "https://registry.yarnpkg.com/next-pwa/-/next-pwa-5.6.0.tgz#f7b1960c4fdd7be4253eb9b41b612ac773392bf4"
@@ -5977,6 +6046,11 @@ next-pwa@^5.6.0:
workbox-webpack-plugin "^6.5.4"
workbox-window "^6.5.4"
+next-theme@^0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/next-theme/-/next-theme-0.1.5.tgz#aa6655c516892925e577349d7715a8ed54bad727"
+ integrity sha512-WR8UCLEFjWvRl+UO2lTM4pGo7R4jzGZqQ6YL3hiL1Ns587Qb91GhJZLPu/Aa4ExtGQ/5wlcDX8zDYZoCN9oDPw==
+
next-themes@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.2.1.tgz#0c9f128e847979daf6c67f70b38e6b6567856e45"
@@ -6008,30 +6082,6 @@ next@12.3.2:
"@next/swc-win32-ia32-msvc" "12.3.2"
"@next/swc-win32-x64-msvc" "12.3.2"
-next@^13.4.16:
- version "13.4.16"
- resolved "https://registry.yarnpkg.com/next/-/next-13.4.16.tgz#327ef6885b22161ed001cd5943c20b5e409a9406"
- integrity sha512-1xaA/5DrfpPu0eV31Iro7JfPeqO8uxQWb1zYNTe+KDKdzqkAGapLcDYHMLNKXKB7lHjZ7LfKUOf9dyuzcibrhA==
- dependencies:
- "@next/env" "13.4.16"
- "@swc/helpers" "0.5.1"
- busboy "1.6.0"
- caniuse-lite "^1.0.30001406"
- postcss "8.4.14"
- styled-jsx "5.1.1"
- watchpack "2.4.0"
- zod "3.21.4"
- optionalDependencies:
- "@next/swc-darwin-arm64" "13.4.16"
- "@next/swc-darwin-x64" "13.4.16"
- "@next/swc-linux-arm64-gnu" "13.4.16"
- "@next/swc-linux-arm64-musl" "13.4.16"
- "@next/swc-linux-x64-gnu" "13.4.16"
- "@next/swc-linux-x64-musl" "13.4.16"
- "@next/swc-win32-arm64-msvc" "13.4.16"
- "@next/swc-win32-ia32-msvc" "13.4.16"
- "@next/swc-win32-x64-msvc" "13.4.16"
-
no-case@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
@@ -6041,9 +6091,9 @@ no-case@^3.0.4:
tslib "^2.0.3"
node-abi@^3.3.0:
- version "3.45.0"
- resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.45.0.tgz#f568f163a3bfca5aacfce1fbeee1fa2cc98441f5"
- integrity sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ==
+ version "3.47.0"
+ resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.47.0.tgz#6cbfa2916805ae25c2b7156ca640131632eb05e8"
+ integrity sha512-2s6B2CWZM//kPgwnuI0KrYwNjfdByE25zvAaEpq9IH4zcNsarH8Ihu/UuX6XMPEogDAxkuUFeZn60pXNHAqn3A==
dependencies:
semver "^7.3.5"
@@ -6053,9 +6103,9 @@ node-addon-api@^6.1.0:
integrity sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==
node-fetch@^2.6.7:
- version "2.6.12"
- resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba"
- integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
+ integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
dependencies:
whatwg-url "^5.0.0"
@@ -6123,40 +6173,40 @@ object.assign@^4.1.4:
object-keys "^1.1.1"
object.entries@^1.1.5, object.entries@^1.1.6:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.6.tgz#9737d0e5b8291edd340a3e3264bb8a3b00d5fa23"
- integrity sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==
- dependencies:
- call-bind "^1.0.2"
- define-properties "^1.1.4"
- es-abstract "^1.20.4"
-
-object.fromentries@^2.0.5, object.fromentries@^2.0.6:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.6.tgz#cdb04da08c539cffa912dcd368b886e0904bfa73"
- integrity sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==
- dependencies:
- call-bind "^1.0.2"
- define-properties "^1.1.4"
- es-abstract "^1.20.4"
-
-object.groupby@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.0.tgz#cb29259cf90f37e7bac6437686c1ea8c916d12a9"
- integrity sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw==
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.7.tgz#2b47760e2a2e3a752f39dd874655c61a7f03c131"
+ integrity sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==
dependencies:
call-bind "^1.0.2"
define-properties "^1.2.0"
- es-abstract "^1.21.2"
+ es-abstract "^1.22.1"
+
+object.fromentries@^2.0.5, object.fromentries@^2.0.6:
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616"
+ integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
+
+object.groupby@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.1.tgz#d41d9f3c8d6c778d9cbac86b4ee9f5af103152ee"
+ integrity sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
get-intrinsic "^1.2.1"
object.hasown@^1.1.1, object.hasown@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.2.tgz#f919e21fad4eb38a57bc6345b3afd496515c3f92"
- integrity sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.3.tgz#6a5f2897bb4d3668b8e79364f98ccf971bda55ae"
+ integrity sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==
dependencies:
- define-properties "^1.1.4"
- es-abstract "^1.20.4"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
object.omit@^3.0.0:
version "3.0.0"
@@ -6173,13 +6223,13 @@ object.pick@^1.3.0:
isobject "^3.0.1"
object.values@^1.1.5, object.values@^1.1.6:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d"
- integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a"
+ integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.4"
- es-abstract "^1.20.4"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
once@^1.3.0, once@^1.3.1, once@^1.4.0:
version "1.4.0"
@@ -6432,9 +6482,9 @@ postcss@8.4.14:
source-map-js "^1.0.2"
postcss@^8.4.14, postcss@^8.4.21, postcss@^8.4.23:
- version "8.4.27"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057"
- integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==
+ version "8.4.29"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.29.tgz#33bc121cf3b3688d4ddef50be869b2a54185a1dd"
+ integrity sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw==
dependencies:
nanoid "^3.3.6"
picocolors "^1.0.0"
@@ -6469,9 +6519,9 @@ prettier@^2.8.7:
integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
prettier@latest:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.1.tgz#65271fc9320ce4913c57747a70ce635b30beaa40"
- integrity sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.3.tgz#432a51f7ba422d1469096c0fdc28e235db8f9643"
+ integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==
pretty-bytes@^5.3.0, pretty-bytes@^5.4.1:
version "5.6.0"
@@ -6493,9 +6543,9 @@ prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.6.1, prop-types@^15.6.2,
react-is "^16.13.1"
property-information@^6.0.0:
- version "6.2.0"
- resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.2.0.tgz#b74f522c31c097b5149e3c3cb8d7f3defd986a1d"
- integrity sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.3.0.tgz#ba4a06ec6b4e1e90577df9931286953cdf4282c3"
+ integrity sha512-gVNZ74nqhRMiIUYWGQdosYetaKc83x8oT41a0LlV3AAFCAZwCpg4vmGkq8t34+cUhp3cnM4XDiU/7xlgK7HGrg==
prosemirror-changeset@^2.2.0:
version "2.2.1"
@@ -6574,23 +6624,16 @@ prosemirror-markdown@^1.10.1, prosemirror-markdown@^1.11.1:
prosemirror-model "^1.0.0"
prosemirror-menu@^1.2.1:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/prosemirror-menu/-/prosemirror-menu-1.2.2.tgz#c545a2de0b8cb79babc07682b1d93de0f273aa33"
- integrity sha512-437HIWTq4F9cTX+kPfqZWWm+luJm95Aut/mLUy+9OMrOml0bmWDS26ceC6SNfb2/S94et1sZ186vLO7pDHzxSw==
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/prosemirror-menu/-/prosemirror-menu-1.2.4.tgz#3cfdc7c06d10f9fbd1bce29082c498bd11a0a79a"
+ integrity sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==
dependencies:
crelt "^1.0.0"
prosemirror-commands "^1.0.0"
prosemirror-history "^1.0.0"
prosemirror-state "^1.0.0"
-prosemirror-model@^1.0.0, prosemirror-model@^1.16.0, prosemirror-model@^1.18.1, prosemirror-model@^1.8.1:
- version "1.18.1"
- resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.18.1.tgz#1d5d6b6de7b983ee67a479dc607165fdef3935bd"
- integrity sha512-IxSVBKAEMjD7s3n8cgtwMlxAXZrC7Mlag7zYsAKDndAqnDScvSmp/UdnRTV/B33lTCVU3CCm7dyAn/rVVD0mcw==
- dependencies:
- orderedmap "^2.0.0"
-
-prosemirror-model@^1.19.0:
+prosemirror-model@^1.0.0, prosemirror-model@^1.16.0, prosemirror-model@^1.18.1, prosemirror-model@^1.19.0, prosemirror-model@^1.8.1:
version "1.19.3"
resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.19.3.tgz#f0d55285487fefd962d0ac695f716f4ec6705006"
integrity sha512-tgSnwN7BS7/UM0sSARcW+IQryx2vODKX4MI7xpqY2X+iaepJdKBPc7I4aACIsDV/LTaTjt12Z56MhDr9LsyuZQ==
@@ -6643,9 +6686,9 @@ prosemirror-trailing-node@^2.0.2:
escape-string-regexp "^4.0.0"
prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.2.1, prosemirror-transform@^1.7.0, prosemirror-transform@^1.7.3:
- version "1.7.4"
- resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.7.4.tgz#ea878c90563f3586064dd5ccf6cabb50b2753fd9"
- integrity sha512-GO38mvqJ2yeI0BbL5E1CdHcly032Dlfn9nHqlnCHqlNf9e9jZwJixxp6VRtOeDZ1uTDpDIziezMKbA41LpAx3A==
+ version "1.7.5"
+ resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.7.5.tgz#c62aac8645bd4f8cf447d6d53dda80abe8489f03"
+ integrity sha512-U/fWB6frEzY7dzwJUo+ir8dU1JEanaI/RwL12Imy9js/527N0v/IRUKewocP1kTq998JNT18IGtThaDLwLOBxQ==
dependencies:
prosemirror-model "^1.0.0"
@@ -6968,6 +7011,18 @@ redux@^4.0.0, redux@^4.0.4:
dependencies:
"@babel/runtime" "^7.9.2"
+reflect.getprototypeof@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz#aaccbf41aca3821b87bb71d9dcbc7ad0ba50a3f3"
+ integrity sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
+ get-intrinsic "^1.2.1"
+ globalthis "^1.0.3"
+ which-builtin-type "^1.1.3"
+
regenerate-unicode-properties@^10.1.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c"
@@ -6992,7 +7047,7 @@ regenerator-transform@^0.15.2:
dependencies:
"@babel/runtime" "^7.8.4"
-regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.3, regexp.prototype.flags@^1.5.0:
+regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb"
integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==
@@ -7059,7 +7114,7 @@ resolve-pkg-maps@^1.0.0:
resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f"
integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==
-resolve@^1.1.7, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.22.0, resolve@^1.22.2, resolve@^1.22.3, resolve@^1.22.4:
+resolve@^1.1.7, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.22.0, resolve@^1.22.2, resolve@^1.22.4:
version "1.22.4"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34"
integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==
@@ -7179,7 +7234,7 @@ schema-utils@^2.6.5:
ajv "^6.12.4"
ajv-keywords "^3.5.2"
-schema-utils@^3.1.1:
+schema-utils@^3.0.0, schema-utils@^3.1.1:
version "3.3.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe"
integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==
@@ -7240,9 +7295,9 @@ serialize-javascript@^6.0.1:
randombytes "^2.1.0"
sharp@^0.32.1:
- version "0.32.4"
- resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.32.4.tgz#0354653b7924f2520b2264ac9bcd10a58bf411b6"
- integrity sha512-exUnZewqVZC6UXqXuQ8fyJJv0M968feBi04jb9GcUHrWtkRoAKnbJt8IfwT4NJs7FskArbJ14JAFGVuooszoGg==
+ version "0.32.5"
+ resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.32.5.tgz#9ddc78ead6446094f51e50355a2d4ec6e7220cd4"
+ integrity sha512-0dap3iysgDkNaPOaOL4X/0akdu0ma62GcdC2NBQ+93eqpePdDdr2/LM0sFdDSMmN7yS+odyZtPsb7tx/cYBKnQ==
dependencies:
color "^4.2.3"
detect-libc "^2.0.2"
@@ -7379,11 +7434,6 @@ stacktrace-parser@^0.1.10:
dependencies:
type-fest "^0.7.1"
-streamsearch@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
- integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
-
streamx@^2.15.0:
version "2.15.1"
resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.15.1.tgz#396ad286d8bc3eeef8f5cea3f029e81237c024c6"
@@ -7402,17 +7452,17 @@ string-width@^4.2.3:
strip-ansi "^6.0.1"
string.prototype.matchall@^4.0.6, string.prototype.matchall@^4.0.7, string.prototype.matchall@^4.0.8:
- version "4.0.8"
- resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3"
- integrity sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==
+ version "4.0.9"
+ resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.9.tgz#148779de0f75d36b13b15885fec5cadde994520d"
+ integrity sha512-6i5hL3MqG/K2G43mWXWgP+qizFW/QH/7kCNN13JrJS5q48FN5IKksLDscexKP3dnmB6cdm9jlNgAsWNLpSykmA==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.4"
- es-abstract "^1.20.4"
- get-intrinsic "^1.1.3"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
+ get-intrinsic "^1.2.1"
has-symbols "^1.0.3"
- internal-slot "^1.0.3"
- regexp.prototype.flags "^1.4.3"
+ internal-slot "^1.0.5"
+ regexp.prototype.flags "^1.5.0"
side-channel "^1.0.4"
string.prototype.trim@^1.2.7:
@@ -7497,13 +7547,6 @@ styled-jsx@5.0.7:
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.7.tgz#be44afc53771b983769ac654d355ca8d019dff48"
integrity sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==
-styled-jsx@5.1.1:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f"
- integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==
- dependencies:
- client-only "0.0.1"
-
stylis@4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51"
@@ -7548,10 +7591,10 @@ supports-preserve-symlinks-flag@^1.0.0:
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
-swr@^2.1.3:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/swr/-/swr-2.2.1.tgz#19b89a9034a62a73c30dbf06857a0a31981cd60a"
- integrity sha512-KJVA7dGtOBeZ+2sycEuzUfVIP5lZ/cd0xjevv85n2YG0x1uHJQicjAtahVZL6xG3+TjqhbBqimwYzVo3saeVXQ==
+swr@^2.1.3, swr@^2.2.2:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/swr/-/swr-2.2.2.tgz#abcb1f9c97e10527789884169d58b878472d4c98"
+ integrity sha512-CbR41AoMD4TQBQw9ic3GTXspgfM9Y8Mdhb5Ob4uIKXhWqnRLItwA5fpGvB7SmSw3+zEjb0PdhiEumtUvYoQ+bQ==
dependencies:
client-only "^0.0.1"
use-sync-external-store "^1.2.0"
@@ -7573,9 +7616,9 @@ tailwind-merge@^1.14.0:
integrity sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==
tailwindcss-animate@^1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/tailwindcss-animate/-/tailwindcss-animate-1.0.6.tgz#c7195037481552cc47962ea50113830360fd0c28"
- integrity sha512-4WigSGMvbl3gCCact62ZvOngA+PRqhAn7si3TQ3/ZuPuQZcIEtVap+ENSXbzWhpojKB8CpvnIsrwBu8/RnHtuw==
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz#318b692c4c42676cc9e67b19b78775742388bef4"
+ integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==
tailwindcss@^3.1.6, tailwindcss@^3.2.7:
version "3.3.3"
@@ -7676,9 +7719,9 @@ terser-webpack-plugin@^5.3.3:
terser "^5.16.8"
terser@^5.0.0, terser@^5.16.8:
- version "5.19.2"
- resolved "https://registry.yarnpkg.com/terser/-/terser-5.19.2.tgz#bdb8017a9a4a8de4663a7983f45c506534f9234e"
- integrity sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==
+ version "5.19.3"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-5.19.3.tgz#359baeba615aef13db4b8c4d77a2aa0d8814aa9e"
+ integrity sha512-pQzJ9UJzM0IgmT4FAtYI6+VqFf0lj/to58AV0Xfgg0Up37RyPG7Al+1cepC6/BVuAxR9oNb41/DL4DEoHJvTdg==
dependencies:
"@jridgewell/source-map" "^0.3.3"
acorn "^8.8.2"
@@ -7796,9 +7839,9 @@ tslib@^1.8.1:
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0, "tslib@^2.4.1 || ^1.9.3":
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410"
- integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
+ integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
tslib@~2.5.0:
version "2.5.3"
@@ -7819,47 +7862,47 @@ tunnel-agent@^0.6.0:
dependencies:
safe-buffer "^5.0.1"
-turbo-darwin-64@1.10.12:
- version "1.10.12"
- resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-1.10.12.tgz#a3d9d6bd3436e795254865bc3d76a9c79aff8085"
- integrity sha512-vmDfGVPl5/aFenAbOj3eOx3ePNcWVUyZwYr7taRl0ZBbmv2TzjRiFotO4vrKCiTVnbqjQqAFQWY2ugbqCI1kOQ==
+turbo-darwin-64@1.10.13:
+ version "1.10.13"
+ resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-1.10.13.tgz#7abc33838bf74c7e7ba2955cb6acc40342d6964c"
+ integrity sha512-vmngGfa2dlYvX7UFVncsNDMuT4X2KPyPJ2Jj+xvf5nvQnZR/3IeDEGleGVuMi/hRzdinoxwXqgk9flEmAYp0Xw==
-turbo-darwin-arm64@1.10.12:
- version "1.10.12"
- resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-1.10.12.tgz#ff1d9466935687ca68c0dee88a909c34cc654357"
- integrity sha512-3JliEESLNX2s7g54SOBqqkqJ7UhcOGkS0ywMr5SNuvF6kWVTbuUq7uBU/sVbGq8RwvK1ONlhPvJne5MUqBCTCQ==
+turbo-darwin-arm64@1.10.13:
+ version "1.10.13"
+ resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-1.10.13.tgz#89f2d14a28789e5eaf276a17fecd4116d61fd16d"
+ integrity sha512-eMoJC+k7gIS4i2qL6rKmrIQGP6Wr9nN4odzzgHFngLTMimok2cGLK3qbJs5O5F/XAtEeRAmuxeRnzQwTl/iuAw==
-turbo-linux-64@1.10.12:
- version "1.10.12"
- resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-1.10.12.tgz#d184a491cc67c07672d339e36427378d0fc6b82e"
- integrity sha512-siYhgeX0DidIfHSgCR95b8xPee9enKSOjCzx7EjTLmPqPaCiVebRYvbOIYdQWRqiaKh9yfhUtFmtMOMScUf1gg==
+turbo-linux-64@1.10.13:
+ version "1.10.13"
+ resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-1.10.13.tgz#803e2b351984ec81034dc4b6935cdfb0a7d7d572"
+ integrity sha512-0CyYmnKTs6kcx7+JRH3nPEqCnzWduM0hj8GP/aodhaIkLNSAGAa+RiYZz6C7IXN+xUVh5rrWTnU2f1SkIy7Gdg==
-turbo-linux-arm64@1.10.12:
- version "1.10.12"
- resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-1.10.12.tgz#44e6ca10b20fd4c59f8c85acf8366c7c09ebca81"
- integrity sha512-K/ZhvD9l4SslclaMkTiIrnfcACgos79YcAo4kwc8bnMQaKuUeRpM15sxLpZp3xDjDg8EY93vsKyjaOhdFG2UbA==
+turbo-linux-arm64@1.10.13:
+ version "1.10.13"
+ resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-1.10.13.tgz#92439a927ec98801be1be266016736be5730e40c"
+ integrity sha512-0iBKviSGQQlh2OjZgBsGjkPXoxvRIxrrLLbLObwJo3sOjIH0loGmVIimGS5E323soMfi/o+sidjk2wU1kFfD7Q==
-turbo-windows-64@1.10.12:
- version "1.10.12"
- resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-1.10.12.tgz#36380eca8e7b0505d08b87a084efab1500b2a80e"
- integrity sha512-7FSgSwvktWDNOqV65l9AbZwcoueAILeE4L7JvjauNASAjjbuzXGCEq5uN8AQU3U5BOFj4TdXrVmO2dX+lLu8Zg==
+turbo-windows-64@1.10.13:
+ version "1.10.13"
+ resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-1.10.13.tgz#870815cdcb20f2480296c208778f9127be61eec6"
+ integrity sha512-S5XySRfW2AmnTeY1IT+Jdr6Goq7mxWganVFfrmqU+qqq3Om/nr0GkcUX+KTIo9mPrN0D3p5QViBRzulwB5iuUQ==
-turbo-windows-arm64@1.10.12:
- version "1.10.12"
- resolved "https://registry.yarnpkg.com/turbo-windows-arm64/-/turbo-windows-arm64-1.10.12.tgz#757ad59b9abf1949f22280bee6e8aad253743ba5"
- integrity sha512-gCNXF52dwom1HLY9ry/cneBPOKTBHhzpqhMylcyvJP0vp9zeMQQkt6yjYv+6QdnmELC92CtKNp2FsNZo+z0pyw==
+turbo-windows-arm64@1.10.13:
+ version "1.10.13"
+ resolved "https://registry.yarnpkg.com/turbo-windows-arm64/-/turbo-windows-arm64-1.10.13.tgz#2da38b71b1716732541dfc5bd7475dc0903921f8"
+ integrity sha512-nKol6+CyiExJIuoIc3exUQPIBjP9nIq5SkMJgJuxsot2hkgGrafAg/izVDRDrRduQcXj2s8LdtxJHvvnbI8hEQ==
turbo@latest:
- version "1.10.12"
- resolved "https://registry.yarnpkg.com/turbo/-/turbo-1.10.12.tgz#cd6f56b92da0600dae9fd94230483556a5c83187"
- integrity sha512-WM3+jTfQWnB9W208pmP4oeehZcC6JQNlydb/ZHMRrhmQa+htGhWLCzd6Q9rLe0MwZLPpSPFV2/bN5egCLyoKjQ==
+ version "1.10.13"
+ resolved "https://registry.yarnpkg.com/turbo/-/turbo-1.10.13.tgz#8050bcd09f8a20d5a626f41e86cd8760e49a0df6"
+ integrity sha512-vOF5IPytgQPIsgGtT0n2uGZizR2N3kKuPIn4b5p5DdeLoI0BV7uNiydT7eSzdkPRpdXNnO8UwS658VaI4+YSzQ==
optionalDependencies:
- turbo-darwin-64 "1.10.12"
- turbo-darwin-arm64 "1.10.12"
- turbo-linux-64 "1.10.12"
- turbo-linux-arm64 "1.10.12"
- turbo-windows-64 "1.10.12"
- turbo-windows-arm64 "1.10.12"
+ turbo-darwin-64 "1.10.13"
+ turbo-darwin-arm64 "1.10.13"
+ turbo-linux-64 "1.10.13"
+ turbo-linux-arm64 "1.10.13"
+ turbo-windows-64 "1.10.13"
+ turbo-windows-arm64 "1.10.13"
type-check@^0.4.0, type-check@~0.4.0:
version "0.4.0"
@@ -8082,6 +8125,15 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
+url-loader@^4.1.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2"
+ integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==
+ dependencies:
+ loader-utils "^2.0.0"
+ mime-types "^2.1.27"
+ schema-utils "^3.0.0"
+
use-callback-ref@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.0.tgz#772199899b9c9a50526fedc4993fc7fa1f7e32d5"
@@ -8138,9 +8190,9 @@ uvu@^0.5.0:
sade "^1.7.3"
v8-compile-cache@^2.0.3:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
- integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128"
+ integrity sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==
vfile-message@^3.0.0:
version "3.1.4"
@@ -8172,14 +8224,6 @@ warning@^4.0.2, warning@^4.0.3:
dependencies:
loose-envify "^1.0.0"
-watchpack@2.4.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
- integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
- dependencies:
- glob-to-regexp "^0.4.1"
- graceful-fs "^4.1.2"
-
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
@@ -8231,7 +8275,35 @@ which-boxed-primitive@^1.0.2:
is-string "^1.0.5"
is-symbol "^1.0.3"
-which-typed-array@^1.1.10, which-typed-array@^1.1.11:
+which-builtin-type@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b"
+ integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==
+ dependencies:
+ function.prototype.name "^1.1.5"
+ has-tostringtag "^1.0.0"
+ is-async-function "^2.0.0"
+ is-date-object "^1.0.5"
+ is-finalizationregistry "^1.0.2"
+ is-generator-function "^1.0.10"
+ is-regex "^1.1.4"
+ is-weakref "^1.0.2"
+ isarray "^2.0.5"
+ which-boxed-primitive "^1.0.2"
+ which-collection "^1.0.1"
+ which-typed-array "^1.1.9"
+
+which-collection@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906"
+ integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==
+ dependencies:
+ is-map "^2.0.1"
+ is-set "^2.0.1"
+ is-weakmap "^2.0.1"
+ is-weakset "^2.0.1"
+
+which-typed-array@^1.1.10, which-typed-array@^1.1.11, which-typed-array@^1.1.9:
version "1.1.11"
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a"
integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==
@@ -8439,16 +8511,11 @@ yaml@^1.10.0:
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
yaml@^2.1.1:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b"
- integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.2.tgz#f522db4313c671a0ca963a75670f1c12ea909144"
+ integrity sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
-
-zod@3.21.4:
- version "3.21.4"
- resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db"
- integrity sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==