[WEB-2273] Fix: page alignments (#5541)
* 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 * fix: header-alignments * fix: tabs * fix: settings page * fix: subgroup page * fix: mobile headers * fix: settings mobile header made observable * fix: lint error + edge case handling
This commit is contained in:
parent
751cd6c862
commit
c95aa6a0f7
52 changed files with 234 additions and 219 deletions
|
|
@ -11,6 +11,7 @@ export interface HeaderProps {
|
|||
showOnMobile?: boolean;
|
||||
}
|
||||
|
||||
const HeaderContext = React.createContext<THeaderVariant | null>(null);
|
||||
const Header = (props: HeaderProps) => {
|
||||
const {
|
||||
variant = EHeaderVariant.PRIMARY,
|
||||
|
|
@ -23,13 +24,15 @@ const Header = (props: HeaderProps) => {
|
|||
|
||||
const style = getHeaderStyle(variant, setHeight, showOnMobile);
|
||||
return (
|
||||
<Row
|
||||
variant={variant === EHeaderVariant.PRIMARY ? ERowVariant.HUGGING : ERowVariant.REGULAR}
|
||||
className={cn(style, className)}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</Row>
|
||||
<HeaderContext.Provider value={variant}>
|
||||
<Row
|
||||
variant={variant === EHeaderVariant.PRIMARY ? ERowVariant.HUGGING : ERowVariant.REGULAR}
|
||||
className={cn(style, className)}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</Row>
|
||||
</HeaderContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
@ -40,9 +43,23 @@ const LeftItem = (props: HeaderProps) => (
|
|||
{props.children}
|
||||
</div>
|
||||
);
|
||||
const RightItem = (props: HeaderProps) => (
|
||||
<div className={cn("flex justify-end gap-3 w-auto items-baseline", props.className)}>{props.children}</div>
|
||||
);
|
||||
const RightItem = (props: HeaderProps) => {
|
||||
const variant = React.useContext(HeaderContext);
|
||||
if (variant === undefined) throw new Error("RightItem must be used within Header");
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"flex justify-end gap-3 w-auto items-start",
|
||||
{
|
||||
"items-baseline": variant === EHeaderVariant.TERNARY,
|
||||
},
|
||||
props.className
|
||||
)}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Header.LeftItem = LeftItem;
|
||||
Header.RightItem = RightItem;
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ const AnalyticsPage = observer(() => {
|
|||
<div className="flex h-full flex-col overflow-hidden bg-custom-background-100">
|
||||
<Tab.Group as={Fragment} defaultIndex={analytics_tab === "custom" ? 1 : 0}>
|
||||
<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 h-full">
|
||||
{ANALYTICS_TABS.map((tab) => (
|
||||
<Tab key={tab.key} as={Fragment}>
|
||||
{({ selected }) => (
|
||||
<button
|
||||
className={`text-sm group relative flex items-center gap-1 h-[50px] px-3 cursor-pointer transition-all font-medium outline-none ${
|
||||
className={`text-sm group relative flex items-center gap-1 h-full px-3 cursor-pointer transition-all font-medium outline-none ${
|
||||
selected ? "text-custom-primary-100 " : "hover:text-custom-text-200"
|
||||
}`}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -48,63 +48,63 @@ export const UserProfileHeader: FC<TUserProfileHeader> = observer((props) => {
|
|||
return (
|
||||
<Header>
|
||||
<Header.LeftItem>
|
||||
<div className="flex w-full justify-between">
|
||||
<Breadcrumbs>
|
||||
<Breadcrumbs.BreadcrumbItem
|
||||
type="text"
|
||||
link={
|
||||
<BreadcrumbLink
|
||||
label={breadcrumbLabel}
|
||||
disableTooltip
|
||||
icon={<UserActivityIcon className="h-4 w-4 text-custom-text-300" />}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Breadcrumbs>
|
||||
<div className="hidden md:flex md:items-center">{showProfileIssuesFilter && <ProfileIssuesFilter />}</div>
|
||||
<div className="flex gap-4 md:hidden">
|
||||
<CustomMenu
|
||||
maxHeight={"md"}
|
||||
className="flex flex-grow justify-center text-sm text-custom-text-200"
|
||||
placement="bottom-start"
|
||||
customButton={
|
||||
<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>
|
||||
<ChevronDown className="h-4 w-4 text-custom-text-400" />
|
||||
</div>
|
||||
}
|
||||
customButtonClassName="flex flex-grow justify-center text-custom-text-200 text-sm"
|
||||
closeOnSelect
|
||||
>
|
||||
<></>
|
||||
{tabsList.map((tab) => (
|
||||
<CustomMenu.MenuItem className="flex items-center gap-2" key={tab.route}>
|
||||
<Link
|
||||
key={tab.route}
|
||||
href={`/${workspaceSlug}/profile/${userId}/${tab.route}`}
|
||||
className="w-full text-custom-text-300"
|
||||
>
|
||||
{tab.label}
|
||||
</Link>
|
||||
</CustomMenu.MenuItem>
|
||||
))}
|
||||
</CustomMenu>
|
||||
<button
|
||||
className="block transition-all md:hidden"
|
||||
onClick={() => {
|
||||
toggleProfileSidebar();
|
||||
}}
|
||||
>
|
||||
<PanelRight
|
||||
className={cn(
|
||||
"block h-4 w-4 md:hidden",
|
||||
!profileSidebarCollapsed ? "text-[#3E63DD]" : "text-custom-text-200"
|
||||
)}
|
||||
<Breadcrumbs>
|
||||
<Breadcrumbs.BreadcrumbItem
|
||||
type="text"
|
||||
link={
|
||||
<BreadcrumbLink
|
||||
label={breadcrumbLabel}
|
||||
disableTooltip
|
||||
icon={<UserActivityIcon className="h-4 w-4 text-custom-text-300" />}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</Breadcrumbs>
|
||||
</Header.LeftItem>
|
||||
<Header.RightItem>
|
||||
<div className="hidden md:flex md:items-center">{showProfileIssuesFilter && <ProfileIssuesFilter />}</div>
|
||||
<div className="flex gap-4 md:hidden">
|
||||
<CustomMenu
|
||||
maxHeight={"md"}
|
||||
className="flex flex-grow justify-center text-sm text-custom-text-200"
|
||||
placement="bottom-start"
|
||||
customButton={
|
||||
<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>
|
||||
<ChevronDown className="h-4 w-4 text-custom-text-400" />
|
||||
</div>
|
||||
}
|
||||
customButtonClassName="flex flex-grow justify-center text-custom-text-200 text-sm"
|
||||
closeOnSelect
|
||||
>
|
||||
<></>
|
||||
{tabsList.map((tab) => (
|
||||
<CustomMenu.MenuItem className="flex items-center gap-2" key={tab.route}>
|
||||
<Link
|
||||
key={tab.route}
|
||||
href={`/${workspaceSlug}/profile/${userId}/${tab.route}`}
|
||||
className="w-full text-custom-text-300"
|
||||
>
|
||||
{tab.label}
|
||||
</Link>
|
||||
</CustomMenu.MenuItem>
|
||||
))}
|
||||
</CustomMenu>
|
||||
<button
|
||||
className="block transition-all md:hidden"
|
||||
onClick={() => {
|
||||
toggleProfileSidebar();
|
||||
}}
|
||||
>
|
||||
<PanelRight
|
||||
className={cn(
|
||||
"block h-4 w-4 md:hidden",
|
||||
!profileSidebarCollapsed ? "text-[#3E63DD]" : "text-custom-text-200"
|
||||
)}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</Header.RightItem>
|
||||
</Header>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { ChevronDown } from "lucide-react";
|
|||
// types
|
||||
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "@plane/types";
|
||||
// ui
|
||||
import { CustomMenu, Row } from "@plane/ui";
|
||||
import { CustomMenu } from "@plane/ui";
|
||||
// components
|
||||
import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues";
|
||||
// constants
|
||||
|
|
@ -109,18 +109,18 @@ export const ProfileIssuesMobileHeader = observer(() => {
|
|||
);
|
||||
|
||||
return (
|
||||
<div className="flex justify-start border-b border-custom-border-200 py-2 md:hidden">
|
||||
<div className="flex justify-evenly border-b border-custom-border-200 py-2 md:hidden">
|
||||
<CustomMenu
|
||||
maxHeight={"md"}
|
||||
className="flex justify-center text-sm text-custom-text-200"
|
||||
className="flex flex-grow justify-center text-sm text-custom-text-200"
|
||||
placement="bottom-start"
|
||||
customButton={
|
||||
<Row className="flex flex-start text-sm text-custom-text-200">
|
||||
<div className="flex flex-center text-sm text-custom-text-200">
|
||||
Layout
|
||||
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200 my-auto" strokeWidth={1} />
|
||||
</Row>
|
||||
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200 my-auto" strokeWidth={2} />
|
||||
</div>
|
||||
}
|
||||
customButtonClassName="flex flex-start text-custom-text-200 text-sm"
|
||||
customButtonClassName="flex flex-center text-custom-text-200 text-sm"
|
||||
closeOnSelect
|
||||
>
|
||||
{ISSUE_LAYOUTS.map((layout, index) => {
|
||||
|
|
@ -139,15 +139,15 @@ export const ProfileIssuesMobileHeader = observer(() => {
|
|||
);
|
||||
})}
|
||||
</CustomMenu>
|
||||
<div className="flex items-center justify-start border-l border-custom-border-200 text-sm text-custom-text-200">
|
||||
<div className="flex flex-grow items-center justify-center border-l border-custom-border-200 text-sm text-custom-text-200">
|
||||
<FiltersDropdown
|
||||
title="Filters"
|
||||
placement="bottom-end"
|
||||
menuButton={
|
||||
<Row className="flex flex-start text-sm text-custom-text-200">
|
||||
<div className="flex flex-center text-sm text-custom-text-200">
|
||||
Filters
|
||||
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={1} />
|
||||
</Row>
|
||||
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={2} />
|
||||
</div>
|
||||
}
|
||||
isFiltersApplied={isIssueFilterActive(issueFilters)}
|
||||
>
|
||||
|
|
@ -165,15 +165,15 @@ export const ProfileIssuesMobileHeader = observer(() => {
|
|||
/>
|
||||
</FiltersDropdown>
|
||||
</div>
|
||||
<div className="flex items-center justify-start border-l border-custom-border-200 text-sm text-custom-text-200">
|
||||
<div className="flex flex-grow items-center justify-center border-l border-custom-border-200 text-sm text-custom-text-200">
|
||||
<FiltersDropdown
|
||||
title="Display"
|
||||
placement="bottom-end"
|
||||
menuButton={
|
||||
<Row className="flex flex-start text-sm text-custom-text-200">
|
||||
<div className="flex flex-center text-sm text-custom-text-200">
|
||||
Display
|
||||
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={1} />
|
||||
</Row>
|
||||
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={2} />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<DisplayFiltersSelection
|
||||
|
|
|
|||
|
|
@ -291,6 +291,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
|
|||
</Button>
|
||||
{!isCompletedCycle && (
|
||||
<Button
|
||||
className="h-full self-start"
|
||||
onClick={() => {
|
||||
setTrackElement("Cycle issues page");
|
||||
toggleCreateIssueModal(true, EIssuesStoreType.CYCLE);
|
||||
|
|
|
|||
|
|
@ -55,25 +55,23 @@ export const CyclesListHeader: FC = observer(() => {
|
|||
/>
|
||||
</Breadcrumbs>
|
||||
</Header.LeftItem>
|
||||
<Header.RightItem>
|
||||
{canUserCreateCycle && currentProjectDetails ? (
|
||||
<div className="flex items-center gap-3">
|
||||
<CyclesViewHeader projectId={currentProjectDetails.id} />
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setTrackElement("Cycles page");
|
||||
toggleCreateCycleModal(true);
|
||||
}}
|
||||
>
|
||||
<div className="hidden sm:block">Add</div> Cycle
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</Header.RightItem>
|
||||
{canUserCreateCycle && currentProjectDetails ? (
|
||||
<Header.RightItem>
|
||||
<CyclesViewHeader projectId={currentProjectDetails.id} />
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setTrackElement("Cycles page");
|
||||
toggleCreateCycleModal(true);
|
||||
}}
|
||||
>
|
||||
<div className="hidden sm:block">Add</div> Cycle
|
||||
</Button>
|
||||
</Header.RightItem>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</Header>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { Calendar, ChevronDown, Kanban, List } from "lucide-react";
|
|||
// types
|
||||
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
|
||||
// ui
|
||||
import { CustomMenu, Row } from "@plane/ui";
|
||||
import { CustomMenu } from "@plane/ui";
|
||||
// components
|
||||
import { ProjectAnalyticsModal } from "@/components/analytics";
|
||||
import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues/issue-layouts";
|
||||
|
|
@ -107,10 +107,10 @@ export const ProjectIssuesMobileHeader = observer(() => {
|
|||
className="flex flex-grow justify-center text-sm text-custom-text-200"
|
||||
placement="bottom-start"
|
||||
customButton={
|
||||
<Row className="flex flex-start text-sm text-custom-text-200">
|
||||
<div 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>
|
||||
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200 my-auto" strokeWidth={2} />
|
||||
</div>
|
||||
}
|
||||
customButtonClassName="flex flex-grow justify-center text-custom-text-200 text-sm"
|
||||
closeOnSelect
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export const ModulesListMobileHeader = observer(() => {
|
|||
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"
|
||||
customButton={
|
||||
<Row className="flex flex-grow justify-start text-custom-text-200 text-sm gap-2">
|
||||
<Row className="flex flex-grow justify-center 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>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,27 +57,25 @@ export const PagesListHeader = observer(() => {
|
|||
</Breadcrumbs>
|
||||
</div>
|
||||
</Header.LeftItem>
|
||||
<Header.RightItem>
|
||||
{canUserCreatePage ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setTrackElement("Project pages page");
|
||||
toggleCreatePageModal({
|
||||
isOpen: true,
|
||||
pageAccess: pageType === "private" ? EPageAccess.PRIVATE : EPageAccess.PUBLIC,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Add page
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</Header.RightItem>
|
||||
{canUserCreatePage ? (
|
||||
<Header.RightItem>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setTrackElement("Project pages page");
|
||||
toggleCreatePageModal({
|
||||
isOpen: true,
|
||||
pageAccess: pageType === "private" ? EPageAccess.PRIVATE : EPageAccess.PUBLIC,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Add page
|
||||
</Button>
|
||||
</Header.RightItem>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</Header>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -45,9 +45,9 @@ const AutomationSettingsPage = observer(() => {
|
|||
return (
|
||||
<>
|
||||
<PageHead title={pageTitle} />
|
||||
<section className={`w-full overflow-y-auto py-8 pr-9 ${canPerformProjectAdminActions ? "" : "opacity-60"}`}>
|
||||
<div className="flex items-center border-b border-custom-border-100 py-3.5">
|
||||
<h3 className="text-xl font-medium">Automations</h3>
|
||||
<section className={`w-full overflow-y-auto ${canPerformProjectAdminActions ? "" : "opacity-60"}`}>
|
||||
<div className="flex flex-col items-start border-b border-custom-border-100 pb-3.5">
|
||||
<h3 className="text-xl font-medium leading-normal">Automations</h3>
|
||||
</div>
|
||||
<AutoArchiveAutomation handleChange={handleChange} />
|
||||
<AutoCloseAutomation handleChange={handleChange} />
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ const EstimatesSettingsPage = observer(() => {
|
|||
<>
|
||||
<PageHead title={pageTitle} />
|
||||
<div
|
||||
className={`w-full overflow-y-auto py-8 pr-9 ${canPerformProjectAdminActions ? "" : "pointer-events-none opacity-60"}`}
|
||||
className={`w-full overflow-y-auto ${canPerformProjectAdminActions ? "" : "pointer-events-none opacity-60"}`}
|
||||
>
|
||||
<EstimateRoot
|
||||
workspaceSlug={workspaceSlug?.toString()}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ const FeaturesSettingsPage = observer(() => {
|
|||
return (
|
||||
<>
|
||||
<PageHead title={pageTitle} />
|
||||
<section className={`w-full overflow-y-auto py-8 pr-9 ${canPerformProjectAdminActions ? "" : "opacity-60"}`}>
|
||||
<section className={`w-full overflow-y-auto ${canPerformProjectAdminActions ? "" : "opacity-60"}`}>
|
||||
<ProjectFeaturesList
|
||||
workspaceSlug={workspaceSlug.toString()}
|
||||
projectId={projectId.toString()}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ const LabelsSettingsPage = observer(() => {
|
|||
return (
|
||||
<>
|
||||
<PageHead title={pageTitle} />
|
||||
<div ref={scrollableContainerRef} className="h-full w-full gap-10 overflow-y-auto py-2 pr-9">
|
||||
<div ref={scrollableContainerRef} className="h-full w-full gap-10 overflow-y-auto">
|
||||
<ProjectSettingsLabelList />
|
||||
</div>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
import { FC, ReactNode } from "react";
|
||||
// components
|
||||
import { AppHeader, ContentWrapper } from "@/components/core";
|
||||
import { ContentWrapper } from "@plane/ui";
|
||||
import { AppHeader } from "@/components/core";
|
||||
// local components
|
||||
import { ProjectSettingHeader } from "./header";
|
||||
import { ProjectSettingsSidebar } from "./sidebar";
|
||||
|
|
@ -16,14 +17,12 @@ const ProjectSettingLayout: FC<IProjectSettingLayout> = (props) => {
|
|||
return (
|
||||
<>
|
||||
<AppHeader header={<ProjectSettingHeader />} />
|
||||
<ContentWrapper>
|
||||
<div className="inset-y-0 z-20 flex flex-grow-0 h-full w-full">
|
||||
<div className="w-80 flex-shrink-0 overflow-y-hidden pt-8 sm:hidden hidden md:block lg:block">
|
||||
<ProjectSettingsSidebar />
|
||||
</div>
|
||||
<div className="w-full pl-10 sm:pl-10 md:pl-3 lg:pl-3 overflow-y-scroll vertical-scrollbar scrollbar-md">
|
||||
{children}
|
||||
</div>
|
||||
<ContentWrapper className="flex-row inset-y-0 gap-4">
|
||||
<div className="w-80 flex-shrink-0 overflow-y-hidden sm:hidden hidden md:block lg:block">
|
||||
<ProjectSettingsSidebar />
|
||||
</div>
|
||||
<div className="flex flex-col relative w-full overflow-hidden">
|
||||
<div className="w-full overflow-x-hidden overflow-y-scroll vertical-scrollbar scrollbar-md">{children}</div>
|
||||
</div>
|
||||
</ContentWrapper>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ const MembersSettingsPage = observer(() => {
|
|||
return (
|
||||
<>
|
||||
<PageHead title={pageTitle} />
|
||||
<section className={`w-full overflow-y-auto py-8 pr-9`}>
|
||||
<section className={`w-full overflow-y-auto`}>
|
||||
<ProjectSettingsMemberDefaults />
|
||||
<ProjectMemberList />
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ const GeneralSettingsPage = observer(() => {
|
|||
</>
|
||||
)}
|
||||
|
||||
<div className={`w-full overflow-y-auto py-8 pr-9 ${isAdmin ? "" : "opacity-60"}`}>
|
||||
<div className={`w-full overflow-y-auto ${isAdmin ? "" : "opacity-60"}`}>
|
||||
{currentProjectDetails && workspaceSlug && projectId && !isLoading ? (
|
||||
<ProjectDetailsForm
|
||||
project={currentProjectDetails}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export const ProjectSettingsSidebar = observer(() => {
|
|||
|
||||
if (!currentProjectRole) {
|
||||
return (
|
||||
<div className="flex w-80 flex-col gap-6 px-5">
|
||||
<div className="flex w-[280px] flex-col gap-6">
|
||||
<div className="flex flex-col gap-2">
|
||||
<span className="text-xs font-semibold text-custom-sidebar-text-400">SETTINGS</span>
|
||||
<Loader className="flex w-full flex-col gap-2">
|
||||
|
|
@ -41,7 +41,7 @@ export const ProjectSettingsSidebar = observer(() => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="flex w-80 flex-col gap-6 px-5">
|
||||
<div className="flex w-[280px] flex-col gap-6">
|
||||
<div className="flex flex-col gap-2">
|
||||
<span className="text-xs font-semibold text-custom-sidebar-text-400">SETTINGS</span>
|
||||
<div className="flex w-full flex-col gap-1">
|
||||
|
|
|
|||
|
|
@ -27,14 +27,12 @@ const StatesSettingsPage = observer(() => {
|
|||
return (
|
||||
<>
|
||||
<PageHead title={pageTitle} />
|
||||
<div className="py-8 pr-9">
|
||||
<div className="flex items-center border-b border-custom-border-100 py-3.5">
|
||||
<h3 className="text-xl font-medium">States</h3>
|
||||
</div>
|
||||
{workspaceSlug && projectId && (
|
||||
<ProjectStateRoot workspaceSlug={workspaceSlug.toString()} projectId={projectId.toString()} />
|
||||
)}
|
||||
<div className="flex items-center border-b border-custom-border-100">
|
||||
<h3 className="text-xl font-medium">States</h3>
|
||||
</div>
|
||||
{workspaceSlug && projectId && (
|
||||
<ProjectStateRoot workspaceSlug={workspaceSlug.toString()} projectId={projectId.toString()} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export const ViewMobileHeader = observer(() => {
|
|||
return (
|
||||
<>
|
||||
<div className="md:hidden flex justify-evenly border-b border-custom-border-200 py-2 z-[13] bg-custom-background-100">
|
||||
<Row className="flex items-center justify-start border-l border-custom-border-200 text-sm text-custom-text-200">
|
||||
<Row className="flex flex-grow items-center justify-center border-l border-custom-border-200 text-sm text-custom-text-200">
|
||||
<ViewOrderByDropdown
|
||||
sortBy={filters.sortBy}
|
||||
sortKey={filters.sortKey}
|
||||
|
|
@ -32,7 +32,7 @@ export const ViewMobileHeader = observer(() => {
|
|||
isMobile
|
||||
/>
|
||||
</Row>
|
||||
<div className="flex flex-grow items-center justify-start border-l border-custom-border-200 text-sm text-custom-text-200">
|
||||
<div className="flex flex-grow items-center justify-center border-l border-custom-border-200 text-sm text-custom-text-200">
|
||||
<FiltersDropdown
|
||||
icon={<ListFilter className="h-3 w-3" />}
|
||||
title="Filters"
|
||||
|
|
@ -41,7 +41,7 @@ export const ViewMobileHeader = observer(() => {
|
|||
menuButton={
|
||||
<Row className="flex items-center text-sm text-custom-text-200">
|
||||
Filters
|
||||
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={1} />
|
||||
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={2} />
|
||||
</Row>
|
||||
}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ const ApiTokensPage = observer(() => {
|
|||
<section className="w-full overflow-y-auto">
|
||||
{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 pb-3.5">
|
||||
<h3 className="text-xl font-medium">API tokens</h3>
|
||||
<Button variant="primary" onClick={() => setIsCreateTokenModalOpen(true)}>
|
||||
Add API token
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ const WorkspaceMembersSettingsPage = observer(() => {
|
|||
"opacity-60": !canPerformWorkspaceMemberActions,
|
||||
})}
|
||||
>
|
||||
<div className="flex items-center justify-between gap-4 pb-3.5">
|
||||
<div className="flex justify-between gap-4 pb-3.5 items-start ">
|
||||
<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">
|
||||
<Search className="h-3.5 w-3.5 text-custom-text-400" />
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { observer } from "mobx-react";
|
||||
import { useParams, usePathname } from "next/navigation";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles } from "@/constants/workspace";
|
||||
|
|
@ -9,7 +10,7 @@ import { WORKSPACE_SETTINGS_LINKS } from "@/plane-web/constants/workspace";
|
|||
// plane web helpers
|
||||
import { shouldRenderSettingLink } from "@/plane-web/helpers/workspace.helper";
|
||||
|
||||
export const MobileWorkspaceSettingsTabs = () => {
|
||||
export const MobileWorkspaceSettingsTabs = observer(() => {
|
||||
const router = useAppRouter();
|
||||
const { workspaceSlug } = useParams();
|
||||
const pathname = usePathname();
|
||||
|
|
@ -28,10 +29,11 @@ export const MobileWorkspaceSettingsTabs = () => {
|
|||
shouldRenderSettingLink(item.key) &&
|
||||
workspaceMemberInfo >= item.access && (
|
||||
<div
|
||||
className={`${item.highlight(pathname, `/${workspaceSlug}`)
|
||||
? "text-custom-primary-100 text-sm py-2 px-3 whitespace-nowrap flex flex-grow cursor-pointer justify-around border-b border-custom-primary-200"
|
||||
: "text-custom-text-200 flex flex-grow cursor-pointer justify-around border-b border-custom-border-200 text-sm py-2 px-3 whitespace-nowrap"
|
||||
}`}
|
||||
className={`${
|
||||
item.highlight(pathname, `/${workspaceSlug}`)
|
||||
? "text-custom-primary-100 text-sm py-2 px-3 whitespace-nowrap flex flex-grow cursor-pointer justify-around border-b border-custom-primary-200"
|
||||
: "text-custom-text-200 flex flex-grow cursor-pointer justify-around border-b border-custom-border-200 text-sm py-2 px-3 whitespace-nowrap"
|
||||
}`}
|
||||
key={index}
|
||||
onClick={() => router.push(`/${workspaceSlug}${item.href}`)}
|
||||
>
|
||||
|
|
@ -41,4 +43,4 @@ export const MobileWorkspaceSettingsTabs = () => {
|
|||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export const WorkspaceSettingsSidebar = observer(() => {
|
|||
const workspaceMemberInfo = currentWorkspaceRole || EUserWorkspaceRoles.GUEST;
|
||||
|
||||
return (
|
||||
<div className="flex w-80 flex-col gap-6">
|
||||
<div className="flex w-[280px] flex-col gap-6">
|
||||
<div className="flex flex-col gap-2">
|
||||
<span className="text-xs font-semibold text-custom-sidebar-text-400">SETTINGS</span>
|
||||
<div className="flex w-full flex-col gap-1">
|
||||
|
|
|
|||
|
|
@ -90,8 +90,8 @@ const WebhookDetailsPage = observer(() => {
|
|||
<>
|
||||
<PageHead title={pageTitle} />
|
||||
<DeleteWebhookModal isOpen={deleteWebhookModal} onClose={() => setDeleteWebhookModal(false)} />
|
||||
<div className="w-full space-y-8 overflow-y-auto md:py-8 py-4 md:pr-9 pr-4">
|
||||
<div className="-m-5">
|
||||
<div className="w-full space-y-8 overflow-y-auto">
|
||||
<div className="">
|
||||
<WebhookForm onSubmit={async (data) => await handleUpdateWebhook(data)} data={currentWebhook} />
|
||||
</div>
|
||||
{currentWebhook && <WebhookDeleteSection openDeleteModal={() => setDeleteWebhookModal(true)} />}
|
||||
|
|
@ -100,4 +100,4 @@ const WebhookDetailsPage = observer(() => {
|
|||
);
|
||||
});
|
||||
|
||||
export default WebhookDetailsPage;
|
||||
export default WebhookDetailsPage;
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ const WebhooksListPage = observer(() => {
|
|||
/>
|
||||
{Object.keys(webhooks).length > 0 ? (
|
||||
<div className="flex h-full w-full flex-col">
|
||||
<div className="flex items-center justify-between gap-4 border-b border-custom-border-200 py-3.5">
|
||||
<div className="flex items-center justify-between gap-4 border-b border-custom-border-200 pb-3.5">
|
||||
<div className="text-xl font-medium">Webhooks</div>
|
||||
<Button variant="primary" size="sm" onClick={() => setShowCreateWebhookModal(true)}>
|
||||
Add webhook
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ export const WorkspaceActiveCyclesUpgrade = observer(() => {
|
|||
<div className="grid h-full grid-cols-1 gap-5 pb-8 lg:grid-cols-2 xl:grid-cols-3">
|
||||
{WORKSPACE_ACTIVE_CYCLES_DETAILS.map((item) => (
|
||||
<div key={item.title} className="flex min-h-32 w-full flex-col gap-2 rounded-md bg-custom-background-80 p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-2 justify-between">
|
||||
<h3 className="font-medium">{item.title}</h3>
|
||||
<item.icon className="h-4 w-4 text-blue-500" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export const BillingRoot = () => (
|
|||
<h3 className="text-xl font-medium">Billing and Plans</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-4 py-6">
|
||||
<div className="py-6">
|
||||
<div>
|
||||
<h4 className="text-md mb-1 leading-6">Current plan</h4>
|
||||
<p className="mb-3 text-sm text-custom-text-200">You are currently using the free plan</p>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export const ApiTokenListItem: React.FC<Props> = (props) => {
|
|||
return (
|
||||
<>
|
||||
<DeleteApiTokenModal isOpen={deleteModalOpen} onClose={() => setDeleteModalOpen(false)} tokenId={token.id} />
|
||||
<div className="group relative flex flex-col justify-center border-b border-custom-border-200 px-4 py-3">
|
||||
<div className="group relative flex flex-col justify-center border-b border-custom-border-200 py-3">
|
||||
<Tooltip tooltipContent="Delete token" isMobile={isMobile}>
|
||||
<button
|
||||
onClick={() => setDeleteModalOpen(true)}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export const AutoArchiveAutomation: React.FC<Props> = observer((props) => {
|
|||
handleClose={() => setmonthModal(false)}
|
||||
handleChange={handleChange}
|
||||
/>
|
||||
<div className="flex flex-col gap-4 border-b border-custom-border-100 px-4 py-6">
|
||||
<div className="flex flex-col gap-4 border-b border-custom-border-100 py-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="flex items-center justify-center rounded bg-custom-background-90 p-3">
|
||||
|
|
@ -68,7 +68,7 @@ export const AutoArchiveAutomation: React.FC<Props> = observer((props) => {
|
|||
|
||||
{currentProjectDetails ? (
|
||||
currentProjectDetails.archive_in !== 0 && (
|
||||
<div className="ml-12">
|
||||
<div className="mx-6">
|
||||
<div className="flex w-full items-center justify-between gap-2 rounded border border-custom-border-200 bg-custom-background-90 px-5 py-4">
|
||||
<div className="w-1/2 text-sm font-medium">Auto-archive issues that are closed for</div>
|
||||
<div className="w-1/2">
|
||||
|
|
@ -104,7 +104,7 @@ export const AutoArchiveAutomation: React.FC<Props> = observer((props) => {
|
|||
</div>
|
||||
)
|
||||
) : (
|
||||
<Loader className="ml-12">
|
||||
<Loader className="mx-6">
|
||||
<Loader.Item height="50px" />
|
||||
</Loader>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
|
|||
handleClose={() => setmonthModal(false)}
|
||||
handleChange={handleChange}
|
||||
/>
|
||||
<div className="flex flex-col gap-4 border-b border-custom-border-200 px-4 py-6">
|
||||
<div className="flex flex-col gap-4 border-b border-custom-border-200 py-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="flex items-center justify-center rounded bg-custom-background-90 p-3">
|
||||
|
|
@ -95,7 +95,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
|
|||
|
||||
{currentProjectDetails ? (
|
||||
currentProjectDetails.close_in !== 0 && (
|
||||
<div className="ml-12">
|
||||
<div className="mx-6">
|
||||
<div className="flex flex-col rounded border border-custom-border-200 bg-custom-background-90">
|
||||
<div className="flex w-full items-center justify-between gap-2 px-5 py-4">
|
||||
<div className="w-1/2 text-sm font-medium">Auto-close issues that are inactive for</div>
|
||||
|
|
@ -155,7 +155,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
|
|||
)}
|
||||
{selectedOption?.name
|
||||
? selectedOption.name
|
||||
: currentDefaultState?.name ?? <span className="text-custom-text-200">State</span>}
|
||||
: (currentDefaultState?.name ?? <span className="text-custom-text-200">State</span>)}
|
||||
</div>
|
||||
}
|
||||
onChange={(val: string) => {
|
||||
|
|
@ -171,7 +171,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
|
|||
</div>
|
||||
)
|
||||
) : (
|
||||
<Loader className="ml-12">
|
||||
<Loader className="mx-6">
|
||||
<Loader.Item height="50px" />
|
||||
</Loader>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ export const WidgetIssuesList: React.FC<WidgetIssuesListProps> = (props) => {
|
|||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="h-full grid place-items-center">
|
||||
<div className="h-full grid place-items-center my-6">
|
||||
{type === "assigned" && <AssignedIssuesEmptyState type={tab} />}
|
||||
{type === "created" && <CreatedIssuesEmptyState type={tab} />}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -41,10 +41,10 @@ export const EstimateRoot: FC<TEstimateRoot> = observer((props) => {
|
|||
{loader === "init-loader" || isSWRLoading ? (
|
||||
<EstimateLoaderScreen />
|
||||
) : (
|
||||
<div className="space-y-12">
|
||||
<div className="space-y-2">
|
||||
{/* header */}
|
||||
<div className="text-xl font-medium text-custom-text-100 border-b border-custom-border-200 py-3.5">
|
||||
Estimates
|
||||
<div className="flex flex-col items-start border-b border-custom-border-100 pb-3.5">
|
||||
<h3 className="text-xl font-medium leading-normal">Estimates</h3>
|
||||
</div>
|
||||
|
||||
{/* current active estimate section */}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ const IntegrationGuide = observer(() => {
|
|||
{EXPORTERS_LIST.map((service) => (
|
||||
<div
|
||||
key={service.provider}
|
||||
className="flex items-center justify-between gap-2 border-b border-custom-border-100 bg-custom-background-100 px-4 py-6"
|
||||
className="flex items-center justify-between gap-2 border-b border-custom-border-100 bg-custom-background-100 py-6"
|
||||
>
|
||||
<div className="flex w-full items-start justify-between gap-4">
|
||||
<div className="item-center flex gap-2.5">
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const smallButton = <ListFilter className="h-3 " />;
|
|||
const largeButton = (
|
||||
<div className={cn(getButtonStyling("neutral-primary", "sm"), "text-custom-text-300")}>
|
||||
<ListFilter className="h-3 " />
|
||||
<span className="hidden lg:flex">Filters</span>
|
||||
<span className="hidden xl:flex">Filters</span>
|
||||
|
||||
<ChevronDown className="h-3 w-3" strokeWidth={2} />
|
||||
</div>
|
||||
|
|
@ -21,8 +21,8 @@ export const FiltersRoot: FC = () => (
|
|||
<FiltersDropdown
|
||||
menuButton={
|
||||
<>
|
||||
<div className="hidden 2xl:flex">{largeButton}</div>
|
||||
<div className="flex 2xl:hidden">{smallButton}</div>
|
||||
<div className="hidden xl:flex">{largeButton}</div>
|
||||
<div className="flex xl:hidden">{smallButton}</div>
|
||||
</>
|
||||
}
|
||||
title=""
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ export const InboxIssueOrderByDropdown: FC = observer(() => {
|
|||
<CustomMenu
|
||||
customButton={
|
||||
<>
|
||||
<div className="hidden 2xl:flex">{largeButton}</div>
|
||||
<div className="flex 2xl:hidden">{smallButton}</div>
|
||||
<div className="hidden xl:flex">{largeButton}</div>
|
||||
<div className="flex xl:hidden">{smallButton}</div>
|
||||
</>
|
||||
}
|
||||
placement="bottom-end"
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ export const InboxSidebar: FC<IInboxSidebarProps> = observer((props) => {
|
|||
<div
|
||||
key={option?.key}
|
||||
className={cn(
|
||||
`text-sm relative flex items-center gap-1 h-[50px] px-3 cursor-pointer transition-all font-medium`,
|
||||
`text-sm relative flex items-center gap-1 h-full px-3 cursor-pointer transition-all font-medium`,
|
||||
currentTab === option?.key ? `text-custom-primary-100` : `hover:text-custom-text-200`
|
||||
)}
|
||||
onClick={() => {
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
|||
const isGroupByCreatedBy = group_by === "created_by";
|
||||
|
||||
return (
|
||||
<ContentWrapper className={`flex-row relative gap-4`}>
|
||||
<ContentWrapper className={`flex-row relative gap-4 py-4`}>
|
||||
{list &&
|
||||
list.length > 0 &&
|
||||
list.map((subList: IGroupByColumn) => {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export const HeaderSubGroupByCard: FC<IHeaderSubGroupByCard> = observer((props)
|
|||
const { icon, title, count, column_id, kanbanFilters, handleKanbanFilters } = props;
|
||||
return (
|
||||
<div
|
||||
className={`relative flex w-full flex-shrink-0 flex-row items-center gap-2 rounded-sm p-1.5 cursor-pointer`}
|
||||
className={`relative flex w-full flex-shrink-0 flex-row items-center gap-1 rounded-sm py-1.5 cursor-pointer`}
|
||||
onClick={() => handleKanbanFilters("sub_group_by", column_id)}
|
||||
>
|
||||
<div className="flex h-[20px] w-[20px] flex-shrink-0 items-center justify-center overflow-hidden rounded-sm transition-all hover:bg-custom-background-80">
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import {
|
|||
TIssueGroupByOptions,
|
||||
TIssueOrderByOptions,
|
||||
} from "@plane/types";
|
||||
// UI
|
||||
import { Row } from "@plane/ui";
|
||||
// hooks
|
||||
import { useCycle, useLabel, useMember, useModule, useProject, useProjectState } from "@/hooks/store";
|
||||
import { useIssueStoreType } from "@/hooks/use-issue-layout-store";
|
||||
|
|
@ -160,7 +162,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
|
|||
return (
|
||||
<div key={_list.id} className="flex flex-shrink-0 flex-col">
|
||||
<div className="sticky top-[50px] z-[3] py-1 flex w-full items-center bg-custom-background-100 border-y-[0.5px] border-custom-border-200">
|
||||
<div className="sticky left-0 flex-shrink-0">
|
||||
<Row className="sticky left-0 flex-shrink-0">
|
||||
<HeaderSubGroupByCard
|
||||
column_id={_list.id}
|
||||
icon={_list.icon}
|
||||
|
|
@ -169,7 +171,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
|
|||
kanbanFilters={kanbanFilters}
|
||||
handleKanbanFilters={handleKanbanFilters}
|
||||
/>
|
||||
</div>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
{subGroupByVisibilityToggle.showIssues && (
|
||||
|
|
@ -295,7 +297,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
|||
|
||||
return (
|
||||
<div className="relative">
|
||||
<div className="sticky top-0 z-[4] h-[50px] bg-custom-background-90 px-2">
|
||||
<Row className="sticky top-0 z-[4] h-[50px] bg-custom-background-90">
|
||||
<SubGroupSwimlaneHeader
|
||||
getGroupIssueCount={getGroupIssueCount}
|
||||
group_by={group_by}
|
||||
|
|
@ -305,7 +307,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
|||
list={groupByList}
|
||||
showEmptyGroup={showEmptyGroup}
|
||||
/>
|
||||
</div>
|
||||
</Row>
|
||||
|
||||
{sub_group_by && (
|
||||
<SubGroupSwimlane
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export const KanbanQuickAddIssueButton: FC<TQuickAddIssueButton> = observer((pro
|
|||
|
||||
return (
|
||||
<div
|
||||
className="flex w-full cursor-pointer items-center gap-2 p-3 py-1.5 text-custom-text-350 hover:text-custom-text-300"
|
||||
className="flex w-full cursor-pointer items-center gap-2 py-1.5 text-custom-text-350 hover:text-custom-text-300"
|
||||
onClick={onClick}
|
||||
>
|
||||
<PlusIcon className="h-3.5 w-3.5 stroke-2" />
|
||||
|
|
|
|||
|
|
@ -63,13 +63,13 @@ export const ProjectSettingsLabelList: React.FC = observer(() => {
|
|||
data={selectDeleteLabel ?? null}
|
||||
onClose={() => setSelectDeleteLabel(null)}
|
||||
/>
|
||||
<div className="flex items-center justify-between border-b border-custom-border-100 py-3.5">
|
||||
<div className="flex items-center justify-between border-b border-custom-border-100 pb-3.5">
|
||||
<h3 className="text-xl font-medium">Labels</h3>
|
||||
<Button variant="primary" onClick={newLabel} size="sm">
|
||||
Add label
|
||||
</Button>
|
||||
</div>
|
||||
<div className="w-full py-8">
|
||||
<div className="w-full py-2">
|
||||
{showLabelForm && (
|
||||
<div className="my-2 w-full rounded border border-custom-border-200 px-3.5 py-2">
|
||||
<CreateUpdateLabelInline
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export const ProfileStateDistribution: React.FC<Props> = ({ stateDistribution, u
|
|||
return (
|
||||
<div className="flex flex-col space-y-2">
|
||||
<h3 className="text-lg font-medium">Issues by state</h3>
|
||||
<Card>
|
||||
<Card className="h-full">
|
||||
{userProfile.state_distribution.length > 0 ? (
|
||||
<div className="grid grid-cols-1 gap-x-6 md:grid-cols-2">
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ export const ProjectDetailsForm: FC<IProjectDetailsForm> = (props) => {
|
|||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className="relative mt-6 h-44 w-full">
|
||||
<div className="relative h-44 w-full">
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent" />
|
||||
<img src={watch("cover_image")!} alt={watch("cover_image")!} className="h-44 w-full rounded-md object-cover" />
|
||||
<div className="z-5 absolute bottom-4 flex w-full items-end justify-between gap-3 px-4">
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ export const ProjectsBaseHeader = observer(() => {
|
|||
setTrackElement("Projects page");
|
||||
toggleCreateProjectModal(true);
|
||||
}}
|
||||
className="items-center gap-1 my-auto"
|
||||
className="items-center gap-1"
|
||||
>
|
||||
<span className="hidden sm:inline-block">Add</span> Project
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -67,9 +67,9 @@ export const ProjectSettingsMemberDefaults: React.FC = observer(() => {
|
|||
default_assignee:
|
||||
formData.default_assignee === "none"
|
||||
? null
|
||||
: formData.default_assignee ?? currentProjectDetails?.default_assignee,
|
||||
: (formData.default_assignee ?? currentProjectDetails?.default_assignee),
|
||||
project_lead:
|
||||
formData.project_lead === "none" ? null : formData.project_lead ?? currentProjectDetails?.project_lead,
|
||||
formData.project_lead === "none" ? null : (formData.project_lead ?? currentProjectDetails?.project_lead),
|
||||
})
|
||||
.then(() => {
|
||||
setToast({
|
||||
|
|
@ -85,12 +85,12 @@ export const ProjectSettingsMemberDefaults: React.FC = observer(() => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<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">Defaults</h3>
|
||||
</div>
|
||||
|
||||
<div className="flex w-full flex-col gap-2 pb-4">
|
||||
<div className="flex w-full items-center gap-4 py-8">
|
||||
<div className="flex w-full items-center gap-4 py-4">
|
||||
<div className="flex w-1/2 flex-col gap-2">
|
||||
<h4 className="text-sm">Project Lead</h4>
|
||||
<div className="">
|
||||
|
|
|
|||
|
|
@ -56,12 +56,12 @@ export const ProjectFeaturesList: FC<Props> = observer((props) => {
|
|||
if (!currentUser) return <></>;
|
||||
|
||||
return (
|
||||
<div className="mx-4 space-y-6">
|
||||
<div className="space-y-6">
|
||||
{Object.keys(PROJECT_FEATURES_LIST).map((featureSectionKey) => {
|
||||
const feature = PROJECT_FEATURES_LIST[featureSectionKey];
|
||||
return (
|
||||
<div key={featureSectionKey} className="">
|
||||
<div className="flex flex-col justify-center border-b border-custom-border-100 py-3">
|
||||
<div className="flex flex-col justify-center border-b border-custom-border-100">
|
||||
<h3 className="text-xl font-medium">{feature.title}</h3>
|
||||
<h4 className="text-sm leading-5 text-custom-text-200">{feature.description}</h4>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { forwardRef } from "react";
|
|||
import { ContentWrapper } from "@plane/ui";
|
||||
|
||||
export const KanbanIssueBlockLoader = forwardRef<HTMLSpanElement>((props, ref) => (
|
||||
<span ref={ref} className="block h-28 m-1.5 animate-pulse bg-custom-background-80 rounded" />
|
||||
<span ref={ref} className="block h-28 animate-pulse bg-custom-background-80 rounded" />
|
||||
));
|
||||
|
||||
KanbanIssueBlockLoader.displayName = "KanbanIssueBlockLoader";
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export const ViewOrderByDropdown: React.FC<Props> = (props) => {
|
|||
];
|
||||
|
||||
const buttonClassName = isMobile
|
||||
? "flex items-center text-sm text-custom-text-200 gap-2"
|
||||
? "flex items-center text-sm text-custom-text-200 gap-2 w-full"
|
||||
: `${getButtonStyling("neutral-primary", "sm")} px-2 text-custom-text-300`;
|
||||
|
||||
const chevronClassName = isMobile ? "h-4 w-4 text-custom-text-200" : "h-3 w-3";
|
||||
|
|
@ -38,11 +38,11 @@ export const ViewOrderByDropdown: React.FC<Props> = (props) => {
|
|||
<span className={buttonClassName}>
|
||||
{!isMobile && <ArrowDownWideNarrow className="h-3 w-3" />}
|
||||
<span className="flex-shrink-0"> {orderByDetails?.label}</span>
|
||||
<ChevronDown className={chevronClassName} strokeWidth={1} />
|
||||
<ChevronDown className={chevronClassName} strokeWidth={2} />
|
||||
</span>
|
||||
}
|
||||
placement="bottom-end"
|
||||
className="w-full"
|
||||
className="w-full flex justify-center"
|
||||
maxHeight="lg"
|
||||
closeOnSelect
|
||||
>
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ export const WebhookForm: FC<Props> = observer((props) => {
|
|||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(handleFormSubmit)}>
|
||||
<div className="space-y-5 p-5">
|
||||
<div className="space-y-5 ">
|
||||
<div className="text-xl font-medium text-custom-text-200">{data ? "Webhook details" : "Create webhook"}</div>
|
||||
<div className="space-y-3">
|
||||
<div className="space-y-1">
|
||||
|
|
@ -85,7 +85,7 @@ export const WebhookForm: FC<Props> = observer((props) => {
|
|||
</div>
|
||||
</div>
|
||||
{data ? (
|
||||
<div className="p-5 pt-0 space-y-5">
|
||||
<div className="pt-0 space-y-5">
|
||||
<WebhookSecretKey data={data} />
|
||||
<Button type="submit" loading={isSubmitting}>
|
||||
{isSubmitting ? "Updating" : "Update"}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export const WebhooksListItem: FC<IWebhookListItem> = (props) => {
|
|||
return (
|
||||
<div className="border-b border-custom-border-200">
|
||||
<Link href={`/${workspaceSlug}/settings/webhooks/${webhook?.id}`}>
|
||||
<span className="flex items-center justify-between gap-4 px-3.5 py-[18px]">
|
||||
<span className="flex items-center justify-between gap-4 py-[18px]">
|
||||
<h5 className="truncate text-base font-medium">{webhook.url}</h5>
|
||||
<ToggleSwitch value={webhook.is_active} onChange={handleToggle} />
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ export const WorkspaceDetails: FC = observer(() => {
|
|||
)}
|
||||
/>
|
||||
<div className={`w-full overflow-y-auto md:pr-9 pr-4 ${isAdmin ? "" : "opacity-60"}`}>
|
||||
<div className="flex items-center gap-5 border-b border-custom-border-100 pb-7">
|
||||
<div className="flex gap-5 border-b border-custom-border-100 pb-7 items-start">
|
||||
<div className="flex flex-col gap-1">
|
||||
<button type="button" onClick={() => setIsImageUploadModalOpen(true)} disabled={!isAdmin}>
|
||||
{watch("logo") && watch("logo") !== null && watch("logo") !== "" ? (
|
||||
|
|
@ -190,7 +190,7 @@ export const WorkspaceDetails: FC = observer(() => {
|
|||
</button>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<h3 className="text-lg font-semibold leading-6">{watch("name")}</h3>
|
||||
<div className="text-lg font-semibold leading-6 mb:-my-5">{watch("name")}</div>
|
||||
<button type="button" onClick={handleCopyUrl} className="text-sm tracking-tight text-left">{`${
|
||||
typeof window !== "undefined" && window.location.origin.replace("http://", "").replace("https://", "")
|
||||
}/${currentWorkspace.slug}`}</button>
|
||||
|
|
@ -212,7 +212,7 @@ export const WorkspaceDetails: FC = observer(() => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="my-10 flex flex-col gap-8">
|
||||
<div className="my-8 flex flex-col gap-8">
|
||||
<div className="grid-col grid w-full grid-cols-1 items-center justify-between gap-10 xl:grid-cols-2 2xl:grid-cols-3">
|
||||
<div className="flex flex-col gap-1">
|
||||
<h4 className="text-sm">Workspace name</h4>
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ export const GlobalViewsHeader: React.FC = observer(() => {
|
|||
const isAuthorizedUser = !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER;
|
||||
|
||||
return (
|
||||
<Header variant={EHeaderVariant.SECONDARY}>
|
||||
<Header variant={EHeaderVariant.SECONDARY} className="min-h-[44px]">
|
||||
<CreateUpdateWorkspaceViewModal isOpen={createViewModal} onClose={() => setCreateViewModal(false)} />
|
||||
<div
|
||||
ref={containerRef}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue