fix: removed unused packages and upgraded to next 14 (#2944)

* fix: upgrading next package and removed unused deps

* chore: unused variable removed

* chore: next image icon fix

* chore: unused component removed

* chore: next image icon fix

* chore: replace use-debounce with lodash debounce

* chore: unused component removed

* resolved: fixed issue with next link component

* fix: updates in next config

* fix: updating types pages

---------

Co-authored-by: Anmol Singh Bhatia <anmolsinghbhatia@plane.so>
This commit is contained in:
sriram veeraghanta 2023-11-29 20:32:10 +05:30
parent 804313413b
commit ee30eb0590
137 changed files with 469 additions and 1524 deletions

View File

@ -30,7 +30,7 @@
"turbo": "^1.10.16"
},
"resolutions": {
"@types/react": "18.2.0"
"@types/react": "18.2.39"
},
"packageManager": "yarn@1.22.19"
}

View File

@ -65,7 +65,7 @@
"postcss": "^8.4.29",
"eslint-config-next": "13.2.4",
"@types/node": "18.15.3",
"@types/react": "^18.2.5",
"@types/react": "^18.2.39",
"@types/react-dom": "18.0.11",
"tailwind-config-custom": "*",
"tsconfig": "*",

View File

@ -35,7 +35,7 @@
"@tiptap/core": "^2.1.7",
"@tiptap/extension-placeholder": "^2.1.11",
"@types/node": "18.15.3",
"@types/react": "^18.2.5",
"@types/react": "^18.2.39",
"@types/react-dom": "18.0.11",
"eslint": "8.36.0",
"eslint-config-next": "13.2.4",

View File

@ -41,7 +41,7 @@
},
"devDependencies": {
"@types/node": "18.15.3",
"@types/react": "^18.2.35",
"@types/react": "^18.2.39",
"@types/react-dom": "^18.2.14",
"eslint": "^7.32.0",
"postcss": "^8.4.29",

View File

@ -35,7 +35,7 @@
},
"devDependencies": {
"@types/node": "18.15.3",
"@types/react": "^18.2.35",
"@types/react": "^18.2.39",
"@types/react-dom": "^18.2.14",
"eslint": "^7.32.0",
"postcss": "^8.4.29",

View File

@ -38,7 +38,7 @@
},
"devDependencies": {
"@types/node": "18.15.3",
"@types/react": "^18.2.35",
"@types/react": "^18.2.39",
"@types/react-dom": "^18.2.14",
"eslint": "^7.32.0",
"postcss": "^8.4.29",

View File

@ -33,7 +33,7 @@
},
"devDependencies": {
"@types/node": "18.15.3",
"@types/react": "^18.2.35",
"@types/react": "^18.2.39",
"@types/react-dom": "^18.2.14",
"eslint": "^7.32.0",
"tsconfig": "*",

View File

@ -19,7 +19,7 @@
},
"devDependencies": {
"@types/node": "^20.5.2",
"@types/react": "^18.2.37",
"@types/react": "^18.2.39",
"@types/react-color": "^3.0.9",
"@types/react-dom": "^18.2.15",
"classnames": "^2.3.2",

View File

@ -77,7 +77,9 @@ export const EmailPasswordForm: React.FC<Props> = ({ onSubmit }) => {
<div className="text-right text-xs">
{isSignUpPage ? (
<Link href="/">
<a className="text-custom-text-200 hover:text-custom-primary-100">Already have an account? Sign in.</a>
<span className="text-custom-text-200 hover:text-custom-primary-100">
Already have an account? Sign in.
</span>
</Link>
) : (
<button
@ -100,9 +102,9 @@ export const EmailPasswordForm: React.FC<Props> = ({ onSubmit }) => {
</PrimaryButton>
{!isSignUpPage && (
<Link href="/sign-up">
<a className="block text-custom-text-200 hover:text-custom-primary-100 text-xs mt-4">
<span className="block text-custom-text-200 hover:text-custom-primary-100 text-xs mt-4">
Don{"'"}t have an account? Sign up.
</a>
</span>
</Link>
)}
</div>

View File

@ -130,11 +130,11 @@ const IssueNavbar = observer(() => {
) : (
<div className="flex-shrink-0">
<Link href={`/login/?next_path=${router.asPath}`}>
<a>
<span>
<PrimaryButton className="flex-shrink-0" outline>
Sign in
</PrimaryButton>
</a>
</span>
</Link>
</div>
)}

View File

@ -53,9 +53,9 @@ export const PeekOverviewIssueActivity: React.FC<Props> = observer((props) => {
Sign in to add your comment
</p>
<Link href={`/?next_path=${router.asPath}`}>
<a>
<span>
<PrimaryButton className="flex-shrink-0 !px-7">Sign in</PrimaryButton>
</a>
</span>
</Link>
</div>
)}

View File

@ -44,7 +44,7 @@
"@types/js-cookie": "^3.0.3",
"@types/node": "18.14.1",
"@types/nprogress": "^0.2.0",
"@types/react": "18.2.35",
"@types/react": "18.2.39",
"@types/react-dom": "18.0.11",
"@types/uuid": "^9.0.1",
"@typescript-eslint/eslint-plugin": "^5.48.2",

View File

@ -114,7 +114,9 @@ export const EmailSignUpForm: React.FC<Props> = (props) => {
</div>
<div className="text-right text-xs">
<Link href="/">
<a className="text-custom-text-200 hover:text-custom-primary-100">Already have an account? Sign in.</a>
<span className="text-custom-text-200 hover:text-custom-primary-100">
Already have an account? Sign in.
</span>
</Link>
</div>
<div>

View File

@ -2,8 +2,9 @@
import { BarDatum } from "@nivo/bar";
// components
import { CustomTooltip } from "./custom-tooltip";
import { Tooltip } from "@plane/ui";
// ui
import { BarGraph, Tooltip } from "components/ui";
import { BarGraph } from "components/ui";
// helpers
import { findStringWithMostCharacters } from "helpers/array.helper";
import { generateBarColor, generateDisplayName } from "helpers/analytics.helper";

View File

@ -38,7 +38,7 @@ export const NotAuthorizedView: React.FC<Props> = ({ actionButton, type }) => {
<p>
You have signed in as {user.email}. <br />
<Link href={`/?next=${currentPath}`}>
<a className="font-medium text-custom-text-100">Sign in</a>
<span className="font-medium text-custom-text-100">Sign in</span>
</Link>{" "}
with different account that has access to this page.
</p>
@ -46,7 +46,7 @@ export const NotAuthorizedView: React.FC<Props> = ({ actionButton, type }) => {
<p>
You need to{" "}
<Link href={`/?next=${currentPath}`}>
<a className="font-medium text-custom-text-100">Sign in</a>
<span className="font-medium text-custom-text-100">Sign in</span>
</Link>{" "}
with an account that has access to this page.
</p>

View File

@ -18,14 +18,14 @@ export const NotAWorkspaceMember = () => (
</div>
<div className="flex items-center justify-center gap-2">
<Link href="/invitations">
<a>
<span>
<Button variant="neutral-primary">Check pending invites</Button>
</a>
</span>
</Link>
<Link href="/create-workspace">
<a>
<span>
<Button variant="primary">Create new workspace</Button>
</a>
</span>
</Link>
</div>
</div>

View File

@ -45,12 +45,12 @@ const BreadcrumbItem: React.FC<BreadcrumbItemProps> = ({
<>
{link ? (
<Link href={link}>
<a className={`border-r-2 border-custom-sidebar-border-200 px-3 text-sm ${linkTruncate ? "truncate" : ""}`}>
<span className={`border-r-2 border-custom-sidebar-border-200 px-3 text-sm ${linkTruncate ? "truncate" : ""}`}>
<p className={`${linkTruncate ? "truncate" : ""}${icon ? "flex items-center gap-2" : ""}`}>
{icon ?? null}
{title}
</p>
</a>
</span>
</Link>
) : (
<div className={`px-3 text-sm truncate ${unshrinkTitle ? "flex-shrink-0" : ""}`}>

View File

@ -28,7 +28,7 @@ export const EmptyState: React.FC<Props> = ({
}) => (
<div className={`flex items-center justify-center h-full w-full`}>
<div className="text-center flex flex-col items-center w-full">
<Image src={image} className="w-52 sm:w-60" alt={primaryButton?.text} />
<Image src={image} className="w-52 sm:w-60" alt={primaryButton?.text || "button image"} />
<h6 className="text-xl font-semibold mt-6 sm:mt-8 mb-3">{title}</h6>
{description && <p className="text-custom-text-300 mb-7 sm:mb-8 px-5">{description}</p>}
<div className="flex items-center gap-4">

View File

@ -20,7 +20,6 @@ type Props = {
text: string;
onClick: () => void;
};
secondaryButton?: React.ReactNode;
disabled?: boolean;
};
@ -29,7 +28,6 @@ export const NewEmptyState: React.FC<Props> = ({
description,
image,
primaryButton,
secondaryButton,
disabled = false,
comicBox,
}) => {
@ -48,7 +46,7 @@ export const NewEmptyState: React.FC<Props> = ({
<h3 className="font-semibold text-2xl">{title}</h3>
{description && <p className=" text-lg">{description}</p>}
<div className="relative w-full max-w-6xl">
<Image src={image} className="w-52 sm:w-60" alt={primaryButton?.text} />
<Image src={image} className="w-52 sm:w-60" alt={primaryButton?.text || "button image"} />
</div>
<div className="flex justify-center items-start relative">

View File

@ -317,9 +317,9 @@ export const ActiveCycleDetails: React.FC<IActiveCycleDetails> = observer((props
</div>
<Link href={`/${workspaceSlug}/projects/${projectId}/cycles/${cycle.id}`}>
<a className="bg-custom-primary text-white px-4 rounded-md py-2 text-center text-sm font-medium w-full hover:bg-custom-primary/90">
<span className="bg-custom-primary text-white px-4 rounded-md py-2 text-center text-sm font-medium w-full hover:bg-custom-primary/90">
View Cycle
</a>
</span>
</Link>
</div>
</div>

View File

@ -152,7 +152,7 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = (props) => {
/>
<Link href={`/${workspaceSlug}/projects/${projectId}/cycles/${cycle.id}`}>
<a className="flex flex-col justify-between p-4 h-44 w-full min-w-[250px] text-sm rounded bg-custom-background-100 border border-custom-border-100 hover:shadow-md">
<span className="flex flex-col justify-between p-4 h-44 w-full min-w-[250px] text-sm rounded bg-custom-background-100 border border-custom-border-100 hover:shadow-md">
<div className="flex items-center justify-between gap-2">
<div className="flex items-center gap-3 truncate">
<span className="flex-shrink-0">
@ -268,7 +268,7 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = (props) => {
</div>
</div>
</div>
</a>
</span>
</Link>
</div>
);

View File

@ -153,7 +153,7 @@ export const CyclesListItem: FC<TCyclesListItem> = (props) => {
projectId={projectId}
/>
<Link href={`/${workspaceSlug}/projects/${projectId}/cycles/${cycle.id}`}>
<a className="group flex items-center justify-between gap-5 px-5 py-6 h-16 w-full text-sm bg-custom-background-100 border-b border-custom-border-100 hover:bg-custom-background-90">
<span className="group flex items-center justify-between gap-5 px-5 py-6 h-16 w-full text-sm bg-custom-background-100 border-b border-custom-border-100 hover:bg-custom-background-90">
<div className="flex items-center gap-3 w-full truncate">
<div className="flex items-center gap-4 truncate">
<span className="flex-shrink-0">
@ -262,7 +262,7 @@ export const CyclesListItem: FC<TCyclesListItem> = (props) => {
</CustomMenu.MenuItem>
</CustomMenu>
</div>
</a>
</span>
</Link>
</>
);

View File

@ -24,7 +24,10 @@ interface ICycleDelete {
export const CycleDeleteModal: React.FC<ICycleDelete> = observer((props) => {
const { isOpen, handleClose, cycle, workspaceSlug, projectId } = props;
// store
const { cycle: cycleStore, trackEvent: { postHogEventTracker } } = useMobxStore();
const {
cycle: cycleStore,
trackEvent: { postHogEventTracker },
} = useMobxStore();
// toast
const { setToastAlert } = useToast();
// states
@ -36,26 +39,23 @@ export const CycleDeleteModal: React.FC<ICycleDelete> = observer((props) => {
setLoader(true);
if (cycle?.id)
try {
await cycleStore.removeCycle(workspaceSlug, projectId, cycle?.id).then((res) => {
setToastAlert({
type: "success",
title: "Success!",
message: "Cycle deleted successfully.",
await cycleStore
.removeCycle(workspaceSlug, projectId, cycle?.id)
.then(() => {
setToastAlert({
type: "success",
title: "Success!",
message: "Cycle deleted successfully.",
});
postHogEventTracker("CYCLE_DELETE", {
state: "SUCCESS",
});
})
.catch(() => {
postHogEventTracker("CYCLE_DELETE", {
state: "FAILED",
});
});
postHogEventTracker(
"CYCLE_DELETE",
{
state: "SUCCESS"
}
);
}).catch((error) => {
postHogEventTracker(
"CYCLE_DELETE",
{
state: "FAILED"
}
);
});
if (cycleId || peekCycle) router.push(`/${workspaceSlug}/projects/${projectId}/cycles`);

View File

@ -67,11 +67,11 @@ const IntegrationGuide = () => {
</div>
<div className="flex-shrink-0">
<Link href={`/${workspaceSlug}/settings/exports?provider=${service.provider}`}>
<a>
<span>
<Button variant="primary" className="capitalize">
{service.type}
</Button>
</a>
</span>
</Link>
</div>
</div>

View File

@ -119,7 +119,7 @@ export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
<div className="flex items-center gap-1 p-1 rounded bg-custom-background-80">
{GLOBAL_VIEW_LAYOUTS.map((layout) => (
<Link key={layout.key} href={`/${workspaceSlug}/${layout.link}`}>
<a>
<span>
<Tooltip tooltipContent={layout.title}>
<div
className={`w-7 h-[22px] rounded grid place-items-center transition-all hover:bg-custom-background-100 overflow-hidden group ${
@ -133,7 +133,7 @@ export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
/>
</div>
</Tooltip>
</a>
</span>
</Link>
))}
</div>

View File

@ -185,7 +185,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
</FiltersDropdown>
{projectId && inboxStore.isInboxEnabled && inboxDetails && (
<Link href={`/${workspaceSlug}/projects/${projectId}/inbox/${inboxStore.getInboxId(projectId)}`}>
<a>
<span>
<Button variant="neutral-primary" size="sm" className="relative">
Inbox
{inboxDetails.pending_issue_count > 0 && (
@ -194,7 +194,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
</span>
)}
</Button>
</a>
</span>
</Link>
)}
<Button onClick={() => setAnalyticsModal(true)} variant="neutral-primary" size="sm">

View File

@ -1,9 +1,13 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import AudioFileIcon from "public/attachment/audio-icon.png";
export const AudioIcon: React.FC<Props> = ({ width, height }) => (
export type AudioIconProps = {
width?: number;
height?: number;
};
export const AudioIcon: React.FC<AudioIconProps> = ({ width, height }) => (
<Image src={AudioFileIcon} height={height} width={width} alt="AudioFileIcon" />
);

View File

@ -1,10 +1,11 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import CMDIcon from "public/mac-command.svg";
// type
import type { ImageIconPros } from "./types";
export const MacCommandIcon: React.FC<Props> = ({ width = "14", height = "14" }) => (
export const MacCommandIcon: React.FC<ImageIconPros> = ({ width = 14, height = 14 }) => (
<Image src={CMDIcon} height={height} width={width} alt="CMDIcon" />
);

View File

@ -1,9 +1,10 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import CssFileIcon from "public/attachment/css-icon.png";
// type
import type { ImageIconPros } from "./types";
export const CssIcon: React.FC<Props> = ({ width, height }) => (
export const CssIcon: React.FC<ImageIconPros> = ({ width, height }) => (
<Image src={CssFileIcon} height={height} width={width} alt="CssFileIcon" />
);

View File

@ -1,9 +1,10 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import CSVFileIcon from "public/attachment/csv-icon.png";
// type
import type { ImageIconPros } from "./types";
export const CsvIcon: React.FC<Props> = ({ width, height }) => (
export const CsvIcon: React.FC<ImageIconPros> = ({ width, height }) => (
<Image src={CSVFileIcon} height={height} width={width} alt="CSVFileIcon" />
);

View File

@ -1,9 +1,10 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import DefaultFileIcon from "public/attachment/default-icon.png";
// type
import type { ImageIconPros } from "./types";
export const DefaultIcon: React.FC<Props> = ({ width, height }) => (
export const DefaultIcon: React.FC<ImageIconPros> = ({ width, height }) => (
<Image src={DefaultFileIcon} height={height} width={width} alt="DefaultFileIcon" />
);

View File

@ -1,9 +1,10 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import DocFileIcon from "public/attachment/doc-icon.png";
// type
import type { ImageIconPros } from "./types";
export const DocIcon: React.FC<Props> = ({ width, height }) => (
export const DocIcon: React.FC<ImageIconPros> = ({ width, height }) => (
<Image src={DocFileIcon} height={height} width={width} alt="DocFileIcon" />
);

View File

@ -1,9 +1,10 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import FigmaFileIcon from "public/attachment/figma-icon.png";
// type
import type { ImageIconPros } from "./types";
export const FigmaIcon: React.FC<Props> = ({ width, height }) => (
export const FigmaIcon: React.FC<ImageIconPros> = ({ width, height }) => (
<Image src={FigmaFileIcon} height={height} width={width} alt="FigmaFileIcon" />
);

View File

@ -1,9 +1,10 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import HtmlFileIcon from "public/attachment/html-icon.png";
// type
import type { ImageIconPros } from "./types";
export const HtmlIcon: React.FC<Props> = ({ width, height }) => (
export const HtmlIcon: React.FC<ImageIconPros> = ({ width, height }) => (
<Image src={HtmlFileIcon} height={height} width={width} alt="HtmlFileIcon" />
);

View File

@ -1,9 +1,10 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import ImgFileIcon from "public/attachment/img-icon.png";
// type
import type { ImageIconPros } from "./types";
export const ImgIcon: React.FC<Props> = ({ width, height }) => (
export const ImgIcon: React.FC<ImageIconPros> = ({ width, height }) => (
<Image src={ImgFileIcon} height={height} width={width} alt="ImgFileIcon" />
);

View File

@ -1,9 +1,10 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import JpgFileIcon from "public/attachment/jpg-icon.png";
// type
import type { ImageIconPros } from "./types";
export const JpgIcon: React.FC<Props> = ({ width, height }) => (
export const JpgIcon: React.FC<ImageIconPros> = ({ width, height }) => (
<Image src={JpgFileIcon} height={height} width={width} alt="JpgFileIcon" />
);

View File

@ -1,9 +1,10 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import JsFileIcon from "public/attachment/js-icon.png";
// type
import type { ImageIconPros } from "./types";
export const JavaScriptIcon: React.FC<Props> = ({ width, height }) => (
export const JavaScriptIcon: React.FC<ImageIconPros> = ({ width, height }) => (
<Image src={JsFileIcon} height={height} width={width} alt="JsFileIcon" />
);

View File

@ -1,9 +1,10 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import PDFFileIcon from "public/attachment/pdf-icon.png";
// type
import type { ImageIconPros } from "./types";
export const PdfIcon: React.FC<Props> = ({ width, height }) => (
export const PdfIcon: React.FC<ImageIconPros> = ({ width, height }) => (
<Image src={PDFFileIcon} height={height} width={width} alt="PDFFileIcon" />
);

View File

@ -1,9 +1,10 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import PngFileIcon from "public/attachment/png-icon.png";
// type
import type { ImageIconPros } from "./types";
export const PngIcon: React.FC<Props> = ({ width, height }) => (
export const PngIcon: React.FC<ImageIconPros> = ({ width, height }) => (
<Image src={PngFileIcon} height={height} width={width} alt="PngFileIcon" />
);

View File

@ -1,9 +1,10 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import SheetFileIcon from "public/attachment/excel-icon.png";
// type
import type { ImageIconPros } from "./types";
export const SheetIcon: React.FC<Props> = ({ width, height }) => (
export const SheetIcon: React.FC<ImageIconPros> = ({ width, height }) => (
<Image src={SheetFileIcon} height={height} width={width} alt="SheetFileIcon" />
);

View File

@ -1,9 +1,10 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import SvgFileIcon from "public/attachment/svg-icon.png";
// type
import type { ImageIconPros } from "./types";
export const SvgIcon: React.FC<Props> = ({ width, height }) => (
export const SvgIcon: React.FC<ImageIconPros> = ({ width, height }) => (
<Image src={SvgFileIcon} height={height} width={width} alt="SvgFileIcon" />
);

View File

@ -1,9 +1,10 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import TxtFileIcon from "public/attachment/txt-icon.png";
// type
import type { ImageIconPros } from "./types";
export const TxtIcon: React.FC<Props> = ({ width, height }) => (
export const TxtIcon: React.FC<ImageIconPros> = ({ width, height }) => (
<Image src={TxtFileIcon} height={height} width={width} alt="TxtFileIcon" />
);

View File

@ -4,3 +4,8 @@ export type Props = {
height?: string | number;
color?: string;
};
export type ImageIconPros = {
width?: number;
height?: number;
};

View File

@ -1,9 +1,10 @@
import React from "react";
import Image from "next/image";
import type { Props } from "./types";
// image
import VideoFileIcon from "public/attachment/video-icon.png";
// type
import type { ImageIconPros } from "./types";
export const VideoIcon: React.FC<Props> = ({ width, height }) => (
export const VideoIcon: React.FC<ImageIconPros> = ({ width, height }) => (
<Image src={VideoFileIcon} height={height} width={width} alt="VideoFileIcon" />
);

View File

@ -27,7 +27,7 @@ export const InboxIssueCard: React.FC<Props> = (props) => {
return (
<Link href={`/${workspaceSlug}/projects/${projectId}/inbox/${inboxId}?inboxIssueId=${issue.issue_inbox[0].id}`}>
<a>
<span>
<div
id={issue.id}
className={`relative min-h-[5rem] cursor-pointer select-none space-y-3 py-2 px-4 border-b border-custom-border-200 hover:bg-custom-primary/5 ${
@ -91,7 +91,7 @@ export const InboxIssueCard: React.FC<Props> = (props) => {
)}
</div>
</div>
</a>
</span>
</Link>
);
};

View File

@ -1,7 +1,7 @@
import { FC } from "react";
import { Controller, useForm } from "react-hook-form";
// ui
import { Button, Input, ToggleSwitch } from "@plane/ui";
import { Button, Input } from "@plane/ui";
// types
import { IInstance, IInstanceAdmin } from "types/instance";
// hooks

View File

@ -97,16 +97,13 @@ export const InstanceHelpSection: FC = () => {
{helpOptions.map(({ name, Icon, href, onClick }) => {
if (href)
return (
<Link href={href} key={name}>
<a
target="_blank"
className="flex items-center gap-x-2 rounded px-2 py-1 text-xs hover:bg-custom-background-80"
>
<Link href={href} key={name} target="_blank">
<span className="flex items-center gap-x-2 rounded px-2 py-1 text-xs hover:bg-custom-background-80">
<div className="grid place-items-center flex-shrink-0">
<Icon className="text-custom-text-200 h-3.5 w-3.5" size={14} />
</div>
<span className="text-xs">{name}</span>
</a>
</span>
</Link>
);
else

View File

@ -67,12 +67,12 @@ export const InstanceAdminRestriction: FC<InstanceAdminRestrictionProps> = ({ re
</div>
<div className="flex items-center justify-center gap-2">
<Link href={`/${redirectWorkspaceSlug}`}>
<a>
<span>
<Button variant="primary" size="sm">
<LayoutGrid width={16} height={16} />
To the workspace
</Button>
</a>
</span>
</Link>
</div>
</div>

View File

@ -78,9 +78,9 @@ export const InstanceSidebarDropdown = observer(() => {
<Tooltip position="bottom-left" tooltipContent="Exit God Mode">
<div className="flex-shrink-0">
<Link href={`/${redirectWorkspaceSlug}`}>
<a>
<span>
<LogIn className="h-5 w-5 text-custom-text-200 rotate-180" />
</a>
</span>
</Link>
</div>
</Tooltip>
@ -119,10 +119,10 @@ export const InstanceSidebarDropdown = observer(() => {
{PROFILE_LINKS.map((link) => (
<Menu.Item key={link.key} as="button" type="button">
<Link href={link.link}>
<a className="flex w-full items-center gap-2 rounded px-2 py-1 hover:bg-custom-sidebar-background-80">
<span className="flex w-full items-center gap-2 rounded px-2 py-1 hover:bg-custom-sidebar-background-80">
<link.icon className="h-4 w-4 stroke-[1.5]" />
{link.name}
</a>
</span>
</Link>
</Menu.Item>
))}
@ -142,9 +142,9 @@ export const InstanceSidebarDropdown = observer(() => {
<div className="p-2 pb-0">
<Menu.Item as="button" type="button" className="w-full">
<Link href={`/${redirectWorkspaceSlug}`}>
<a className="flex w-full items-center justify-center rounded px-2 py-1 text-sm font-medium text-custom-primary-100 hover:text-custom-primary-200 bg-custom-primary-100/20 hover:bg-custom-primary-100/30">
<span className="flex w-full items-center justify-center rounded px-2 py-1 text-sm font-medium text-custom-primary-100 hover:text-custom-primary-200 bg-custom-primary-100/20 hover:bg-custom-primary-100/30">
Exit God Mode
</a>
</span>
</Link>
</Menu.Item>
</div>

View File

@ -54,7 +54,7 @@ export const InstanceAdminSidebarMenu = () => {
return (
<Link key={index} href={item.href}>
<a className="block w-full">
<span className="block w-full">
<Tooltip tooltipContent={item.name} position="right" className="ml-2" disabled={!sidebarCollapsed}>
<div
className={`group flex w-full items-center gap-3 rounded-md px-3 py-2 outline-none ${
@ -84,7 +84,7 @@ export const InstanceAdminSidebarMenu = () => {
)}
</div>
</Tooltip>
</a>
</span>
</Link>
);
})}

View File

@ -165,10 +165,10 @@ export const GithubImporterRoot: React.FC<Props> = () => {
<form onSubmit={handleSubmit(createGithubImporterService)}>
<div className="space-y-2 mt-4">
<Link href={`/${workspaceSlug}/settings/imports`}>
<div className="inline-flex cursor-pointer items-center gap-2 text-sm font-medium text-custom-text-200 hover:text-custom-text-100">
<span className="inline-flex cursor-pointer items-center gap-2 text-sm font-medium text-custom-text-200 hover:text-custom-text-100">
<ArrowLeft className="h-3 w-3" />
<div>Cancel import & go back</div>
</div>
</span>
</Link>
<div className="space-y-4 rounded-[10px] border border-custom-border-200 bg-custom-background-100 p-4">

View File

@ -89,9 +89,9 @@ const IntegrationGuide = () => {
</div>
<div className="flex-shrink-0">
<Link href={`/${workspaceSlug}/settings/imports?provider=${service.provider}`}>
<a>
<span>
<Button variant="primary">{service.type}</Button>
</a>
</span>
</Link>
</div>
</div>

View File

@ -16,7 +16,11 @@ export const JiraGetImportDetail: React.FC = observer(() => {
const router = useRouter();
const { workspaceSlug } = router.query;
const { project: projectStore, commandPalette: commandPaletteStore, trackEvent: { setTrackElement } } = useMobxStore();
const {
project: projectStore,
commandPalette: commandPaletteStore,
trackEvent: { setTrackElement },
} = useMobxStore();
const projects = workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : undefined;
const {
@ -31,10 +35,8 @@ export const JiraGetImportDetail: React.FC = observer(() => {
<h3 className="font-semibold">Jira Personal Access Token</h3>
<p className="text-sm text-custom-text-200">
Get to know your access token by navigating to{" "}
<Link href="https://id.atlassian.com/manage-profile/security/api-tokens">
<a className="text-custom-primary underline" target="_blank" rel="noreferrer">
Atlassian Settings
</a>
<Link href="https://id.atlassian.com/manage-profile/security/api-tokens" target="_blank" rel="noreferrer">
<span className="text-custom-primary underline">Atlassian Settings</span>
</Link>
</p>
</div>
@ -192,7 +194,7 @@ export const JiraGetImportDetail: React.FC = observer(() => {
type="button"
onClick={() => {
setTrackElement("JIRA_IMPORT_DETAIL");
commandPaletteStore.toggleCreateProjectModal(true)
commandPaletteStore.toggleCreateProjectModal(true);
}}
className="flex cursor-pointer select-none items-center space-x-2 truncate rounded px-1 py-1.5 text-custom-text-200"
>

View File

@ -5,7 +5,7 @@ import { useRouter } from "next/router";
import { mutate } from "swr";
import { FormProvider, useForm } from "react-hook-form";
// icons
import { ArrowLeft, Check, List, Settings, Users2 } from "lucide-react";
import { ArrowLeft, Check, List, Settings } from "lucide-react";
// services
import { JiraImporterService } from "services/integrations";
// fetch keys
@ -100,12 +100,12 @@ export const JiraImporterRoot: React.FC<Props> = () => {
return (
<div className="flex h-full flex-col space-y-2 mt-4">
<Link href={`/${workspaceSlug}/settings/imports`}>
<div className="inline-flex cursor-pointer items-center gap-2 text-sm font-medium text-custom-text-200 hover:text-custom-text-100">
<span className="inline-flex cursor-pointer items-center gap-2 text-sm font-medium text-custom-text-200 hover:text-custom-text-100">
<div>
<ArrowLeft className="h-3 w-3" />
</div>
<div>Cancel import & go back</div>
</div>
</span>
</Link>
<div className="flex h-full flex-col space-y-4 rounded-[10px] border border-custom-border-200 bg-custom-background-100 p-4">

View File

@ -105,11 +105,11 @@ export const IssueActivitySection: React.FC<Props> = ({
<span className="text-gray font-medium">{activityItem.actor_detail.first_name} Bot</span>
) : (
<Link href={`/${workspaceSlug}/profile/${activityItem.actor_detail.id}`}>
<a className="text-gray font-medium">
<span className="text-gray font-medium">
{activityItem.actor_detail.is_bot
? activityItem.actor_detail.first_name
: activityItem.actor_detail.display_name}
</a>
</span>
</Link>
)}{" "}
{message}{" "}

View File

@ -59,8 +59,8 @@ export const IssueAttachments = () => {
key={file.id}
className="flex h-[60px] items-center justify-between gap-1 rounded-md border-[2px] border-custom-border-200 bg-custom-background-100 px-4 py-2 text-sm"
>
<Link href={file.asset}>
<a target="_blank">
<Link href={file.asset} target="_blank">
<span>
<div className="flex items-center gap-3">
<div className="h-7 w-7">{getFileIcon(getFileExtension(file.asset))}</div>
<div className="flex flex-col gap-1">
@ -85,7 +85,7 @@ export const IssueAttachments = () => {
</div>
</div>
</div>
</a>
</span>
</Link>
<button

View File

@ -2,7 +2,7 @@ import { ChangeEvent, FC, useCallback, useEffect, useState } from "react";
import { Controller, useForm } from "react-hook-form";
// hooks
import useReloadConfirmations from "hooks/use-reload-confirmation";
import { useDebouncedCallback } from "use-debounce";
import debounce from "lodash/debounce";
// components
import { TextArea } from "@plane/ui";
import { RichTextEditor } from "@plane/rich-text-editor";
@ -93,7 +93,7 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = (props) => {
});
}, [issue, reset]);
const debouncedFormSave = useDebouncedCallback(async () => {
const debouncedFormSave = debounce(async () => {
handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting("submitted"));
}, 1500);

View File

@ -7,12 +7,8 @@ import { EmptyState } from "components/common";
// assets
import emptyIssue from "public/empty-state/issue.svg";
import { EProjectStore } from "store/command-palette.store";
import { useRouter } from "next/router";
export const ProjectViewEmptyState: React.FC = observer(() => {
const router = useRouter();
const { viewId } = router.query as { viewId: string };
const {
commandPalette: commandPaletteStore,
trackEvent: { setTrackElement },

View File

@ -3,11 +3,10 @@ import { PlusIcon } from "lucide-react";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// components
import { EmptyState } from "components/common";
import { NewEmptyState } from "components/common/new-empty-state";
// assets
import emptyIssue from "public/empty-state/empty_issues.webp";
import { EProjectStore } from "store/command-palette.store";
import { NewEmptyState } from "components/common/new-empty-state";
export const ProjectEmptyState: React.FC = observer(() => {
const {

View File

@ -1,4 +1,3 @@
import { useEffect } from "react";
import { useRouter } from "next/router";
import { observer } from "mobx-react-lite";

View File

@ -2,7 +2,7 @@ import React, { useState } from "react";
import { observer } from "mobx-react-lite";
// components
import { FilterHeader, FilterOption } from "components/issues";
import { FilterOption } from "components/issues";
// types
import { IIssueDisplayFilterOptions, TIssueExtraOptions } from "types";
// constants

View File

@ -10,7 +10,6 @@ import { KanbanIssueBlocksList, KanBanQuickAddIssueForm } from "components/issue
import { IIssueDisplayProperties, IIssue, IState } from "types";
// constants
import { getValueFromObject } from "constants/issue";
import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
import { EIssueActions } from "../types";
import { IIssueResponse, IGroupedIssues, ISubGroupedIssues, TUnGroupedIssues } from "store/issues/types";
import { EProjectStore } from "store/command-palette.store";

View File

@ -1,8 +1,5 @@
import React, { FC } from "react";
import { useRouter } from "next/router";
// services
import { ModuleService } from "services/module.service";
import { IssueService } from "services/issue";
// components
import { CustomMenu } from "@plane/ui";
import { CreateUpdateIssueModal } from "components/issues/modal";

View File

@ -1,6 +1,5 @@
import { FC } from "react";
import { observer } from "mobx-react-lite";
import { AlertCircle, SignalHigh, SignalMedium, SignalLow, Ban } from "lucide-react";
// components
import { HeaderGroupByCard } from "./group-by-card";
import { HeaderSubGroupByCard } from "./sub-group-by-card";

View File

@ -81,7 +81,7 @@ export const KanBanQuickAddIssueForm: React.FC<IKanBanQuickAddIssueForm> = obser
handleSubmit,
setFocus,
register,
formState: { errors, isSubmitting },
formState: { isSubmitting },
} = useForm<IIssue>({ defaultValues });
useEffect(() => {

View File

@ -4,7 +4,7 @@ import { ListGroupByHeaderRoot } from "./headers/group-by-root";
import { IssueBlocksList, ListQuickAddIssueForm } from "components/issues";
// types
import { IIssue, IIssueDisplayProperties, IIssueLabel, IProject, IState, IUserLite } from "types";
import { IIssueResponse, IGroupedIssues, TUnGroupedIssues, ViewFlags } from "store/issues/types";
import { IIssueResponse, IGroupedIssues, TUnGroupedIssues } from "store/issues/types";
import { EIssueActions } from "../types";
// constants
import { getValueFromObject } from "constants/issue";

View File

@ -10,7 +10,6 @@ import { Avatar, AvatarGroup, Tooltip } from "@plane/ui";
import { Placement } from "@popperjs/core";
export interface IIssuePropertyAssignee {
view?: "profile" | "workspace" | "project";
projectId: string | null;
value: string[] | string;
onChange: (data: string[]) => void;
@ -26,7 +25,6 @@ export interface IIssuePropertyAssignee {
export const IssuePropertyAssignee: React.FC<IIssuePropertyAssignee> = observer((props) => {
const {
view,
projectId,
value,
onChange,

View File

@ -12,7 +12,6 @@ import { Placement } from "@popperjs/core";
import { RootStore } from "store/root";
export interface IIssuePropertyLabels {
view?: "profile" | "workspace" | "project";
projectId: string | null;
value: string[];
onChange: (data: string[]) => void;
@ -28,7 +27,6 @@ export interface IIssuePropertyLabels {
export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((props) => {
const {
view,
projectId,
value,
onChange,

View File

@ -15,7 +15,6 @@ import { Placement } from "@popperjs/core";
import { RootStore } from "store/root";
export interface IIssuePropertyState {
view?: "profile" | "workspace" | "project";
projectId: string | null;
value: any | string | null;
onChange: (state: IState) => void;
@ -29,7 +28,6 @@ export interface IIssuePropertyState {
export const IssuePropertyState: React.FC<IIssuePropertyState> = observer((props) => {
const {
view,
projectId,
value,
onChange,

View File

@ -93,11 +93,11 @@ export const IssueActivityCard: FC<IssueActivityCard> = (props) => {
<span className="text-gray font-medium">{activityItem.actor_detail.first_name} Bot</span>
) : (
<Link href={`/${workspaceSlug}/profile/${activityItem.actor_detail.id}`}>
<a className="text-gray font-medium">
<span className="text-gray font-medium">
{activityItem.actor_detail.is_bot
? activityItem.actor_detail.first_name
: activityItem.actor_detail.display_name}
</a>
</span>
</Link>
)}{" "}
{message}{" "}

View File

@ -6,7 +6,7 @@ import { RichTextEditor } from "@plane/rich-text-editor";
import { TextArea } from "@plane/ui";
import { IssueReaction } from "./reactions";
// hooks
import { useDebouncedCallback } from "use-debounce";
import debounce from "lodash/debounce";
import useReloadConfirmations from "hooks/use-reload-confirmation";
import useEditorSuggestions from "hooks/use-editor-suggestions";
// types
@ -74,7 +74,7 @@ export const PeekOverviewIssueDetails: FC<IPeekOverviewIssueDetails> = (props) =
}
}, [issueTitleCurrentValue, localTitleValue]);
const debouncedFormSave = useDebouncedCallback(async () => {
const debouncedFormSave = debounce(async () => {
handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting("submitted"));
}, 1500);

View File

@ -280,7 +280,7 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
await issueDraftService
.createDraftIssue(workspaceSlug as string, activeProject ?? "", payload)
.then((res) => {
.then(() => {
setToastAlert({
type: "success",
title: "Success!",

View File

@ -139,7 +139,7 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
)}
<DeleteModuleModal data={module} isOpen={deleteModal} onClose={() => setDeleteModal(false)} />
<Link href={`/${workspaceSlug}/projects/${module.project}/modules/${module.id}`}>
<a className="flex flex-col justify-between p-4 h-44 w-full min-w-[250px] text-sm rounded bg-custom-background-100 border border-custom-border-100 hover:shadow-md">
<span className="flex flex-col justify-between p-4 h-44 w-full min-w-[250px] text-sm rounded bg-custom-background-100 border border-custom-border-100 hover:shadow-md">
<div>
<div className="flex items-center justify-between gap-2">
<Tooltip tooltipContent={module.name} position="top">
@ -249,7 +249,7 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
</div>
</div>
</div>
</a>
</span>
</Link>
</>
);

View File

@ -128,7 +128,7 @@ export const ModuleListItem: React.FC<Props> = observer((props) => {
)}
<DeleteModuleModal data={module} isOpen={deleteModal} onClose={() => setDeleteModal(false)} />
<Link href={`/${workspaceSlug}/projects/${module.project}/modules/${module.id}`}>
<a className="group flex items-center justify-between gap-5 px-5 py-6 h-16 w-full text-sm bg-custom-background-100 border-b border-custom-border-100 hover:bg-custom-background-90">
<span className="group flex items-center justify-between gap-5 px-5 py-6 h-16 w-full text-sm bg-custom-background-100 border-b border-custom-border-100 hover:bg-custom-background-90">
<div className="flex items-center gap-3 w-full truncate">
<div className="flex items-center gap-4 truncate">
<span className="flex-shrink-0">
@ -225,7 +225,7 @@ export const ModuleListItem: React.FC<Props> = observer((props) => {
</CustomMenu.MenuItem>
</CustomMenu>
</div>
</a>
</span>
</Link>
</>
);

View File

@ -7,7 +7,6 @@ import { useMobxStore } from "lib/mobx/store-provider";
import useLocalStorage from "hooks/use-local-storage";
// components
import { ModuleCardItem, ModuleListItem, ModulePeekOverview, ModulesListGanttChartView } from "components/modules";
import { EmptyState } from "components/common";
// ui
import { Loader } from "@plane/ui";
// assets

View File

@ -32,14 +32,12 @@ export const Invitations: React.FC<Props> = (props) => {
const {
workspace: workspaceStore,
user: { currentUser, updateCurrentUser },
trackEvent: { postHogEventTracker }
trackEvent: { postHogEventTracker },
} = useMobxStore();
const {
data: invitations,
mutate: mutateInvitations,
isLoading,
} = useSWR(USER_WORKSPACE_INVITATIONS, () => workspaceService.userWorkspaceInvitations());
const { data: invitations, mutate: mutateInvitations } = useSWR(USER_WORKSPACE_INVITATIONS, () =>
workspaceService.userWorkspaceInvitations()
);
const handleInvitation = (workspace_invitation: IWorkspaceMemberInvitation, action: "accepted" | "withdraw") => {
if (action === "accepted") {
@ -74,7 +72,8 @@ export const Invitations: React.FC<Props> = (props) => {
.catch((error) => {
console.log(error);
postHogEventTracker("WORKSPACE_USER_INVITE_ACCEPT", { state: "FAILED" });
}).finally(() => setIsJoiningWorkspaces(false));
})
.finally(() => setIsJoiningWorkspaces(false));
};
return invitations && invitations.length > 0 ? (
@ -89,10 +88,11 @@ export const Invitations: React.FC<Props> = (props) => {
return (
<div
key={invitation.id}
className={`flex cursor-pointer items-center gap-2 border p-3.5 rounded ${isSelected
? "border-custom-primary-100"
: "border-onboarding-border-200 hover:bg-onboarding-background-300/30"
}`}
className={`flex cursor-pointer items-center gap-2 border p-3.5 rounded ${
isSelected
? "border-custom-primary-100"
: "border-onboarding-border-200 hover:bg-onboarding-background-300/30"
}`}
onClick={() => handleInvitation(invitation, isSelected ? "withdraw" : "accepted")}
>
<div className="flex-shrink-0">

View File

@ -20,7 +20,7 @@ export const JoinWorkspaces: React.FC<Props> = ({ stepChange, setTryDiffAccount
control,
setValue,
watch,
formState: { errors, isSubmitting, isValid },
formState: { errors, isSubmitting },
} = useForm<IWorkspace>({
defaultValues: {
name: "",

View File

@ -1,5 +1,4 @@
import { useState } from "react";
import Image from "next/image";
import { useRouter } from "next/router";
import useSWR from "swr";
import { observer } from "mobx-react-lite";
@ -9,9 +8,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
import { TourRoot } from "components/onboarding";
import { UserGreetingsView } from "components/user";
import { CompletedIssuesGraph, IssuesList, IssuesPieChart, IssuesStats } from "components/workspace";
import { Button } from "@plane/ui";
// images
import emptyDashboard from "public/empty-state/dashboard.svg";
import { NewEmptyState } from "components/common/new-empty-state";
import emptyProject from "public/empty-state/dashboard_empty_project.webp";

View File

@ -157,7 +157,7 @@ export const PagesListItem: FC<IPagesListItem> = observer((props) => {
<DeletePageModal isOpen={deletePageModal} onClose={() => setDeletePageModal(false)} data={page} />
<li>
<Link href={`/${workspaceSlug}/projects/${projectId}/pages/${page.id}`}>
<a>
<span>
<div className="relative rounded p-4 text-custom-text-200 hover:bg-custom-background-80">
<div className="flex items-center justify-between">
<div className="flex overflow-hidden items-center gap-2">
@ -295,7 +295,7 @@ export const PagesListItem: FC<IPagesListItem> = observer((props) => {
</div>
</div>
</div>
</a>
</span>
</Link>
</li>
</>

View File

@ -50,7 +50,7 @@ export const ProfileNavbar: React.FC<Props> = (props) => {
<div className="flex items-center overflow-x-scroll">
{tabsList.map((tab) => (
<Link key={tab.route} href={`/${workspaceSlug}/profile/${userId}/${tab.route}`}>
<a
<span
className={`border-b-2 p-4 text-sm font-medium outline-none whitespace-nowrap ${
router.pathname === tab.selected
? "border-custom-primary-100 text-custom-primary-100"
@ -58,7 +58,7 @@ export const ProfileNavbar: React.FC<Props> = (props) => {
}`}
>
{tab.label}
</a>
</span>
</Link>
))}
</div>

View File

@ -43,7 +43,7 @@ export const ProfileStats: React.FC<Props> = ({ userProfile }) => {
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{overviewCards.map((card) => (
<Link key={card.route} href={`/${workspaceSlug}/profile/${userId}/${card.route}`}>
<a className="flex items-center gap-3 p-4 rounded border border-custom-border-100 whitespace-nowrap">
<span className="flex items-center gap-3 p-4 rounded border border-custom-border-100 whitespace-nowrap">
<div className="h-11 w-11 bg-custom-background-90 rounded grid place-items-center">
<card.icon className="h-5 w-5" />
</div>
@ -51,7 +51,7 @@ export const ProfileStats: React.FC<Props> = ({ userProfile }) => {
<p className="text-custom-text-400 text-sm">{card.title}</p>
<p className="text-xl font-semibold">{card.value}</p>
</div>
</a>
</span>
</Link>
))}
</div>

View File

@ -68,9 +68,9 @@ export const ProfileSidebar = () => {
{user?.id === userId && (
<div className="absolute top-3.5 right-3.5 h-5 w-5 bg-white rounded grid place-items-center">
<Link href="/profile">
<a className="grid place-items-center text-black">
<span className="grid place-items-center text-black">
<Pencil className="h-3 w-3" />
</a>
</span>
</Link>
</div>
)}

View File

@ -4,12 +4,10 @@ import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider";
// components
import { ProjectCard } from "components/project";
import { EmptyState } from "components/project/empty-state";
import { Loader } from "@plane/ui";
// images
import emptyProject from "public/empty-state/empty_project.webp";
// icons
import { Plus } from "lucide-react";
import { NewEmptyState } from "components/common/new-empty-state";
export interface IProjectCardList {

View File

@ -28,7 +28,7 @@ export const EmptyState: React.FC<Props> = ({
}) => (
<div className="flex items-center lg:p-20 md:px-10 px-5 justify-center h-full w-full">
<div className="relative h-full w-full max-w-6xl">
<Image src={image} className="w-52 sm:w-60" alt={primaryButton?.text} layout="fill" />
<Image src={image} className="w-52 sm:w-60" alt={primaryButton?.text ?? ""} layout="fill" />
</div>
<div className="absolute pt-[30vh] md:pt-[35vh] lg:pt-[45vh] text-center flex flex-col items-center w-full">
<h6 className="text-xl font-semibold mt-6">{title}</h6>

View File

@ -76,27 +76,27 @@ export const ProjectMemberListItem: React.FC<Props> = observer((props) => {
<div className="flex items-center gap-x-4 gap-y-2">
{memberDetails.avatar && memberDetails.avatar !== "" ? (
<Link href={`/${workspaceSlug}/profile/${memberDetails.id}`}>
<a className="relative flex h-10 w-10 items-center justify-center rounded p-4 capitalize text-white">
<span className="relative flex h-10 w-10 items-center justify-center rounded p-4 capitalize text-white">
<img
src={memberDetails.avatar}
alt={memberDetails.display_name || memberDetails.email}
className="absolute top-0 left-0 h-full w-full object-cover rounded"
/>
</a>
</span>
</Link>
) : (
<Link href={`/${workspaceSlug}/profile/${memberDetails.id}`}>
<a className="relative flex h-10 w-10 items-center justify-center rounded p-4 capitalize bg-gray-700 text-white">
<span className="relative flex h-10 w-10 items-center justify-center rounded p-4 capitalize bg-gray-700 text-white">
{(memberDetails.display_name ?? memberDetails.email ?? "?")[0]}
</a>
</span>
</Link>
)}
<div>
<Link href={`/${workspaceSlug}/profile/${memberDetails.id}`}>
<a className="text-sm font-medium">
<span className="text-sm font-medium">
{memberDetails.first_name} {memberDetails.last_name}
</a>
</span>
</Link>
<div className="flex items-center">
<p className="text-xs text-custom-text-300">{memberDetails.display_name}</p>

View File

@ -12,8 +12,6 @@ import { Avatar, Button, CustomSelect, CustomSearchSelect } from "@plane/ui";
import { ProjectMemberService } from "services/project";
// hooks
import useToast from "hooks/use-toast";
// helpers
import { trackEvent } from "helpers/event-tracker.helper";
// types
import { IProjectMember, TUserProjectRole } from "types";
// constants
@ -58,7 +56,7 @@ export const SendProjectInvitationModal: React.FC<Props> = observer((props) => {
const {
user: { currentProjectRole },
workspaceMember: { workspaceMembers },
trackEvent: { postHogEventTracker }
trackEvent: { postHogEventTracker },
} = useMobxStore();
const {
@ -94,22 +92,16 @@ export const SendProjectInvitationModal: React.FC<Props> = observer((props) => {
type: "success",
message: "Member added successfully",
});
postHogEventTracker(
'PROJECT_MEMBER_INVITE',
{
...res,
state: "SUCCESS"
}
);
postHogEventTracker("PROJECT_MEMBER_INVITE", {
...res,
state: "SUCCESS",
});
})
.catch((error) => {
console.log(error);
postHogEventTracker(
'PROJECT_MEMBER_INVITE',
{
state: "FAILED",
}
);
postHogEventTracker("PROJECT_MEMBER_INVITE", {
state: "FAILED",
});
})
.finally(() => {
reset(defaultValues);

View File

@ -75,7 +75,11 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { project, provided, snapshot, handleCopyText, shortContextMenu = false } = props;
// store
const { project: projectStore, theme: themeStore, trackEvent: { setTrackElement } } = useMobxStore();
const {
project: projectStore,
theme: themeStore,
trackEvent: { setTrackElement },
} = useMobxStore();
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
@ -308,7 +312,7 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
return (
<Link key={item.name} href={item.href}>
<a className="block w-full">
<span className="block w-full">
<Tooltip
tooltipContent={`${project?.name}: ${item.name}`}
position="right"
@ -326,7 +330,7 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
{!isCollapsed && item.name}
</div>
</Tooltip>
</a>
</span>
</Link>
);
})}

View File

@ -18,7 +18,6 @@ import type { IState } from "types";
import { STATES_LIST } from "constants/fetch-keys";
// constants
import { GROUP_CHOICES } from "constants/project";
import { stat } from "fs";
type Props = {
data: IState | null;
@ -44,7 +43,10 @@ export const CreateUpdateStateInline: React.FC<Props> = observer((props) => {
const { workspaceSlug, projectId } = router.query;
// store
const { projectState: projectStateStore, trackEvent: { postHogEventTracker, setTrackElement } } = useMobxStore();
const {
projectState: projectStateStore,
trackEvent: { postHogEventTracker, setTrackElement },
} = useMobxStore();
// hooks
const { setToastAlert } = useToast();
@ -95,13 +97,10 @@ export const CreateUpdateStateInline: React.FC<Props> = observer((props) => {
title: "Success!",
message: "State created successfully.",
});
postHogEventTracker(
'STATE_CREATE',
{
...res,
state: "SUCCESS"
}
);
postHogEventTracker("STATE_CREATE", {
...res,
state: "SUCCESS",
});
})
.catch((error) => {
if (error.status === 400)
@ -116,12 +115,9 @@ export const CreateUpdateStateInline: React.FC<Props> = observer((props) => {
title: "Error!",
message: "State could not be created. Please try again.",
});
postHogEventTracker(
'STATE_CREATE',
{
state: "FAILED"
}
);
postHogEventTracker("STATE_CREATE", {
state: "FAILED",
});
});
};
@ -133,13 +129,10 @@ export const CreateUpdateStateInline: React.FC<Props> = observer((props) => {
.then((res) => {
mutate(STATES_LIST(projectId.toString()));
handleClose();
postHogEventTracker(
'STATE_UPDATE',
{
...res,
state: "SUCCESS",
}
);
postHogEventTracker("STATE_UPDATE", {
...res,
state: "SUCCESS",
});
setToastAlert({
type: "success",
title: "Success!",
@ -159,12 +152,9 @@ export const CreateUpdateStateInline: React.FC<Props> = observer((props) => {
title: "Error!",
message: "State could not be updated. Please try again.",
});
postHogEventTracker(
'STATE_UPDATE',
{
state: "FAILED",
}
);
postHogEventTracker("STATE_UPDATE", {
state: "FAILED",
});
});
};
@ -187,8 +177,9 @@ export const CreateUpdateStateInline: React.FC<Props> = observer((props) => {
{({ open }) => (
<>
<Popover.Button
className={`group inline-flex items-center text-base font-medium focus:outline-none ${open ? "text-custom-text-100" : "text-custom-text-200"
}`}
className={`group inline-flex items-center text-base font-medium focus:outline-none ${
open ? "text-custom-text-100" : "text-custom-text-200"
}`}
>
{watch("color") && watch("color") !== "" && (
<span
@ -292,10 +283,14 @@ export const CreateUpdateStateInline: React.FC<Props> = observer((props) => {
<Button variant="neutral-primary" onClick={handleClose}>
Cancel
</Button>
<Button variant="primary" type="submit" loading={isSubmitting} onClick={() => {
setTrackElement("PROJECT_SETTINGS_STATE_PAGE");
}
}>
<Button
variant="primary"
type="submit"
loading={isSubmitting}
onClick={() => {
setTrackElement("PROJECT_SETTINGS_STATE_PAGE");
}}
>
{isSubmitting ? (data ? "Updating..." : "Creating...") : data ? "Update" : "Create"}
</Button>
</form>

View File

@ -28,7 +28,10 @@ export const DeleteStateModal: React.FC<Props> = observer((props) => {
const { workspaceSlug } = router.query;
// store
const { projectState: projectStateStore, trackEvent: { postHogEventTracker } } = useMobxStore();
const {
projectState: projectStateStore,
trackEvent: { postHogEventTracker },
} = useMobxStore();
// states
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
@ -47,13 +50,10 @@ export const DeleteStateModal: React.FC<Props> = observer((props) => {
await projectStateStore
.deleteState(workspaceSlug.toString(), data.project, data.id)
.then((res) => {
postHogEventTracker(
'STATE_DELETE',
{
state: "SUCCESS"
}
);
.then(() => {
postHogEventTracker("STATE_DELETE", {
state: "SUCCESS",
});
handleClose();
})
.catch((err) => {
@ -70,12 +70,9 @@ export const DeleteStateModal: React.FC<Props> = observer((props) => {
title: "Error!",
message: "State could not be deleted. Please try again.",
});
postHogEventTracker(
'STATE_DELETE',
{
state: "FAILED"
}
)
postHogEventTracker("STATE_DELETE", {
state: "FAILED",
});
})
.finally(() => {
setIsDeleteLoading(false);

View File

@ -1,39 +0,0 @@
import React, { useEffect, useState } from "react";
export const CircularProgress = ({ progress }: { progress: number }) => {
const [circumference, setCircumference] = useState(0);
useEffect(() => {
const radius = 40;
const calcCircumference = 2 * Math.PI * radius;
setCircumference(calcCircumference);
}, []);
const progressAngle = (progress / 100) * 360 >= 360 ? 359.9 : (progress / 100) * 360;
const progressX = 50 + Math.cos((progressAngle - 90) * (Math.PI / 180)) * 40;
const progressY = 50 + Math.sin((progressAngle - 90) * (Math.PI / 180)) * 40;
return (
<div className="relative h-5 w-5">
<svg className="absolute top-0 left-0" viewBox="0 0 100 100">
<circle
className="stroke-current"
cx="50"
cy="50"
r="40"
strokeWidth="12"
fill="none"
strokeDasharray={`${circumference} ${circumference}`}
/>
<path
className="fill-current"
d={`M50 10
A40 40 0 ${progress > 50 ? 1 : 0} 1 ${progressX} ${progressY}
L50 50 Z`}
strokeWidth="12"
strokeLinecap="round"
/>
</svg>
</div>
);
};

View File

@ -1,123 +0,0 @@
import React, { useEffect, useRef } from "react";
import Link from "next/link";
// hooks
import useOutsideClickDetector from "hooks/use-outside-click-detector";
type Props = {
clickEvent: React.MouseEvent | null;
children: React.ReactNode;
title?: string | JSX.Element;
isOpen: boolean;
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
};
const ContextMenu = ({ clickEvent, children, title, isOpen, setIsOpen }: Props) => {
const contextMenuRef = useRef<HTMLDivElement>(null);
// Close the context menu when clicked outside
useOutsideClickDetector(contextMenuRef, () => {
if (isOpen) setIsOpen(false);
});
useEffect(() => {
const hideContextMenu = () => {
if (isOpen) setIsOpen(false);
};
const escapeKeyEvent = (e: KeyboardEvent) => {
if (e.key === "Escape") hideContextMenu();
};
window.addEventListener("click", hideContextMenu);
window.addEventListener("keydown", escapeKeyEvent);
return () => {
window.removeEventListener("click", hideContextMenu);
window.removeEventListener("keydown", escapeKeyEvent);
};
}, [isOpen, setIsOpen]);
useEffect(() => {
const contextMenu = contextMenuRef.current;
if (contextMenu && isOpen) {
const contextMenuWidth = contextMenu.clientWidth;
const contextMenuHeight = contextMenu.clientHeight;
const clickX = clickEvent?.pageX || 0;
const clickY = clickEvent?.pageY || 0;
let top = clickY;
// check if there's enough space at the bottom, otherwise show at the top
if (clickY + contextMenuHeight > window.innerHeight) top = clickY - contextMenuHeight;
// check if there's enough space on the right, otherwise show on the left
let left = clickX;
if (clickX + contextMenuWidth > window.innerWidth) left = clickX - contextMenuWidth;
contextMenu.style.top = `${top}px`;
contextMenu.style.left = `${left}px`;
}
}, [clickEvent, isOpen]);
return (
<div
className={`fixed z-50 top-0 left-0 h-full w-full ${
isOpen ? "pointer-events-auto opacity-100" : "pointer-events-none opacity-0"
}`}
>
<div
ref={contextMenuRef}
className={`fixed z-50 flex min-w-[8rem] flex-col items-stretch gap-1 rounded-md border border-custom-border-200 bg-custom-background-90 p-2 text-xs shadow-lg`}
>
{title && (
<h4 className="border-b border-custom-border-200 px-1 py-1 pb-2 text-[0.8rem] font-medium">{title}</h4>
)}
{children}
</div>
</div>
);
};
type MenuItemProps = {
children: JSX.Element | string;
renderAs?: "button" | "a";
href?: string;
onClick?: () => void;
className?: string;
Icon?: any;
};
const MenuItem: React.FC<MenuItemProps> = ({ children, renderAs, href = "", onClick, className = "", Icon }) => (
<>
{renderAs === "a" ? (
<Link href={href}>
<a
className={`${className} flex w-full items-center gap-2 rounded px-1 py-1.5 text-left text-custom-text-200 hover:bg-custom-background-80`}
>
<>
{Icon && <Icon />}
{children}
</>
</a>
</Link>
) : (
<button
type="button"
className={`${className} flex w-full items-center gap-2 rounded px-1 py-1.5 text-left text-custom-text-200 hover:bg-custom-background-80`}
onClick={onClick}
>
<>
{Icon && <Icon height={12} width={12} />}
{children}
</>
</button>
)}
</>
);
ContextMenu.Item = MenuItem;
export { ContextMenu };

View File

@ -1,162 +0,0 @@
import React, { useState } from "react";
import Link from "next/link";
// react-poppper
import { usePopper } from "react-popper";
// headless ui
import { Menu } from "@headlessui/react";
// ui
import { DropdownProps } from "components/ui";
// icons
import { ChevronDown, MoreHorizontal } from "lucide-react";
export type CustomMenuProps = DropdownProps & {
children: React.ReactNode;
ellipsis?: boolean;
noBorder?: boolean;
verticalEllipsis?: boolean;
menuButtonOnClick?: (...args: any) => void;
};
const CustomMenu = ({
buttonClassName = "",
customButtonClassName = "",
placement,
children,
className = "",
customButton,
disabled = false,
ellipsis = false,
label,
maxHeight = "md",
noBorder = false,
noChevron = false,
optionsClassName = "",
verticalEllipsis = false,
width = "auto",
menuButtonOnClick,
}: CustomMenuProps) => {
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
const { styles, attributes } = usePopper(referenceElement, popperElement, {
placement: placement ?? "bottom-start",
});
return (
<Menu as="div" className={`relative w-min text-left ${className}`}>
{({ open }) => (
<>
{customButton ? (
<Menu.Button as={React.Fragment}>
<button
ref={setReferenceElement}
type="button"
onClick={menuButtonOnClick}
className={customButtonClassName}
>
{customButton}
</button>
</Menu.Button>
) : (
<>
{ellipsis || verticalEllipsis ? (
<Menu.Button as={React.Fragment}>
<button
ref={setReferenceElement}
type="button"
onClick={menuButtonOnClick}
disabled={disabled}
className={`relative grid place-items-center rounded p-1 text-custom-text-200 hover:text-custom-text-100 outline-none ${
disabled ? "cursor-not-allowed" : "cursor-pointer hover:bg-custom-background-80"
} ${buttonClassName}`}
>
<MoreHorizontal className={`h-3.5 w-3.5 ${verticalEllipsis ? "rotate-90" : ""}`} />
</button>
</Menu.Button>
) : (
<Menu.Button as={React.Fragment}>
<button
ref={setReferenceElement}
type="button"
className={`flex items-center justify-between gap-1 rounded-md px-2.5 py-1 text-xs whitespace-nowrap duration-300 ${
open ? "bg-custom-background-90 text-custom-text-100" : "text-custom-text-200"
} ${noBorder ? "" : "border border-custom-border-300 shadow-sm focus:outline-none"} ${
disabled
? "cursor-not-allowed text-custom-text-200"
: "cursor-pointer hover:bg-custom-background-80"
} ${buttonClassName}`}
>
{label}
{!noChevron && <ChevronDown className="h-3.5 w-3.5" />}
</button>
</Menu.Button>
)}
</>
)}
<Menu.Items>
<div
className={`z-10 overflow-y-scroll whitespace-nowrap rounded-md border border-custom-border-300 p-1 text-xs shadow-custom-shadow-rg focus:outline-none bg-custom-background-90 my-1 ${
maxHeight === "lg"
? "max-h-60"
: maxHeight === "md"
? "max-h-48"
: maxHeight === "rg"
? "max-h-36"
: maxHeight === "sm"
? "max-h-28"
: ""
} ${width === "auto" ? "min-w-[8rem] whitespace-nowrap" : width} ${optionsClassName}`}
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
>
<div className="py-1">{children}</div>
</div>
</Menu.Items>
</>
)}
</Menu>
);
};
type MenuItemProps = {
children: React.ReactNode;
renderAs?: "button" | "a";
href?: string;
onClick?: (args?: any) => void;
className?: string;
};
const MenuItem: React.FC<MenuItemProps> = ({ children, renderAs, href, onClick, className = "" }) => (
<Menu.Item as="div">
{({ active, close }) =>
renderAs === "a" ? (
<Link href={href ?? ""}>
<a
className={`inline-block 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" : ""
} ${className}`}
onClick={close}
>
{children}
</a>
</Link>
) : (
<button
type="button"
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" : ""
} ${className}`}
onClick={onClick}
>
{children}
</button>
)
}
</Menu.Item>
);
CustomMenu.MenuItem = MenuItem;
export { CustomMenu };

View File

@ -1,188 +0,0 @@
import React, { useState } from "react";
// react-popper
import { usePopper } from "react-popper";
// headless ui
import { Combobox } from "@headlessui/react";
// icons
import { Check, ChevronDown, Search } from "lucide-react";
// types
import { DropdownProps } from "./types";
export type CustomSearchSelectProps = DropdownProps & {
footerOption?: JSX.Element;
onChange: any;
options:
| {
value: any;
query: string;
content: React.ReactNode;
}[]
| undefined;
} & (
| { multiple?: false; value: any } // if multiple is false, value can be anything
| {
multiple?: true;
value: any[] | null; // if multiple is true, value should be an array
}
);
export const CustomSearchSelect = ({
customButtonClassName = "",
buttonClassName = "",
className = "",
customButton,
placement,
disabled = false,
footerOption,
input = false,
label,
maxHeight = "md",
multiple = false,
noChevron = false,
onChange,
options,
onOpen,
optionsClassName = "",
value,
width = "auto",
}: CustomSearchSelectProps) => {
const [query, setQuery] = useState("");
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
const { styles, attributes } = usePopper(referenceElement, popperElement, {
placement: placement ?? "bottom-start",
});
const filteredOptions =
query === "" ? options : options?.filter((option) => option.query.toLowerCase().includes(query.toLowerCase()));
const props: any = {
value,
onChange,
disabled,
};
if (multiple) props.multiple = true;
return (
<Combobox as="div" className={`relative flex-shrink-0 text-left ${className}`} {...props}>
{({ open }: { open: boolean }) => {
if (open && onOpen) onOpen();
return (
<>
{customButton ? (
<Combobox.Button as={React.Fragment}>
<button
ref={setReferenceElement}
type="button"
className={`flex items-center justify-between gap-1 w-full text-xs ${
disabled
? "cursor-not-allowed text-custom-text-200"
: "cursor-pointer hover:bg-custom-background-80"
} ${customButtonClassName}`}
>
{customButton}
</button>
</Combobox.Button>
) : (
<Combobox.Button as={React.Fragment}>
<button
ref={setReferenceElement}
type="button"
className={`flex items-center justify-between gap-1 w-full rounded-md border border-custom-border-300 shadow-sm duration-300 focus:outline-none ${
input ? "px-3 py-2 text-sm" : "px-2.5 py-1 text-xs"
} ${
disabled
? "cursor-not-allowed text-custom-text-200"
: "cursor-pointer hover:bg-custom-background-80"
} ${buttonClassName}`}
>
{label}
{!noChevron && !disabled && <ChevronDown className="h-3 w-3" aria-hidden="true" />}
</button>
</Combobox.Button>
)}
<Combobox.Options as={React.Fragment}>
<div
className={`z-10 min-w-[10rem] border border-custom-border-300 p-2 rounded-md bg-custom-background-90 text-xs shadow-custom-shadow-rg focus:outline-none my-1 ${
width === "auto" ? "min-w-[8rem] whitespace-nowrap" : width
} ${optionsClassName}`}
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
>
<div className="flex w-full items-center justify-start rounded-sm border-[0.6px] border-custom-border-200 bg-custom-background-90 px-2">
<Search className="h-3 w-3 text-custom-text-200" />
<Combobox.Input
className="w-full bg-transparent py-1 px-2 text-xs text-custom-text-200 placeholder:text-custom-text-400 focus:outline-none"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Type to search..."
displayValue={(assigned: any) => assigned?.name}
/>
</div>
<div
className={`mt-2 space-y-1 ${
maxHeight === "lg"
? "max-h-60"
: maxHeight === "md"
? "max-h-48"
: maxHeight === "rg"
? "max-h-36"
: maxHeight === "sm"
? "max-h-28"
: ""
} overflow-y-scroll`}
>
{filteredOptions ? (
filteredOptions.length > 0 ? (
filteredOptions.map((option) => (
<Combobox.Option
key={option.value}
value={option.value}
className={({ active, selected }) =>
`flex items-center justify-between gap-2 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"}`
}
>
{({ active, selected }) => (
<>
{option.content}
{multiple ? (
<div
className={`flex items-center justify-center rounded border border-custom-border-400 p-0.5 ${
active || selected ? "opacity-100" : "opacity-0"
}`}
>
<Check className={`h-3 w-3 ${selected ? "opacity-100" : "opacity-0"}`} />
</div>
) : (
<Check className={`h-3 w-3 ${selected ? "opacity-100" : "opacity-0"}`} />
)}
</>
)}
</Combobox.Option>
))
) : (
<span className="flex items-center gap-2 p-1">
<p className="text-left text-custom-text-200 ">No matching results</p>
</span>
)
) : (
<p className="text-center text-custom-text-200">Loading...</p>
)}
</div>
{footerOption}
</div>
</Combobox.Options>
</>
);
}}
</Combobox>
);
};

View File

@ -1,130 +0,0 @@
import React, { useState } from "react";
// react-popper
import { usePopper } from "react-popper";
// headless ui
import { Listbox } from "@headlessui/react";
// icons
import { Check, ChevronDown } from "lucide-react";
// types
import { DropdownProps } from "./types";
export type CustomSelectProps = DropdownProps & {
children: React.ReactNode;
value: any;
onChange: any;
};
const CustomSelect = ({
customButtonClassName = "",
buttonClassName = "",
placement,
children,
className = "",
customButton,
disabled = false,
input = false,
label,
maxHeight = "md",
noChevron = false,
onChange,
optionsClassName = "",
value,
width = "auto",
}: CustomSelectProps) => {
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
const { styles, attributes } = usePopper(referenceElement, popperElement, {
placement: placement ?? "bottom-start",
});
return (
<Listbox
as="div"
value={value}
onChange={onChange}
className={`relative flex-shrink-0 text-left ${className}`}
disabled={disabled}
>
<>
{customButton ? (
<Listbox.Button as={React.Fragment}>
<button
ref={setReferenceElement}
type="button"
className={`flex items-center justify-between gap-1 w-full text-xs ${
disabled ? "cursor-not-allowed text-custom-text-200" : "cursor-pointer hover:bg-custom-background-80"
} ${customButtonClassName}`}
>
{customButton}
</button>
</Listbox.Button>
) : (
<Listbox.Button as={React.Fragment}>
<button
ref={setReferenceElement}
type="button"
className={`flex items-center justify-between gap-1 w-full rounded-md border border-custom-border-300 shadow-sm duration-300 focus:outline-none ${
input ? "px-3 py-2 text-sm" : "px-2.5 py-1 text-xs"
} ${
disabled ? "cursor-not-allowed text-custom-text-200" : "cursor-pointer hover:bg-custom-background-80"
} ${buttonClassName}`}
>
{label}
{!noChevron && !disabled && <ChevronDown className="h-3 w-3" aria-hidden="true" />}
</button>
</Listbox.Button>
)}
</>
<Listbox.Options>
<div
className={`z-10 border border-custom-border-300 overflow-y-auto rounded-md bg-custom-background-90 text-xs shadow-custom-shadow-rg focus:outline-none my-1 ${
maxHeight === "lg"
? "max-h-60"
: maxHeight === "md"
? "max-h-48"
: maxHeight === "rg"
? "max-h-36"
: maxHeight === "sm"
? "max-h-28"
: ""
} ${width === "auto" ? "min-w-[8rem] whitespace-nowrap" : width} ${optionsClassName}`}
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
>
<div className="space-y-1 p-2">{children}</div>
</div>
</Listbox.Options>
</Listbox>
);
};
type OptionProps = {
children: React.ReactNode;
value: any;
className?: string;
};
const Option: React.FC<OptionProps> = ({ children, value, className }) => (
<Listbox.Option
value={value}
className={({ active, selected }) =>
`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"
} ${className}`
}
>
{({ selected }) => (
<div className="flex items-center justify-between gap-2">
<div className="flex items-center gap-2">{children}</div>
{selected && <Check className="h-4 w-4 flex-shrink-0" />}
</div>
)}
</Listbox.Option>
);
CustomSelect.Option = Option;
export { CustomSelect };

View File

@ -1,5 +0,0 @@
export * from "./context-menu";
export * from "./custom-menu";
export * from "./custom-search-select";
export * from "./custom-select";
export * from "./types.d";

View File

@ -1,18 +0,0 @@
import { Placement } from "@popperjs/core";
export type DropdownProps = {
customButtonClassName?: string;
buttonClassName?: string;
customButtonClassName?: string;
className?: string;
customButton?: JSX.Element;
disabled?: boolean;
input?: boolean;
label?: string | JSX.Element;
maxHeight?: "sm" | "rg" | "md" | "lg";
noChevron?: boolean;
onOpen?: () => void;
optionsClassName?: string;
width?: "auto" | string;
placement?: Placement;
};

View File

@ -30,10 +30,10 @@ const EmptySpace: React.FC<EmptySpaceProps> = ({ title, description, children, I
{link ? (
<div className="mt-6 flex">
<Link href={link.href}>
<a className="text-sm font-medium text-custom-primary hover:text-custom-primary">
<span className="text-sm font-medium text-custom-primary hover:text-custom-primary">
{link.text}
<span aria-hidden="true"> &rarr;</span>
</a>
</span>
</Link>
</div>
) : null}

View File

@ -1,10 +0,0 @@
import React from "react";
type Props = {
iconName: string;
className?: string;
};
export const Icon: React.FC<Props> = ({ iconName, className = "" }) => (
<span className={`material-symbols-rounded text-sm leading-5 font-light ${className}`}>{iconName}</span>
);

View File

@ -1,23 +1,12 @@
export * from "./dropdowns";
export * from "./graphs";
export * from "./input";
export * from "./text-area";
export * from "./date";
export * from "./datepicker";
export * from "./empty-space";
export * from "./icon";
export * from "./labels-list";
export * from "./linear-progress-indicator";
export * from "./loader";
export * from "./multi-level-dropdown";
export * from "./multi-level-select";
export * from "./progress-bar";
export * from "./spinner";
export * from "./tooltip";
export * from "./toggle-switch";
export * from "./markdown-to-component";
export * from "./product-updates-modal";
export * from "./integration-and-import-export-banner";
export * from "./range-datepicker";
export * from "./circular-progress";
export * from "./profile-empty-state";

View File

@ -1,52 +0,0 @@
import * as React from "react";
// types
import { Props } from "./types";
export const Input: React.FC<Props> = ({
label,
value,
name,
register,
validations,
error,
mode = "primary",
onChange,
className = "",
type,
id,
size = "rg",
fullWidth = true,
...rest
}) => (
<>
{label && (
<label htmlFor={id} className="text-custom-text-200 mb-2">
{label}
</label>
)}
<input
type={type}
id={id}
value={value}
{...(register && register(name ?? "", validations))}
onChange={(e) => {
register && register(name ?? "").onChange(e);
onChange && onChange(e);
}}
className={`block rounded-md bg-transparent text-sm focus:outline-none placeholder-custom-text-400 ${
mode === "primary"
? "rounded-md border border-custom-border-200"
: mode === "transparent"
? "rounded border-none bg-transparent ring-0 transition-all focus:ring-1 focus:ring-custom-primary"
: mode === "trueTransparent"
? "rounded border-none bg-transparent ring-0"
: ""
} ${error ? "border-red-500" : ""} ${error && mode === "primary" ? "bg-red-500/20" : ""} ${
fullWidth ? "w-full" : ""
} ${size === "rg" ? "px-3 py-2" : size === "lg" ? "p-3" : ""} ${className}`}
{...rest}
/>
{error?.message && <div className="text-sm text-red-500">{error.message}</div>}
</>
);

Some files were not shown because too many files have changed in this diff Show More