[WEB-2273] Chore: page alignments (#5505)
* chore: headers + common containers * fix: filters code splitting * fix: home header * fix: header changes * chore: page alignments fixed * fix: uncommented filters * fix: used enums * fix: cards + filters * fix: enum changes * fix: reverted package changes * fix: reverted package changes * fix: Card + tags seperated + naming fixed * fix: card + tags seperated + naming fixed * fix: mobile headers fixed partially * fix: build errors + minor css * fix: checkbox spacing * fix: review changes * fix: lint errors * fix: minor review changes
This commit is contained in:
parent
c78b2344b8
commit
87dbb9b888
181 changed files with 1323 additions and 1122 deletions
|
|
@ -440,8 +440,8 @@ module.exports = {
|
||||||
const newUtilities = {
|
const newUtilities = {
|
||||||
// Mobile screens
|
// Mobile screens
|
||||||
'.px-page-x': {
|
'.px-page-x': {
|
||||||
paddingLeft: '0.675rem',
|
paddingLeft: '1.25rem',
|
||||||
paddingRight: '0.675rem',
|
paddingRight: '1.25rem',
|
||||||
},
|
},
|
||||||
// Medium screens (768px and up)
|
// Medium screens (768px and up)
|
||||||
'@media (min-width: 768px)': {
|
'@media (min-width: 768px)': {
|
||||||
|
|
|
||||||
41
packages/ui/src/card/card.tsx
Normal file
41
packages/ui/src/card/card.tsx
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import { cn } from "../../helpers";
|
||||||
|
import {
|
||||||
|
ECardDirection,
|
||||||
|
ECardSpacing,
|
||||||
|
ECardVariant,
|
||||||
|
getCardStyle,
|
||||||
|
TCardDirection,
|
||||||
|
TCardSpacing,
|
||||||
|
TCardVariant,
|
||||||
|
} from "./helper";
|
||||||
|
|
||||||
|
export interface CardProps {
|
||||||
|
variant?: TCardVariant;
|
||||||
|
spacing?: TCardSpacing;
|
||||||
|
direction?: TCardDirection;
|
||||||
|
className?: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Card = React.forwardRef<HTMLDivElement, CardProps>((props, ref) => {
|
||||||
|
const {
|
||||||
|
variant = ECardVariant.WITH_SHADOW,
|
||||||
|
direction = ECardDirection.COLUMN,
|
||||||
|
className = "",
|
||||||
|
spacing = ECardSpacing.LG,
|
||||||
|
children,
|
||||||
|
...rest
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const style = getCardStyle(variant, spacing, direction);
|
||||||
|
return (
|
||||||
|
<div ref={ref} className={cn(style, className)} {...rest}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Card.displayName = "plane-ui-card";
|
||||||
|
|
||||||
|
export { Card, ECardVariant, ECardSpacing, ECardDirection };
|
||||||
36
packages/ui/src/card/helper.tsx
Normal file
36
packages/ui/src/card/helper.tsx
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
export enum ECardVariant {
|
||||||
|
WITHOUT_SHADOW = "without-shadow",
|
||||||
|
WITH_SHADOW = "with-shadow",
|
||||||
|
}
|
||||||
|
export enum ECardDirection {
|
||||||
|
ROW = "row",
|
||||||
|
COLUMN = "column",
|
||||||
|
}
|
||||||
|
export enum ECardSpacing {
|
||||||
|
SM = "sm",
|
||||||
|
LG = "lg",
|
||||||
|
}
|
||||||
|
export type TCardVariant = ECardVariant.WITHOUT_SHADOW | ECardVariant.WITH_SHADOW;
|
||||||
|
export type TCardDirection = ECardDirection.ROW | ECardDirection.COLUMN;
|
||||||
|
export type TCardSpacing = ECardSpacing.SM | ECardSpacing.LG;
|
||||||
|
|
||||||
|
export interface ICardProperties {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_STYLE =
|
||||||
|
"bg-custom-background-100 rounded-lg border-[0.5px] border-custom-border-200 w-full flex flex-col";
|
||||||
|
export const containerStyle: ICardProperties = {
|
||||||
|
[ECardVariant.WITHOUT_SHADOW]: "",
|
||||||
|
[ECardVariant.WITH_SHADOW]: "hover:shadow-custom-shadow-4xl duration-300",
|
||||||
|
};
|
||||||
|
export const spacings = {
|
||||||
|
[ECardSpacing.SM]: "p-4",
|
||||||
|
[ECardSpacing.LG]: "p-6",
|
||||||
|
};
|
||||||
|
export const directions = {
|
||||||
|
[ECardDirection.ROW]: "flex-row space-x-3",
|
||||||
|
[ECardDirection.COLUMN]: "flex-col space-y-3",
|
||||||
|
};
|
||||||
|
export const getCardStyle = (variant: TCardVariant, spacing: TCardSpacing, direction: TCardDirection) =>
|
||||||
|
DEFAULT_STYLE + " " + directions[direction] + " " + containerStyle[variant] + " " + spacings[spacing];
|
||||||
1
packages/ui/src/card/index.ts
Normal file
1
packages/ui/src/card/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export * from "./card";
|
||||||
36
packages/ui/src/content-wrapper/content-wrapper.tsx
Normal file
36
packages/ui/src/content-wrapper/content-wrapper.tsx
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import { cn } from "../../helpers";
|
||||||
|
import { Row } from "../row";
|
||||||
|
import { ERowVariant, TRowVariant } from "../row/helper";
|
||||||
|
|
||||||
|
export interface ContentWrapperProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||||
|
variant?: TRowVariant;
|
||||||
|
className?: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
const DEFAULT_STYLE = "flex flex-col vertical-scrollbar scrollbar-lg h-full w-full overflow-y-auto";
|
||||||
|
|
||||||
|
const ContentWrapper = React.forwardRef<HTMLDivElement, ContentWrapperProps>((props, ref) => {
|
||||||
|
const { variant = ERowVariant.REGULAR, className = "", children, ...rest } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row
|
||||||
|
ref={ref}
|
||||||
|
variant={variant}
|
||||||
|
className={cn(
|
||||||
|
DEFAULT_STYLE,
|
||||||
|
{
|
||||||
|
"py-page-y": variant === ERowVariant.REGULAR,
|
||||||
|
},
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
ContentWrapper.displayName = "plane-ui-wrapper";
|
||||||
|
|
||||||
|
export { ContentWrapper };
|
||||||
1
packages/ui/src/content-wrapper/index.ts
Normal file
1
packages/ui/src/content-wrapper/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export * from "./content-wrapper";
|
||||||
|
|
@ -1,39 +1,51 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { cn } from "../../helpers";
|
import { cn } from "../../helpers";
|
||||||
import { EHeaderVariant, getHeaderStyle, THeaderVariant } from "./helper";
|
import { EHeaderVariant, getHeaderStyle, THeaderVariant } from "./helper";
|
||||||
import { ERowVariant, CustomRow } from "../row";
|
import { ERowVariant, Row } from "../row";
|
||||||
|
|
||||||
export interface CustomHeaderProps {
|
export interface HeaderProps {
|
||||||
variant?: THeaderVariant;
|
variant?: THeaderVariant;
|
||||||
setHeight?: boolean;
|
setHeight?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
showOnMobile?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CustomHeader = (props: CustomHeaderProps) => {
|
const Header = (props: HeaderProps) => {
|
||||||
const { variant = EHeaderVariant.PRIMARY, className = "", setHeight = true, children, ...rest } = props;
|
const {
|
||||||
|
variant = EHeaderVariant.PRIMARY,
|
||||||
|
className = "",
|
||||||
|
showOnMobile = true,
|
||||||
|
setHeight = true,
|
||||||
|
children,
|
||||||
|
...rest
|
||||||
|
} = props;
|
||||||
|
|
||||||
const style = getHeaderStyle(variant, setHeight);
|
const style = getHeaderStyle(variant, setHeight, showOnMobile);
|
||||||
return (
|
return (
|
||||||
<CustomRow
|
<Row
|
||||||
variant={variant === EHeaderVariant.PRIMARY ? ERowVariant.HUGGING : ERowVariant.REGULAR}
|
variant={variant === EHeaderVariant.PRIMARY ? ERowVariant.HUGGING : ERowVariant.REGULAR}
|
||||||
className={cn(style, className)}
|
className={cn(style, className)}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</CustomRow>
|
</Row>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const LeftItem = (props: CustomHeaderProps) => (
|
const LeftItem = (props: HeaderProps) => (
|
||||||
<div className="flex flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">{props.children}</div>
|
<div
|
||||||
|
className={cn("flex flex-wrap items-center gap-2 overflow-ellipsis whitespace-nowrap max-w-[80%]", props.className)}
|
||||||
|
>
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
const RightItem = (props: CustomHeaderProps) => (
|
const RightItem = (props: HeaderProps) => (
|
||||||
<div className="w-full flex items-center justify-end gap-3">{props.children}</div>
|
<div className={cn("flex justify-end gap-3 w-auto items-baseline", props.className)}>{props.children}</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
CustomHeader.LeftItem = LeftItem;
|
Header.LeftItem = LeftItem;
|
||||||
CustomHeader.RightItem = RightItem;
|
Header.RightItem = RightItem;
|
||||||
CustomHeader.displayName = "plane-ui-header";
|
Header.displayName = "plane-ui-header";
|
||||||
|
|
||||||
export { CustomHeader, EHeaderVariant };
|
export { Header, EHeaderVariant };
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,16 @@ export interface IHeaderProperties {
|
||||||
export const headerStyle: IHeaderProperties = {
|
export const headerStyle: IHeaderProperties = {
|
||||||
[EHeaderVariant.PRIMARY]:
|
[EHeaderVariant.PRIMARY]:
|
||||||
"relative flex w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 bg-custom-sidebar-background-100",
|
"relative flex w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 bg-custom-sidebar-background-100",
|
||||||
[EHeaderVariant.SECONDARY]: "block !py-0 overflow-y-hidden border-b border-custom-border-200",
|
[EHeaderVariant.SECONDARY]: "!py-0 overflow-y-hidden border-b border-custom-border-200 justify-between",
|
||||||
[EHeaderVariant.TERNARY]: "flex justify-between py-2 border-b border-custom-border-200",
|
[EHeaderVariant.TERNARY]: "flex flex-wrap justify-between py-2 border-b border-custom-border-200 gap-2",
|
||||||
};
|
};
|
||||||
export const minHeights: IHeaderProperties = {
|
export const minHeights: IHeaderProperties = {
|
||||||
[EHeaderVariant.PRIMARY]: "",
|
[EHeaderVariant.PRIMARY]: "",
|
||||||
[EHeaderVariant.SECONDARY]: "min-h-[52px]",
|
[EHeaderVariant.SECONDARY]: "min-h-[52px]",
|
||||||
[EHeaderVariant.TERNARY]: "",
|
[EHeaderVariant.TERNARY]: "",
|
||||||
};
|
};
|
||||||
export const getHeaderStyle = (variant: THeaderVariant, setMinHeight: boolean) => {
|
export const getHeaderStyle = (variant: THeaderVariant, setMinHeight: boolean, showOnMobile: boolean) => {
|
||||||
const height = setMinHeight ? minHeights[variant] : "";
|
const height = setMinHeight ? minHeights[variant] : "";
|
||||||
return headerStyle[variant] + " " + height;
|
const display = variant === EHeaderVariant.SECONDARY ? (showOnMobile ? "flex" : "hidden md:flex") : "";
|
||||||
|
return " " + headerStyle[variant] + " " + height + " " + display;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -25,3 +25,6 @@ export * from "./popovers";
|
||||||
export * from "./tables";
|
export * from "./tables";
|
||||||
export * from "./header";
|
export * from "./header";
|
||||||
export * from "./row";
|
export * from "./row";
|
||||||
|
export * from "./content-wrapper";
|
||||||
|
export * from "./card";
|
||||||
|
export * from "./tag";
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ import * as React from "react";
|
||||||
import { cn } from "../../helpers";
|
import { cn } from "../../helpers";
|
||||||
import { ERowVariant, rowStyle, TRowVariant } from "./helper";
|
import { ERowVariant, rowStyle, TRowVariant } from "./helper";
|
||||||
|
|
||||||
export interface CustomRowProps extends React.HTMLAttributes<HTMLDivElement> {
|
export interface RowProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||||
variant?: TRowVariant;
|
variant?: TRowVariant;
|
||||||
className?: string;
|
className?: string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CustomRow = React.forwardRef<HTMLDivElement, CustomRowProps>((props, ref) => {
|
const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {
|
||||||
const { variant = ERowVariant.REGULAR, className = "", children, ...rest } = props;
|
const { variant = ERowVariant.REGULAR, className = "", children, ...rest } = props;
|
||||||
|
|
||||||
const style = rowStyle[variant];
|
const style = rowStyle[variant];
|
||||||
|
|
@ -20,6 +20,6 @@ const CustomRow = React.forwardRef<HTMLDivElement, CustomRowProps>((props, ref)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
CustomRow.displayName = "plane-ui-row";
|
Row.displayName = "plane-ui-row";
|
||||||
|
|
||||||
export { CustomRow, ERowVariant };
|
export { Row, ERowVariant };
|
||||||
|
|
|
||||||
24
packages/ui/src/tag/helper.tsx
Normal file
24
packages/ui/src/tag/helper.tsx
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
export enum ETagVariant {
|
||||||
|
OUTLINED = "outlined",
|
||||||
|
}
|
||||||
|
export enum ETagSize {
|
||||||
|
SM = "sm",
|
||||||
|
LG = "lg",
|
||||||
|
}
|
||||||
|
export type TTagVariant = ETagVariant.OUTLINED;
|
||||||
|
|
||||||
|
export type TTagSize = ETagSize.SM | ETagSize.LG;
|
||||||
|
export interface ITagProperties {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const containerStyle: ITagProperties = {
|
||||||
|
[ETagVariant.OUTLINED]:
|
||||||
|
"flex items-center rounded-md border border-custom-border-200 text-xs text-custom-text-300 hover:text-custom-text-200 min-h-[36px] my-auto capitalize flex-wrap cursor-pointer gap-1.5",
|
||||||
|
};
|
||||||
|
export const sizes = {
|
||||||
|
[ETagSize.SM]: "p-1.5",
|
||||||
|
[ETagSize.LG]: "p-6",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getTagStyle = (variant: TTagVariant, size: TTagSize) => containerStyle[variant] + " " + sizes[size];
|
||||||
1
packages/ui/src/tag/index.ts
Normal file
1
packages/ui/src/tag/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export * from "./tag";
|
||||||
25
packages/ui/src/tag/tag.tsx
Normal file
25
packages/ui/src/tag/tag.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import { cn } from "../../helpers";
|
||||||
|
import { ETagSize, ETagVariant, getTagStyle, TTagSize, TTagVariant } from "./helper";
|
||||||
|
|
||||||
|
export interface TagProps extends React.ComponentProps<"div"> {
|
||||||
|
variant?: TTagVariant;
|
||||||
|
size?: TTagSize;
|
||||||
|
className?: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Tag = React.forwardRef<HTMLDivElement, TagProps>((props, ref) => {
|
||||||
|
const { variant = ETagVariant.OUTLINED, className = "", size = ETagSize.SM, children, ...rest } = props;
|
||||||
|
|
||||||
|
const style = getTagStyle(variant, size);
|
||||||
|
return (
|
||||||
|
<div ref={ref} className={cn(style, className)} {...rest}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Tag.displayName = "plane-ui-container";
|
||||||
|
|
||||||
|
export { Tag, ETagVariant, ETagSize };
|
||||||
|
|
@ -2,15 +2,15 @@
|
||||||
|
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, ContrastIcon, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, ContrastIcon, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink } from "@/components/common";
|
import { BreadcrumbLink } from "@/components/common";
|
||||||
// plane web components
|
// plane web components
|
||||||
import { UpgradeBadge } from "@/plane-web/components/workspace";
|
import { UpgradeBadge } from "@/plane-web/components/workspace";
|
||||||
|
|
||||||
export const WorkspaceActiveCycleHeader = observer(() => (
|
export const WorkspaceActiveCycleHeader = observer(() => (
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<Breadcrumbs>
|
<Breadcrumbs>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -23,6 +23,6 @@ export const WorkspaceActiveCycleHeader = observer(() => (
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
<UpgradeBadge size="md" />
|
<UpgradeBadge size="md" />
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { useSearchParams } from "next/navigation";
|
||||||
// icons
|
// icons
|
||||||
import { BarChart2, PanelRight } from "lucide-react";
|
import { BarChart2, PanelRight } from "lucide-react";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink } from "@/components/common";
|
import { BreadcrumbLink } from "@/components/common";
|
||||||
// helpers
|
// helpers
|
||||||
|
|
@ -36,8 +36,8 @@ export const WorkspaceAnalyticsHeader = observer(() => {
|
||||||
}, [toggleWorkspaceAnalyticsSidebar, workspaceAnalyticsSidebarCollapsed]);
|
}, [toggleWorkspaceAnalyticsSidebar, workspaceAnalyticsSidebarCollapsed]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<Breadcrumbs>
|
<Breadcrumbs>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -61,7 +61,7 @@ export const WorkspaceAnalyticsHeader = observer(() => {
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { observer } from "mobx-react";
|
||||||
import { useSearchParams } from "next/navigation";
|
import { useSearchParams } from "next/navigation";
|
||||||
import { Tab } from "@headlessui/react";
|
import { Tab } from "@headlessui/react";
|
||||||
// components
|
// components
|
||||||
import { CustomHeader, EHeaderVariant } from "@plane/ui";
|
import { Header, EHeaderVariant } from "@plane/ui";
|
||||||
import { CustomAnalytics, ScopeAndDemand } from "@/components/analytics";
|
import { CustomAnalytics, ScopeAndDemand } from "@/components/analytics";
|
||||||
import { PageHead } from "@/components/core";
|
import { PageHead } from "@/components/core";
|
||||||
import { EmptyState } from "@/components/empty-state";
|
import { EmptyState } from "@/components/empty-state";
|
||||||
|
|
@ -35,7 +35,7 @@ const AnalyticsPage = observer(() => {
|
||||||
{workspaceProjectIds.length > 0 || loader ? (
|
{workspaceProjectIds.length > 0 || loader ? (
|
||||||
<div className="flex h-full flex-col overflow-hidden bg-custom-background-100">
|
<div className="flex h-full flex-col overflow-hidden bg-custom-background-100">
|
||||||
<Tab.Group as={Fragment} defaultIndex={analytics_tab === "custom" ? 1 : 0}>
|
<Tab.Group as={Fragment} defaultIndex={analytics_tab === "custom" ? 1 : 0}>
|
||||||
<CustomHeader variant={EHeaderVariant.SECONDARY}>
|
<Header variant={EHeaderVariant.SECONDARY}>
|
||||||
<Tab.List as="div" className="flex space-x-2 border-b h-[50px] border-custom-border-200">
|
<Tab.List as="div" className="flex space-x-2 border-b h-[50px] border-custom-border-200">
|
||||||
{ANALYTICS_TABS.map((tab) => (
|
{ANALYTICS_TABS.map((tab) => (
|
||||||
<Tab key={tab.key} as={Fragment}>
|
<Tab key={tab.key} as={Fragment}>
|
||||||
|
|
@ -54,7 +54,7 @@ const AnalyticsPage = observer(() => {
|
||||||
</Tab>
|
</Tab>
|
||||||
))}
|
))}
|
||||||
</Tab.List>
|
</Tab.List>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
<Tab.Panels as={Fragment}>
|
<Tab.Panels as={Fragment}>
|
||||||
<Tab.Panel as={Fragment}>
|
<Tab.Panel as={Fragment}>
|
||||||
<ScopeAndDemand fullScreen />
|
<ScopeAndDemand fullScreen />
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import { Home } from "lucide-react";
|
||||||
import githubBlackImage from "/public/logos/github-black.png";
|
import githubBlackImage from "/public/logos/github-black.png";
|
||||||
import githubWhiteImage from "/public/logos/github-white.png";
|
import githubWhiteImage from "/public/logos/github-white.png";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink } from "@/components/common";
|
import { BreadcrumbLink } from "@/components/common";
|
||||||
// constants
|
// constants
|
||||||
|
|
@ -22,8 +22,8 @@ export const WorkspaceDashboardHeader = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<div>
|
<div>
|
||||||
<Breadcrumbs>
|
<Breadcrumbs>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
|
|
@ -32,8 +32,8 @@ export const WorkspaceDashboardHeader = () => {
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</div>
|
</div>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
<CustomHeader.RightItem>
|
<Header.RightItem>
|
||||||
<a
|
<a
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
captureEvent(GITHUB_REDIRECTED, {
|
captureEvent(GITHUB_REDIRECTED, {
|
||||||
|
|
@ -53,8 +53,8 @@ export const WorkspaceDashboardHeader = () => {
|
||||||
/>
|
/>
|
||||||
<span className="hidden text-xs font-medium sm:hidden md:block">Star us on GitHub</span>
|
<span className="hidden text-xs font-medium sm:hidden md:block">Star us on GitHub</span>
|
||||||
</a>
|
</a>
|
||||||
</CustomHeader.RightItem>
|
</Header.RightItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import Link from "next/link";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import { ChevronDown, PanelRight } from "lucide-react";
|
import { ChevronDown, PanelRight } from "lucide-react";
|
||||||
import { IUserProfileProjectSegregation } from "@plane/types";
|
import { IUserProfileProjectSegregation } from "@plane/types";
|
||||||
import { Breadcrumbs, CustomHeader, CustomMenu, UserActivityIcon } from "@plane/ui";
|
import { Breadcrumbs, Header, CustomMenu, UserActivityIcon } from "@plane/ui";
|
||||||
import { BreadcrumbLink } from "@/components/common";
|
import { BreadcrumbLink } from "@/components/common";
|
||||||
// components
|
// components
|
||||||
import { ProfileIssuesFilter } from "@/components/profile";
|
import { ProfileIssuesFilter } from "@/components/profile";
|
||||||
|
|
@ -46,8 +46,8 @@ export const UserProfileHeader: FC<TUserProfileHeader> = observer((props) => {
|
||||||
const breadcrumbLabel = `${isCurrentUser ? "Your" : userName} Work`;
|
const breadcrumbLabel = `${isCurrentUser ? "Your" : userName} Work`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<div className="flex w-full justify-between">
|
<div className="flex w-full justify-between">
|
||||||
<Breadcrumbs>
|
<Breadcrumbs>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
|
|
@ -68,7 +68,7 @@ export const UserProfileHeader: FC<TUserProfileHeader> = observer((props) => {
|
||||||
className="flex flex-grow justify-center text-sm text-custom-text-200"
|
className="flex flex-grow justify-center text-sm text-custom-text-200"
|
||||||
placement="bottom-start"
|
placement="bottom-start"
|
||||||
customButton={
|
customButton={
|
||||||
<div className="flex items-center gap-2 rounded-md border border-custom-border-400 px-2 py-1.5">
|
<div className="flex items-center gap-2 rounded-md border border-custom-border-200 px-2 py-1.5">
|
||||||
<span className="flex flex-grow justify-center text-sm text-custom-text-200">{type}</span>
|
<span className="flex flex-grow justify-center text-sm text-custom-text-200">{type}</span>
|
||||||
<ChevronDown className="h-4 w-4 text-custom-text-400" />
|
<ChevronDown className="h-4 w-4 text-custom-text-400" />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -104,7 +104,7 @@ export const UserProfileHeader: FC<TUserProfileHeader> = observer((props) => {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import { ChevronDown } from "lucide-react";
|
||||||
// types
|
// types
|
||||||
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "@plane/types";
|
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "@plane/types";
|
||||||
// ui
|
// ui
|
||||||
import { CustomMenu } from "@plane/ui";
|
import { CustomMenu, Row } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues";
|
import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues";
|
||||||
// constants
|
// constants
|
||||||
|
|
@ -109,13 +109,18 @@ export const ProfileIssuesMobileHeader = observer(() => {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-evenly border-b border-custom-border-200 py-2 md:hidden">
|
<div className="flex justify-start border-b border-custom-border-200 py-2 md:hidden">
|
||||||
<CustomMenu
|
<CustomMenu
|
||||||
maxHeight={"md"}
|
maxHeight={"md"}
|
||||||
className="flex flex-grow justify-center text-sm text-custom-text-200"
|
className="flex justify-center text-sm text-custom-text-200"
|
||||||
placement="bottom-start"
|
placement="bottom-start"
|
||||||
customButton={<span className="flex flex-grow justify-center text-sm text-custom-text-200">Layout</span>}
|
customButton={
|
||||||
customButtonClassName="flex flex-grow justify-center text-custom-text-200 text-sm"
|
<Row className="flex flex-start text-sm text-custom-text-200">
|
||||||
|
Layout
|
||||||
|
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200 my-auto" strokeWidth={1} />
|
||||||
|
</Row>
|
||||||
|
}
|
||||||
|
customButtonClassName="flex flex-start text-custom-text-200 text-sm"
|
||||||
closeOnSelect
|
closeOnSelect
|
||||||
>
|
>
|
||||||
{ISSUE_LAYOUTS.map((layout, index) => {
|
{ISSUE_LAYOUTS.map((layout, index) => {
|
||||||
|
|
@ -134,15 +139,15 @@ export const ProfileIssuesMobileHeader = observer(() => {
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</CustomMenu>
|
</CustomMenu>
|
||||||
<div className="flex flex-grow items-center justify-center border-l border-custom-border-200 text-sm text-custom-text-200">
|
<div className="flex items-center justify-start border-l border-custom-border-200 text-sm text-custom-text-200">
|
||||||
<FiltersDropdown
|
<FiltersDropdown
|
||||||
title="Filters"
|
title="Filters"
|
||||||
placement="bottom-end"
|
placement="bottom-end"
|
||||||
menuButton={
|
menuButton={
|
||||||
<span className="flex items-center text-sm text-custom-text-200">
|
<Row className="flex flex-start text-sm text-custom-text-200">
|
||||||
Filters
|
Filters
|
||||||
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" />
|
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={1} />
|
||||||
</span>
|
</Row>
|
||||||
}
|
}
|
||||||
isFiltersApplied={isIssueFilterActive(issueFilters)}
|
isFiltersApplied={isIssueFilterActive(issueFilters)}
|
||||||
>
|
>
|
||||||
|
|
@ -160,15 +165,15 @@ export const ProfileIssuesMobileHeader = observer(() => {
|
||||||
/>
|
/>
|
||||||
</FiltersDropdown>
|
</FiltersDropdown>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-grow items-center justify-center border-l border-custom-border-200 text-sm text-custom-text-200">
|
<div className="flex items-center justify-start border-l border-custom-border-200 text-sm text-custom-text-200">
|
||||||
<FiltersDropdown
|
<FiltersDropdown
|
||||||
title="Display"
|
title="Display"
|
||||||
placement="bottom-end"
|
placement="bottom-end"
|
||||||
menuButton={
|
menuButton={
|
||||||
<span className="flex items-center text-sm text-custom-text-200">
|
<Row className="flex flex-start text-sm text-custom-text-200">
|
||||||
Display
|
Display
|
||||||
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" />
|
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={1} />
|
||||||
</span>
|
</Row>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<DisplayFiltersSelection
|
<DisplayFiltersSelection
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { useParams, usePathname } from "next/navigation";
|
||||||
|
|
||||||
// components
|
// components
|
||||||
// constants
|
// constants
|
||||||
import { CustomHeader, EHeaderVariant } from "@plane/ui";
|
import { Header, EHeaderVariant } from "@plane/ui";
|
||||||
import { PROFILE_ADMINS_TAB, PROFILE_VIEWER_TAB } from "@/constants/profile";
|
import { PROFILE_ADMINS_TAB, PROFILE_VIEWER_TAB } from "@/constants/profile";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
@ -21,7 +21,7 @@ export const ProfileNavbar: React.FC<Props> = (props) => {
|
||||||
const tabsList = isAuthorized ? [...PROFILE_VIEWER_TAB, ...PROFILE_ADMINS_TAB] : PROFILE_VIEWER_TAB;
|
const tabsList = isAuthorized ? [...PROFILE_VIEWER_TAB, ...PROFILE_ADMINS_TAB] : PROFILE_VIEWER_TAB;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader variant={EHeaderVariant.SECONDARY} className="sticky -top-0.5 hidden md:flex md:static">
|
<Header variant={EHeaderVariant.SECONDARY} showOnMobile={false}>
|
||||||
<div className="flex items-center overflow-x-scroll">
|
<div className="flex items-center overflow-x-scroll">
|
||||||
{tabsList.map((tab) => (
|
{tabsList.map((tab) => (
|
||||||
<Link key={tab.route} href={`/${workspaceSlug}/profile/${userId}/${tab.route}`}>
|
<Link key={tab.route} href={`/${workspaceSlug}/profile/${userId}/${tab.route}`}>
|
||||||
|
|
@ -37,6 +37,6 @@ export const ProfileNavbar: React.FC<Props> = (props) => {
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import useSWR from "swr";
|
||||||
// types
|
// types
|
||||||
import { IUserStateDistribution, TStateGroups } from "@plane/types";
|
import { IUserStateDistribution, TStateGroups } from "@plane/types";
|
||||||
// components
|
// components
|
||||||
|
import { ContentWrapper } from "@plane/ui";
|
||||||
import { PageHead } from "@/components/core";
|
import { PageHead } from "@/components/core";
|
||||||
import {
|
import {
|
||||||
ProfileActivity,
|
ProfileActivity,
|
||||||
|
|
@ -40,7 +41,7 @@ export default function ProfileOverviewPage() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHead title="Your work" />
|
<PageHead title="Your work" />
|
||||||
<div className="h-full w-full space-y-7 overflow-y-auto px-5 py-5 md:px-9 vertical-scrollbar scrollbar-md">
|
<ContentWrapper className="space-y-7">
|
||||||
<ProfileStats userProfile={userProfile} />
|
<ProfileStats userProfile={userProfile} />
|
||||||
<ProfileWorkload stateDistribution={stateDistribution} />
|
<ProfileWorkload stateDistribution={stateDistribution} />
|
||||||
<div className="grid grid-cols-1 items-stretch gap-5 xl:grid-cols-2">
|
<div className="grid grid-cols-1 items-stretch gap-5 xl:grid-cols-2">
|
||||||
|
|
@ -48,7 +49,7 @@ export default function ProfileOverviewPage() {
|
||||||
<ProfileStateDistribution stateDistribution={stateDistribution} userProfile={userProfile} />
|
<ProfileStateDistribution stateDistribution={stateDistribution} userProfile={userProfile} />
|
||||||
</div>
|
</div>
|
||||||
<ProfileActivity />
|
<ProfileActivity />
|
||||||
</div>
|
</ContentWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { FC } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
// ui
|
// ui
|
||||||
import { ArchiveIcon, Breadcrumbs, Tooltip, CustomHeader } from "@plane/ui";
|
import { ArchiveIcon, Breadcrumbs, Tooltip, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink, Logo } from "@/components/common";
|
import { BreadcrumbLink, Logo } from "@/components/common";
|
||||||
// constants
|
// constants
|
||||||
|
|
@ -38,8 +38,8 @@ export const ProjectArchivesHeader: FC<TProps> = observer((props: TProps) => {
|
||||||
PROJECT_ARCHIVES_BREADCRUMB_LIST[activeTab as keyof typeof PROJECT_ARCHIVES_BREADCRUMB_LIST];
|
PROJECT_ARCHIVES_BREADCRUMB_LIST[activeTab as keyof typeof PROJECT_ARCHIVES_BREADCRUMB_LIST];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<div className="flex items-center gap-2.5">
|
<div className="flex items-center gap-2.5">
|
||||||
<Breadcrumbs onBack={router.back} isLoading={loader}>
|
<Breadcrumbs onBack={router.back} isLoading={loader}>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
|
|
@ -92,7 +92,7 @@ export const ProjectArchivesHeader: FC<TProps> = observer((props: TProps) => {
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { observer } from "mobx-react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
// ui
|
// ui
|
||||||
import { ArchiveIcon, Breadcrumbs, LayersIcon, CustomHeader } from "@plane/ui";
|
import { ArchiveIcon, Breadcrumbs, LayersIcon, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink, Logo } from "@/components/common";
|
import { BreadcrumbLink, Logo } from "@/components/common";
|
||||||
import { IssueDetailQuickActions } from "@/components/issues";
|
import { IssueDetailQuickActions } from "@/components/issues";
|
||||||
|
|
@ -36,8 +36,8 @@ export const ProjectArchivedIssueDetailsHeader = observer(() => {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<Breadcrumbs isLoading={loader}>
|
<Breadcrumbs isLoading={loader}>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -88,14 +88,14 @@ export const ProjectArchivedIssueDetailsHeader = observer(() => {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
<CustomHeader.RightItem>
|
<Header.RightItem>
|
||||||
<IssueDetailQuickActions
|
<IssueDetailQuickActions
|
||||||
workspaceSlug={workspaceSlug.toString()}
|
workspaceSlug={workspaceSlug.toString()}
|
||||||
projectId={projectId.toString()}
|
projectId={projectId.toString()}
|
||||||
issueId={archivedIssueId.toString()}
|
issueId={archivedIssueId.toString()}
|
||||||
/>
|
/>
|
||||||
</CustomHeader.RightItem>
|
</Header.RightItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import { ArrowRight, PanelRight } from "lucide-react";
|
||||||
// types
|
// types
|
||||||
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
|
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, Button, ContrastIcon, CustomMenu, Tooltip, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, Button, ContrastIcon, CustomMenu, Tooltip, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { ProjectAnalyticsModal } from "@/components/analytics";
|
import { ProjectAnalyticsModal } from "@/components/analytics";
|
||||||
import { BreadcrumbLink, Logo } from "@/components/common";
|
import { BreadcrumbLink, Logo } from "@/components/common";
|
||||||
|
|
@ -161,8 +161,8 @@ export const CycleIssuesHeader: React.FC = observer(() => {
|
||||||
onClose={() => setAnalyticsModal(false)}
|
onClose={() => setAnalyticsModal(false)}
|
||||||
cycleDetails={cycleDetails ?? undefined}
|
cycleDetails={cycleDetails ?? undefined}
|
||||||
/>
|
/>
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Breadcrumbs onBack={router.back} isLoading={loader}>
|
<Breadcrumbs onBack={router.back} isLoading={loader}>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
|
|
@ -235,8 +235,8 @@ export const CycleIssuesHeader: React.FC = observer(() => {
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</div>
|
</div>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
<CustomHeader.RightItem>
|
<Header.RightItem>
|
||||||
<div className="hidden items-center gap-2 md:flex ">
|
<div className="hidden items-center gap-2 md:flex ">
|
||||||
<LayoutSelection
|
<LayoutSelection
|
||||||
layouts={[
|
layouts={[
|
||||||
|
|
@ -317,8 +317,8 @@ export const CycleIssuesHeader: React.FC = observer(() => {
|
||||||
>
|
>
|
||||||
<PanelRight className={cn("h-4 w-4", !isSidebarCollapsed ? "text-[#3E63DD]" : "text-custom-text-200")} />
|
<PanelRight className={cn("h-4 w-4", !isSidebarCollapsed ? "text-[#3E63DD]" : "text-custom-text-200")} />
|
||||||
</button>
|
</button>
|
||||||
</CustomHeader.RightItem>
|
</Header.RightItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { FC } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, Button, ContrastIcon, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, Button, ContrastIcon, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink, Logo } from "@/components/common";
|
import { BreadcrumbLink, Logo } from "@/components/common";
|
||||||
import { CyclesViewHeader } from "@/components/cycles";
|
import { CyclesViewHeader } from "@/components/cycles";
|
||||||
|
|
@ -30,8 +30,8 @@ export const CyclesListHeader: FC = observer(() => {
|
||||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<Breadcrumbs onBack={router.back} isLoading={loader}>
|
<Breadcrumbs onBack={router.back} isLoading={loader}>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -54,8 +54,8 @@ export const CyclesListHeader: FC = observer(() => {
|
||||||
link={<BreadcrumbLink label="Cycles" icon={<ContrastIcon className="h-4 w-4 text-custom-text-300" />} />}
|
link={<BreadcrumbLink label="Cycles" icon={<ContrastIcon className="h-4 w-4 text-custom-text-300" />} />}
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
<CustomHeader.RightItem>
|
<Header.RightItem>
|
||||||
{canUserCreateCycle && currentProjectDetails ? (
|
{canUserCreateCycle && currentProjectDetails ? (
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<CyclesViewHeader projectId={currentProjectDetails.id} />
|
<CyclesViewHeader projectId={currentProjectDetails.id} />
|
||||||
|
|
@ -73,7 +73,7 @@ export const CyclesListHeader: FC = observer(() => {
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
</CustomHeader.RightItem>
|
</Header.RightItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { useParams } from "next/navigation";
|
||||||
// types
|
// types
|
||||||
import { TCycleFilters } from "@plane/types";
|
import { TCycleFilters } from "@plane/types";
|
||||||
// components
|
// components
|
||||||
import { CustomHeader, EHeaderVariant } from "@plane/ui";
|
import { Header, EHeaderVariant } from "@plane/ui";
|
||||||
import { PageHead } from "@/components/core";
|
import { PageHead } from "@/components/core";
|
||||||
import { CyclesView, CycleCreateUpdateModal, CycleAppliedFiltersList } from "@/components/cycles";
|
import { CyclesView, CycleCreateUpdateModal, CycleAppliedFiltersList } from "@/components/cycles";
|
||||||
import { EmptyState } from "@/components/empty-state";
|
import { EmptyState } from "@/components/empty-state";
|
||||||
|
|
@ -82,13 +82,13 @@ const ProjectCyclesPage = observer(() => {
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{calculateTotalFilters(currentProjectFilters ?? {}) !== 0 && (
|
{calculateTotalFilters(currentProjectFilters ?? {}) !== 0 && (
|
||||||
<CustomHeader variant={EHeaderVariant.TERNARY}>
|
<Header variant={EHeaderVariant.TERNARY}>
|
||||||
<CycleAppliedFiltersList
|
<CycleAppliedFiltersList
|
||||||
appliedFilters={currentProjectFilters ?? {}}
|
appliedFilters={currentProjectFilters ?? {}}
|
||||||
handleClearAllFilters={() => clearAllFilters(projectId.toString())}
|
handleClearAllFilters={() => clearAllFilters(projectId.toString())}
|
||||||
handleRemoveFilter={handleRemoveFilter}
|
handleRemoveFilter={handleRemoveFilter}
|
||||||
/>
|
/>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<CyclesView workspaceSlug={workspaceSlug.toString()} projectId={projectId.toString()} />
|
<CyclesView workspaceSlug={workspaceSlug.toString()} projectId={projectId.toString()} />
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { observer } from "mobx-react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import { RefreshCcw } from "lucide-react";
|
import { RefreshCcw } from "lucide-react";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, Button, Intake, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, Button, Intake, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink, Logo } from "@/components/common";
|
import { BreadcrumbLink, Logo } from "@/components/common";
|
||||||
import { InboxIssueCreateEditModalRoot } from "@/components/inbox";
|
import { InboxIssueCreateEditModalRoot } from "@/components/inbox";
|
||||||
|
|
@ -30,8 +30,8 @@ export const ProjectInboxHeader: FC = observer(() => {
|
||||||
const isViewer = currentProjectRole === EUserProjectRoles.VIEWER;
|
const isViewer = currentProjectRole === EUserProjectRoles.VIEWER;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<Breadcrumbs isLoading={currentProjectDetailsLoader}>
|
<Breadcrumbs isLoading={currentProjectDetailsLoader}>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
|
|
@ -64,8 +64,8 @@ export const ProjectInboxHeader: FC = observer(() => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
<CustomHeader.RightItem>
|
<Header.RightItem>
|
||||||
{currentProjectDetails?.inbox_view && workspaceSlug && projectId && !isViewer ? (
|
{currentProjectDetails?.inbox_view && workspaceSlug && projectId && !isViewer ? (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<InboxIssueCreateEditModalRoot
|
<InboxIssueCreateEditModalRoot
|
||||||
|
|
@ -83,7 +83,7 @@ export const ProjectInboxHeader: FC = observer(() => {
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
</CustomHeader.RightItem>
|
</Header.RightItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { observer } from "mobx-react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import { PanelRight } from "lucide-react";
|
import { PanelRight } from "lucide-react";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, LayersIcon, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, LayersIcon, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink, Logo } from "@/components/common";
|
import { BreadcrumbLink, Logo } from "@/components/common";
|
||||||
import { IssueDetailQuickActions } from "@/components/issues";
|
import { IssueDetailQuickActions } from "@/components/issues";
|
||||||
|
|
@ -29,8 +29,8 @@ export const ProjectIssueDetailsHeader = observer(() => {
|
||||||
const isSidebarCollapsed = issueDetailSidebarCollapsed;
|
const isSidebarCollapsed = issueDetailSidebarCollapsed;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<div>
|
<div>
|
||||||
<Breadcrumbs onBack={router.back} isLoading={loader}>
|
<Breadcrumbs onBack={router.back} isLoading={loader}>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
|
|
@ -75,8 +75,8 @@ export const ProjectIssueDetailsHeader = observer(() => {
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</div>
|
</div>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
<CustomHeader.RightItem>
|
<Header.RightItem>
|
||||||
<IssueDetailQuickActions
|
<IssueDetailQuickActions
|
||||||
workspaceSlug={workspaceSlug.toString()}
|
workspaceSlug={workspaceSlug.toString()}
|
||||||
projectId={projectId.toString()}
|
projectId={projectId.toString()}
|
||||||
|
|
@ -87,7 +87,7 @@ export const ProjectIssueDetailsHeader = observer(() => {
|
||||||
className={cn("h-4 w-4 ", !isSidebarCollapsed ? "text-custom-primary-100" : " text-custom-text-200")}
|
className={cn("h-4 w-4 ", !isSidebarCollapsed ? "text-custom-primary-100" : " text-custom-text-200")}
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
</CustomHeader.RightItem>
|
</Header.RightItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { useParams } from "next/navigation";
|
||||||
// icons
|
// icons
|
||||||
import { Briefcase, Circle, ExternalLink } from "lucide-react";
|
import { Briefcase, Circle, ExternalLink } from "lucide-react";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, Button, LayersIcon, Tooltip, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, Button, LayersIcon, Tooltip, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink, CountChip, Logo } from "@/components/common";
|
import { BreadcrumbLink, CountChip, Logo } from "@/components/common";
|
||||||
// constants
|
// constants
|
||||||
|
|
@ -46,8 +46,8 @@ export const ProjectIssuesHeader = observer(() => {
|
||||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<div className="flex items-center gap-2.5">
|
<div className="flex items-center gap-2.5">
|
||||||
<Breadcrumbs onBack={() => router.back()} isLoading={loader}>
|
<Breadcrumbs onBack={() => router.back()} isLoading={loader}>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
|
|
@ -102,8 +102,8 @@ export const ProjectIssuesHeader = observer(() => {
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
<CustomHeader.RightItem>
|
<Header.RightItem>
|
||||||
<div className="hidden gap-3 md:flex">
|
<div className="hidden gap-3 md:flex">
|
||||||
<HeaderFilters
|
<HeaderFilters
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
|
|
@ -125,7 +125,7 @@ export const ProjectIssuesHeader = observer(() => {
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
</CustomHeader.RightItem>
|
</Header.RightItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import { Calendar, ChevronDown, Kanban, List } from "lucide-react";
|
||||||
// types
|
// types
|
||||||
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
|
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
|
||||||
// ui
|
// ui
|
||||||
import { CustomMenu } from "@plane/ui";
|
import { CustomMenu, Row } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { ProjectAnalyticsModal } from "@/components/analytics";
|
import { ProjectAnalyticsModal } from "@/components/analytics";
|
||||||
import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues/issue-layouts";
|
import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues/issue-layouts";
|
||||||
|
|
@ -106,7 +106,12 @@ export const ProjectIssuesMobileHeader = observer(() => {
|
||||||
maxHeight={"md"}
|
maxHeight={"md"}
|
||||||
className="flex flex-grow justify-center text-sm text-custom-text-200"
|
className="flex flex-grow justify-center text-sm text-custom-text-200"
|
||||||
placement="bottom-start"
|
placement="bottom-start"
|
||||||
customButton={<span className="flex flex-grow justify-center text-sm text-custom-text-200">Layout</span>}
|
customButton={
|
||||||
|
<Row className="flex flex-start text-sm text-custom-text-200">
|
||||||
|
Layout
|
||||||
|
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200 my-auto" strokeWidth={1} />
|
||||||
|
</Row>
|
||||||
|
}
|
||||||
customButtonClassName="flex flex-grow justify-center text-custom-text-200 text-sm"
|
customButtonClassName="flex flex-grow justify-center text-custom-text-200 text-sm"
|
||||||
closeOnSelect
|
closeOnSelect
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import { ArrowRight, PanelRight } from "lucide-react";
|
||||||
// types
|
// types
|
||||||
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
|
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, Button, CustomMenu, DiceIcon, Tooltip, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, Button, CustomMenu, DiceIcon, Tooltip, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { ProjectAnalyticsModal } from "@/components/analytics";
|
import { ProjectAnalyticsModal } from "@/components/analytics";
|
||||||
import { BreadcrumbLink, Logo } from "@/components/common";
|
import { BreadcrumbLink, Logo } from "@/components/common";
|
||||||
|
|
@ -161,8 +161,8 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
|
||||||
onClose={() => setAnalyticsModal(false)}
|
onClose={() => setAnalyticsModal(false)}
|
||||||
moduleDetails={moduleDetails ?? undefined}
|
moduleDetails={moduleDetails ?? undefined}
|
||||||
/>
|
/>
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<Breadcrumbs onBack={router.back} isLoading={loader}>
|
<Breadcrumbs onBack={router.back} isLoading={loader}>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -233,8 +233,8 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
<CustomHeader.RightItem>
|
<Header.RightItem>
|
||||||
<div className="hidden gap-2 md:flex">
|
<div className="hidden gap-2 md:flex">
|
||||||
<LayoutSelection
|
<LayoutSelection
|
||||||
layouts={[
|
layouts={[
|
||||||
|
|
@ -317,8 +317,8 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
|
||||||
className={cn("block h-4 w-4 md:hidden", !isSidebarCollapsed ? "text-[#3E63DD]" : "text-custom-text-200")}
|
className={cn("block h-4 w-4 md:hidden", !isSidebarCollapsed ? "text-[#3E63DD]" : "text-custom-text-200")}
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
</CustomHeader.RightItem>
|
</Header.RightItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, Button, DiceIcon, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, Button, DiceIcon, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink, Logo } from "@/components/common";
|
import { BreadcrumbLink, Logo } from "@/components/common";
|
||||||
import { ModuleViewHeader } from "@/components/modules";
|
import { ModuleViewHeader } from "@/components/modules";
|
||||||
|
|
@ -30,8 +30,8 @@ export const ModulesListHeader: React.FC = observer(() => {
|
||||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<div>
|
<div>
|
||||||
<Breadcrumbs onBack={router.back} isLoading={loader}>
|
<Breadcrumbs onBack={router.back} isLoading={loader}>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
|
|
@ -56,8 +56,8 @@ export const ModulesListHeader: React.FC = observer(() => {
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</div>
|
</div>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
<CustomHeader.RightItem>
|
<Header.RightItem>
|
||||||
<ModuleViewHeader />
|
<ModuleViewHeader />
|
||||||
{canUserCreateModule ? (
|
{canUserCreateModule ? (
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -73,7 +73,7 @@ export const ModulesListHeader: React.FC = observer(() => {
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
</CustomHeader.RightItem>
|
</Header.RightItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { CustomMenu } from "@plane/ui";
|
import { ChevronDown } from "lucide-react";
|
||||||
|
import { CustomMenu, Row } from "@plane/ui";
|
||||||
import { MODULE_VIEW_LAYOUTS } from "@/constants/module";
|
import { MODULE_VIEW_LAYOUTS } from "@/constants/module";
|
||||||
import { useModuleFilter, useProject } from "@/hooks/store";
|
import { useModuleFilter, useProject } from "@/hooks/store";
|
||||||
|
|
||||||
|
|
@ -10,12 +11,16 @@ export const ModulesListMobileHeader = observer(() => {
|
||||||
const { updateDisplayFilters } = useModuleFilter();
|
const { updateDisplayFilters } = useModuleFilter();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-center md:hidden">
|
<div className="flex justify-start md:hidden">
|
||||||
<CustomMenu
|
<CustomMenu
|
||||||
maxHeight={"md"}
|
maxHeight={"md"}
|
||||||
className="flex flex-grow justify-center text-custom-text-200 text-sm py-2 border-b border-custom-border-200 bg-custom-sidebar-background-100"
|
className="flex flex-grow justify-start text-custom-text-200 text-sm py-2 border-b border-custom-border-200 bg-custom-sidebar-background-100"
|
||||||
// placement="bottom-start"
|
// placement="bottom-start"
|
||||||
customButton={<span className="flex flex-grow justify-center text-custom-text-200 text-sm">Layout</span>}
|
customButton={
|
||||||
|
<Row className="flex flex-grow justify-start text-custom-text-200 text-sm gap-2">
|
||||||
|
<span>Layout</span> <ChevronDown className="h-4 w-4 text-custom-text-200 my-auto" strokeWidth={1} />
|
||||||
|
</Row>
|
||||||
|
}
|
||||||
customButtonClassName="flex flex-grow justify-center items-center text-custom-text-200 text-sm"
|
customButtonClassName="flex flex-grow justify-center items-center text-custom-text-200 text-sm"
|
||||||
closeOnSelect
|
closeOnSelect
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,7 @@ import { FileText } from "lucide-react";
|
||||||
// types
|
// types
|
||||||
import { TLogoProps } from "@plane/types";
|
import { TLogoProps } from "@plane/types";
|
||||||
// ui
|
// ui
|
||||||
import {
|
import { Breadcrumbs, EmojiIconPicker, EmojiIconPickerTypes, TOAST_TYPE, Tooltip, setToast, Header } from "@plane/ui";
|
||||||
Breadcrumbs,
|
|
||||||
EmojiIconPicker,
|
|
||||||
EmojiIconPickerTypes,
|
|
||||||
TOAST_TYPE,
|
|
||||||
Tooltip,
|
|
||||||
setToast,
|
|
||||||
CustomHeader,
|
|
||||||
} from "@plane/ui";
|
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink, Logo } from "@/components/common";
|
import { BreadcrumbLink, Logo } from "@/components/common";
|
||||||
import { PageEditInformationPopover } from "@/components/pages";
|
import { PageEditInformationPopover } from "@/components/pages";
|
||||||
|
|
@ -67,8 +59,8 @@ export const PageDetailsHeader = observer(() => {
|
||||||
const pageTitle = getPageName(name);
|
const pageTitle = getPageName(name);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<div>
|
<div>
|
||||||
<Breadcrumbs isLoading={loader}>
|
<Breadcrumbs isLoading={loader}>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
|
|
@ -166,11 +158,11 @@ export const PageDetailsHeader = observer(() => {
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</div>
|
</div>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
<CustomHeader.RightItem>
|
<Header.RightItem>
|
||||||
<PageEditInformationPopover page={page} />
|
<PageEditInformationPopover page={page} />
|
||||||
<PageDetailsHeaderExtraActions />
|
<PageDetailsHeaderExtraActions />
|
||||||
</CustomHeader.RightItem>
|
</Header.RightItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { observer } from "mobx-react";
|
||||||
import { useParams, useSearchParams } from "next/navigation";
|
import { useParams, useSearchParams } from "next/navigation";
|
||||||
import { FileText } from "lucide-react";
|
import { FileText } from "lucide-react";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, Button, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, Button, Header } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { BreadcrumbLink, Logo } from "@/components/common";
|
import { BreadcrumbLink, Logo } from "@/components/common";
|
||||||
// constants
|
// constants
|
||||||
|
|
@ -30,8 +30,8 @@ export const PagesListHeader = observer(() => {
|
||||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<div>
|
<div>
|
||||||
<Breadcrumbs isLoading={loader}>
|
<Breadcrumbs isLoading={loader}>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
|
|
@ -56,8 +56,8 @@ export const PagesListHeader = observer(() => {
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</div>
|
</div>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
<CustomHeader.RightItem>
|
<Header.RightItem>
|
||||||
{canUserCreatePage ? (
|
{canUserCreatePage ? (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -77,7 +77,7 @@ export const PagesListHeader = observer(() => {
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
</CustomHeader.RightItem>
|
</Header.RightItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { observer } from "mobx-react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
// ui
|
// ui
|
||||||
import { Settings } from "lucide-react";
|
import { Settings } from "lucide-react";
|
||||||
import { Breadcrumbs, CustomMenu, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, CustomMenu, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink, Logo } from "@/components/common";
|
import { BreadcrumbLink, Logo } from "@/components/common";
|
||||||
// constants
|
// constants
|
||||||
|
|
@ -29,8 +29,8 @@ export const ProjectSettingHeader: FC = observer(() => {
|
||||||
const projectMemberInfo = currentProjectRole || EUserProjectRoles.GUEST;
|
const projectMemberInfo = currentProjectRole || EUserProjectRoles.GUEST;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<div>
|
<div>
|
||||||
<div className="z-50">
|
<div className="z-50">
|
||||||
<Breadcrumbs onBack={router.back} isLoading={loader}>
|
<Breadcrumbs onBack={router.back} isLoading={loader}>
|
||||||
|
|
@ -84,7 +84,7 @@ export const ProjectSettingHeader: FC = observer(() => {
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</CustomMenu>
|
</CustomMenu>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ const LabelsSettingsPage = observer(() => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHead title={pageTitle} />
|
<PageHead title={pageTitle} />
|
||||||
<div ref={scrollableContainerRef} className="h-full w-full gap-10 overflow-y-auto py-8 pr-9">
|
<div ref={scrollableContainerRef} className="h-full w-full gap-10 overflow-y-auto py-2 pr-9">
|
||||||
<ProjectSettingsLabelList />
|
<ProjectSettingsLabelList />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import { Layers, Lock } from "lucide-react";
|
||||||
// types
|
// types
|
||||||
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
|
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, Button, CustomMenu, Tooltip, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, Button, CustomMenu, Tooltip, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink, Logo } from "@/components/common";
|
import { BreadcrumbLink, Logo } from "@/components/common";
|
||||||
import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "@/components/issues";
|
import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "@/components/issues";
|
||||||
|
|
@ -136,8 +136,8 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
|
||||||
const publishLink = getPublishViewLink(viewDetails?.anchor);
|
const publishLink = getPublishViewLink(viewDetails?.anchor);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<Breadcrumbs isLoading={loader}>
|
<Breadcrumbs isLoading={loader}>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -231,8 +231,8 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
<CustomHeader.RightItem>
|
<Header.RightItem>
|
||||||
{!viewDetails?.is_locked ? (
|
{!viewDetails?.is_locked ? (
|
||||||
<>
|
<>
|
||||||
<LayoutSelection
|
<LayoutSelection
|
||||||
|
|
@ -298,7 +298,7 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
</CustomHeader.RightItem>
|
</Header.RightItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { observer } from "mobx-react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import { Layers } from "lucide-react";
|
import { Layers } from "lucide-react";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, Button, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, Button, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink, Logo } from "@/components/common";
|
import { BreadcrumbLink, Logo } from "@/components/common";
|
||||||
import { ViewListHeader } from "@/components/views";
|
import { ViewListHeader } from "@/components/views";
|
||||||
|
|
@ -20,8 +20,8 @@ export const ProjectViewsHeader = observer(() => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<Breadcrumbs isLoading={loader}>
|
<Breadcrumbs isLoading={loader}>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -44,16 +44,16 @@ export const ProjectViewsHeader = observer(() => {
|
||||||
link={<BreadcrumbLink label="Views" icon={<Layers className="h-4 w-4 text-custom-text-300" />} />}
|
link={<BreadcrumbLink label="Views" icon={<Layers className="h-4 w-4 text-custom-text-300" />} />}
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
<CustomHeader.RightItem>
|
<Header.RightItem>
|
||||||
<ViewListHeader />
|
<ViewListHeader />
|
||||||
<div>
|
<div>
|
||||||
<Button variant="primary" size="sm" onClick={() => toggleCreateViewModal(true)}>
|
<Button variant="primary" size="sm" onClick={() => toggleCreateViewModal(true)}>
|
||||||
Add view
|
Add view
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</CustomHeader.RightItem>
|
</Header.RightItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { observer } from "mobx-react";
|
||||||
// icons
|
// icons
|
||||||
import { ChevronDown, ListFilter } from "lucide-react";
|
import { ChevronDown, ListFilter } from "lucide-react";
|
||||||
// components
|
// components
|
||||||
|
import { Row } from "@plane/ui";
|
||||||
import { FiltersDropdown } from "@/components/issues/issue-layouts";
|
import { FiltersDropdown } from "@/components/issues/issue-layouts";
|
||||||
import { ViewFiltersSelection } from "@/components/views/filters/filter-selection";
|
import { ViewFiltersSelection } from "@/components/views/filters/filter-selection";
|
||||||
import { ViewOrderByDropdown } from "@/components/views/filters/order-by";
|
import { ViewOrderByDropdown } from "@/components/views/filters/order-by";
|
||||||
|
|
@ -20,7 +21,7 @@ export const ViewMobileHeader = observer(() => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="md:hidden flex justify-evenly border-b border-custom-border-200 py-2 z-[13] bg-custom-background-100">
|
<div className="md:hidden flex justify-evenly border-b border-custom-border-200 py-2 z-[13] bg-custom-background-100">
|
||||||
<div className="flex flex-grow items-center justify-center border-l border-custom-border-200 text-sm text-custom-text-200">
|
<Row className="flex items-center justify-start border-l border-custom-border-200 text-sm text-custom-text-200">
|
||||||
<ViewOrderByDropdown
|
<ViewOrderByDropdown
|
||||||
sortBy={filters.sortBy}
|
sortBy={filters.sortBy}
|
||||||
sortKey={filters.sortKey}
|
sortKey={filters.sortKey}
|
||||||
|
|
@ -30,18 +31,18 @@ export const ViewMobileHeader = observer(() => {
|
||||||
}}
|
}}
|
||||||
isMobile
|
isMobile
|
||||||
/>
|
/>
|
||||||
</div>
|
</Row>
|
||||||
<div className="flex flex-grow items-center justify-center border-l border-custom-border-200 text-sm text-custom-text-200">
|
<div className="flex flex-grow items-center justify-start border-l border-custom-border-200 text-sm text-custom-text-200">
|
||||||
<FiltersDropdown
|
<FiltersDropdown
|
||||||
icon={<ListFilter className="h-3 w-3" />}
|
icon={<ListFilter className="h-3 w-3" />}
|
||||||
title="Filters"
|
title="Filters"
|
||||||
placement="bottom-end"
|
placement="bottom-end"
|
||||||
isFiltersApplied={false}
|
isFiltersApplied={false}
|
||||||
menuButton={
|
menuButton={
|
||||||
<span className="flex items-center text-sm text-custom-text-200">
|
<Row className="flex items-center text-sm text-custom-text-200">
|
||||||
Filters
|
Filters
|
||||||
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" />
|
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={1} />
|
||||||
</span>
|
</Row>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ViewFiltersSelection
|
<ViewFiltersSelection
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { observer } from "mobx-react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
// components
|
// components
|
||||||
import { TViewFilterProps } from "@plane/types";
|
import { TViewFilterProps } from "@plane/types";
|
||||||
import { CustomHeader, EHeaderVariant } from "@plane/ui";
|
import { Header, EHeaderVariant } from "@plane/ui";
|
||||||
import { PageHead } from "@/components/core";
|
import { PageHead } from "@/components/core";
|
||||||
import { EmptyState } from "@/components/empty-state";
|
import { EmptyState } from "@/components/empty-state";
|
||||||
import { ProjectViewsList } from "@/components/views";
|
import { ProjectViewsList } from "@/components/views";
|
||||||
|
|
@ -63,14 +63,14 @@ const ProjectViewsPage = observer(() => {
|
||||||
<>
|
<>
|
||||||
<PageHead title={pageTitle} />
|
<PageHead title={pageTitle} />
|
||||||
{isFiltersApplied && (
|
{isFiltersApplied && (
|
||||||
<CustomHeader variant={EHeaderVariant.TERNARY}>
|
<Header variant={EHeaderVariant.TERNARY}>
|
||||||
<ViewAppliedFiltersList
|
<ViewAppliedFiltersList
|
||||||
appliedFilters={filters.filters ?? {}}
|
appliedFilters={filters.filters ?? {}}
|
||||||
handleClearAllFilters={clearAllFilters}
|
handleClearAllFilters={clearAllFilters}
|
||||||
handleRemoveFilter={handleRemoveFilter}
|
handleRemoveFilter={handleRemoveFilter}
|
||||||
alwaysAllowEditing
|
alwaysAllowEditing
|
||||||
/>
|
/>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
)}
|
)}
|
||||||
<ProjectViewsList />
|
<ProjectViewsList />
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ const ApiTokensPage = observer(() => {
|
||||||
<>
|
<>
|
||||||
<PageHead title={pageTitle} />
|
<PageHead title={pageTitle} />
|
||||||
<CreateApiTokenModal isOpen={isCreateTokenModalOpen} onClose={() => setIsCreateTokenModalOpen(false)} />
|
<CreateApiTokenModal isOpen={isCreateTokenModalOpen} onClose={() => setIsCreateTokenModalOpen(false)} />
|
||||||
<section className="w-full overflow-y-auto md:pr-9 pr-4">
|
<section className="w-full overflow-y-auto">
|
||||||
{tokens.length > 0 ? (
|
{tokens.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
<div className="flex items-center justify-between border-b border-custom-border-200 py-3.5">
|
<div className="flex items-center justify-between border-b border-custom-border-200 py-3.5">
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,11 @@ const ExportsPage = observer(() => {
|
||||||
<>
|
<>
|
||||||
<PageHead title={pageTitle} />
|
<PageHead title={pageTitle} />
|
||||||
<div
|
<div
|
||||||
className={cn("w-full overflow-y-auto md:pr-9 pr-4", {
|
className={cn("w-full overflow-y-auto", {
|
||||||
"opacity-60": !canPerformWorkspaceMemberActions,
|
"opacity-60": !canPerformWorkspaceMemberActions,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<div className="flex items-center border-b border-custom-border-100 py-3.5">
|
<div className="flex items-center border-b border-custom-border-100 pb-3.5">
|
||||||
<h3 className="text-xl font-medium">Exports</h3>
|
<h3 className="text-xl font-medium">Exports</h3>
|
||||||
</div>
|
</div>
|
||||||
<ExportGuide />
|
<ExportGuide />
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { FC } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { Settings } from "lucide-react";
|
import { Settings } from "lucide-react";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink } from "@/components/common";
|
import { BreadcrumbLink } from "@/components/common";
|
||||||
// hooks
|
// hooks
|
||||||
|
|
@ -14,8 +14,8 @@ export const WorkspaceSettingHeader: FC = observer(() => {
|
||||||
const { currentWorkspace, loader } = useWorkspace();
|
const { currentWorkspace, loader } = useWorkspace();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<Breadcrumbs isLoading={loader}>
|
<Breadcrumbs isLoading={loader}>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -29,7 +29,7 @@ export const WorkspaceSettingHeader: FC = observer(() => {
|
||||||
/>
|
/>
|
||||||
<Breadcrumbs.BreadcrumbItem type="text" link={<BreadcrumbLink label="Settings" />} />
|
<Breadcrumbs.BreadcrumbItem type="text" link={<BreadcrumbLink label="Settings" />} />
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@ const ImportsPage = observer(() => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHead title={pageTitle} />
|
<PageHead title={pageTitle} />
|
||||||
<section className="w-full overflow-y-auto py-8 pr-9">
|
<section className="w-full overflow-y-auto">
|
||||||
<div className="flex items-center border-b border-custom-border-100 py-3.5">
|
<div className="flex items-center border-b border-custom-border-100 pb-3.5">
|
||||||
<h3 className="text-xl font-medium">Imports</h3>
|
<h3 className="text-xl font-medium">Imports</h3>
|
||||||
</div>
|
</div>
|
||||||
<IntegrationGuide />
|
<IntegrationGuide />
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
"use client"
|
"use client";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
@ -33,7 +33,7 @@ const WorkspaceIntegrationsPage = observer(() => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHead title={pageTitle} />
|
<PageHead title={pageTitle} />
|
||||||
<div className="mt-10 flex h-full w-full justify-center p-4">
|
<div className="mt-10 flex h-full w-full justify-center">
|
||||||
<p className="text-sm text-custom-text-300">You are not authorized to access this page.</p>
|
<p className="text-sm text-custom-text-300">You are not authorized to access this page.</p>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
@ -46,7 +46,7 @@ const WorkspaceIntegrationsPage = observer(() => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHead title={pageTitle} />
|
<PageHead title={pageTitle} />
|
||||||
<section className="w-full overflow-y-auto py-8 pr-9">
|
<section className="w-full overflow-y-auto">
|
||||||
<IntegrationAndImportExportBanner bannerName="Integrations" />
|
<IntegrationAndImportExportBanner bannerName="Integrations" />
|
||||||
<div>
|
<div>
|
||||||
{appIntegrations ? (
|
{appIntegrations ? (
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
// components
|
// components
|
||||||
import { AppHeader, ContentWrapper } from "@/components/core";
|
import { ContentWrapper } from "@plane/ui";
|
||||||
|
import { AppHeader } from "@/components/core";
|
||||||
// local components
|
// local components
|
||||||
import { WorkspaceSettingHeader } from "./header";
|
import { WorkspaceSettingHeader } from "./header";
|
||||||
import { MobileWorkspaceSettingsTabs } from "./mobile-header-tabs";
|
import { MobileWorkspaceSettingsTabs } from "./mobile-header-tabs";
|
||||||
|
|
@ -18,17 +19,13 @@ export default function WorkspaceSettingLayout(props: IWorkspaceSettingLayout) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AppHeader header={<WorkspaceSettingHeader />} />
|
<AppHeader header={<WorkspaceSettingHeader />} />
|
||||||
<ContentWrapper>
|
<MobileWorkspaceSettingsTabs />
|
||||||
<div className="inset-y-0 z-20 flex h-full w-full gap-2">
|
<ContentWrapper className="flex-row inset-y-0 gap-4">
|
||||||
<div className="w-80 flex-shrink-0 overflow-y-hidden pt-8 sm:hidden hidden md:block lg:block">
|
<div className="w-80 flex-shrink-0 overflow-y-hidden sm:hidden hidden md:block lg:block">
|
||||||
<WorkspaceSettingsSidebar />
|
<WorkspaceSettingsSidebar />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col relative w-full overflow-hidden">
|
<div className="flex flex-col relative w-full overflow-hidden">
|
||||||
<MobileWorkspaceSettingsTabs />
|
<div className="w-full overflow-x-hidden overflow-y-scroll vertical-scrollbar scrollbar-md">{children}</div>
|
||||||
<div className="w-full pl-4 md:pl-0 md:py-8 py-2 overflow-x-hidden overflow-y-scroll vertical-scrollbar scrollbar-md">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</ContentWrapper>
|
</ContentWrapper>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -99,11 +99,11 @@ const WorkspaceMembersSettingsPage = observer(() => {
|
||||||
onSubmit={handleWorkspaceInvite}
|
onSubmit={handleWorkspaceInvite}
|
||||||
/>
|
/>
|
||||||
<section
|
<section
|
||||||
className={cn("w-full overflow-y-auto md:pr-9 pr-4", {
|
className={cn("w-full overflow-y-auto", {
|
||||||
"opacity-60": !canPerformWorkspaceMemberActions,
|
"opacity-60": !canPerformWorkspaceMemberActions,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between gap-4 py-3.5">
|
<div className="flex items-center justify-between gap-4 pb-3.5">
|
||||||
<h4 className="text-xl font-medium">Members</h4>
|
<h4 className="text-xl font-medium">Members</h4>
|
||||||
<div className="ml-auto flex items-center gap-1.5 rounded-md border border-custom-border-200 bg-custom-background-100 px-2.5 py-1.5">
|
<div className="ml-auto flex items-center gap-1.5 rounded-md border border-custom-border-200 bg-custom-background-100 px-2.5 py-1.5">
|
||||||
<Search className="h-3.5 w-3.5 text-custom-text-400" />
|
<Search className="h-3.5 w-3.5 text-custom-text-400" />
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ export const WorkspaceSettingsSidebar = observer(() => {
|
||||||
const workspaceMemberInfo = currentWorkspaceRole || EUserWorkspaceRoles.GUEST;
|
const workspaceMemberInfo = currentWorkspaceRole || EUserWorkspaceRoles.GUEST;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex w-80 flex-col gap-6 px-5">
|
<div className="flex w-80 flex-col gap-6">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<span className="text-xs font-semibold text-custom-sidebar-text-400">SETTINGS</span>
|
<span className="text-xs font-semibold text-custom-sidebar-text-400">SETTINGS</span>
|
||||||
<div className="flex w-full flex-col gap-1">
|
<div className="flex w-full flex-col gap-1">
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ const WebhooksListPage = observer(() => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHead title={pageTitle} />
|
<PageHead title={pageTitle} />
|
||||||
<div className="w-full overflow-y-auto md:pr-9 pr-4">
|
<div className="w-full overflow-y-auto">
|
||||||
<CreateWebhookModal
|
<CreateWebhookModal
|
||||||
createWebhook={createWebhook}
|
createWebhook={createWebhook}
|
||||||
clearSecretKey={clearSecretKey}
|
clearSecretKey={clearSecretKey}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import { useParams } from "next/navigation";
|
||||||
import { Layers } from "lucide-react";
|
import { Layers } from "lucide-react";
|
||||||
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
|
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, Button, CustomHeader } from "@plane/ui";
|
import { Breadcrumbs, Button, Header } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { BreadcrumbLink } from "@/components/common";
|
import { BreadcrumbLink } from "@/components/common";
|
||||||
import { DisplayFiltersSelection, FiltersDropdown, FilterSelection } from "@/components/issues";
|
import { DisplayFiltersSelection, FiltersDropdown, FilterSelection } from "@/components/issues";
|
||||||
|
|
@ -98,17 +98,17 @@ export const GlobalIssuesHeader = observer(() => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CreateUpdateWorkspaceViewModal isOpen={createViewModal} onClose={() => setCreateViewModal(false)} />
|
<CreateUpdateWorkspaceViewModal isOpen={createViewModal} onClose={() => setCreateViewModal(false)} />
|
||||||
<CustomHeader>
|
<Header>
|
||||||
<CustomHeader.LeftItem>
|
<Header.LeftItem>
|
||||||
<Breadcrumbs>
|
<Breadcrumbs>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
type="text"
|
type="text"
|
||||||
link={<BreadcrumbLink label={`Views`} icon={<Layers className="h-4 w-4 text-custom-text-300" />} />}
|
link={<BreadcrumbLink label={`Views`} icon={<Layers className="h-4 w-4 text-custom-text-300" />} />}
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</CustomHeader.LeftItem>
|
</Header.LeftItem>
|
||||||
|
|
||||||
<CustomHeader.RightItem>
|
<Header.RightItem>
|
||||||
{!isLocked ? (
|
{!isLocked ? (
|
||||||
<>
|
<>
|
||||||
<FiltersDropdown
|
<FiltersDropdown
|
||||||
|
|
@ -143,8 +143,8 @@ export const GlobalIssuesHeader = observer(() => {
|
||||||
<Button variant="primary" size="sm" onClick={() => setCreateViewModal(true)}>
|
<Button variant="primary" size="sm" onClick={() => setCreateViewModal(true)}>
|
||||||
Add view
|
Add view
|
||||||
</Button>
|
</Button>
|
||||||
</CustomHeader.RightItem>
|
</Header.RightItem>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import React from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
// ui
|
// ui
|
||||||
import { getButtonStyling } from "@plane/ui";
|
import { ContentWrapper, getButtonStyling } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { ProIcon } from "@/components/common";
|
import { ProIcon } from "@/components/common";
|
||||||
// constants
|
// constants
|
||||||
|
|
@ -24,7 +24,7 @@ export const WorkspaceActiveCyclesUpgrade = observer(() => {
|
||||||
const isDarkMode = userProfile?.theme.theme === "dark";
|
const isDarkMode = userProfile?.theme.theme === "dark";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="vertical-scrollbar scrollbar-lg flex h-full flex-col gap-10 rounded-xl px-8 pt-8">
|
<ContentWrapper className="gap-10">
|
||||||
<div
|
<div
|
||||||
className={cn("item-center flex min-h-[25rem] justify-between rounded-xl", {
|
className={cn("item-center flex min-h-[25rem] justify-between rounded-xl", {
|
||||||
"bg-gradient-to-l from-[#CFCFCF] to-[#212121]": userProfile?.theme.theme === "dark",
|
"bg-gradient-to-l from-[#CFCFCF] to-[#212121]": userProfile?.theme.theme === "dark",
|
||||||
|
|
@ -89,6 +89,6 @@ export const WorkspaceActiveCyclesUpgrade = observer(() => {
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ContentWrapper>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { MARKETING_PRICING_PAGE_LINK } from "@/constants/common";
|
||||||
export const BillingRoot = () => (
|
export const BillingRoot = () => (
|
||||||
<section className="w-full overflow-y-auto md:pr-9 pr-4">
|
<section className="w-full overflow-y-auto md:pr-9 pr-4">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center border-b border-custom-border-100 py-3.5">
|
<div className="flex items-center border-b border-custom-border-100 pb-3.5">
|
||||||
<h3 className="text-xl font-medium">Billing and Plans</h3>
|
<h3 className="text-xl font-medium">Billing and Plans</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import useSWR from "swr";
|
||||||
import { IAnalyticsParams } from "@plane/types";
|
import { IAnalyticsParams } from "@plane/types";
|
||||||
// services
|
// services
|
||||||
// components
|
// components
|
||||||
|
import { ContentWrapper } from "@plane/ui";
|
||||||
import { CustomAnalyticsSelectBar, CustomAnalyticsMainContent, CustomAnalyticsSidebar } from "@/components/analytics";
|
import { CustomAnalyticsSelectBar, CustomAnalyticsMainContent, CustomAnalyticsSidebar } from "@/components/analytics";
|
||||||
// types
|
// types
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
|
|
@ -53,7 +54,7 @@ export const CustomAnalytics: React.FC<Props> = observer((props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn("relative flex h-full w-full overflow-hidden", isProjectLevel ? "flex-col-reverse" : "")}>
|
<div className={cn("relative flex h-full w-full overflow-hidden", isProjectLevel ? "flex-col-reverse" : "")}>
|
||||||
<div className="flex h-full w-full flex-col overflow-hidden">
|
<ContentWrapper>
|
||||||
<CustomAnalyticsSelectBar
|
<CustomAnalyticsSelectBar
|
||||||
control={control}
|
control={control}
|
||||||
setValue={setValue}
|
setValue={setValue}
|
||||||
|
|
@ -67,7 +68,7 @@ export const CustomAnalytics: React.FC<Props> = observer((props) => {
|
||||||
params={params}
|
params={params}
|
||||||
fullScreen={fullScreen}
|
fullScreen={fullScreen}
|
||||||
/>
|
/>
|
||||||
</div>
|
</ContentWrapper>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ export const CustomAnalyticsMainContent: React.FC<Props> = (props) => {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
<Loader className="space-y-6 p-5">
|
<Loader className="space-y-6">
|
||||||
<Loader.Item height="300px" />
|
<Loader.Item height="300px" />
|
||||||
<Loader className="space-y-4">
|
<Loader className="space-y-4">
|
||||||
<Loader.Item height="30px" />
|
<Loader.Item height="30px" />
|
||||||
|
|
|
||||||
|
|
@ -31,13 +31,13 @@ export const CustomAnalyticsSelectBar: React.FC<Props> = observer((props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`grid items-center gap-4 px-5 py-2.5 ${
|
className={`grid items-center gap-4 pb-2.5 ${
|
||||||
isProjectLevel ? "grid-cols-1 sm:grid-cols-3" : "grid-cols-2"
|
isProjectLevel ? "grid-cols-1 sm:grid-cols-3" : "grid-cols-2"
|
||||||
} ${fullScreen ? "md:py-5 lg:grid-cols-4" : ""}`}
|
} ${fullScreen ? "md:pb-5 lg:grid-cols-4" : ""}`}
|
||||||
>
|
>
|
||||||
{!isProjectLevel && (
|
{!isProjectLevel && (
|
||||||
<div>
|
<div>
|
||||||
<h6 className="text-xs text-custom-text-200">Project</h6>
|
<h6 className="text-xs text-custom-text-200 mb-2">Project</h6>
|
||||||
<Controller
|
<Controller
|
||||||
name="project"
|
name="project"
|
||||||
control={control}
|
control={control}
|
||||||
|
|
@ -52,7 +52,7 @@ export const CustomAnalyticsSelectBar: React.FC<Props> = observer((props) => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
<h6 className="text-xs text-custom-text-200">Measure (y-axis)</h6>
|
<h6 className="text-xs text-custom-text-200 mb-2">Measure (y-axis)</h6>
|
||||||
<Controller
|
<Controller
|
||||||
name="y_axis"
|
name="y_axis"
|
||||||
control={control}
|
control={control}
|
||||||
|
|
@ -60,7 +60,7 @@ export const CustomAnalyticsSelectBar: React.FC<Props> = observer((props) => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h6 className="text-xs text-custom-text-200">Dimension (x-axis)</h6>
|
<h6 className="text-xs text-custom-text-200 mb-2">Dimension (x-axis)</h6>
|
||||||
<Controller
|
<Controller
|
||||||
name="x_axis"
|
name="x_axis"
|
||||||
control={control}
|
control={control}
|
||||||
|
|
@ -79,7 +79,7 @@ export const CustomAnalyticsSelectBar: React.FC<Props> = observer((props) => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h6 className="text-xs text-custom-text-200">Group</h6>
|
<h6 className="text-xs text-custom-text-200 mb-2">Group</h6>
|
||||||
<Controller
|
<Controller
|
||||||
name="segment"
|
name="segment"
|
||||||
control={control}
|
control={control}
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,11 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AnalyticsTable: React.FC<Props> = ({ analytics, barGraphData, params, yAxisKey }) => (
|
export const AnalyticsTable: React.FC<Props> = ({ analytics, barGraphData, params, yAxisKey }) => (
|
||||||
<div className="w-full overflow-hidden overflow-x-auto">
|
<div className="w-full overflow-hidden overflow-x-auto absolute left-0">
|
||||||
<table className="w-full overflow-hidden divide-y divide-custom-border-200 whitespace-nowrap border-y border-custom-border-200">
|
<table className="w-full overflow-hidden divide-y divide-custom-border-200 whitespace-nowrap border-y border-custom-border-200">
|
||||||
<thead className="bg-custom-background-80">
|
<thead className="bg-custom-background-80">
|
||||||
<tr className="divide-x divide-custom-border-200 text-sm text-custom-text-100">
|
<tr className="divide-x divide-custom-border-200 text-sm text-custom-text-100">
|
||||||
<th scope="col" className="px-2.5 py-3 text-left font-medium">
|
<th scope="col" className="px-page-x py-3 text-left font-medium">
|
||||||
{ANALYTICS_X_AXIS_VALUES.find((v) => v.value === params.x_axis)?.label}
|
{ANALYTICS_X_AXIS_VALUES.find((v) => v.value === params.x_axis)?.label}
|
||||||
</th>
|
</th>
|
||||||
{params.segment ? (
|
{params.segment ? (
|
||||||
|
|
@ -31,7 +31,7 @@ export const AnalyticsTable: React.FC<Props> = ({ analytics, barGraphData, param
|
||||||
<th
|
<th
|
||||||
key={`segment-${key}`}
|
key={`segment-${key}`}
|
||||||
scope="col"
|
scope="col"
|
||||||
className={`px-2.5 py-3 text-left font-medium ${
|
className={`px-page-x py-3 text-left font-medium ${
|
||||||
params.segment === "priority" || params.segment === "state__group" ? "capitalize" : ""
|
params.segment === "priority" || params.segment === "state__group" ? "capitalize" : ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
|
@ -51,7 +51,7 @@ export const AnalyticsTable: React.FC<Props> = ({ analytics, barGraphData, param
|
||||||
</th>
|
</th>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<th scope="col" className="px-2.5 py-3 text-left font-medium sm:pr-0">
|
<th scope="col" className="px-page-x py-3 text-left font-medium sm:pr-0">
|
||||||
{ANALYTICS_Y_AXIS_VALUES.find((v) => v.value === params.y_axis)?.label}
|
{ANALYTICS_Y_AXIS_VALUES.find((v) => v.value === params.y_axis)?.label}
|
||||||
</th>
|
</th>
|
||||||
)}
|
)}
|
||||||
|
|
@ -60,7 +60,7 @@ export const AnalyticsTable: React.FC<Props> = ({ analytics, barGraphData, param
|
||||||
<tbody className="divide-y divide-custom-border-200">
|
<tbody className="divide-y divide-custom-border-200">
|
||||||
{barGraphData.data.map((item, index) => (
|
{barGraphData.data.map((item, index) => (
|
||||||
<tr key={`table-row-${index}`} className="divide-x divide-custom-border-200 text-xs text-custom-text-200">
|
<tr key={`table-row-${index}`} className="divide-x divide-custom-border-200 text-xs text-custom-text-200">
|
||||||
<td className="px-2.5 py-2">
|
<td className="px-page-x py-2">
|
||||||
<div className="relative flex items-center gap-2 w-full overflow-hidden">
|
<div className="relative flex items-center gap-2 w-full overflow-hidden">
|
||||||
<div className="flex-shrink-0 h-3 w-3 rounded overflow-hidden">
|
<div className="flex-shrink-0 h-3 w-3 rounded overflow-hidden">
|
||||||
{params.x_axis === "priority" ? (
|
{params.x_axis === "priority" ? (
|
||||||
|
|
@ -90,12 +90,12 @@ export const AnalyticsTable: React.FC<Props> = ({ analytics, barGraphData, param
|
||||||
</td>
|
</td>
|
||||||
{params.segment ? (
|
{params.segment ? (
|
||||||
barGraphData.xAxisKeys.map((key, index) => (
|
barGraphData.xAxisKeys.map((key, index) => (
|
||||||
<td key={`segment-value-${index}`} className="whitespace-nowrap px-2.5 py-2 sm:pr-0">
|
<td key={`segment-value-${index}`} className="whitespace-nowrap px-page-x py-2 sm:pr-0">
|
||||||
{item[key] ?? 0}
|
{item[key] ?? 0}
|
||||||
</td>
|
</td>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<td className="whitespace-nowrap px-2.5 py-2 sm:pr-0">{item[yAxisKey]}</td>
|
<td className="whitespace-nowrap px-page-x py-2 sm:pr-0">{item[yAxisKey]}</td>
|
||||||
)}
|
)}
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// types
|
// types
|
||||||
import { IDefaultAnalyticsResponse, TStateGroups } from "@plane/types";
|
import { IDefaultAnalyticsResponse, TStateGroups } from "@plane/types";
|
||||||
// constants
|
// constants
|
||||||
|
import { Card } from "@plane/ui";
|
||||||
import { STATE_GROUPS } from "@/constants/state";
|
import { STATE_GROUPS } from "@/constants/state";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
@ -8,7 +9,7 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AnalyticsDemand: React.FC<Props> = ({ defaultAnalytics }) => (
|
export const AnalyticsDemand: React.FC<Props> = ({ defaultAnalytics }) => (
|
||||||
<div className="space-y-3 rounded-[10px] border border-custom-border-200 p-3">
|
<Card>
|
||||||
<div>
|
<div>
|
||||||
<h4 className="text-base font-medium text-custom-text-100">Total open tasks</h4>
|
<h4 className="text-base font-medium text-custom-text-100">Total open tasks</h4>
|
||||||
<h3 className="mt-1 text-xl font-semibold">{defaultAnalytics.open_issues}</h3>
|
<h3 className="mt-1 text-xl font-semibold">{defaultAnalytics.open_issues}</h3>
|
||||||
|
|
@ -47,5 +48,5 @@ export const AnalyticsDemand: React.FC<Props> = ({ defaultAnalytics }) => (
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// ui
|
// ui
|
||||||
|
import { Card } from "@plane/ui";
|
||||||
import { ProfileEmptyState } from "@/components/ui";
|
import { ProfileEmptyState } from "@/components/ui";
|
||||||
// image
|
// image
|
||||||
import emptyUsers from "@/public/empty-state/empty_users.svg";
|
import emptyUsers from "@/public/empty-state/empty_users.svg";
|
||||||
|
|
@ -18,7 +19,7 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AnalyticsLeaderBoard: React.FC<Props> = ({ users, title, emptyStateMessage, workspaceSlug }) => (
|
export const AnalyticsLeaderBoard: React.FC<Props> = ({ users, title, emptyStateMessage, workspaceSlug }) => (
|
||||||
<div className="rounded-[10px] border border-custom-border-200 p-3">
|
<Card>
|
||||||
<h6 className="text-base font-medium">{title}</h6>
|
<h6 className="text-base font-medium">{title}</h6>
|
||||||
{users.length > 0 ? (
|
{users.length > 0 ? (
|
||||||
<div className="mt-3 space-y-3">
|
<div className="mt-3 space-y-3">
|
||||||
|
|
@ -57,5 +58,5 @@ export const AnalyticsLeaderBoard: React.FC<Props> = ({ users, title, emptyState
|
||||||
<ProfileEmptyState title="No Data yet" description={emptyStateMessage} image={emptyUsers} />
|
<ProfileEmptyState title="No Data yet" description={emptyStateMessage} image={emptyUsers} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
// ui
|
// ui
|
||||||
import { Button, Loader } from "@plane/ui";
|
import { Button, ContentWrapper, Loader } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { AnalyticsDemand, AnalyticsLeaderBoard, AnalyticsScope, AnalyticsYearWiseIssues } from "@/components/analytics";
|
import { AnalyticsDemand, AnalyticsLeaderBoard, AnalyticsScope, AnalyticsYearWiseIssues } from "@/components/analytics";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
|
|
@ -50,7 +50,7 @@ export const ScopeAndDemand: React.FC<Props> = (props) => {
|
||||||
<>
|
<>
|
||||||
{!defaultAnalyticsError ? (
|
{!defaultAnalyticsError ? (
|
||||||
defaultAnalytics ? (
|
defaultAnalytics ? (
|
||||||
<div className="h-full overflow-y-auto p-5 text-sm vertical-scrollbar scrollbar-lg">
|
<ContentWrapper>
|
||||||
<div className={`grid grid-cols-1 gap-5 ${fullScreen ? "md:grid-cols-2" : ""}`}>
|
<div className={`grid grid-cols-1 gap-5 ${fullScreen ? "md:grid-cols-2" : ""}`}>
|
||||||
<AnalyticsDemand defaultAnalytics={defaultAnalytics} />
|
<AnalyticsDemand defaultAnalytics={defaultAnalytics} />
|
||||||
<AnalyticsScope
|
<AnalyticsScope
|
||||||
|
|
@ -87,7 +87,7 @@ export const ScopeAndDemand: React.FC<Props> = (props) => {
|
||||||
<AnalyticsYearWiseIssues defaultAnalytics={defaultAnalytics} />
|
<AnalyticsYearWiseIssues defaultAnalytics={defaultAnalytics} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ContentWrapper>
|
||||||
) : (
|
) : (
|
||||||
<Loader className="grid grid-cols-1 gap-5 p-5 lg:grid-cols-2">
|
<Loader className="grid grid-cols-1 gap-5 p-5 lg:grid-cols-2">
|
||||||
<Loader.Item height="250px" />
|
<Loader.Item height="250px" />
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
// ui
|
// ui
|
||||||
import { IDefaultAnalyticsUser } from "@plane/types";
|
import { IDefaultAnalyticsUser } from "@plane/types";
|
||||||
|
import { Card } from "@plane/ui";
|
||||||
import { BarGraph, ProfileEmptyState } from "@/components/ui";
|
import { BarGraph, ProfileEmptyState } from "@/components/ui";
|
||||||
// image
|
// image
|
||||||
import emptyBarGraph from "@/public/empty-state/empty_bar_graph.svg";
|
import emptyBarGraph from "@/public/empty-state/empty_bar_graph.svg";
|
||||||
|
|
@ -11,7 +12,7 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AnalyticsScope: React.FC<Props> = ({ pendingUnAssignedIssuesUser, pendingAssignedIssues }) => (
|
export const AnalyticsScope: React.FC<Props> = ({ pendingUnAssignedIssuesUser, pendingAssignedIssues }) => (
|
||||||
<div className="rounded-[10px] border border-custom-border-200 p-3">
|
<Card>
|
||||||
<div className="divide-y divide-custom-border-200">
|
<div className="divide-y divide-custom-border-200">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
|
|
@ -87,5 +88,5 @@ export const AnalyticsScope: React.FC<Props> = ({ pendingUnAssignedIssuesUser, p
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
// ui
|
// ui
|
||||||
import { IDefaultAnalyticsResponse } from "@plane/types";
|
import { IDefaultAnalyticsResponse } from "@plane/types";
|
||||||
|
import { Card } from "@plane/ui";
|
||||||
import { LineGraph, ProfileEmptyState } from "@/components/ui";
|
import { LineGraph, ProfileEmptyState } from "@/components/ui";
|
||||||
// image
|
// image
|
||||||
import { MONTHS_LIST } from "@/constants/calendar";
|
import { MONTHS_LIST } from "@/constants/calendar";
|
||||||
|
|
@ -12,8 +13,8 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AnalyticsYearWiseIssues: React.FC<Props> = ({ defaultAnalytics }) => (
|
export const AnalyticsYearWiseIssues: React.FC<Props> = ({ defaultAnalytics }) => (
|
||||||
<div className="rounded-[10px] border border-custom-border-200 py-3">
|
<Card>
|
||||||
<h1 className="px-3 text-base font-medium">Issues closed in a year</h1>
|
<h1 className="py-3 text-base font-medium">Issues closed in a year</h1>
|
||||||
{defaultAnalytics.issue_completed_month_wise.length > 0 ? (
|
{defaultAnalytics.issue_completed_month_wise.length > 0 ? (
|
||||||
<LineGraph
|
<LineGraph
|
||||||
data={[
|
data={[
|
||||||
|
|
@ -55,5 +56,5 @@ export const AnalyticsYearWiseIssues: React.FC<Props> = ({ defaultAnalytics }) =
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ export const AppliedDateFilters: React.FC<Props> = observer((props) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{values.map((date) => (
|
{values.map((date) => (
|
||||||
<div key={date} className="flex items-center gap-1 rounded bg-custom-background-80 p-1 text-xs">
|
<div key={date} className="flex items-center gap-1 rounded bg-custom-background-80 py-1 px-1.5 text-xs">
|
||||||
<span className="normal-case">{getDateLabel(date)}</span>
|
<span className="normal-case">{getDateLabel(date)}</span>
|
||||||
{editable && (
|
{editable && (
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ export const AppliedMembersFilters: React.FC<Props> = observer((props) => {
|
||||||
if (!memberDetails) return null;
|
if (!memberDetails) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={memberId} className="flex items-center gap-1 rounded bg-custom-background-80 p-1 text-xs">
|
<div key={memberId} className="flex items-center gap-1 rounded bg-custom-background-80 py-1 px-1.5 text-xs">
|
||||||
<Avatar name={memberDetails.display_name} src={memberDetails.avatar} showTooltip={false} />
|
<Avatar name={memberDetails.display_name} src={memberDetails.avatar} showTooltip={false} size={"sm"} />
|
||||||
<span className="normal-case">{memberDetails.display_name}</span>
|
<span className="normal-case">{memberDetails.display_name}</span>
|
||||||
{editable && (
|
{editable && (
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export const BreadcrumbLink: React.FC<Props> = (props) => {
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex cursor-default items-center gap-1 text-sm font-medium text-custom-text-100">
|
<div className="flex cursor-default items-center gap-1 text-sm font-medium text-custom-text-100">
|
||||||
{icon && <div className="flex h-5 w-5 items-center justify-center overflow-hidden">{icon}</div>}
|
{icon && <div className="flex h-5 w-5 items-center justify-start overflow-hidden">{icon}</div>}
|
||||||
<div className="relative line-clamp-1 block max-w-[150px] overflow-hidden truncate">{label}</div>
|
<div className="relative line-clamp-1 block max-w-[150px] overflow-hidden truncate">{label}</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
// components
|
// components
|
||||||
import { CustomRow } from "@plane/ui";
|
import { Row } from "@plane/ui";
|
||||||
import { SidebarHamburgerToggle } from "@/components/core";
|
import { SidebarHamburgerToggle } from "@/components/core";
|
||||||
|
|
||||||
export interface AppHeaderProps {
|
export interface AppHeaderProps {
|
||||||
|
|
@ -15,12 +15,12 @@ export const AppHeader = (props: AppHeaderProps) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="z-[15]">
|
<div className="z-[15]">
|
||||||
<CustomRow className="h-[3.75rem] z-10 flex gap-2 w-full items-center border-b border-custom-border-200">
|
<Row className="h-[3.75rem] z-10 flex gap-2 w-full items-center border-b border-custom-border-200">
|
||||||
<div className="block bg-custom-sidebar-background-100 md:hidden">
|
<div className="block bg-custom-sidebar-background-100 md:hidden">
|
||||||
<SidebarHamburgerToggle />
|
<SidebarHamburgerToggle />
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">{header}</div>
|
<div className="w-full">{header}</div>
|
||||||
</CustomRow>
|
</Row>
|
||||||
{mobileHeader && mobileHeader}
|
{mobileHeader && mobileHeader}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
"use client";
|
"use client";
|
||||||
import React, { FC } from "react";
|
import React, { FC } from "react";
|
||||||
// ui
|
// ui
|
||||||
import { ControlLink, Tooltip } from "@plane/ui";
|
import { ControlLink, Row, Tooltip } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { cn } from "@/helpers/common.helper";
|
import { cn } from "@/helpers/common.helper";
|
||||||
// hooks
|
// hooks
|
||||||
|
|
@ -51,9 +51,9 @@ export const ListItem: FC<IListItemProps> = (props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={parentRef} className="relative">
|
<div ref={parentRef} className="relative">
|
||||||
<div
|
<Row
|
||||||
className={cn(
|
className={cn(
|
||||||
"group min-h-[52px] flex w-full flex-col items-center justify-between gap-3 px-6 py-4 text-sm border-b border-custom-border-200 bg-custom-background-100 hover:bg-custom-background-90 ",
|
"group min-h-[52px] flex w-full flex-col items-center justify-between gap-3 py-4 text-sm border-b border-custom-border-200 bg-custom-background-100 hover:bg-custom-background-90 ",
|
||||||
{
|
{
|
||||||
"xl:gap-5 xl:py-0 xl:flex-row": isSidebarOpen,
|
"xl:gap-5 xl:py-0 xl:flex-row": isSidebarOpen,
|
||||||
"lg:gap-5 lg:py-0 lg:flex-row": !isSidebarOpen,
|
"lg:gap-5 lg:py-0 lg:flex-row": !isSidebarOpen,
|
||||||
|
|
@ -93,7 +93,7 @@ export const ListItem: FC<IListItemProps> = (props) => {
|
||||||
{actionableItems}
|
{actionableItems}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import React, { FC } from "react";
|
import React, { FC } from "react";
|
||||||
|
import { Row, ERowVariant } from "@plane/ui";
|
||||||
|
|
||||||
interface IListContainer {
|
interface IListContainer {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|
@ -6,5 +7,12 @@ interface IListContainer {
|
||||||
|
|
||||||
export const ListLayout: FC<IListContainer> = (props) => {
|
export const ListLayout: FC<IListContainer> = (props) => {
|
||||||
const { children } = props;
|
const { children } = props;
|
||||||
return <div className="flex h-full w-full flex-col overflow-y-auto vertical-scrollbar scrollbar-lg">{children}</div>;
|
return (
|
||||||
|
<Row
|
||||||
|
variant={ERowVariant.HUGGING}
|
||||||
|
className="flex h-full w-full flex-col overflow-y-auto vertical-scrollbar scrollbar-lg"
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { Disclosure } from "@headlessui/react";
|
import { Disclosure } from "@headlessui/react";
|
||||||
|
// ui
|
||||||
|
import { Row } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import {
|
import {
|
||||||
ActiveCycleProductivity,
|
ActiveCycleProductivity,
|
||||||
|
|
@ -36,14 +38,14 @@ export const ActiveCycleRoot: React.FC<IActiveCycleDetails> = observer((props) =
|
||||||
<Disclosure as="div" className="flex flex-shrink-0 flex-col" defaultOpen>
|
<Disclosure as="div" className="flex flex-shrink-0 flex-col" defaultOpen>
|
||||||
{({ open }) => (
|
{({ open }) => (
|
||||||
<>
|
<>
|
||||||
<Disclosure.Button className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-custom-border-200 bg-custom-background-90 px-7 py-1 cursor-pointer">
|
<Disclosure.Button className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-custom-border-200 bg-custom-background-90 cursor-pointer">
|
||||||
<CycleListGroupHeader title="Active cycle" type="current" isExpanded={open} />
|
<CycleListGroupHeader title="Active cycle" type="current" isExpanded={open} />
|
||||||
</Disclosure.Button>
|
</Disclosure.Button>
|
||||||
<Disclosure.Panel>
|
<Disclosure.Panel>
|
||||||
{!currentProjectActiveCycle ? (
|
{!currentProjectActiveCycle ? (
|
||||||
<EmptyState type={EmptyStateType.PROJECT_CYCLE_ACTIVE} size="sm" />
|
<EmptyState type={EmptyStateType.PROJECT_CYCLE_ACTIVE} size="sm" />
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-col bg-custom-background-90 border-b border-custom-border-200">
|
<div className="flex flex-col border-b border-custom-border-200">
|
||||||
{currentProjectActiveCycleId && (
|
{currentProjectActiveCycleId && (
|
||||||
<CyclesListItem
|
<CyclesListItem
|
||||||
key={currentProjectActiveCycleId}
|
key={currentProjectActiveCycleId}
|
||||||
|
|
@ -53,7 +55,7 @@ export const ActiveCycleRoot: React.FC<IActiveCycleDetails> = observer((props) =
|
||||||
className="!border-b-transparent"
|
className="!border-b-transparent"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div className="bg-custom-background-100 pt-3 pb-6 px-6">
|
<Row className="bg-custom-background-100 pt-3 pb-6">
|
||||||
<div className="grid grid-cols-1 bg-custom-background-100 gap-3 lg:grid-cols-2 xl:grid-cols-3">
|
<div className="grid grid-cols-1 bg-custom-background-100 gap-3 lg:grid-cols-2 xl:grid-cols-3">
|
||||||
<ActiveCycleProgress
|
<ActiveCycleProgress
|
||||||
handleFiltersUpdate={handleFiltersUpdate}
|
handleFiltersUpdate={handleFiltersUpdate}
|
||||||
|
|
@ -75,7 +77,7 @@ export const ActiveCycleRoot: React.FC<IActiveCycleDetails> = observer((props) =
|
||||||
cycleIssueDetails={cycleIssueDetails as ActiveCycleIssueDetails}
|
cycleIssueDetails={cycleIssueDetails as ActiveCycleIssueDetails}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Disclosure.Panel>
|
</Disclosure.Panel>
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ export const AppliedDateFilters: React.FC<Props> = observer((props) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{values.map((date) => (
|
{values.map((date) => (
|
||||||
<div key={date} className="flex items-center gap-1 rounded bg-custom-background-80 p-1 text-xs">
|
<div key={date} className="flex items-center gap-1 rounded bg-custom-background-80 py-1 px-1.5 text-xs">
|
||||||
<span className="normal-case">{getDateLabel(date)}</span>
|
<span className="normal-case">{getDateLabel(date)}</span>
|
||||||
{editable && (
|
{editable && (
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { observer } from "mobx-react";
|
||||||
import { X } from "lucide-react";
|
import { X } from "lucide-react";
|
||||||
import { TCycleFilters } from "@plane/types";
|
import { TCycleFilters } from "@plane/types";
|
||||||
// hooks
|
// hooks
|
||||||
|
import { Tag } from "@plane/ui";
|
||||||
import { AppliedDateFilters, AppliedStatusFilters } from "@/components/cycles";
|
import { AppliedDateFilters, AppliedStatusFilters } from "@/components/cycles";
|
||||||
import { EUserProjectRoles } from "@/constants/project";
|
import { EUserProjectRoles } from "@/constants/project";
|
||||||
import { replaceUnderscoreIfSnakeCase } from "@/helpers/string.helper";
|
import { replaceUnderscoreIfSnakeCase } from "@/helpers/string.helper";
|
||||||
|
|
@ -42,10 +43,7 @@ export const CycleAppliedFiltersList: React.FC<Props> = observer((props) => {
|
||||||
if (Array.isArray(value) && value.length === 0) return;
|
if (Array.isArray(value) && value.length === 0) return;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tag key={filterKey}>
|
||||||
key={filterKey}
|
|
||||||
className="flex flex-wrap items-center gap-2 rounded-md border border-custom-border-200 px-2 py-1 capitalize"
|
|
||||||
>
|
|
||||||
<span className="text-xs text-custom-text-300">{replaceUnderscoreIfSnakeCase(filterKey)}</span>
|
<span className="text-xs text-custom-text-300">{replaceUnderscoreIfSnakeCase(filterKey)}</span>
|
||||||
<div className="flex flex-wrap items-center gap-1">
|
<div className="flex flex-wrap items-center gap-1">
|
||||||
{filterKey === "status" && (
|
{filterKey === "status" && (
|
||||||
|
|
@ -72,17 +70,15 @@ export const CycleAppliedFiltersList: React.FC<Props> = observer((props) => {
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Tag>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{isEditingAllowed && (
|
{isEditingAllowed && (
|
||||||
<button
|
<button type="button" onClick={handleClearAllFilters}>
|
||||||
type="button"
|
<Tag>
|
||||||
onClick={handleClearAllFilters}
|
Clear all
|
||||||
className="flex items-center gap-2 rounded-md border border-custom-border-200 px-2 py-1 text-xs text-custom-text-300 hover:text-custom-text-200"
|
<X size={12} strokeWidth={2} />
|
||||||
>
|
</Tag>
|
||||||
Clear all
|
|
||||||
<X size={12} strokeWidth={2} />
|
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ export const AppliedStatusFilters: React.FC<Props> = observer((props) => {
|
||||||
<div
|
<div
|
||||||
key={status}
|
key={status}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center gap-1 rounded p-1 text-xs",
|
"flex items-center gap-1 rounded py-1 px-1.5 text-xs",
|
||||||
statusDetails?.bgColor,
|
statusDetails?.bgColor,
|
||||||
statusDetails?.textColor
|
statusDetails?.textColor
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -50,14 +50,12 @@ export const CyclesView: FC<ICyclesView> = observer((props) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<CyclesList
|
||||||
<CyclesList
|
completedCycleIds={filteredCompletedCycleIds ?? []}
|
||||||
completedCycleIds={filteredCompletedCycleIds ?? []}
|
upcomingCycleIds={filteredUpcomingCycleIds}
|
||||||
upcomingCycleIds={filteredUpcomingCycleIds}
|
cycleIds={filteredCycleIds}
|
||||||
cycleIds={filteredCycleIds}
|
workspaceSlug={workspaceSlug}
|
||||||
workspaceSlug={workspaceSlug}
|
projectId={projectId}
|
||||||
projectId={projectId}
|
/>
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { ChevronDown } from "lucide-react";
|
||||||
// types
|
// types
|
||||||
import { TCycleGroups } from "@plane/types";
|
import { TCycleGroups } from "@plane/types";
|
||||||
// icons
|
// icons
|
||||||
import { CycleGroupIcon } from "@plane/ui";
|
import { Row, CycleGroupIcon } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { cn } from "@/helpers/common.helper";
|
import { cn } from "@/helpers/common.helper";
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ type Props = {
|
||||||
export const CycleListGroupHeader: FC<Props> = (props) => {
|
export const CycleListGroupHeader: FC<Props> = (props) => {
|
||||||
const { type, title, count, showCount = false, isExpanded = false } = props;
|
const { type, title, count, showCount = false, isExpanded = false } = props;
|
||||||
return (
|
return (
|
||||||
<div className="relative flex items-center justify-between w-full gap-5 py-1.5">
|
<Row className="flex items-center justify-between py-2.5">
|
||||||
<div className="flex items-center gap-5 flex-shrink-0">
|
<div className="flex items-center gap-5 flex-shrink-0">
|
||||||
<div className="flex h-5 w-5 flex-shrink-0 items-center justify-center overflow-hidden rounded-sm">
|
<div className="flex h-5 w-5 flex-shrink-0 items-center justify-center overflow-hidden rounded-sm">
|
||||||
<CycleGroupIcon cycleGroup={type} className="h-5 w-5" />
|
<CycleGroupIcon cycleGroup={type} className="h-5 w-5" />
|
||||||
|
|
@ -36,6 +36,6 @@ export const CycleListGroupHeader: FC<Props> = (props) => {
|
||||||
"rotate-180": isExpanded,
|
"rotate-180": isExpanded,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</div>
|
</Row>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { FC } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { Disclosure } from "@headlessui/react";
|
import { Disclosure } from "@headlessui/react";
|
||||||
// components
|
// components
|
||||||
|
import { ContentWrapper, ERowVariant } from "@plane/ui";
|
||||||
import { ListLayout } from "@/components/core/list";
|
import { ListLayout } from "@/components/core/list";
|
||||||
import { ActiveCycleRoot, CycleListGroupHeader, CyclePeekOverview, CyclesListMap } from "@/components/cycles";
|
import { ActiveCycleRoot, CycleListGroupHeader, CyclePeekOverview, CyclesListMap } from "@/components/cycles";
|
||||||
|
|
||||||
|
|
@ -18,7 +19,7 @@ export const CyclesList: FC<ICyclesList> = observer((props) => {
|
||||||
const { completedCycleIds, upcomingCycleIds, cycleIds, workspaceSlug, projectId, isArchived = false } = props;
|
const { completedCycleIds, upcomingCycleIds, cycleIds, workspaceSlug, projectId, isArchived = false } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full justify-between ">
|
<ContentWrapper variant={ERowVariant.HUGGING}>
|
||||||
<ListLayout>
|
<ListLayout>
|
||||||
{isArchived ? (
|
{isArchived ? (
|
||||||
<>
|
<>
|
||||||
|
|
@ -32,7 +33,7 @@ export const CyclesList: FC<ICyclesList> = observer((props) => {
|
||||||
<Disclosure as="div" className="flex flex-shrink-0 flex-col" defaultOpen>
|
<Disclosure as="div" className="flex flex-shrink-0 flex-col" defaultOpen>
|
||||||
{({ open }) => (
|
{({ open }) => (
|
||||||
<>
|
<>
|
||||||
<Disclosure.Button className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-custom-border-200 bg-custom-background-90 px-7 py-1 cursor-pointer">
|
<Disclosure.Button className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-custom-border-200 bg-custom-background-90 cursor-pointer">
|
||||||
<CycleListGroupHeader
|
<CycleListGroupHeader
|
||||||
title="Upcoming cycle"
|
title="Upcoming cycle"
|
||||||
type="upcoming"
|
type="upcoming"
|
||||||
|
|
@ -52,7 +53,7 @@ export const CyclesList: FC<ICyclesList> = observer((props) => {
|
||||||
<Disclosure as="div" className="flex flex-shrink-0 flex-col pb-7">
|
<Disclosure as="div" className="flex flex-shrink-0 flex-col pb-7">
|
||||||
{({ open }) => (
|
{({ open }) => (
|
||||||
<>
|
<>
|
||||||
<Disclosure.Button className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-custom-border-200 bg-custom-background-90 px-7 py-1 cursor-pointer">
|
<Disclosure.Button className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-custom-border-200 bg-custom-background-90 cursor-pointer">
|
||||||
<CycleListGroupHeader
|
<CycleListGroupHeader
|
||||||
title="Completed cycle"
|
title="Completed cycle"
|
||||||
type="completed"
|
type="completed"
|
||||||
|
|
@ -71,6 +72,6 @@ export const CyclesList: FC<ICyclesList> = observer((props) => {
|
||||||
)}
|
)}
|
||||||
</ListLayout>
|
</ListLayout>
|
||||||
<CyclePeekOverview projectId={projectId} workspaceSlug={workspaceSlug} isArchived={isArchived} />
|
<CyclePeekOverview projectId={projectId} workspaceSlug={workspaceSlug} isArchived={isArchived} />
|
||||||
</div>
|
</ContentWrapper>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import Link from "next/link";
|
||||||
import { Tab } from "@headlessui/react";
|
import { Tab } from "@headlessui/react";
|
||||||
import { TAssignedIssuesWidgetFilters, TAssignedIssuesWidgetResponse } from "@plane/types";
|
import { TAssignedIssuesWidgetFilters, TAssignedIssuesWidgetResponse } from "@plane/types";
|
||||||
// hooks
|
// hooks
|
||||||
|
import { Card } from "@plane/ui";
|
||||||
import {
|
import {
|
||||||
DurationFilterDropdown,
|
DurationFilterDropdown,
|
||||||
IssuesErrorState,
|
IssuesErrorState,
|
||||||
|
|
@ -79,7 +80,7 @@ export const AssignedIssuesWidget: React.FC<WidgetProps> = observer((props) => {
|
||||||
if ((!widgetDetails || !widgetStats) && !widgetStatsError) return <WidgetLoader widgetKey={WIDGET_KEY} />;
|
if ((!widgetDetails || !widgetStats) && !widgetStatsError) return <WidgetLoader widgetKey={WIDGET_KEY} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-custom-background-100 rounded-xl border-[0.5px] border-custom-border-200 w-full hover:shadow-custom-shadow-4xl duration-300 flex flex-col min-h-96">
|
<Card>
|
||||||
{widgetStatsError ? (
|
{widgetStatsError ? (
|
||||||
<IssuesErrorState
|
<IssuesErrorState
|
||||||
isRefreshing={fetching}
|
isRefreshing={fetching}
|
||||||
|
|
@ -93,7 +94,7 @@ export const AssignedIssuesWidget: React.FC<WidgetProps> = observer((props) => {
|
||||||
) : (
|
) : (
|
||||||
widgetStats && (
|
widgetStats && (
|
||||||
<>
|
<>
|
||||||
<div className="flex items-center justify-between gap-2 p-6 pl-7">
|
<div className="flex items-center justify-between gap-2 mb-4">
|
||||||
<Link
|
<Link
|
||||||
href={`/${workspaceSlug}/workspace-views/assigned/${filterParams}`}
|
href={`/${workspaceSlug}/workspace-views/assigned/${filterParams}`}
|
||||||
className="text-lg font-semibold text-custom-text-300 hover:underline"
|
className="text-lg font-semibold text-custom-text-300 hover:underline"
|
||||||
|
|
@ -137,9 +138,7 @@ export const AssignedIssuesWidget: React.FC<WidgetProps> = observer((props) => {
|
||||||
}}
|
}}
|
||||||
className="h-full flex flex-col"
|
className="h-full flex flex-col"
|
||||||
>
|
>
|
||||||
<div className="px-6">
|
<TabsList durationFilter={selectedDurationFilter} selectedTab={selectedTab} />
|
||||||
<TabsList durationFilter={selectedDurationFilter} selectedTab={selectedTab} />
|
|
||||||
</div>
|
|
||||||
<Tab.Panels as="div" className="h-full">
|
<Tab.Panels as="div" className="h-full">
|
||||||
{tabsList.map((tab) => {
|
{tabsList.map((tab) => {
|
||||||
if (tab.key !== selectedTab) return null;
|
if (tab.key !== selectedTab) return null;
|
||||||
|
|
@ -161,6 +160,6 @@ export const AssignedIssuesWidget: React.FC<WidgetProps> = observer((props) => {
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import Link from "next/link";
|
||||||
import { Tab } from "@headlessui/react";
|
import { Tab } from "@headlessui/react";
|
||||||
import { TCreatedIssuesWidgetFilters, TCreatedIssuesWidgetResponse } from "@plane/types";
|
import { TCreatedIssuesWidgetFilters, TCreatedIssuesWidgetResponse } from "@plane/types";
|
||||||
// hooks
|
// hooks
|
||||||
|
import { Card } from "@plane/ui";
|
||||||
import {
|
import {
|
||||||
DurationFilterDropdown,
|
DurationFilterDropdown,
|
||||||
IssuesErrorState,
|
IssuesErrorState,
|
||||||
|
|
@ -76,7 +77,7 @@ export const CreatedIssuesWidget: React.FC<WidgetProps> = observer((props) => {
|
||||||
if ((!widgetDetails || !widgetStats) && !widgetStatsError) return <WidgetLoader widgetKey={WIDGET_KEY} />;
|
if ((!widgetDetails || !widgetStats) && !widgetStatsError) return <WidgetLoader widgetKey={WIDGET_KEY} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-custom-background-100 rounded-xl border-[0.5px] border-custom-border-200 w-full hover:shadow-custom-shadow-4xl duration-300 flex flex-col min-h-96">
|
<Card>
|
||||||
{widgetStatsError ? (
|
{widgetStatsError ? (
|
||||||
<IssuesErrorState
|
<IssuesErrorState
|
||||||
isRefreshing={fetching}
|
isRefreshing={fetching}
|
||||||
|
|
@ -90,7 +91,7 @@ export const CreatedIssuesWidget: React.FC<WidgetProps> = observer((props) => {
|
||||||
) : (
|
) : (
|
||||||
widgetStats && (
|
widgetStats && (
|
||||||
<>
|
<>
|
||||||
<div className="flex items-center justify-between gap-2 p-6 pl-7">
|
<div className="flex items-center justify-between gap-2 mb-4">
|
||||||
<Link
|
<Link
|
||||||
href={`/${workspaceSlug}/workspace-views/created/${filterParams}`}
|
href={`/${workspaceSlug}/workspace-views/created/${filterParams}`}
|
||||||
className="text-lg font-semibold text-custom-text-300 hover:underline"
|
className="text-lg font-semibold text-custom-text-300 hover:underline"
|
||||||
|
|
@ -134,9 +135,7 @@ export const CreatedIssuesWidget: React.FC<WidgetProps> = observer((props) => {
|
||||||
}}
|
}}
|
||||||
className="h-full flex flex-col"
|
className="h-full flex flex-col"
|
||||||
>
|
>
|
||||||
<div className="px-6">
|
<TabsList durationFilter={selectedDurationFilter} selectedTab={selectedTab} />
|
||||||
<TabsList durationFilter={selectedDurationFilter} selectedTab={selectedTab} />
|
|
||||||
</div>
|
|
||||||
<Tab.Panels as="div" className="h-full">
|
<Tab.Panels as="div" className="h-full">
|
||||||
{tabsList.map((tab) => {
|
{tabsList.map((tab) => {
|
||||||
if (tab.key !== selectedTab) return null;
|
if (tab.key !== selectedTab) return null;
|
||||||
|
|
@ -158,6 +157,6 @@ export const CreatedIssuesWidget: React.FC<WidgetProps> = observer((props) => {
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ export const WidgetIssuesList: React.FC<WidgetIssuesListProps> = (props) => {
|
||||||
<>
|
<>
|
||||||
<div className="h-full">
|
<div className="h-full">
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Loader className="space-y-4 mx-6 mt-7">
|
<Loader className="space-y-4 mt-7">
|
||||||
<Loader.Item height="25px" />
|
<Loader.Item height="25px" />
|
||||||
<Loader.Item height="25px" />
|
<Loader.Item height="25px" />
|
||||||
<Loader.Item height="25px" />
|
<Loader.Item height="25px" />
|
||||||
|
|
@ -74,7 +74,7 @@ export const WidgetIssuesList: React.FC<WidgetIssuesListProps> = (props) => {
|
||||||
</Loader>
|
</Loader>
|
||||||
) : issuesList.length > 0 ? (
|
) : issuesList.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
<div className="mt-7 mx-6 border-b-[0.5px] border-custom-border-200 grid grid-cols-12 gap-1 text-xs text-custom-text-300 pb-1">
|
<div className="mt-7 border-b-[0.5px] border-custom-border-200 grid grid-cols-12 gap-1 text-xs text-custom-text-300 pb-1">
|
||||||
<h6
|
<h6
|
||||||
className={cn("pl-1 flex items-center gap-1 col-span-7", {
|
className={cn("pl-1 flex items-center gap-1 col-span-7", {
|
||||||
"col-span-11": type === "assigned" && tab === "completed",
|
"col-span-11": type === "assigned" && tab === "completed",
|
||||||
|
|
@ -92,7 +92,7 @@ export const WidgetIssuesList: React.FC<WidgetIssuesListProps> = (props) => {
|
||||||
{type === "assigned" && tab !== "completed" && <h6 className="text-center col-span-2">Blocked by</h6>}
|
{type === "assigned" && tab !== "completed" && <h6 className="text-center col-span-2">Blocked by</h6>}
|
||||||
{type === "created" && <h6 className="text-center col-span-2">Assigned to</h6>}
|
{type === "created" && <h6 className="text-center col-span-2">Assigned to</h6>}
|
||||||
</div>
|
</div>
|
||||||
<div className="px-4 pb-3 mt-2">
|
<div className="pb-3 mt-2">
|
||||||
{issuesList.map((issue) => {
|
{issuesList.map((issue) => {
|
||||||
const IssueListItem = ISSUE_LIST_ITEM[type][tab];
|
const IssueListItem = ISSUE_LIST_ITEM[type][tab];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import Link from "next/link";
|
||||||
// types
|
// types
|
||||||
import { TIssuesByPriorityWidgetFilters, TIssuesByPriorityWidgetResponse } from "@plane/types";
|
import { TIssuesByPriorityWidgetFilters, TIssuesByPriorityWidgetResponse } from "@plane/types";
|
||||||
// components
|
// components
|
||||||
|
import { Card } from "@plane/ui";
|
||||||
import {
|
import {
|
||||||
DurationFilterDropdown,
|
DurationFilterDropdown,
|
||||||
IssuesByPriorityEmptyState,
|
IssuesByPriorityEmptyState,
|
||||||
|
|
@ -69,8 +70,8 @@ export const IssuesByPriorityWidget: React.FC<WidgetProps> = observer((props) =>
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-96 w-full flex-col overflow-hidden rounded-xl border-[0.5px] border-custom-border-200 bg-custom-background-100 py-6 duration-300 hover:shadow-custom-shadow-4xl">
|
<Card>
|
||||||
<div className="flex items-center justify-between gap-2 pl-7 pr-6">
|
<div className="flex items-center justify-between gap-2 mb-4">
|
||||||
<Link
|
<Link
|
||||||
href={`/${workspaceSlug}/workspace-views/assigned`}
|
href={`/${workspaceSlug}/workspace-views/assigned`}
|
||||||
className="text-lg font-semibold text-custom-text-300 hover:underline"
|
className="text-lg font-semibold text-custom-text-300 hover:underline"
|
||||||
|
|
@ -106,6 +107,6 @@ export const IssuesByPriorityWidget: React.FC<WidgetProps> = observer((props) =>
|
||||||
<IssuesByPriorityEmptyState />
|
<IssuesByPriorityEmptyState />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import Link from "next/link";
|
||||||
// types
|
// types
|
||||||
import { TIssuesByStateGroupsWidgetFilters, TIssuesByStateGroupsWidgetResponse, TStateGroups } from "@plane/types";
|
import { TIssuesByStateGroupsWidgetFilters, TIssuesByStateGroupsWidgetResponse, TStateGroups } from "@plane/types";
|
||||||
// components
|
// components
|
||||||
|
import { Card } from "@plane/ui";
|
||||||
import {
|
import {
|
||||||
DurationFilterDropdown,
|
DurationFilterDropdown,
|
||||||
IssuesByStateGroupEmptyState,
|
IssuesByStateGroupEmptyState,
|
||||||
|
|
@ -79,14 +80,14 @@ export const IssuesByStateGroupWidget: React.FC<WidgetProps> = observer((props)
|
||||||
startedCount > 0
|
startedCount > 0
|
||||||
? "started"
|
? "started"
|
||||||
: unStartedCount > 0
|
: unStartedCount > 0
|
||||||
? "unstarted"
|
? "unstarted"
|
||||||
: backlogCount > 0
|
: backlogCount > 0
|
||||||
? "backlog"
|
? "backlog"
|
||||||
: completedCount > 0
|
: completedCount > 0
|
||||||
? "completed"
|
? "completed"
|
||||||
: canceledCount > 0
|
: canceledCount > 0
|
||||||
? "cancelled"
|
? "cancelled"
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
setActiveStateGroup(stateGroup);
|
setActiveStateGroup(stateGroup);
|
||||||
setDefaultStateGroup(stateGroup);
|
setDefaultStateGroup(stateGroup);
|
||||||
|
|
@ -134,8 +135,8 @@ export const IssuesByStateGroupWidget: React.FC<WidgetProps> = observer((props)
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-custom-background-100 rounded-xl border-[0.5px] border-custom-border-200 w-full py-6 hover:shadow-custom-shadow-4xl duration-300 overflow-hidden min-h-96 flex flex-col">
|
<Card>
|
||||||
<div className="flex items-center justify-between gap-2 pl-7 pr-6">
|
<div className="flex items-center justify-between gap-2 mb-4">
|
||||||
<Link
|
<Link
|
||||||
href={`/${workspaceSlug}/workspace-views/assigned`}
|
href={`/${workspaceSlug}/workspace-views/assigned`}
|
||||||
className="text-lg font-semibold text-custom-text-300 hover:underline"
|
className="text-lg font-semibold text-custom-text-300 hover:underline"
|
||||||
|
|
@ -154,7 +155,7 @@ export const IssuesByStateGroupWidget: React.FC<WidgetProps> = observer((props)
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{totalCount > 0 ? (
|
{totalCount > 0 ? (
|
||||||
<div className="flex items-center pl-10 md:pl-11 lg:pl-14 pr-11 mt-11">
|
<div className="flex items-center mt-11">
|
||||||
<div className="flex flex-col sm:flex-row md:flex-row lg:flex-row items-center justify-evenly gap-x-10 gap-y-8 w-full">
|
<div className="flex flex-col sm:flex-row md:flex-row lg:flex-row items-center justify-evenly gap-x-10 gap-y-8 w-full">
|
||||||
<div>
|
<div>
|
||||||
<PieGraph
|
<PieGraph
|
||||||
|
|
@ -215,6 +216,6 @@ export const IssuesByStateGroupWidget: React.FC<WidgetProps> = observer((props)
|
||||||
<IssuesByStateGroupEmptyState />
|
<IssuesByStateGroupEmptyState />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { observer } from "mobx-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { TOverviewStatsWidgetResponse } from "@plane/types";
|
import { TOverviewStatsWidgetResponse } from "@plane/types";
|
||||||
// hooks
|
// hooks
|
||||||
|
import { Card, ECardSpacing } from "@plane/ui";
|
||||||
import { WidgetLoader } from "@/components/dashboard/widgets";
|
import { WidgetLoader } from "@/components/dashboard/widgets";
|
||||||
import { cn } from "@/helpers/common.helper";
|
import { cn } from "@/helpers/common.helper";
|
||||||
import { renderFormattedPayloadDate } from "@/helpers/date-time.helper";
|
import { renderFormattedPayloadDate } from "@/helpers/date-time.helper";
|
||||||
|
|
@ -63,8 +64,9 @@ export const OverviewStatsWidget: React.FC<WidgetProps> = observer((props) => {
|
||||||
if (!widgetStats) return <WidgetLoader widgetKey={WIDGET_KEY} />;
|
if (!widgetStats) return <WidgetLoader widgetKey={WIDGET_KEY} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Card
|
||||||
className="bg-custom-background-100 rounded-xl border-[0.5px] border-custom-border-200 w-full grid lg:grid-cols-4 md:grid-cols-2 sm:grid-cols-2 grid-cols-2 p-0.5 hover:shadow-custom-shadow-4xl duration-300
|
spacing={ECardSpacing.SM}
|
||||||
|
className="flex-row grid lg:grid-cols-4 md:grid-cols-2 sm:grid-cols-2 grid-cols-2 space-y-0
|
||||||
[&>div>a>div]:border-r
|
[&>div>a>div]:border-r
|
||||||
[&>div:last-child>a>div]:border-0
|
[&>div:last-child>a>div]:border-0
|
||||||
[&>div>a>div]:border-custom-border-200
|
[&>div>a>div]:border-custom-border-200
|
||||||
|
|
@ -93,6 +95,6 @@ export const OverviewStatsWidget: React.FC<WidgetProps> = observer((props) => {
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,8 @@ import Link from "next/link";
|
||||||
import { History } from "lucide-react";
|
import { History } from "lucide-react";
|
||||||
// types
|
// types
|
||||||
import { TRecentActivityWidgetResponse } from "@plane/types";
|
import { TRecentActivityWidgetResponse } from "@plane/types";
|
||||||
// UI
|
|
||||||
import { Avatar, getButtonStyling } from "@plane/ui";
|
|
||||||
// components
|
// components
|
||||||
|
import { Card, Avatar, getButtonStyling } from "@plane/ui";
|
||||||
import { ActivityIcon, ActivityMessage, IssueLink } from "@/components/core";
|
import { ActivityIcon, ActivityMessage, IssueLink } from "@/components/core";
|
||||||
import { RecentActivityEmptyState, WidgetLoader, WidgetProps } from "@/components/dashboard/widgets";
|
import { RecentActivityEmptyState, WidgetLoader, WidgetProps } from "@/components/dashboard/widgets";
|
||||||
// helpers
|
// helpers
|
||||||
|
|
@ -38,12 +37,12 @@ export const RecentActivityWidget: React.FC<WidgetProps> = observer((props) => {
|
||||||
if (!widgetStats) return <WidgetLoader widgetKey={WIDGET_KEY} />;
|
if (!widgetStats) return <WidgetLoader widgetKey={WIDGET_KEY} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-96 w-full rounded-xl border-[0.5px] border-custom-border-200 bg-custom-background-100 py-6 duration-300 hover:shadow-custom-shadow-4xl">
|
<Card>
|
||||||
<Link href={redirectionLink} className="mx-7 text-lg font-semibold text-custom-text-300 hover:underline">
|
<Link href={redirectionLink} className="text-lg font-semibold text-custom-text-300 hover:underline mb-4">
|
||||||
Your issue activities
|
Your issue activities
|
||||||
</Link>
|
</Link>
|
||||||
{widgetStats.length > 0 ? (
|
{widgetStats.length > 0 ? (
|
||||||
<div className="mx-7 mt-4 space-y-6">
|
<div className="mt-4 space-y-6">
|
||||||
{widgetStats.map((activity) => (
|
{widgetStats.map((activity) => (
|
||||||
<div key={activity.id} className="flex gap-5">
|
<div key={activity.id} className="flex gap-5">
|
||||||
<div className="flex-shrink-0">
|
<div className="flex-shrink-0">
|
||||||
|
|
@ -104,6 +103,6 @@ export const RecentActivityWidget: React.FC<WidgetProps> = observer((props) => {
|
||||||
<RecentActivityEmptyState />
|
<RecentActivityEmptyState />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Search } from "lucide-react";
|
import { Search } from "lucide-react";
|
||||||
// types
|
// types
|
||||||
|
import { Card } from "@plane/ui";
|
||||||
import { WidgetProps } from "@/components/dashboard/widgets";
|
import { WidgetProps } from "@/components/dashboard/widgets";
|
||||||
// components
|
// components
|
||||||
import { DefaultCollaboratorsList } from "./default-list";
|
import { DefaultCollaboratorsList } from "./default-list";
|
||||||
|
|
@ -14,15 +15,15 @@ export const RecentCollaboratorsWidget: React.FC<WidgetProps> = (props) => {
|
||||||
const [searchQuery, setSearchQuery] = useState("");
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full rounded-xl border-[0.5px] border-custom-border-200 bg-custom-background-100 duration-300 hover:shadow-custom-shadow-4xl">
|
<Card>
|
||||||
<div className="flex flex-col sm:flex-row items-start justify-between px-7 pt-6">
|
<div className="flex flex-col sm:flex-row items-start justify-between mb-6">
|
||||||
<div>
|
<div>
|
||||||
<h4 className="text-lg font-semibold text-custom-text-300">Collaborators</h4>
|
<h4 className="text-lg font-semibold text-custom-text-300">Collaborators</h4>
|
||||||
<p className="mt-2 text-xs font-medium text-custom-text-300">
|
<p className="mt-2 text-xs font-medium text-custom-text-300">
|
||||||
View and find all members you collaborate with across projects
|
View and find all members you collaborate with across projects
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-5 sm:mt-0 flex min-w-72 items-center justify-start gap-2 rounded-md border border-custom-border-200 px-2.5 py-1.5 placeholder:text-custom-text-400">
|
<div className="mt-5 sm:mt-0 flex min-w-full md:min-w-72 items-center justify-start gap-2 rounded-md border border-custom-border-200 px-2.5 py-1.5 placeholder:text-custom-text-400">
|
||||||
<Search className="h-3.5 w-3.5 text-custom-text-400" />
|
<Search className="h-3.5 w-3.5 text-custom-text-400" />
|
||||||
<input
|
<input
|
||||||
className="w-full border-none bg-transparent text-sm focus:outline-none"
|
className="w-full border-none bg-transparent text-sm focus:outline-none"
|
||||||
|
|
@ -42,6 +43,6 @@ export const RecentCollaboratorsWidget: React.FC<WidgetProps> = (props) => {
|
||||||
) : (
|
) : (
|
||||||
<DefaultCollaboratorsList dashboardId={dashboardId} perPage={PER_PAGE} workspaceSlug={workspaceSlug} />
|
<DefaultCollaboratorsList dashboardId={dashboardId} perPage={PER_PAGE} workspaceSlug={workspaceSlug} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@ import { Plus } from "lucide-react";
|
||||||
// types
|
// types
|
||||||
import { TRecentProjectsWidgetResponse } from "@plane/types";
|
import { TRecentProjectsWidgetResponse } from "@plane/types";
|
||||||
// ui
|
// ui
|
||||||
import { Avatar, AvatarGroup } from "@plane/ui";
|
import { Avatar, AvatarGroup, Card } from "@plane/ui";
|
||||||
|
|
||||||
// components
|
// components
|
||||||
import { Logo } from "@/components/common";
|
import { Logo } from "@/components/common";
|
||||||
import { WidgetLoader, WidgetProps } from "@/components/dashboard/widgets";
|
import { WidgetLoader, WidgetProps } from "@/components/dashboard/widgets";
|
||||||
|
|
@ -82,14 +83,14 @@ export const RecentProjectsWidget: React.FC<WidgetProps> = observer((props) => {
|
||||||
if (!widgetStats) return <WidgetLoader widgetKey={WIDGET_KEY} />;
|
if (!widgetStats) return <WidgetLoader widgetKey={WIDGET_KEY} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-96 w-full rounded-xl border-[0.5px] border-custom-border-200 bg-custom-background-100 py-6 duration-300 hover:shadow-custom-shadow-4xl">
|
<Card>
|
||||||
<Link
|
<Link
|
||||||
href={`/${workspaceSlug}/projects`}
|
href={`/${workspaceSlug}/projects`}
|
||||||
className="mx-7 text-lg font-semibold text-custom-text-300 hover:underline"
|
className="text-lg font-semibold text-custom-text-300 hover:underline mb-4"
|
||||||
>
|
>
|
||||||
Recent projects
|
Recent projects
|
||||||
</Link>
|
</Link>
|
||||||
<div className="mx-7 mt-4 space-y-8">
|
<div className="mt-4 space-y-8">
|
||||||
{canCreateProject && (
|
{canCreateProject && (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|
@ -113,6 +114,6 @@ export const RecentProjectsWidget: React.FC<WidgetProps> = observer((props) => {
|
||||||
<ProjectListItem key={projectId} projectId={projectId} workspaceSlug={workspaceSlug} />
|
<ProjectListItem key={projectId} projectId={projectId} workspaceSlug={workspaceSlug} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ const ButtonContent: React.FC<ButtonContentProps> = (props) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={moduleId}
|
key={moduleId}
|
||||||
className="flex max-w-full items-center gap-1 rounded bg-custom-background-80 px-1.5 py-1 text-custom-text-200"
|
className="flex max-w-full items-center gap-1 rounded bg-custom-background-80 py-1 text-custom-text-200"
|
||||||
>
|
>
|
||||||
{!hideIcon && <DiceIcon className="h-2.5 w-2.5 flex-shrink-0" />}
|
{!hideIcon && <DiceIcon className="h-2.5 w-2.5 flex-shrink-0" />}
|
||||||
{!hideText && (
|
{!hideText && (
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { observer } from "mobx-react";
|
||||||
import { Expand, Shrink } from "lucide-react";
|
import { Expand, Shrink } from "lucide-react";
|
||||||
// hooks
|
// hooks
|
||||||
// helpers
|
// helpers
|
||||||
|
import { Row } from "@plane/ui";
|
||||||
import { VIEWS_LIST } from "@/components/gantt-chart/data";
|
import { VIEWS_LIST } from "@/components/gantt-chart/data";
|
||||||
import { cn } from "@/helpers/common.helper";
|
import { cn } from "@/helpers/common.helper";
|
||||||
// types
|
// types
|
||||||
|
|
@ -26,7 +27,7 @@ export const GanttChartHeader: React.FC<Props> = observer((props) => {
|
||||||
const { currentView } = useGanttChart();
|
const { currentView } = useGanttChart();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative flex w-full flex-shrink-0 flex-wrap items-center gap-2 whitespace-nowrap px-2.5 py-2">
|
<Row className="relative flex w-full flex-shrink-0 flex-wrap items-center gap-2 whitespace-nowrap py-2">
|
||||||
<div className="ml-auto">
|
<div className="ml-auto">
|
||||||
<div className="ml-auto text-sm font-medium">
|
<div className="ml-auto text-sm font-medium">
|
||||||
{blockIds ? `${blockIds.length} ${loaderTitle}` : "Loading..."}
|
{blockIds ? `${blockIds.length} ${loaderTitle}` : "Loading..."}
|
||||||
|
|
@ -65,6 +66,6 @@ export const GanttChartHeader: React.FC<Props> = observer((props) => {
|
||||||
>
|
>
|
||||||
{fullScreenMode ? <Shrink className="h-4 w-4" /> : <Expand className="h-4 w-4" />}
|
{fullScreenMode ? <Shrink className="h-4 w-4" /> : <Expand className="h-4 w-4" />}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</Row>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export const CyclesSidebarBlock: React.FC<Props> = observer((props) => {
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
id={`sidebar-block-${block.id}`}
|
id={`sidebar-block-${block.id}`}
|
||||||
className={cn("group w-full flex items-center gap-2 pl-2 pr-4", {
|
className={cn("group w-full flex items-center gap-2 pr-4", {
|
||||||
"bg-custom-background-90": isBlockActive(block.id),
|
"bg-custom-background-90": isBlockActive(block.id),
|
||||||
})}
|
})}
|
||||||
style={{
|
style={{
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
// components
|
// components
|
||||||
|
import { Row } from "@plane/ui";
|
||||||
import { MultipleSelectEntityAction } from "@/components/core";
|
import { MultipleSelectEntityAction } from "@/components/core";
|
||||||
import { useGanttChart } from "@/components/gantt-chart/hooks";
|
import { useGanttChart } from "@/components/gantt-chart/hooks";
|
||||||
import { IssueGanttSidebarBlock } from "@/components/issues";
|
import { IssueGanttSidebarBlock } from "@/components/issues";
|
||||||
|
|
@ -45,8 +46,8 @@ export const IssuesSidebarBlock = observer((props: Props) => {
|
||||||
onMouseEnter={() => updateActiveBlockId(block.id)}
|
onMouseEnter={() => updateActiveBlockId(block.id)}
|
||||||
onMouseLeave={() => updateActiveBlockId(null)}
|
onMouseLeave={() => updateActiveBlockId(null)}
|
||||||
>
|
>
|
||||||
<div
|
<Row
|
||||||
className={cn("group w-full flex items-center gap-2 pl-2 pr-4", {
|
className={cn("group w-full flex items-center gap-2 pr-4", {
|
||||||
"bg-custom-background-90": isBlockHoveredOn,
|
"bg-custom-background-90": isBlockHoveredOn,
|
||||||
"bg-custom-primary-100/5 hover:bg-custom-primary-100/10": isIssueSelected,
|
"bg-custom-primary-100/5 hover:bg-custom-primary-100/10": isIssueSelected,
|
||||||
"bg-custom-primary-100/10": isIssueSelected && isBlockHoveredOn,
|
"bg-custom-primary-100/10": isIssueSelected && isBlockHoveredOn,
|
||||||
|
|
@ -55,8 +56,8 @@ export const IssuesSidebarBlock = observer((props: Props) => {
|
||||||
height: `${BLOCK_HEIGHT}px`,
|
height: `${BLOCK_HEIGHT}px`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-2">
|
{enableSelection && selectionHelpers && (
|
||||||
{enableSelection && selectionHelpers && (
|
<div className="flex items-center gap-2 absolute left-1">
|
||||||
<MultipleSelectEntityAction
|
<MultipleSelectEntityAction
|
||||||
className={cn(
|
className={cn(
|
||||||
"opacity-0 pointer-events-none group-hover/list-block:opacity-100 group-hover/list-block:pointer-events-auto transition-opacity",
|
"opacity-0 pointer-events-none group-hover/list-block:opacity-100 group-hover/list-block:pointer-events-auto transition-opacity",
|
||||||
|
|
@ -68,8 +69,8 @@ export const IssuesSidebarBlock = observer((props: Props) => {
|
||||||
id={block.id}
|
id={block.id}
|
||||||
selectionHelpers={selectionHelpers}
|
selectionHelpers={selectionHelpers}
|
||||||
/>
|
/>
|
||||||
)}
|
</div>
|
||||||
</div>
|
)}
|
||||||
<div className="flex h-full flex-grow items-center justify-between gap-2 truncate">
|
<div className="flex h-full flex-grow items-center justify-between gap-2 truncate">
|
||||||
<div className="flex-grow truncate">
|
<div className="flex-grow truncate">
|
||||||
<IssueGanttSidebarBlock issueId={block.data.id} />
|
<IssueGanttSidebarBlock issueId={block.data.id} />
|
||||||
|
|
@ -82,7 +83,7 @@ export const IssuesSidebarBlock = observer((props: Props) => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
// hooks
|
// hooks
|
||||||
|
import { Row } from "@plane/ui";
|
||||||
import { BLOCK_HEIGHT } from "@/components/gantt-chart/constants";
|
import { BLOCK_HEIGHT } from "@/components/gantt-chart/constants";
|
||||||
import { useGanttChart } from "@/components/gantt-chart/hooks";
|
import { useGanttChart } from "@/components/gantt-chart/hooks";
|
||||||
// components
|
// components
|
||||||
|
|
@ -31,9 +32,9 @@ export const ModulesSidebarBlock: React.FC<Props> = observer((props) => {
|
||||||
onMouseEnter={() => updateActiveBlockId(block.id)}
|
onMouseEnter={() => updateActiveBlockId(block.id)}
|
||||||
onMouseLeave={() => updateActiveBlockId(null)}
|
onMouseLeave={() => updateActiveBlockId(null)}
|
||||||
>
|
>
|
||||||
<div
|
<Row
|
||||||
id={`sidebar-block-${block.id}`}
|
id={`sidebar-block-${block.id}`}
|
||||||
className={cn("group w-full flex items-center gap-2 pl-2 pr-4", {
|
className={cn("group w-full flex items-center gap-2 pr-4", {
|
||||||
"bg-custom-background-90": isBlockActive(block.id),
|
"bg-custom-background-90": isBlockActive(block.id),
|
||||||
})}
|
})}
|
||||||
style={{
|
style={{
|
||||||
|
|
@ -50,7 +51,7 @@ export const ModulesSidebarBlock: React.FC<Props> = observer((props) => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { RefObject } from "react";
|
import { RefObject } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
// components
|
// components
|
||||||
|
import { Row, ERowVariant } from "@plane/ui";
|
||||||
import { MultipleSelectGroupAction } from "@/components/core";
|
import { MultipleSelectGroupAction } from "@/components/core";
|
||||||
import { ChartDataType, IBlockUpdateData, IGanttBlock } from "@/components/gantt-chart";
|
import { ChartDataType, IBlockUpdateData, IGanttBlock } from "@/components/gantt-chart";
|
||||||
// helpers
|
// helpers
|
||||||
|
|
@ -44,27 +45,24 @@ export const GanttChartSidebar: React.FC<Props> = observer((props) => {
|
||||||
const isGroupSelectionEmpty = selectionHelpers.isGroupSelected(GANTT_SELECT_GROUP) === "empty";
|
const isGroupSelectionEmpty = selectionHelpers.isGroupSelected(GANTT_SELECT_GROUP) === "empty";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Row
|
||||||
// DO NOT REMOVE THE ID
|
// DO NOT REMOVE THE ID
|
||||||
id="gantt-sidebar"
|
id="gantt-sidebar"
|
||||||
className="sticky left-0 z-10 min-h-full h-max flex-shrink-0 border-r-[0.5px] border-custom-border-200 bg-custom-background-100"
|
className="sticky left-0 z-10 min-h-full h-max flex-shrink-0 border-r-[0.5px] border-custom-border-200 bg-custom-background-100"
|
||||||
style={{
|
style={{
|
||||||
width: `${SIDEBAR_WIDTH}px`,
|
width: `${SIDEBAR_WIDTH}px`,
|
||||||
}}
|
}}
|
||||||
|
variant={ERowVariant.HUGGING}
|
||||||
>
|
>
|
||||||
<div
|
<Row
|
||||||
className="group/list-header box-border flex-shrink-0 flex items-end justify-between gap-2 border-b-[0.5px] border-custom-border-200 pb-2 pl-2 pr-4 text-sm font-medium text-custom-text-300 sticky top-0 z-10 bg-custom-background-100"
|
className="group/list-header box-border flex-shrink-0 flex items-end justify-between gap-2 border-b-[0.5px] border-custom-border-200 pb-2 pr-4 text-sm font-medium text-custom-text-300 sticky top-0 z-10 bg-custom-background-100"
|
||||||
style={{
|
style={{
|
||||||
height: `${HEADER_HEIGHT}px`,
|
height: `${HEADER_HEIGHT}px`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div className={cn("flex items-center gap-2")}>
|
||||||
className={cn("flex items-center gap-2", {
|
|
||||||
"pl-2": !enableSelection,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{enableSelection && (
|
{enableSelection && (
|
||||||
<div className="flex-shrink-0 flex items-center w-3.5">
|
<div className="flex-shrink-0 flex items-center w-3.5 absolute left-1">
|
||||||
<MultipleSelectGroupAction
|
<MultipleSelectGroupAction
|
||||||
className={cn(
|
className={cn(
|
||||||
"size-3.5 opacity-0 pointer-events-none group-hover/list-header:opacity-100 group-hover/list-header:pointer-events-auto !outline-none",
|
"size-3.5 opacity-0 pointer-events-none group-hover/list-header:opacity-100 group-hover/list-header:pointer-events-auto !outline-none",
|
||||||
|
|
@ -80,9 +78,9 @@ export const GanttChartSidebar: React.FC<Props> = observer((props) => {
|
||||||
<h6>{title}</h6>
|
<h6>{title}</h6>
|
||||||
</div>
|
</div>
|
||||||
<h6>Duration</h6>
|
<h6>Duration</h6>
|
||||||
</div>
|
</Row>
|
||||||
|
|
||||||
<div className="min-h-full h-max bg-custom-background-100 overflow-hidden">
|
<Row variant={ERowVariant.HUGGING} className="min-h-full h-max bg-custom-background-100 overflow-hidden">
|
||||||
{sidebarToRender &&
|
{sidebarToRender &&
|
||||||
sidebarToRender({
|
sidebarToRender({
|
||||||
title,
|
title,
|
||||||
|
|
@ -96,8 +94,8 @@ export const GanttChartSidebar: React.FC<Props> = observer((props) => {
|
||||||
loadMoreBlocks,
|
loadMoreBlocks,
|
||||||
selectionHelpers,
|
selectionHelpers,
|
||||||
})}
|
})}
|
||||||
</div>
|
</Row>
|
||||||
{quickAdd ? quickAdd : null}
|
{quickAdd ? quickAdd : null}
|
||||||
</div>
|
</Row>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,9 @@ import {
|
||||||
Link,
|
Link,
|
||||||
Trash2,
|
Trash2,
|
||||||
MoveRight,
|
MoveRight,
|
||||||
Copy
|
Copy,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { Button, ControlLink, CustomMenu, TOAST_TYPE, setToast } from "@plane/ui";
|
import { Button, ControlLink, CustomMenu, Row, TOAST_TYPE, setToast } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import {
|
import {
|
||||||
DeclineIssueModal,
|
DeclineIssueModal,
|
||||||
|
|
@ -245,7 +245,7 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
||||||
<div className="hidden relative lg:flex h-full w-full items-center justify-between gap-2 px-4">
|
<Row className="hidden relative lg:flex h-full w-full items-center justify-between gap-2">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
{isNotificationEmbed && (
|
{isNotificationEmbed && (
|
||||||
<button onClick={embedRemoveCurrentNotification}>
|
<button onClick={embedRemoveCurrentNotification}>
|
||||||
|
|
@ -376,7 +376,7 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Row>
|
||||||
|
|
||||||
<div className="lg:hidden">
|
<div className="lg:hidden">
|
||||||
<InboxIssueActionsMobileHeader
|
<InboxIssueActionsMobileHeader
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import {
|
||||||
PanelLeft,
|
PanelLeft,
|
||||||
MoveRight,
|
MoveRight,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { CustomHeader, CustomMenu, EHeaderVariant } from "@plane/ui";
|
import { Header, CustomMenu, EHeaderVariant } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { InboxIssueStatus } from "@/components/inbox";
|
import { InboxIssueStatus } from "@/components/inbox";
|
||||||
import { IssueUpdateStatus } from "@/components/issues";
|
import { IssueUpdateStatus } from "@/components/issues";
|
||||||
|
|
@ -80,7 +80,7 @@ export const InboxIssueActionsMobileHeader: React.FC<Props> = observer((props) =
|
||||||
if (!issue || !inboxIssue) return null;
|
if (!issue || !inboxIssue) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomHeader variant={EHeaderVariant.SECONDARY} className="flex">
|
<Header variant={EHeaderVariant.SECONDARY} className="justify-start">
|
||||||
{isNotificationEmbed && (
|
{isNotificationEmbed && (
|
||||||
<button onClick={embedRemoveCurrentNotification}>
|
<button onClick={embedRemoveCurrentNotification}>
|
||||||
<MoveRight className="h-4 w-4 text-custom-text-300 hover:text-custom-text-200" />
|
<MoveRight className="h-4 w-4 text-custom-text-300 hover:text-custom-text-200" />
|
||||||
|
|
@ -181,6 +181,6 @@ export const InboxIssueActionsMobileHeader: React.FC<Props> = observer((props) =
|
||||||
</CustomMenu>
|
</CustomMenu>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ export const InboxIssueContentProperties: React.FC<Props> = observer((props) =>
|
||||||
if (!issue || !issue?.id) return <></>;
|
if (!issue || !issue?.id) return <></>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-min w-full flex-col divide-y-2 divide-custom-border-200 overflow-hidden">
|
<div className="flex w-full flex-col divide-y-2 divide-custom-border-200">
|
||||||
<div className="h-min w-full overflow-y-auto px-3">
|
<div className="w-full overflow-y-auto">
|
||||||
<h5 className="text-sm font-medium my-4">Properties</h5>
|
<h5 className="text-sm font-medium my-4">Properties</h5>
|
||||||
<div className={`divide-y-2 divide-custom-border-200 ${!isEditable ? "opacity-60" : ""}`}>
|
<div className={`divide-y-2 divide-custom-border-200 ${!isEditable ? "opacity-60" : ""}`}>
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ export const InboxIssueMainContent: React.FC<Props> = observer((props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="rounded-lg space-y-4 pl-3">
|
<div className="rounded-lg space-y-4">
|
||||||
<IssueTitleInput
|
<IssueTitleInput
|
||||||
workspaceSlug={workspaceSlug}
|
workspaceSlug={workspaceSlug}
|
||||||
projectId={issue.project_id}
|
projectId={issue.project_id}
|
||||||
|
|
@ -141,14 +141,12 @@ export const InboxIssueMainContent: React.FC<Props> = observer((props) => {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="pl-3">
|
<IssueAttachmentRoot
|
||||||
<IssueAttachmentRoot
|
workspaceSlug={workspaceSlug}
|
||||||
workspaceSlug={workspaceSlug}
|
projectId={projectId}
|
||||||
projectId={projectId}
|
issueId={issue.id}
|
||||||
issueId={issue.id}
|
disabled={!isEditable}
|
||||||
disabled={!isEditable}
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<InboxIssueContentProperties
|
<InboxIssueContentProperties
|
||||||
workspaceSlug={workspaceSlug}
|
workspaceSlug={workspaceSlug}
|
||||||
|
|
@ -159,9 +157,7 @@ export const InboxIssueMainContent: React.FC<Props> = observer((props) => {
|
||||||
duplicateIssueDetails={inboxIssue?.duplicate_issue_detail}
|
duplicateIssueDetails={inboxIssue?.duplicate_issue_detail}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="pb-12 pl-3">
|
<IssueActivity workspaceSlug={workspaceSlug} projectId={projectId} issueId={issue.id} isIntakeIssue />
|
||||||
<IssueActivity workspaceSlug={workspaceSlug} projectId={projectId} issueId={issue.id} isIntakeIssue />
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { FC, useEffect, useState } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
// components
|
// components
|
||||||
|
import { ContentWrapper } from "@plane/ui";
|
||||||
import { InboxIssueActionsHeader, InboxIssueMainContent } from "@/components/inbox";
|
import { InboxIssueActionsHeader, InboxIssueMainContent } from "@/components/inbox";
|
||||||
// constants
|
// constants
|
||||||
import { EUserProjectRoles } from "@/constants/project";
|
import { EUserProjectRoles } from "@/constants/project";
|
||||||
|
|
@ -83,7 +84,7 @@ export const InboxContentRoot: FC<TInboxContentRoot> = observer((props) => {
|
||||||
embedRemoveCurrentNotification={embedRemoveCurrentNotification}
|
embedRemoveCurrentNotification={embedRemoveCurrentNotification}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="h-full w-full space-y-5 divide-y-2 divide-custom-border-200 overflow-y-auto px-6 py-5 vertical-scrollbar scrollbar-md">
|
<ContentWrapper className="space-y-5 divide-y-2 divide-custom-border-200">
|
||||||
<InboxIssueMainContent
|
<InboxIssueMainContent
|
||||||
workspaceSlug={workspaceSlug}
|
workspaceSlug={workspaceSlug}
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
|
|
@ -92,7 +93,7 @@ export const InboxContentRoot: FC<TInboxContentRoot> = observer((props) => {
|
||||||
isSubmitting={isSubmitting}
|
isSubmitting={isSubmitting}
|
||||||
setIsSubmitting={setIsSubmitting}
|
setIsSubmitting={setIsSubmitting}
|
||||||
/>
|
/>
|
||||||
</div>
|
</ContentWrapper>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { observer } from "mobx-react";
|
||||||
import { X } from "lucide-react";
|
import { X } from "lucide-react";
|
||||||
import { TInboxIssueFilterDateKeys } from "@plane/types";
|
import { TInboxIssueFilterDateKeys } from "@plane/types";
|
||||||
// helpers
|
// helpers
|
||||||
|
import { Tag } from "@plane/ui";
|
||||||
import { renderFormattedDate } from "@/helpers/date-time.helper";
|
import { renderFormattedDate } from "@/helpers/date-time.helper";
|
||||||
// constants
|
// constants
|
||||||
import { PAST_DURATION_FILTER_OPTIONS } from "@/helpers/inbox.helper";
|
import { PAST_DURATION_FILTER_OPTIONS } from "@/helpers/inbox.helper";
|
||||||
|
|
@ -37,7 +38,7 @@ export const InboxIssueAppliedFiltersDate: FC<InboxIssueAppliedFiltersDate> = ob
|
||||||
|
|
||||||
if (filteredValues.length === 0) return <></>;
|
if (filteredValues.length === 0) return <></>;
|
||||||
return (
|
return (
|
||||||
<div className="relative flex flex-wrap items-center gap-2 rounded-md border border-custom-border-200 px-2 py-1">
|
<Tag>
|
||||||
<div className="text-xs text-custom-text-200">{label}</div>
|
<div className="text-xs text-custom-text-200">{label}</div>
|
||||||
{filteredValues.map((value) => {
|
{filteredValues.map((value) => {
|
||||||
const optionDetail = currentOptionDetail(value);
|
const optionDetail = currentOptionDetail(value);
|
||||||
|
|
@ -61,6 +62,6 @@ export const InboxIssueAppliedFiltersDate: FC<InboxIssueAppliedFiltersDate> = ob
|
||||||
>
|
>
|
||||||
<X className={`w-3 h-3`} />
|
<X className={`w-3 h-3`} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Tag>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { FC } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { X } from "lucide-react";
|
import { X } from "lucide-react";
|
||||||
// hooks
|
// hooks
|
||||||
|
import { Tag } from "@plane/ui";
|
||||||
import { useLabel, useProjectInbox } from "@/hooks/store";
|
import { useLabel, useProjectInbox } from "@/hooks/store";
|
||||||
|
|
||||||
const LabelIcons = ({ color }: { color: string }) => (
|
const LabelIcons = ({ color }: { color: string }) => (
|
||||||
|
|
@ -23,7 +24,7 @@ export const InboxIssueAppliedFiltersLabel: FC = observer(() => {
|
||||||
|
|
||||||
if (filteredValues.length === 0) return <></>;
|
if (filteredValues.length === 0) return <></>;
|
||||||
return (
|
return (
|
||||||
<div className="relative flex flex-wrap items-center gap-2 rounded-md border border-custom-border-200 px-2 py-1">
|
<Tag>
|
||||||
<div className="text-xs text-custom-text-200">Label</div>
|
<div className="text-xs text-custom-text-200">Label</div>
|
||||||
{filteredValues.map((value) => {
|
{filteredValues.map((value) => {
|
||||||
const optionDetail = currentOptionDetail(value);
|
const optionDetail = currentOptionDetail(value);
|
||||||
|
|
@ -50,6 +51,6 @@ export const InboxIssueAppliedFiltersLabel: FC = observer(() => {
|
||||||
>
|
>
|
||||||
<X className={`w-3 h-3`} />
|
<X className={`w-3 h-3`} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Tag>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { FC } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { X } from "lucide-react";
|
import { X } from "lucide-react";
|
||||||
import { TInboxIssueFilterMemberKeys } from "@plane/types";
|
import { TInboxIssueFilterMemberKeys } from "@plane/types";
|
||||||
import { Avatar } from "@plane/ui";
|
import { Avatar, Tag } from "@plane/ui";
|
||||||
// hooks
|
// hooks
|
||||||
import { useMember, useProjectInbox } from "@/hooks/store";
|
import { useMember, useProjectInbox } from "@/hooks/store";
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ export const InboxIssueAppliedFiltersMember: FC<InboxIssueAppliedFiltersMember>
|
||||||
|
|
||||||
if (filteredValues.length === 0) return <></>;
|
if (filteredValues.length === 0) return <></>;
|
||||||
return (
|
return (
|
||||||
<div className="relative flex flex-wrap items-center gap-2 rounded-md border border-custom-border-200 px-2 py-1">
|
<Tag>
|
||||||
<div className="text-xs text-custom-text-200">{label}</div>
|
<div className="text-xs text-custom-text-200">{label}</div>
|
||||||
{filteredValues.map((value) => {
|
{filteredValues.map((value) => {
|
||||||
const optionDetail = currentOptionDetail(value);
|
const optionDetail = currentOptionDetail(value);
|
||||||
|
|
@ -56,6 +56,6 @@ export const InboxIssueAppliedFiltersMember: FC<InboxIssueAppliedFiltersMember>
|
||||||
>
|
>
|
||||||
<X className={`w-3 h-3`} />
|
<X className={`w-3 h-3`} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Tag>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { FC } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { X } from "lucide-react";
|
import { X } from "lucide-react";
|
||||||
import { TIssuePriorities } from "@plane/types";
|
import { TIssuePriorities } from "@plane/types";
|
||||||
import { PriorityIcon } from "@plane/ui";
|
import { PriorityIcon, Tag } from "@plane/ui";
|
||||||
// constants
|
// constants
|
||||||
import { ISSUE_PRIORITIES } from "@/constants/issue";
|
import { ISSUE_PRIORITIES } from "@/constants/issue";
|
||||||
// hooks
|
// hooks
|
||||||
|
|
@ -25,7 +25,7 @@ export const InboxIssueAppliedFiltersPriority: FC = observer(() => {
|
||||||
|
|
||||||
if (filteredValues.length === 0) return <></>;
|
if (filteredValues.length === 0) return <></>;
|
||||||
return (
|
return (
|
||||||
<div className="relative flex flex-wrap items-center gap-2 rounded-md border border-custom-border-200 px-2 py-1">
|
<Tag>
|
||||||
<div className="text-xs text-custom-text-200">Priority</div>
|
<div className="text-xs text-custom-text-200">Priority</div>
|
||||||
{filteredValues.map((value) => {
|
{filteredValues.map((value) => {
|
||||||
const optionDetail = currentOptionDetail(value);
|
const optionDetail = currentOptionDetail(value);
|
||||||
|
|
@ -52,6 +52,6 @@ export const InboxIssueAppliedFiltersPriority: FC = observer(() => {
|
||||||
>
|
>
|
||||||
<X className={`w-3 h-3`} />
|
<X className={`w-3 h-3`} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Tag>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
// components
|
// components
|
||||||
import { CustomHeader, EHeaderVariant } from "@plane/ui";
|
import { Header, EHeaderVariant } from "@plane/ui";
|
||||||
import {
|
import {
|
||||||
InboxIssueAppliedFiltersStatus,
|
InboxIssueAppliedFiltersStatus,
|
||||||
InboxIssueAppliedFiltersPriority,
|
InboxIssueAppliedFiltersPriority,
|
||||||
|
|
@ -18,7 +18,7 @@ export const InboxIssueAppliedFilters: FC = observer(() => {
|
||||||
|
|
||||||
if (getAppliedFiltersCount === 0) return <></>;
|
if (getAppliedFiltersCount === 0) return <></>;
|
||||||
return (
|
return (
|
||||||
<CustomHeader variant={EHeaderVariant.TERNARY} className="flex-wrap items-center gap-1 min-h-none">
|
<Header variant={EHeaderVariant.TERNARY}>
|
||||||
{/* status */}
|
{/* status */}
|
||||||
<InboxIssueAppliedFiltersStatus />
|
<InboxIssueAppliedFiltersStatus />
|
||||||
{/* state */}
|
{/* state */}
|
||||||
|
|
@ -35,6 +35,6 @@ export const InboxIssueAppliedFilters: FC = observer(() => {
|
||||||
<InboxIssueAppliedFiltersDate filterKey="created_at" label="Created date" />
|
<InboxIssueAppliedFiltersDate filterKey="created_at" label="Created date" />
|
||||||
{/* updated_at */}
|
{/* updated_at */}
|
||||||
<InboxIssueAppliedFiltersDate filterKey="updated_at" label="Updated date" />
|
<InboxIssueAppliedFiltersDate filterKey="updated_at" label="Updated date" />
|
||||||
</CustomHeader>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue