[WEB-5459] feat(codemods): add function declaration transformer with tests (#8137)
- Add jscodeshift-based codemod to convert arrow function components to function declarations - Support React.FC, observer-wrapped, and forwardRef components - Include comprehensive test suite covering edge cases - Add npm script to run transformer across codebase - Target only .tsx files in source directories, excluding node_modules and declaration files * [WEB-5459] chore: updates after running codemod --------- Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
This commit is contained in:
parent
90866fb925
commit
83fdebf64d
1771 changed files with 17003 additions and 13856 deletions
|
|
@ -1,5 +1,4 @@
|
|||
"use client";
|
||||
|
||||
import React from "react";
|
||||
|
||||
// Minimal shim so code using next/image compiles under React Router + Vite
|
||||
|
|
@ -9,6 +8,8 @@ type NextImageProps = React.ImgHTMLAttributes<HTMLImageElement> & {
|
|||
src: string;
|
||||
};
|
||||
|
||||
const Image: React.FC<NextImageProps> = ({ src, alt = "", ...rest }) => <img src={src} alt={alt} {...rest} />;
|
||||
function Image({ src, alt = "", ...rest }: NextImageProps) {
|
||||
return <img src={src} alt={alt} {...rest} />;
|
||||
}
|
||||
|
||||
export default Image;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { Link as RRLink } from "react-router";
|
||||
import { ensureTrailingSlash } from "./helper";
|
||||
|
|
@ -12,13 +11,8 @@ type NextLinkProps = React.ComponentProps<"a"> & {
|
|||
shallow?: boolean; // next.js prop, ignored
|
||||
};
|
||||
|
||||
const Link: React.FC<NextLinkProps> = ({
|
||||
href,
|
||||
replace,
|
||||
prefetch: _prefetch,
|
||||
scroll: _scroll,
|
||||
shallow: _shallow,
|
||||
...rest
|
||||
}) => <RRLink to={ensureTrailingSlash(href)} replace={replace} {...rest} />;
|
||||
function Link({ href, replace, prefetch: _prefetch, scroll: _scroll, shallow: _shallow, ...rest }: NextLinkProps) {
|
||||
return <RRLink to={ensureTrailingSlash(href)} replace={replace} {...rest} />;
|
||||
}
|
||||
|
||||
export default Link;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
"use client";
|
||||
|
||||
// ui
|
||||
import { Button } from "@plane/propel/button";
|
||||
|
||||
const ErrorPage = () => {
|
||||
function ErrorPage() {
|
||||
const handleRetry = () => {
|
||||
window.location.reload();
|
||||
};
|
||||
|
|
@ -42,6 +41,6 @@ const ErrorPage = () => {
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export default ErrorPage;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { usePublish } from "@/hooks/store/publish";
|
|||
import { useLabel } from "@/hooks/store/use-label";
|
||||
import { useStates } from "@/hooks/store/use-state";
|
||||
|
||||
const IssuesPage = observer(() => {
|
||||
const IssuesPage = observer(function IssuesPage() {
|
||||
// params
|
||||
const params = useParams<{ anchor: string }>();
|
||||
const { anchor } = params;
|
||||
|
|
|
|||
|
|
@ -1,22 +1,23 @@
|
|||
"use client";
|
||||
|
||||
// assets
|
||||
import SomethingWentWrongImage from "@/app/assets/something-went-wrong.svg?url";
|
||||
|
||||
const NotFound = () => (
|
||||
<div className="h-screen w-screen grid place-items-center">
|
||||
<div className="text-center">
|
||||
<div className="mx-auto size-32 md:size-52 grid place-items-center rounded-full bg-custom-background-80">
|
||||
<div className="size-16 md:size-32 grid place-items-center">
|
||||
<img src={SomethingWentWrongImage} alt="Something went wrong" width={128} height={128} />
|
||||
function NotFound() {
|
||||
return (
|
||||
<div className="h-screen w-screen grid place-items-center">
|
||||
<div className="text-center">
|
||||
<div className="mx-auto size-32 md:size-52 grid place-items-center rounded-full bg-custom-background-80">
|
||||
<div className="size-16 md:size-32 grid place-items-center">
|
||||
<img src={SomethingWentWrongImage} alt="Something went wrong" width={128} height={128} />
|
||||
</div>
|
||||
</div>
|
||||
<h1 className="mt-8 md:mt-12 text-xl md:text-3xl font-semibold">That didn{"'"}t work</h1>
|
||||
<p className="mt-2 md:mt-4 text-sm md:text-base">
|
||||
Check the URL you are entering in the browser{"'"}s address bar and try again.
|
||||
</p>
|
||||
</div>
|
||||
<h1 className="mt-8 md:mt-12 text-xl md:text-3xl font-semibold">That didn{"'"}t work</h1>
|
||||
<p className="mt-2 md:mt-4 text-sm md:text-base">
|
||||
Check the URL you are entering in the browser{"'"}s address bar and try again.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
export default NotFound;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { AuthView } from "@/components/views";
|
|||
// hooks
|
||||
import { useUser } from "@/hooks/store/use-user";
|
||||
|
||||
const HomePage = observer(() => {
|
||||
const HomePage = observer(function HomePage() {
|
||||
const { data: currentUser, isAuthenticated, isInitializing } = useUser();
|
||||
const searchParams = useSearchParams();
|
||||
const router = useRouter();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
// plane editor
|
||||
import type { TCallbackMentionComponentProps } from "@plane/editor";
|
||||
|
||||
export const EditorAdditionalMentionsRoot: React.FC<TCallbackMentionComponentProps> = () => null;
|
||||
export function EditorAdditionalMentionsRoot(_props: TCallbackMentionComponentProps) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,4 +6,6 @@ type Props = {
|
|||
publishSettings: PublishStore;
|
||||
};
|
||||
|
||||
export const ViewLayoutsRoot = (_props: Props) => <PageNotFound />;
|
||||
export function ViewLayoutsRoot(_props: Props) {
|
||||
return <PageNotFound />;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,4 +5,6 @@ type Props = {
|
|||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export const ViewNavbarRoot = (props: Props) => <></>;
|
||||
export function ViewNavbarRoot(props: Props) {
|
||||
return <></>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ type TAuthBanner = {
|
|||
handleBannerData?: (bannerData: TAuthErrorInfo | undefined) => void;
|
||||
};
|
||||
|
||||
export const AuthBanner: React.FC<TAuthBanner> = (props) => {
|
||||
export function AuthBanner(props: TAuthBanner) {
|
||||
const { bannerData, handleBannerData } = props;
|
||||
|
||||
if (!bannerData) return <></>;
|
||||
|
|
@ -28,4 +28,4 @@ export const AuthBanner: React.FC<TAuthBanner> = (props) => {
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ const Titles: TAuthHeaderDetails = {
|
|||
},
|
||||
};
|
||||
|
||||
export const AuthHeader: React.FC<TAuthHeader> = (props) => {
|
||||
export function AuthHeader(props: TAuthHeader) {
|
||||
const { authMode } = props;
|
||||
|
||||
const getHeaderSubHeader = (mode: EAuthModes | null): TAuthHeaderContent => {
|
||||
|
|
@ -51,4 +51,4 @@ export const AuthHeader: React.FC<TAuthHeader> = (props) => {
|
|||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import { AuthUniqueCodeForm } from "./unique-code";
|
|||
|
||||
const authService = new SitesAuthService();
|
||||
|
||||
export const AuthRoot: React.FC = observer(() => {
|
||||
export const AuthRoot = observer(function AuthRoot() {
|
||||
// router params
|
||||
const searchParams = useSearchParams();
|
||||
const emailParam = searchParams.get("email") || undefined;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ type TAuthEmailForm = {
|
|||
onSubmit: (data: IEmailCheckData) => Promise<void>;
|
||||
};
|
||||
|
||||
export const AuthEmailForm: React.FC<TAuthEmailForm> = observer((props) => {
|
||||
export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailForm) {
|
||||
const { onSubmit, defaultEmail } = props;
|
||||
// states
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ const defaultValues: TPasswordFormValues = {
|
|||
|
||||
const authService = new AuthService();
|
||||
|
||||
export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
|
||||
export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props) {
|
||||
const { email, nextPath, isSMTPConfigured, handleAuthStep, handleEmailClear, mode } = props;
|
||||
// ref
|
||||
const formRef = useRef<HTMLFormElement>(null);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ const defaultValues: TUniqueCodeFormValues = {
|
|||
code: "",
|
||||
};
|
||||
|
||||
export const AuthUniqueCodeForm: React.FC<TAuthUniqueCodeForm> = (props) => {
|
||||
export function AuthUniqueCodeForm(props: TAuthUniqueCodeForm) {
|
||||
const { mode, email, nextPath, handleEmailClear, generateEmailUniqueCode } = props;
|
||||
// derived values
|
||||
const defaultResetTimerValue = 5;
|
||||
|
|
@ -150,4 +150,4 @@ export const AuthUniqueCodeForm: React.FC<TAuthUniqueCodeForm> = (props) => {
|
|||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ type Props = {
|
|||
isSignUp?: boolean;
|
||||
};
|
||||
|
||||
export const TermsAndConditions: React.FC<Props> = (props) => {
|
||||
export function TermsAndConditions(props: Props) {
|
||||
const { isSignUp = false } = props;
|
||||
return (
|
||||
<span className="flex items-center justify-center py-6">
|
||||
|
|
@ -23,4 +23,4 @@ export const TermsAndConditions: React.FC<Props> = (props) => {
|
|||
</p>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { UserAvatar } from "@/components/issues/navbar/user-avatar";
|
|||
// hooks
|
||||
import { useUser } from "@/hooks/store/use-user";
|
||||
|
||||
export const UserLoggedIn = observer(() => {
|
||||
export const UserLoggedIn = observer(function UserLoggedIn() {
|
||||
// store hooks
|
||||
const { data: user } = useUser();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { useTheme } from "next-themes";
|
|||
import LogoSpinnerDark from "@/app/assets/images/logo-spinner-dark.gif?url";
|
||||
import LogoSpinnerLight from "@/app/assets/images/logo-spinner-light.gif?url";
|
||||
|
||||
export const LogoSpinner = () => {
|
||||
export function LogoSpinner() {
|
||||
const { resolvedTheme } = useTheme();
|
||||
|
||||
const logoSrc = resolvedTheme === "dark" ? LogoSpinnerLight : LogoSpinnerDark;
|
||||
|
|
@ -15,4 +15,4 @@ export const LogoSpinner = () => {
|
|||
<img src={logoSrc} alt="logo" className="h-6 w-auto sm:h-11" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ type TPoweredBy = {
|
|||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export const PoweredBy: React.FC<TPoweredBy> = (props) => {
|
||||
export function PoweredBy(props: TPoweredBy) {
|
||||
// props
|
||||
const { disabled = false } = props;
|
||||
|
||||
|
|
@ -27,4 +27,4 @@ export const PoweredBy: React.FC<TPoweredBy> = (props) => {
|
|||
</div>
|
||||
</a>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ type Props = {
|
|||
logo: TLogoProps;
|
||||
};
|
||||
|
||||
export const ProjectLogo: React.FC<Props> = (props) => {
|
||||
export function ProjectLogo(props: Props) {
|
||||
const { className, logo } = props;
|
||||
|
||||
if (logo.in_use === "icon" && logo.icon)
|
||||
|
|
@ -31,4 +31,4 @@ export const ProjectLogo: React.FC<Props> = (props) => {
|
|||
);
|
||||
|
||||
return <span />;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { EditorAdditionalMentionsRoot } from "@/plane-web/components/editor";
|
|||
// local components
|
||||
import { EditorUserMention } from "./user";
|
||||
|
||||
export const EditorMentionsRoot: React.FC<TCallbackMentionComponentProps> = (props) => {
|
||||
export function EditorMentionsRoot(props: TCallbackMentionComponentProps) {
|
||||
const { entity_identifier, entity_name } = props;
|
||||
|
||||
switch (entity_name) {
|
||||
|
|
@ -14,4 +14,4 @@ export const EditorMentionsRoot: React.FC<TCallbackMentionComponentProps> = (pro
|
|||
default:
|
||||
return <EditorAdditionalMentionsRoot {...props} />;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ type Props = {
|
|||
id: string;
|
||||
};
|
||||
|
||||
export const EditorUserMention: React.FC<Props> = observer((props) => {
|
||||
export const EditorUserMention = observer(function EditorUserMention(props: Props) {
|
||||
const { id } = props;
|
||||
// store hooks
|
||||
const { data: currentUser } = useUser();
|
||||
|
|
|
|||
|
|
@ -32,7 +32,10 @@ type LiteTextEditorWrapperProps = MakeOptional<
|
|||
}
|
||||
);
|
||||
|
||||
export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapperProps>((props, ref) => {
|
||||
export const LiteTextEditor = React.forwardRef(function LiteTextEditor(
|
||||
props: LiteTextEditorWrapperProps,
|
||||
ref: React.ForwardedRef<EditorRefApi>
|
||||
) {
|
||||
const {
|
||||
anchor,
|
||||
containerClassName,
|
||||
|
|
|
|||
|
|
@ -29,7 +29,10 @@ type RichTextEditorWrapperProps = MakeOptional<
|
|||
}
|
||||
);
|
||||
|
||||
export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProps>((props, ref) => {
|
||||
export const RichTextEditor = forwardRef(function RichTextEditor(
|
||||
props: RichTextEditorWrapperProps,
|
||||
ref: React.ForwardedRef<EditorRefApi>
|
||||
) {
|
||||
const {
|
||||
anchor,
|
||||
containerClassName,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ type Props = {
|
|||
|
||||
const toolbarItems = TOOLBAR_ITEMS.lite;
|
||||
|
||||
export const IssueCommentToolbar: React.FC<Props> = (props) => {
|
||||
export function IssueCommentToolbar(props: Props) {
|
||||
const { executeCommand, handleSubmit, isCommentEmpty, editorRef, isSubmitting, showSubmitButton } = props;
|
||||
// states
|
||||
const [activeStates, setActiveStates] = useState<Record<string, boolean>>({});
|
||||
|
|
@ -113,4 +113,4 @@ export const IssueCommentToolbar: React.FC<Props> = (props) => {
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { Button } from "@plane/propel/button";
|
|||
import InstanceFailureDarkImage from "@/app/assets/instance/instance-failure-dark.svg?url";
|
||||
import InstanceFailureImage from "@/app/assets/instance/instance-failure.svg?url";
|
||||
|
||||
export const InstanceFailureView: React.FC = () => {
|
||||
export function InstanceFailureView() {
|
||||
const { resolvedTheme } = useTheme();
|
||||
|
||||
const instanceImage = resolvedTheme === "dark" ? InstanceFailureDarkImage : InstanceFailureImage;
|
||||
|
|
@ -34,4 +34,4 @@ export const InstanceFailureView: React.FC = () => {
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ type Props = {
|
|||
|
||||
export const replaceUnderscoreIfSnakeCase = (str: string) => str.replace(/_/g, " ");
|
||||
|
||||
export const AppliedFiltersList: React.FC<Props> = observer((props) => {
|
||||
export const AppliedFiltersList = observer(function AppliedFiltersList(props: Props) {
|
||||
const { appliedFilters = {}, handleRemoveAllFilters, handleRemoveFilter } = props;
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ type Props = {
|
|||
values: string[];
|
||||
};
|
||||
|
||||
export const AppliedLabelsFilters: React.FC<Props> = (props) => {
|
||||
export function AppliedLabelsFilters(props: Props) {
|
||||
const { handleRemove, labels, values } = props;
|
||||
|
||||
return (
|
||||
|
|
@ -41,4 +41,4 @@ export const AppliedLabelsFilters: React.FC<Props> = (props) => {
|
|||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ type Props = {
|
|||
values: TIssuePriorities[];
|
||||
};
|
||||
|
||||
export const AppliedPriorityFilters: React.FC<Props> = (props) => {
|
||||
export function AppliedPriorityFilters(props: Props) {
|
||||
const { handleRemove, values } = props;
|
||||
|
||||
return (
|
||||
|
|
@ -30,4 +30,4 @@ export const AppliedPriorityFilters: React.FC<Props> = (props) => {
|
|||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ type TIssueAppliedFilters = {
|
|||
anchor: string;
|
||||
};
|
||||
|
||||
export const IssueAppliedFilters: React.FC<TIssueAppliedFilters> = observer((props) => {
|
||||
export const IssueAppliedFilters = observer(function IssueAppliedFilters(props: TIssueAppliedFilters) {
|
||||
const { anchor } = props;
|
||||
// router
|
||||
const router = useRouter();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ type Props = {
|
|||
values: string[];
|
||||
};
|
||||
|
||||
export const AppliedStateFilters: React.FC<Props> = observer((props) => {
|
||||
export const AppliedStateFilters = observer(function AppliedStateFilters(props: Props) {
|
||||
const { handleRemove, values } = props;
|
||||
|
||||
const { sortedStates: states } = useStates();
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ type Props = {
|
|||
placement?: Placement;
|
||||
};
|
||||
|
||||
export const FiltersDropdown: React.FC<Props> = (props) => {
|
||||
export function FiltersDropdown(props: Props) {
|
||||
const { children, title = "Dropdown", placement } = props;
|
||||
|
||||
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
|
||||
|
|
@ -62,4 +62,4 @@ export const FiltersDropdown: React.FC<Props> = (props) => {
|
|||
}}
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,15 +9,17 @@ interface IFilterHeader {
|
|||
handleIsPreviewEnabled: () => void;
|
||||
}
|
||||
|
||||
export const FilterHeader = ({ title, isPreviewEnabled, handleIsPreviewEnabled }: IFilterHeader) => (
|
||||
<div className="sticky top-0 flex items-center justify-between gap-2 bg-custom-background-100">
|
||||
<div className="flex-grow truncate text-xs font-medium text-custom-text-300">{title}</div>
|
||||
<button
|
||||
type="button"
|
||||
className="grid h-5 w-5 flex-shrink-0 place-items-center rounded hover:bg-custom-background-80"
|
||||
onClick={handleIsPreviewEnabled}
|
||||
>
|
||||
{isPreviewEnabled ? <ChevronUpIcon height={14} width={14} /> : <ChevronDownIcon height={14} width={14} />}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
export function FilterHeader({ title, isPreviewEnabled, handleIsPreviewEnabled }: IFilterHeader) {
|
||||
return (
|
||||
<div className="sticky top-0 flex items-center justify-between gap-2 bg-custom-background-100">
|
||||
<div className="flex-grow truncate text-xs font-medium text-custom-text-300">{title}</div>
|
||||
<button
|
||||
type="button"
|
||||
className="grid h-5 w-5 flex-shrink-0 place-items-center rounded hover:bg-custom-background-80"
|
||||
onClick={handleIsPreviewEnabled}
|
||||
>
|
||||
{isPreviewEnabled ? <ChevronUpIcon height={14} width={14} /> : <ChevronDownIcon height={14} width={14} />}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ type Props = {
|
|||
multiple?: boolean;
|
||||
};
|
||||
|
||||
export const FilterOption: React.FC<Props> = (props) => {
|
||||
export function FilterOption(props: Props) {
|
||||
const { icon, isChecked, multiple = true, onClick, title } = props;
|
||||
|
||||
return (
|
||||
|
|
@ -34,4 +34,4 @@ export const FilterOption: React.FC<Props> = (props) => {
|
|||
</div>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
// plane imports
|
||||
import { Loader } from "@plane/ui";
|
||||
|
|
@ -9,9 +8,9 @@ import type { IIssueLabel } from "@/types/issue";
|
|||
import { FilterHeader } from "./helpers/filter-header";
|
||||
import { FilterOption } from "./helpers/filter-option";
|
||||
|
||||
const LabelIcons = ({ color }: { color: string }) => (
|
||||
<span className="h-2.5 w-2.5 rounded-full" style={{ backgroundColor: color }} />
|
||||
);
|
||||
function LabelIcons({ color }: { color: string }) {
|
||||
return <span className="h-2.5 w-2.5 rounded-full" style={{ backgroundColor: color }} />;
|
||||
}
|
||||
|
||||
type Props = {
|
||||
appliedFilters: string[] | null;
|
||||
|
|
@ -20,7 +19,7 @@ type Props = {
|
|||
searchQuery: string;
|
||||
};
|
||||
|
||||
export const FilterLabels: React.FC<Props> = (props) => {
|
||||
export function FilterLabels(props: Props) {
|
||||
const { appliedFilters, handleUpdate, labels, searchQuery } = props;
|
||||
|
||||
const [itemsToRender, setItemsToRender] = useState(5);
|
||||
|
|
@ -82,4 +81,4 @@ export const FilterLabels: React.FC<Props> = (props) => {
|
|||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ type Props = {
|
|||
searchQuery: string;
|
||||
};
|
||||
|
||||
export const FilterPriority: React.FC<Props> = observer((props) => {
|
||||
export const FilterPriority = observer(function FilterPriority(props: Props) {
|
||||
const { appliedFilters, handleUpdate, searchQuery } = props;
|
||||
|
||||
// hooks
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ type IssueFiltersDropdownProps = {
|
|||
anchor: string;
|
||||
};
|
||||
|
||||
export const IssueFiltersDropdown: React.FC<IssueFiltersDropdownProps> = observer((props) => {
|
||||
export const IssueFiltersDropdown = observer(function IssueFiltersDropdown(props: IssueFiltersDropdownProps) {
|
||||
const { anchor } = props;
|
||||
// router
|
||||
const router = useRouter();
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ type Props = {
|
|||
layoutDisplayFiltersOptions: TIssueFilterKeys[];
|
||||
};
|
||||
|
||||
export const FilterSelection: React.FC<Props> = observer((props) => {
|
||||
export const FilterSelection = observer(function FilterSelection(props: Props) {
|
||||
const { filters, handleFilters, layoutDisplayFiltersOptions } = props;
|
||||
|
||||
const [filtersSearchQuery, setFiltersSearchQuery] = useState("");
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ type Props = {
|
|||
searchQuery: string;
|
||||
};
|
||||
|
||||
export const FilterState: React.FC<Props> = observer((props) => {
|
||||
export const FilterState = observer(function FilterState(props: Props) {
|
||||
const { appliedFilters, handleUpdate, searchQuery } = props;
|
||||
|
||||
const { sortedStates: states } = useStates();
|
||||
|
|
|
|||
|
|
@ -1,20 +1,22 @@
|
|||
// assets
|
||||
import SomethingWentWrongImage from "@/app/assets/something-went-wrong.svg?url";
|
||||
|
||||
export const SomethingWentWrongError = () => (
|
||||
<div className="grid min-h-screen w-full place-items-center p-6">
|
||||
<div className="text-center">
|
||||
<div className="mx-auto grid h-52 w-52 place-items-center rounded-full bg-custom-background-80">
|
||||
<div className="grid h-32 w-32 place-items-center">
|
||||
<img
|
||||
src={SomethingWentWrongImage}
|
||||
alt="Oops! Something went wrong"
|
||||
className="w-full h-full object-contain"
|
||||
/>
|
||||
export function SomethingWentWrongError() {
|
||||
return (
|
||||
<div className="grid min-h-screen w-full place-items-center p-6">
|
||||
<div className="text-center">
|
||||
<div className="mx-auto grid h-52 w-52 place-items-center rounded-full bg-custom-background-80">
|
||||
<div className="grid h-32 w-32 place-items-center">
|
||||
<img
|
||||
src={SomethingWentWrongImage}
|
||||
alt="Oops! Something went wrong"
|
||||
className="w-full h-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<h1 className="mt-12 text-3xl font-semibold">Oops! Something went wrong.</h1>
|
||||
<p className="mt-4 text-custom-text-300">The public board does not exist. Please check the URL.</p>
|
||||
</div>
|
||||
<h1 className="mt-12 text-3xl font-semibold">Oops! Something went wrong.</h1>
|
||||
<p className="mt-4 text-custom-text-300">The public board does not exist. Please check the URL.</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ interface Props {
|
|||
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
|
||||
}
|
||||
|
||||
export const IssueLayoutHOC = observer((props: Props) => {
|
||||
export const IssueLayoutHOC = observer(function IssueLayoutHOC(props: Props) {
|
||||
const { getIssueLoader, getGroupIssueCount } = props;
|
||||
|
||||
const issueCount = getGroupIssueCount(undefined, undefined, false);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import { KanBan } from "./default";
|
|||
type Props = {
|
||||
anchor: string;
|
||||
};
|
||||
export const IssueKanbanLayoutRoot: React.FC<Props> = observer((props: Props) => {
|
||||
export const IssueKanbanLayoutRoot = observer(function IssueKanbanLayoutRoot(props: Props) {
|
||||
const { anchor } = props;
|
||||
// store hooks
|
||||
const { groupedIssueIds, getIssueLoader, fetchNextPublicIssues, getGroupIssueCount, getPaginationData } = useIssue();
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { usePublish } from "@/hooks/store/publish";
|
|||
type Props = {
|
||||
issueId: string;
|
||||
};
|
||||
export const BlockReactions = observer((props: Props) => {
|
||||
export const BlockReactions = observer(function BlockReactions(props: Props) {
|
||||
const { issueId } = props;
|
||||
const { anchor } = useParams();
|
||||
const { canVote, canReact } = usePublish(anchor.toString());
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ interface IssueDetailsBlockProps {
|
|||
displayProperties: IIssueDisplayProperties | undefined;
|
||||
}
|
||||
|
||||
const KanbanIssueDetailsBlock: React.FC<IssueDetailsBlockProps> = observer((props) => {
|
||||
const KanbanIssueDetailsBlock = observer(function KanbanIssueDetailsBlock(props: IssueDetailsBlockProps) {
|
||||
const { issue, displayProperties } = props;
|
||||
const { anchor } = useParams();
|
||||
// hooks
|
||||
|
|
@ -67,7 +67,7 @@ const KanbanIssueDetailsBlock: React.FC<IssueDetailsBlockProps> = observer((prop
|
|||
);
|
||||
});
|
||||
|
||||
export const KanbanIssueBlock: React.FC<IssueBlockProps> = observer((props) => {
|
||||
export const KanbanIssueBlock = observer(function KanbanIssueBlock(props: IssueBlockProps) {
|
||||
const { issueId, groupId, subGroupId, displayProperties } = props;
|
||||
const searchParams = useSearchParams();
|
||||
// query params
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ interface IssueBlocksListProps {
|
|||
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
|
||||
}
|
||||
|
||||
export const KanbanIssueBlocksList: React.FC<IssueBlocksListProps> = observer((props) => {
|
||||
export const KanbanIssueBlocksList = observer(function KanbanIssueBlocksList(props: IssueBlocksListProps) {
|
||||
const { subGroupId, groupId, issueIds, displayProperties, scrollableContainerRef } = props;
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ export interface IKanBan {
|
|||
showEmptyGroup?: boolean;
|
||||
}
|
||||
|
||||
export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
export const KanBan = observer(function KanBan(props: IKanBan) {
|
||||
const {
|
||||
groupedIssueIds,
|
||||
displayProperties,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ interface IHeaderGroupByCard {
|
|||
count: number;
|
||||
}
|
||||
|
||||
export const HeaderGroupByCard: React.FC<IHeaderGroupByCard> = observer((props) => {
|
||||
export const HeaderGroupByCard = observer(function HeaderGroupByCard(props: IHeaderGroupByCard) {
|
||||
const { icon, title, count } = props;
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ interface IHeaderSubGroupByCard {
|
|||
toggleExpanded: () => void;
|
||||
}
|
||||
|
||||
export const HeaderSubGroupByCard: React.FC<IHeaderSubGroupByCard> = observer((props) => {
|
||||
export const HeaderSubGroupByCard = observer(function HeaderSubGroupByCard(props: IHeaderSubGroupByCard) {
|
||||
const { icon, title, count, isExpanded, toggleExpanded } = props;
|
||||
return (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -36,12 +36,15 @@ interface IKanbanGroup {
|
|||
}
|
||||
|
||||
// Loader components
|
||||
const KanbanIssueBlockLoader = forwardRef<HTMLSpanElement>((props, ref) => (
|
||||
<span ref={ref} className="block h-28 m-1.5 animate-pulse bg-custom-background-80 rounded" />
|
||||
));
|
||||
const KanbanIssueBlockLoader = forwardRef(function KanbanIssueBlockLoader(
|
||||
props: Record<string, unknown>,
|
||||
ref: React.ForwardedRef<HTMLSpanElement>
|
||||
) {
|
||||
return <span ref={ref} className="block h-28 m-1.5 animate-pulse bg-custom-background-80 rounded" />;
|
||||
});
|
||||
KanbanIssueBlockLoader.displayName = "KanbanIssueBlockLoader";
|
||||
|
||||
export const KanbanGroup = observer((props: IKanbanGroup) => {
|
||||
export const KanbanGroup = observer(function KanbanGroup(props: IKanbanGroup) {
|
||||
const {
|
||||
groupId,
|
||||
subGroupId,
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export interface IKanBanSwimLanes {
|
|||
orderBy: TIssueOrderByOptions | undefined;
|
||||
}
|
||||
|
||||
export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||
export const KanBanSwimLanes = observer(function KanBanSwimLanes(props: IKanBanSwimLanes) {
|
||||
const {
|
||||
groupedIssueIds,
|
||||
displayProperties,
|
||||
|
|
@ -125,8 +125,14 @@ const visibilitySubGroupByGroupCount = (subGroupIssueCount: number, showEmptyGro
|
|||
return subGroupHeaderVisibility;
|
||||
};
|
||||
|
||||
const SubGroupSwimlaneHeader: React.FC<ISubGroupSwimlaneHeader> = observer(
|
||||
({ subGroupBy, groupBy, groupList, showEmptyGroup, getGroupIssueCount }) => (
|
||||
const SubGroupSwimlaneHeader = observer(function SubGroupSwimlaneHeader({
|
||||
subGroupBy,
|
||||
groupBy,
|
||||
groupList,
|
||||
showEmptyGroup,
|
||||
getGroupIssueCount,
|
||||
}: ISubGroupSwimlaneHeader) {
|
||||
return (
|
||||
<div className="relative flex h-max min-h-full w-full items-center gap-2">
|
||||
{groupList &&
|
||||
groupList.length > 0 &&
|
||||
|
|
@ -143,8 +149,8 @@ const SubGroupSwimlaneHeader: React.FC<ISubGroupSwimlaneHeader> = observer(
|
|||
);
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader {
|
||||
groupedIssueIds: TGroupedIssues | TSubGroupedIssues;
|
||||
|
|
@ -162,7 +168,7 @@ interface ISubGroupSwimlane extends ISubGroupSwimlaneHeader {
|
|||
loadMoreIssues: (groupId?: string, subGroupId?: string) => void;
|
||||
}
|
||||
|
||||
const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
|
||||
const SubGroupSwimlane = observer(function SubGroupSwimlane(props: ISubGroupSwimlane) {
|
||||
const {
|
||||
groupedIssueIds,
|
||||
subGroupBy,
|
||||
|
|
@ -219,7 +225,7 @@ interface ISubGroup {
|
|||
loadMoreIssues: (groupId?: string, subGroupId?: string) => void;
|
||||
}
|
||||
|
||||
const SubGroup: React.FC<ISubGroup> = observer((props) => {
|
||||
const SubGroup = observer(function SubGroup(props: ISubGroup) {
|
||||
const {
|
||||
groupedIssueIds,
|
||||
subGroupBy,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ type Props = {
|
|||
anchor: string;
|
||||
};
|
||||
|
||||
export const IssuesListLayoutRoot = observer((props: Props) => {
|
||||
export const IssuesListLayoutRoot = observer(function IssuesListLayoutRoot(props: Props) {
|
||||
const { anchor } = props;
|
||||
// store hooks
|
||||
const {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ interface IssueBlockProps {
|
|||
displayProperties: IIssueDisplayProperties | undefined;
|
||||
}
|
||||
|
||||
export const IssueBlock = observer((props: IssueBlockProps) => {
|
||||
export const IssueBlock = observer(function IssueBlock(props: IssueBlockProps) {
|
||||
const { anchor } = useParams();
|
||||
const { issueId, displayProperties } = props;
|
||||
const searchParams = useSearchParams();
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ interface Props {
|
|||
containerRef: MutableRefObject<HTMLDivElement | null>;
|
||||
}
|
||||
|
||||
export const IssueBlocksList: React.FC<Props> = (props) => {
|
||||
export function IssueBlocksList(props: Props) {
|
||||
const { issueIds = [], groupId, displayProperties } = props;
|
||||
|
||||
return (
|
||||
|
|
@ -22,4 +22,4 @@ export const IssueBlocksList: React.FC<Props> = (props) => {
|
|||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export interface IList {
|
|||
getIssueLoader: (groupId?: string | undefined, subGroupId?: string | undefined) => TLoader;
|
||||
}
|
||||
|
||||
export const List: React.FC<IList> = observer((props) => {
|
||||
export const List = observer(function List(props: IList) {
|
||||
const {
|
||||
groupedIssueIds,
|
||||
groupBy,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ interface IHeaderGroupByCard {
|
|||
toggleListGroup: (id: string) => void;
|
||||
}
|
||||
|
||||
export const HeaderGroupByCard = observer((props: IHeaderGroupByCard) => {
|
||||
export const HeaderGroupByCard = observer(function HeaderGroupByCard(props: IHeaderGroupByCard) {
|
||||
const { groupID, icon, title, count, toggleListGroup } = props;
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -38,24 +38,29 @@ interface Props {
|
|||
}
|
||||
|
||||
// List loader component
|
||||
const ListLoaderItemRow = forwardRef<HTMLDivElement>((props, ref) => (
|
||||
<div ref={ref} className="flex items-center justify-between h-11 p-3 border-b border-custom-border-200">
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="h-5 w-10 bg-custom-background-80 rounded animate-pulse" />
|
||||
<span className={`h-5 w-52 bg-custom-background-80 rounded animate-pulse`} />
|
||||
const ListLoaderItemRow = forwardRef(function ListLoaderItemRow(
|
||||
props: Record<string, unknown>,
|
||||
ref: React.ForwardedRef<HTMLDivElement>
|
||||
) {
|
||||
return (
|
||||
<div ref={ref} className="flex items-center justify-between h-11 p-3 border-b border-custom-border-200">
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="h-5 w-10 bg-custom-background-80 rounded animate-pulse" />
|
||||
<span className={`h-5 w-52 bg-custom-background-80 rounded animate-pulse`} />
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{[...Array(6)].map((_, index) => (
|
||||
<Fragment key={index}>
|
||||
<span key={index} className="h-5 w-5 bg-custom-background-80 rounded animate-pulse" />
|
||||
</Fragment>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{[...Array(6)].map((_, index) => (
|
||||
<Fragment key={index}>
|
||||
<span key={index} className="h-5 w-5 bg-custom-background-80 rounded animate-pulse" />
|
||||
</Fragment>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
));
|
||||
);
|
||||
});
|
||||
ListLoaderItemRow.displayName = "ListLoaderItemRow";
|
||||
|
||||
export const ListGroup = observer((props: Props) => {
|
||||
export const ListGroup = observer(function ListGroup(props: Props) {
|
||||
const {
|
||||
groupIssueIds = [],
|
||||
group,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export interface IIssueProperties {
|
|||
className: string;
|
||||
}
|
||||
|
||||
export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
|
||||
export const IssueProperties = observer(function IssueProperties(props: IIssueProperties) {
|
||||
const { issue, displayProperties, className } = props;
|
||||
|
||||
if (!displayProperties || !issue.project_id) return null;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ type Props = {
|
|||
shouldShowBorder?: boolean;
|
||||
};
|
||||
|
||||
export const IssueBlockCycle = observer(({ cycleId, shouldShowBorder = true }: Props) => {
|
||||
export const IssueBlockCycle = observer(function IssueBlockCycle({ cycleId, shouldShowBorder = true }: Props) {
|
||||
const { getCycleById } = useCycle();
|
||||
|
||||
const cycle = getCycleById(cycleId);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ type Props = {
|
|||
shouldShowBorder?: boolean;
|
||||
};
|
||||
|
||||
export const IssueBlockDate = observer((props: Props) => {
|
||||
export const IssueBlockDate = observer(function IssueBlockDate(props: Props) {
|
||||
const { due_date, stateId, shouldHighLight = true, shouldShowBorder = true } = props;
|
||||
const { getStateById } = useStates();
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ type Props = {
|
|||
shouldShowLabel?: boolean;
|
||||
};
|
||||
|
||||
export const IssueBlockLabels = observer(({ labelIds, shouldShowLabel = false }: Props) => {
|
||||
export const IssueBlockLabels = observer(function IssueBlockLabels({ labelIds, shouldShowLabel = false }: Props) {
|
||||
const { getLabelsByIds } = useLabel();
|
||||
|
||||
const labels = getLabelsByIds(labelIds);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ type AvatarProps = {
|
|||
icon?: LucideIcon;
|
||||
};
|
||||
|
||||
export const ButtonAvatars: React.FC<AvatarProps> = observer((props: AvatarProps) => {
|
||||
export const ButtonAvatars = observer(function ButtonAvatars(props: AvatarProps) {
|
||||
const { showTooltip, members, icon: Icon } = props;
|
||||
|
||||
if (Array.isArray(members)) {
|
||||
|
|
@ -56,7 +56,7 @@ export const ButtonAvatars: React.FC<AvatarProps> = observer((props: AvatarProps
|
|||
);
|
||||
});
|
||||
|
||||
export const IssueBlockMembers = observer(({ memberIds, shouldShowBorder = true }: Props) => {
|
||||
export const IssueBlockMembers = observer(function IssueBlockMembers({ memberIds, shouldShowBorder = true }: Props) {
|
||||
const { getMembersByIds } = useMember();
|
||||
|
||||
const members = getMembersByIds(memberIds);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ type Props = {
|
|||
shouldShowBorder?: boolean;
|
||||
};
|
||||
|
||||
export const IssueBlockModules = observer(({ moduleIds, shouldShowBorder = true }: Props) => {
|
||||
export const IssueBlockModules = observer(function IssueBlockModules({ moduleIds, shouldShowBorder = true }: Props) {
|
||||
const { getModulesByIds } = useModule();
|
||||
|
||||
const modules = getModulesByIds(moduleIds ?? []);
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@ import type { TIssuePriorities } from "@plane/types";
|
|||
// constants
|
||||
import { cn, getIssuePriorityFilters } from "@plane/utils";
|
||||
|
||||
export const IssueBlockPriority = ({
|
||||
export function IssueBlockPriority({
|
||||
priority,
|
||||
shouldShowName = false,
|
||||
}: {
|
||||
priority: TIssuePriorities | null;
|
||||
shouldShowName?: boolean;
|
||||
}) => {
|
||||
}) {
|
||||
// hooks
|
||||
const { t } = useTranslation();
|
||||
const priority_detail = priority != null ? getIssuePriorityFilters(priority) : null;
|
||||
|
|
@ -65,4 +65,4 @@ export const IssueBlockPriority = ({
|
|||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ type Props = {
|
|||
stateId: string | undefined;
|
||||
shouldShowBorder?: boolean;
|
||||
};
|
||||
export const IssueBlockState = observer(({ stateId, shouldShowBorder = true }: Props) => {
|
||||
export const IssueBlockState = observer(function IssueBlockState({ stateId, shouldShowBorder = true }: Props) {
|
||||
const { getStateById } = useStates();
|
||||
|
||||
const state = getStateById(stateId);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ type Props = {
|
|||
publishSettings: PublishStore;
|
||||
};
|
||||
|
||||
export const IssuesLayoutsRoot: React.FC<Props> = observer((props) => {
|
||||
export const IssuesLayoutsRoot = observer(function IssuesLayoutsRoot(props: Props) {
|
||||
const { peekId, publishSettings } = props;
|
||||
// store hooks
|
||||
const { getIssueFilters } = useIssueFilter();
|
||||
|
|
|
|||
|
|
@ -9,18 +9,21 @@ interface IWithDisplayPropertiesHOC {
|
|||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const WithDisplayPropertiesHOC = observer(
|
||||
({ displayProperties, shouldRenderProperty, displayPropertyKey, children }: IWithDisplayPropertiesHOC) => {
|
||||
let shouldDisplayPropertyFromFilters = false;
|
||||
if (Array.isArray(displayPropertyKey))
|
||||
shouldDisplayPropertyFromFilters = displayPropertyKey.every((key) => !!displayProperties[key]);
|
||||
else shouldDisplayPropertyFromFilters = !!displayProperties[displayPropertyKey];
|
||||
export const WithDisplayPropertiesHOC = observer(function WithDisplayPropertiesHOC({
|
||||
displayProperties,
|
||||
shouldRenderProperty,
|
||||
displayPropertyKey,
|
||||
children,
|
||||
}: IWithDisplayPropertiesHOC) {
|
||||
let shouldDisplayPropertyFromFilters = false;
|
||||
if (Array.isArray(displayPropertyKey))
|
||||
shouldDisplayPropertyFromFilters = displayPropertyKey.every((key) => !!displayProperties[key]);
|
||||
else shouldDisplayPropertyFromFilters = !!displayProperties[displayPropertyKey];
|
||||
|
||||
const renderProperty =
|
||||
shouldDisplayPropertyFromFilters && (shouldRenderProperty ? shouldRenderProperty(displayProperties) : true);
|
||||
const renderProperty =
|
||||
shouldDisplayPropertyFromFilters && (shouldRenderProperty ? shouldRenderProperty(displayProperties) : true);
|
||||
|
||||
if (!renderProperty) return null;
|
||||
if (!renderProperty) return null;
|
||||
|
||||
return <>{children}</>;
|
||||
}
|
||||
);
|
||||
return <>{children}</>;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export type NavbarControlsProps = {
|
|||
publishSettings: PublishStore;
|
||||
};
|
||||
|
||||
export const NavbarControls: React.FC<NavbarControlsProps> = observer((props) => {
|
||||
export const NavbarControls = observer(function NavbarControls(props: NavbarControlsProps) {
|
||||
// props
|
||||
const { publishSettings } = props;
|
||||
// router
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ import type { TIssueLayout } from "@plane/constants";
|
|||
import { ListLayoutIcon, BoardLayoutIcon } from "@plane/propel/icons";
|
||||
import type { ISvgIcons } from "@plane/propel/icons";
|
||||
|
||||
export const IssueLayoutIcon = ({
|
||||
export function IssueLayoutIcon({
|
||||
layout,
|
||||
size,
|
||||
...props
|
||||
}: { layout: TIssueLayout; size?: number } & Omit<ISvgIcons, "width" | "height">) => {
|
||||
}: { layout: TIssueLayout; size?: number } & Omit<ISvgIcons, "width" | "height">) {
|
||||
const iconProps = {
|
||||
...props,
|
||||
...(size && { width: size, height: size }),
|
||||
|
|
@ -20,4 +20,4 @@ export const IssueLayoutIcon = ({
|
|||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ type Props = {
|
|||
anchor: string;
|
||||
};
|
||||
|
||||
export const IssuesLayoutSelection: React.FC<Props> = observer((props) => {
|
||||
export const IssuesLayoutSelection = observer(function IssuesLayoutSelection(props: Props) {
|
||||
const { anchor } = props;
|
||||
// hooks
|
||||
const { t } = useTranslation();
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ type Props = {
|
|||
publishSettings: PublishStore;
|
||||
};
|
||||
|
||||
export const IssuesNavbarRoot: React.FC<Props> = observer((props) => {
|
||||
export const IssuesNavbarRoot = observer(function IssuesNavbarRoot(props: Props) {
|
||||
const { publishSettings } = props;
|
||||
// hooks
|
||||
const { project_details } = publishSettings;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { useTheme } from "next-themes";
|
|||
|
||||
// mobx react lite
|
||||
|
||||
export const NavbarTheme = observer(() => {
|
||||
export const NavbarTheme = observer(function NavbarTheme() {
|
||||
const [appTheme, setAppTheme] = useState("light");
|
||||
|
||||
const { setTheme, theme } = useTheme();
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import { useUser } from "@/hooks/store/use-user";
|
|||
|
||||
const authService = new AuthService();
|
||||
|
||||
export const UserAvatar: React.FC = observer(() => {
|
||||
export const UserAvatar = observer(function UserAvatar() {
|
||||
const pathName = usePathname();
|
||||
const searchParams = useSearchParams();
|
||||
// query params
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ type Props = {
|
|||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export const AddComment: React.FC<Props> = observer((props) => {
|
||||
export const AddComment = observer(function AddComment(props: Props) {
|
||||
const { anchor } = props;
|
||||
// states
|
||||
const [uploadedAssetIds, setUploadAssetIds] = useState<string[]>([]);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ type Props = {
|
|||
comment: TIssuePublicComment;
|
||||
};
|
||||
|
||||
export const CommentCard: React.FC<Props> = observer((props) => {
|
||||
export const CommentCard = observer(function CommentCard(props: Props) {
|
||||
const { anchor, comment } = props;
|
||||
// store hooks
|
||||
const { peekId, deleteIssueComment, updateIssueComment, uploadCommentAsset } = useIssueDetails();
|
||||
|
|
@ -157,7 +157,6 @@ export const CommentCard: React.FC<Props> = observer((props) => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{!isInIframe && currentUser?.id === comment?.actor_detail?.id && (
|
||||
<Menu as="div" className="relative w-min text-left">
|
||||
<Menu.Button
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ type Props = {
|
|||
commentId: string;
|
||||
};
|
||||
|
||||
export const CommentReactions: React.FC<Props> = observer((props) => {
|
||||
export const CommentReactions = observer(function CommentReactions(props: Props) {
|
||||
const { anchor, commentId } = props;
|
||||
// state
|
||||
const [isPickerOpen, setIsPickerOpen] = useState(false);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ type Props = {
|
|||
issueDetails: IIssue | undefined;
|
||||
};
|
||||
|
||||
export const FullScreenPeekView: React.FC<Props> = observer((props) => {
|
||||
export const FullScreenPeekView = observer(function FullScreenPeekView(props: Props) {
|
||||
const { anchor, handleClose, issueDetails } = props;
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ const PEEK_MODES: {
|
|||
},
|
||||
];
|
||||
|
||||
export const PeekOverviewHeader: React.FC<Props> = observer((props) => {
|
||||
export const PeekOverviewHeader = observer(function PeekOverviewHeader(props: Props) {
|
||||
const { handleClose } = props;
|
||||
|
||||
const { peekMode, setPeekMode } = useIssueDetails();
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ type Props = {
|
|||
issueDetails: IIssue;
|
||||
};
|
||||
|
||||
export const PeekOverviewIssueActivity: React.FC<Props> = observer((props) => {
|
||||
export const PeekOverviewIssueActivity = observer(function PeekOverviewIssueActivity(props: Props) {
|
||||
const { anchor } = props;
|
||||
// router
|
||||
const pathname = usePathname();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ type Props = {
|
|||
issueDetails: IIssue;
|
||||
};
|
||||
|
||||
export const PeekOverviewIssueDetails: React.FC<Props> = observer((props) => {
|
||||
export const PeekOverviewIssueDetails = observer(function PeekOverviewIssueDetails(props: Props) {
|
||||
const { anchor, issueDetails } = props;
|
||||
// store hooks
|
||||
const { project_details, workspace: workspaceID } = usePublish(anchor);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,10 @@ type Props = {
|
|||
mode?: IPeekMode;
|
||||
};
|
||||
|
||||
export const PeekOverviewIssueProperties: React.FC<Props> = observer(({ issueDetails, mode }) => {
|
||||
export const PeekOverviewIssueProperties = observer(function PeekOverviewIssueProperties({
|
||||
issueDetails,
|
||||
mode,
|
||||
}: Props) {
|
||||
// hooks
|
||||
const { t } = useTranslation();
|
||||
const { getStateById } = useStates();
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ type Props = {
|
|||
anchor: string;
|
||||
};
|
||||
|
||||
export const IssueReactions: React.FC<Props> = observer((props) => {
|
||||
export const IssueReactions = observer(function IssueReactions(props: Props) {
|
||||
const { anchor } = props;
|
||||
// store hooks
|
||||
const { canVote, canReact } = usePublish(anchor);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ type TIssuePeekOverview = {
|
|||
handlePeekClose?: () => void;
|
||||
};
|
||||
|
||||
export const IssuePeekOverview: React.FC<TIssuePeekOverview> = observer((props) => {
|
||||
export const IssuePeekOverview = observer(function IssuePeekOverview(props: TIssuePeekOverview) {
|
||||
const { anchor, peekId, handlePeekClose } = props;
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ type Props = {
|
|||
issueDetails: IIssue | undefined;
|
||||
};
|
||||
|
||||
export const SidePeekView: React.FC<Props> = observer((props) => {
|
||||
export const SidePeekView = observer(function SidePeekView(props: Props) {
|
||||
const { anchor, handleClose, issueDetails } = props;
|
||||
// store hooks
|
||||
const { canComment } = usePublish(anchor);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ type IssueEmojiReactionsProps = {
|
|||
issueIdFromProps?: string;
|
||||
};
|
||||
|
||||
export const IssueEmojiReactions: React.FC<IssueEmojiReactionsProps> = observer((props) => {
|
||||
export const IssueEmojiReactions = observer(function IssueEmojiReactions(props: IssueEmojiReactionsProps) {
|
||||
const { anchor, issueIdFromProps } = props;
|
||||
// state
|
||||
const [isPickerOpen, setIsPickerOpen] = useState(false);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ type TIssueVotes = {
|
|||
size?: "md" | "sm";
|
||||
};
|
||||
|
||||
export const IssueVotes: React.FC<TIssueVotes> = observer((props) => {
|
||||
export const IssueVotes = observer(function IssueVotes(props: TIssueVotes) {
|
||||
const { anchor, issueIdFromProps, size = "md" } = props;
|
||||
// states
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@ type Props = {
|
|||
className?: string;
|
||||
};
|
||||
|
||||
export const Icon: React.FC<Props> = ({ iconName, className = "" }) => (
|
||||
<span className={`material-symbols-rounded text-sm font-light leading-5 ${className}`}>{iconName}</span>
|
||||
);
|
||||
export function Icon({ iconName, className = "" }: Props) {
|
||||
return <span className={`material-symbols-rounded text-sm font-light leading-5 ${className}`}>{iconName}</span>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,21 +3,23 @@
|
|||
// images
|
||||
import Image404 from "@/app/assets/404.svg?url";
|
||||
|
||||
export const PageNotFound = () => (
|
||||
<div className={`h-screen w-full overflow-hidden bg-custom-background-100`}>
|
||||
<div className="grid h-full place-items-center p-4">
|
||||
<div className="space-y-8 text-center">
|
||||
<div className="relative mx-auto h-60 w-60 lg:h-80 lg:w-80">
|
||||
<img src={Image404} alt="404- Page not found" className="w-full h-full object-contain" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h3 className="text-lg font-semibold">Oops! Something went wrong.</h3>
|
||||
<p className="text-sm text-custom-text-200">
|
||||
Sorry, the page you are looking for cannot be found. It may have been removed, had its name changed, or is
|
||||
temporarily unavailable.
|
||||
</p>
|
||||
export function PageNotFound() {
|
||||
return (
|
||||
<div className={`h-screen w-full overflow-hidden bg-custom-background-100`}>
|
||||
<div className="grid h-full place-items-center p-4">
|
||||
<div className="space-y-8 text-center">
|
||||
<div className="relative mx-auto h-60 w-60 lg:h-80 lg:w-80">
|
||||
<img src={Image404} alt="404- Page not found" className="w-full h-full object-contain" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h3 className="text-lg font-semibold">Oops! Something went wrong.</h3>
|
||||
<p className="text-sm text-custom-text-200">
|
||||
Sorry, the page you are looking for cannot be found. It may have been removed, had its name changed, or is
|
||||
temporarily unavailable.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,12 @@ import { PoweredBy } from "@/components/common/powered-by";
|
|||
// local imports
|
||||
import { AuthHeader } from "./header";
|
||||
|
||||
export const AuthView = () => (
|
||||
<div className="relative z-10 flex flex-col items-center w-screen h-screen overflow-hidden overflow-y-auto pt-6 pb-10 px-8">
|
||||
<AuthHeader />
|
||||
<AuthRoot />
|
||||
<PoweredBy />
|
||||
</div>
|
||||
);
|
||||
export function AuthView() {
|
||||
return (
|
||||
<div className="relative z-10 flex flex-col items-center w-screen h-screen overflow-hidden overflow-y-auto pt-6 pb-10 px-8">
|
||||
<AuthHeader />
|
||||
<AuthRoot />
|
||||
<PoweredBy />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,12 @@ import React from "react";
|
|||
import Link from "next/link";
|
||||
import { PlaneLockup } from "@plane/propel/icons";
|
||||
|
||||
export const AuthHeader = () => (
|
||||
<div className="flex items-center justify-between gap-6 w-full flex-shrink-0 sticky top-0">
|
||||
<Link href="/">
|
||||
<PlaneLockup height={20} width={95} className="text-custom-text-100" />
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
export function AuthHeader() {
|
||||
return (
|
||||
<div className="flex items-center justify-between gap-6 w-full flex-shrink-0 sticky top-0">
|
||||
<Link href="/">
|
||||
<PlaneLockup height={20} width={95} className="text-custom-text-100" />
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import { InstanceFailureView } from "@/components/instance/instance-failure-view
|
|||
import { useInstance } from "@/hooks/store/use-instance";
|
||||
import { useUser } from "@/hooks/store/use-user";
|
||||
|
||||
export const InstanceProvider = observer(({ children }: { children: React.ReactNode }) => {
|
||||
export const InstanceProvider = observer(function InstanceProvider({ children }: { children: React.ReactNode }) {
|
||||
const { fetchInstanceInfo, instance, error } = useInstance();
|
||||
const { fetchCurrentUser } = useUser();
|
||||
const { resolvedTheme } = useTheme();
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export type StoreProviderProps = {
|
|||
initialState?: any;
|
||||
};
|
||||
|
||||
export const StoreProvider = ({ children, initialState = undefined }: StoreProviderProps) => {
|
||||
export function StoreProvider({ children, initialState = undefined }: StoreProviderProps) {
|
||||
const store = initializeStore();
|
||||
// If your page has Next.js data fetching methods that use a Mobx store, it will
|
||||
// get hydrated here, check `pages/ssg.js` and `pages/ssr.js` for more details
|
||||
|
|
@ -32,4 +32,4 @@ export const StoreProvider = ({ children, initialState = undefined }: StoreProvi
|
|||
}
|
||||
|
||||
return <StoreContext.Provider value={store}>{children}</StoreContext.Provider>;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { useTheme } from "next-themes";
|
|||
import { Toast } from "@plane/propel/toast";
|
||||
import { resolveGeneralTheme } from "@plane/utils";
|
||||
|
||||
export const ToastProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
export function ToastProvider({ children }: { children: React.ReactNode }) {
|
||||
// themes
|
||||
const { resolvedTheme } = useTheme();
|
||||
|
||||
|
|
@ -15,4 +15,4 @@ export const ToastProvider = ({ children }: { children: React.ReactNode }) => {
|
|||
{children}
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue