[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;
|
showOnMobile?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const HeaderContext = React.createContext<THeaderVariant | null>(null);
|
||||||
const Header = (props: HeaderProps) => {
|
const Header = (props: HeaderProps) => {
|
||||||
const {
|
const {
|
||||||
variant = EHeaderVariant.PRIMARY,
|
variant = EHeaderVariant.PRIMARY,
|
||||||
|
|
@ -23,6 +24,7 @@ const Header = (props: HeaderProps) => {
|
||||||
|
|
||||||
const style = getHeaderStyle(variant, setHeight, showOnMobile);
|
const style = getHeaderStyle(variant, setHeight, showOnMobile);
|
||||||
return (
|
return (
|
||||||
|
<HeaderContext.Provider value={variant}>
|
||||||
<Row
|
<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)}
|
||||||
|
|
@ -30,6 +32,7 @@ const Header = (props: HeaderProps) => {
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Row>
|
</Row>
|
||||||
|
</HeaderContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -40,9 +43,23 @@ const LeftItem = (props: HeaderProps) => (
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
const RightItem = (props: HeaderProps) => (
|
const RightItem = (props: HeaderProps) => {
|
||||||
<div className={cn("flex justify-end gap-3 w-auto items-baseline", props.className)}>{props.children}</div>
|
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.LeftItem = LeftItem;
|
||||||
Header.RightItem = RightItem;
|
Header.RightItem = RightItem;
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,12 @@ const AnalyticsPage = observer(() => {
|
||||||
<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}>
|
||||||
<Header 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 h-full">
|
||||||
{ANALYTICS_TABS.map((tab) => (
|
{ANALYTICS_TABS.map((tab) => (
|
||||||
<Tab key={tab.key} as={Fragment}>
|
<Tab key={tab.key} as={Fragment}>
|
||||||
{({ selected }) => (
|
{({ selected }) => (
|
||||||
<button
|
<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"
|
selected ? "text-custom-primary-100 " : "hover:text-custom-text-200"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,6 @@ export const UserProfileHeader: FC<TUserProfileHeader> = observer((props) => {
|
||||||
return (
|
return (
|
||||||
<Header>
|
<Header>
|
||||||
<Header.LeftItem>
|
<Header.LeftItem>
|
||||||
<div className="flex w-full justify-between">
|
|
||||||
<Breadcrumbs>
|
<Breadcrumbs>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -61,6 +60,8 @@ export const UserProfileHeader: FC<TUserProfileHeader> = observer((props) => {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
|
</Header.LeftItem>
|
||||||
|
<Header.RightItem>
|
||||||
<div className="hidden md:flex md:items-center">{showProfileIssuesFilter && <ProfileIssuesFilter />}</div>
|
<div className="hidden md:flex md:items-center">{showProfileIssuesFilter && <ProfileIssuesFilter />}</div>
|
||||||
<div className="flex gap-4 md:hidden">
|
<div className="flex gap-4 md:hidden">
|
||||||
<CustomMenu
|
<CustomMenu
|
||||||
|
|
@ -103,8 +104,7 @@ export const UserProfileHeader: FC<TUserProfileHeader> = observer((props) => {
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Header.RightItem>
|
||||||
</Header.LeftItem>
|
|
||||||
</Header>
|
</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, Row } from "@plane/ui";
|
import { CustomMenu } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues";
|
import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues";
|
||||||
// constants
|
// constants
|
||||||
|
|
@ -109,18 +109,18 @@ export const ProfileIssuesMobileHeader = observer(() => {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
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
|
<CustomMenu
|
||||||
maxHeight={"md"}
|
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"
|
placement="bottom-start"
|
||||||
customButton={
|
customButton={
|
||||||
<Row className="flex flex-start text-sm text-custom-text-200">
|
<div className="flex flex-center text-sm text-custom-text-200">
|
||||||
Layout
|
Layout
|
||||||
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200 my-auto" strokeWidth={1} />
|
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200 my-auto" strokeWidth={2} />
|
||||||
</Row>
|
</div>
|
||||||
}
|
}
|
||||||
customButtonClassName="flex flex-start text-custom-text-200 text-sm"
|
customButtonClassName="flex flex-center text-custom-text-200 text-sm"
|
||||||
closeOnSelect
|
closeOnSelect
|
||||||
>
|
>
|
||||||
{ISSUE_LAYOUTS.map((layout, index) => {
|
{ISSUE_LAYOUTS.map((layout, index) => {
|
||||||
|
|
@ -139,15 +139,15 @@ export const ProfileIssuesMobileHeader = observer(() => {
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</CustomMenu>
|
</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
|
<FiltersDropdown
|
||||||
title="Filters"
|
title="Filters"
|
||||||
placement="bottom-end"
|
placement="bottom-end"
|
||||||
menuButton={
|
menuButton={
|
||||||
<Row className="flex flex-start text-sm text-custom-text-200">
|
<div className="flex flex-center text-sm text-custom-text-200">
|
||||||
Filters
|
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>
|
</div>
|
||||||
}
|
}
|
||||||
isFiltersApplied={isIssueFilterActive(issueFilters)}
|
isFiltersApplied={isIssueFilterActive(issueFilters)}
|
||||||
>
|
>
|
||||||
|
|
@ -165,15 +165,15 @@ export const ProfileIssuesMobileHeader = observer(() => {
|
||||||
/>
|
/>
|
||||||
</FiltersDropdown>
|
</FiltersDropdown>
|
||||||
</div>
|
</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
|
<FiltersDropdown
|
||||||
title="Display"
|
title="Display"
|
||||||
placement="bottom-end"
|
placement="bottom-end"
|
||||||
menuButton={
|
menuButton={
|
||||||
<Row className="flex flex-start text-sm text-custom-text-200">
|
<div className="flex flex-center text-sm text-custom-text-200">
|
||||||
Display
|
Display
|
||||||
<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>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<DisplayFiltersSelection
|
<DisplayFiltersSelection
|
||||||
|
|
|
||||||
|
|
@ -291,6 +291,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
|
||||||
</Button>
|
</Button>
|
||||||
{!isCompletedCycle && (
|
{!isCompletedCycle && (
|
||||||
<Button
|
<Button
|
||||||
|
className="h-full self-start"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setTrackElement("Cycle issues page");
|
setTrackElement("Cycle issues page");
|
||||||
toggleCreateIssueModal(true, EIssuesStoreType.CYCLE);
|
toggleCreateIssueModal(true, EIssuesStoreType.CYCLE);
|
||||||
|
|
|
||||||
|
|
@ -55,9 +55,8 @@ export const CyclesListHeader: FC = observer(() => {
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</Header.LeftItem>
|
</Header.LeftItem>
|
||||||
<Header.RightItem>
|
|
||||||
{canUserCreateCycle && currentProjectDetails ? (
|
{canUserCreateCycle && currentProjectDetails ? (
|
||||||
<div className="flex items-center gap-3">
|
<Header.RightItem>
|
||||||
<CyclesViewHeader projectId={currentProjectDetails.id} />
|
<CyclesViewHeader projectId={currentProjectDetails.id} />
|
||||||
<Button
|
<Button
|
||||||
variant="primary"
|
variant="primary"
|
||||||
|
|
@ -69,11 +68,10 @@ export const CyclesListHeader: FC = observer(() => {
|
||||||
>
|
>
|
||||||
<div className="hidden sm:block">Add</div> Cycle
|
<div className="hidden sm:block">Add</div> Cycle
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</Header.RightItem>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
</Header.RightItem>
|
|
||||||
</Header>
|
</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, Row } from "@plane/ui";
|
import { CustomMenu } 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";
|
||||||
|
|
@ -107,10 +107,10 @@ export const ProjectIssuesMobileHeader = observer(() => {
|
||||||
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={
|
||||||
<Row className="flex flex-start text-sm text-custom-text-200">
|
<div className="flex flex-start text-sm text-custom-text-200">
|
||||||
Layout
|
Layout
|
||||||
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200 my-auto" strokeWidth={1} />
|
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200 my-auto" strokeWidth={2} />
|
||||||
</Row>
|
</div>
|
||||||
}
|
}
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -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"
|
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={
|
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} />
|
<span>Layout</span> <ChevronDown className="h-4 w-4 text-custom-text-200 my-auto" strokeWidth={1} />
|
||||||
</Row>
|
</Row>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,9 +57,8 @@ export const PagesListHeader = observer(() => {
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</div>
|
</div>
|
||||||
</Header.LeftItem>
|
</Header.LeftItem>
|
||||||
<Header.RightItem>
|
|
||||||
{canUserCreatePage ? (
|
{canUserCreatePage ? (
|
||||||
<div className="flex items-center gap-2">
|
<Header.RightItem>
|
||||||
<Button
|
<Button
|
||||||
variant="primary"
|
variant="primary"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
@ -73,11 +72,10 @@ export const PagesListHeader = observer(() => {
|
||||||
>
|
>
|
||||||
Add page
|
Add page
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</Header.RightItem>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
</Header.RightItem>
|
|
||||||
</Header>
|
</Header>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,9 @@ const AutomationSettingsPage = observer(() => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHead title={pageTitle} />
|
<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"}`}>
|
||||||
<div className="flex items-center border-b border-custom-border-100 py-3.5">
|
<div className="flex flex-col items-start border-b border-custom-border-100 pb-3.5">
|
||||||
<h3 className="text-xl font-medium">Automations</h3>
|
<h3 className="text-xl font-medium leading-normal">Automations</h3>
|
||||||
</div>
|
</div>
|
||||||
<AutoArchiveAutomation handleChange={handleChange} />
|
<AutoArchiveAutomation handleChange={handleChange} />
|
||||||
<AutoCloseAutomation handleChange={handleChange} />
|
<AutoCloseAutomation handleChange={handleChange} />
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ const EstimatesSettingsPage = observer(() => {
|
||||||
<>
|
<>
|
||||||
<PageHead title={pageTitle} />
|
<PageHead title={pageTitle} />
|
||||||
<div
|
<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
|
<EstimateRoot
|
||||||
workspaceSlug={workspaceSlug?.toString()}
|
workspaceSlug={workspaceSlug?.toString()}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ const FeaturesSettingsPage = observer(() => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHead title={pageTitle} />
|
<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
|
<ProjectFeaturesList
|
||||||
workspaceSlug={workspaceSlug.toString()}
|
workspaceSlug={workspaceSlug.toString()}
|
||||||
projectId={projectId.toString()}
|
projectId={projectId.toString()}
|
||||||
|
|
|
||||||
|
|
@ -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-2 pr-9">
|
<div ref={scrollableContainerRef} className="h-full w-full gap-10 overflow-y-auto">
|
||||||
<ProjectSettingsLabelList />
|
<ProjectSettingsLabelList />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
import { FC, ReactNode } from "react";
|
import { FC, 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 { ProjectSettingHeader } from "./header";
|
import { ProjectSettingHeader } from "./header";
|
||||||
import { ProjectSettingsSidebar } from "./sidebar";
|
import { ProjectSettingsSidebar } from "./sidebar";
|
||||||
|
|
@ -16,14 +17,12 @@ const ProjectSettingLayout: FC<IProjectSettingLayout> = (props) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AppHeader header={<ProjectSettingHeader />} />
|
<AppHeader header={<ProjectSettingHeader />} />
|
||||||
<ContentWrapper>
|
<ContentWrapper className="flex-row inset-y-0 gap-4">
|
||||||
<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 sm:hidden hidden md:block lg:block">
|
||||||
<div className="w-80 flex-shrink-0 overflow-y-hidden pt-8 sm:hidden hidden md:block lg:block">
|
|
||||||
<ProjectSettingsSidebar />
|
<ProjectSettingsSidebar />
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full pl-10 sm:pl-10 md:pl-3 lg:pl-3 overflow-y-scroll vertical-scrollbar scrollbar-md">
|
<div className="flex flex-col relative w-full overflow-hidden">
|
||||||
{children}
|
<div className="w-full overflow-x-hidden overflow-y-scroll vertical-scrollbar scrollbar-md">{children}</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</ContentWrapper>
|
</ContentWrapper>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ const MembersSettingsPage = 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`}>
|
||||||
<ProjectSettingsMemberDefaults />
|
<ProjectSettingsMemberDefaults />
|
||||||
<ProjectMemberList />
|
<ProjectMemberList />
|
||||||
</section>
|
</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 ? (
|
{currentProjectDetails && workspaceSlug && projectId && !isLoading ? (
|
||||||
<ProjectDetailsForm
|
<ProjectDetailsForm
|
||||||
project={currentProjectDetails}
|
project={currentProjectDetails}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export const ProjectSettingsSidebar = observer(() => {
|
||||||
|
|
||||||
if (!currentProjectRole) {
|
if (!currentProjectRole) {
|
||||||
return (
|
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">
|
<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>
|
||||||
<Loader className="flex w-full flex-col gap-2">
|
<Loader className="flex w-full flex-col gap-2">
|
||||||
|
|
@ -41,7 +41,7 @@ export const ProjectSettingsSidebar = observer(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
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">
|
<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">
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,12 @@ const StatesSettingsPage = observer(() => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHead title={pageTitle} />
|
<PageHead title={pageTitle} />
|
||||||
<div className="py-8 pr-9">
|
<div className="flex items-center border-b border-custom-border-100">
|
||||||
<div className="flex items-center border-b border-custom-border-100 py-3.5">
|
|
||||||
<h3 className="text-xl font-medium">States</h3>
|
<h3 className="text-xl font-medium">States</h3>
|
||||||
</div>
|
</div>
|
||||||
{workspaceSlug && projectId && (
|
{workspaceSlug && projectId && (
|
||||||
<ProjectStateRoot workspaceSlug={workspaceSlug.toString()} projectId={projectId.toString()} />
|
<ProjectStateRoot workspaceSlug={workspaceSlug.toString()} projectId={projectId.toString()} />
|
||||||
)}
|
)}
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -21,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">
|
||||||
<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
|
<ViewOrderByDropdown
|
||||||
sortBy={filters.sortBy}
|
sortBy={filters.sortBy}
|
||||||
sortKey={filters.sortKey}
|
sortKey={filters.sortKey}
|
||||||
|
|
@ -32,7 +32,7 @@ export const ViewMobileHeader = observer(() => {
|
||||||
isMobile
|
isMobile
|
||||||
/>
|
/>
|
||||||
</Row>
|
</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
|
<FiltersDropdown
|
||||||
icon={<ListFilter className="h-3 w-3" />}
|
icon={<ListFilter className="h-3 w-3" />}
|
||||||
title="Filters"
|
title="Filters"
|
||||||
|
|
@ -41,7 +41,7 @@ export const ViewMobileHeader = observer(() => {
|
||||||
menuButton={
|
menuButton={
|
||||||
<Row 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" strokeWidth={1} />
|
<ChevronDown className="ml-2 h-4 w-4 text-custom-text-200" strokeWidth={2} />
|
||||||
</Row>
|
</Row>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ const ApiTokensPage = observer(() => {
|
||||||
<section className="w-full overflow-y-auto">
|
<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 pb-3.5">
|
||||||
<h3 className="text-xl font-medium">API tokens</h3>
|
<h3 className="text-xl font-medium">API tokens</h3>
|
||||||
<Button variant="primary" onClick={() => setIsCreateTokenModalOpen(true)}>
|
<Button variant="primary" onClick={() => setIsCreateTokenModalOpen(true)}>
|
||||||
Add API token
|
Add API token
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ const WorkspaceMembersSettingsPage = observer(() => {
|
||||||
"opacity-60": !canPerformWorkspaceMemberActions,
|
"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>
|
<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" />
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { observer } from "mobx-react";
|
||||||
import { useParams, usePathname } from "next/navigation";
|
import { useParams, usePathname } from "next/navigation";
|
||||||
// constants
|
// constants
|
||||||
import { EUserWorkspaceRoles } from "@/constants/workspace";
|
import { EUserWorkspaceRoles } from "@/constants/workspace";
|
||||||
|
|
@ -9,7 +10,7 @@ import { WORKSPACE_SETTINGS_LINKS } from "@/plane-web/constants/workspace";
|
||||||
// plane web helpers
|
// plane web helpers
|
||||||
import { shouldRenderSettingLink } from "@/plane-web/helpers/workspace.helper";
|
import { shouldRenderSettingLink } from "@/plane-web/helpers/workspace.helper";
|
||||||
|
|
||||||
export const MobileWorkspaceSettingsTabs = () => {
|
export const MobileWorkspaceSettingsTabs = observer(() => {
|
||||||
const router = useAppRouter();
|
const router = useAppRouter();
|
||||||
const { workspaceSlug } = useParams();
|
const { workspaceSlug } = useParams();
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
|
|
@ -28,7 +29,8 @@ export const MobileWorkspaceSettingsTabs = () => {
|
||||||
shouldRenderSettingLink(item.key) &&
|
shouldRenderSettingLink(item.key) &&
|
||||||
workspaceMemberInfo >= item.access && (
|
workspaceMemberInfo >= item.access && (
|
||||||
<div
|
<div
|
||||||
className={`${item.highlight(pathname, `/${workspaceSlug}`)
|
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-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"
|
: "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"
|
||||||
}`}
|
}`}
|
||||||
|
|
@ -41,4 +43,4 @@ export const MobileWorkspaceSettingsTabs = () => {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
|
||||||
|
|
@ -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">
|
<div className="flex w-[280px] 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">
|
||||||
|
|
|
||||||
|
|
@ -90,8 +90,8 @@ const WebhookDetailsPage = observer(() => {
|
||||||
<>
|
<>
|
||||||
<PageHead title={pageTitle} />
|
<PageHead title={pageTitle} />
|
||||||
<DeleteWebhookModal isOpen={deleteWebhookModal} onClose={() => setDeleteWebhookModal(false)} />
|
<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="w-full space-y-8 overflow-y-auto">
|
||||||
<div className="-m-5">
|
<div className="">
|
||||||
<WebhookForm onSubmit={async (data) => await handleUpdateWebhook(data)} data={currentWebhook} />
|
<WebhookForm onSubmit={async (data) => await handleUpdateWebhook(data)} data={currentWebhook} />
|
||||||
</div>
|
</div>
|
||||||
{currentWebhook && <WebhookDeleteSection openDeleteModal={() => setDeleteWebhookModal(true)} />}
|
{currentWebhook && <WebhookDeleteSection openDeleteModal={() => setDeleteWebhookModal(true)} />}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ const WebhooksListPage = observer(() => {
|
||||||
/>
|
/>
|
||||||
{Object.keys(webhooks).length > 0 ? (
|
{Object.keys(webhooks).length > 0 ? (
|
||||||
<div className="flex h-full w-full flex-col">
|
<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>
|
<div className="text-xl font-medium">Webhooks</div>
|
||||||
<Button variant="primary" size="sm" onClick={() => setShowCreateWebhookModal(true)}>
|
<Button variant="primary" size="sm" onClick={() => setShowCreateWebhookModal(true)}>
|
||||||
Add webhook
|
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">
|
<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) => (
|
{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 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>
|
<h3 className="font-medium">{item.title}</h3>
|
||||||
<item.icon className="h-4 w-4 text-blue-500" />
|
<item.icon className="h-4 w-4 text-blue-500" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ export const BillingRoot = () => (
|
||||||
<h3 className="text-xl font-medium">Billing and Plans</h3>
|
<h3 className="text-xl font-medium">Billing and Plans</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="px-4 py-6">
|
<div className="py-6">
|
||||||
<div>
|
<div>
|
||||||
<h4 className="text-md mb-1 leading-6">Current plan</h4>
|
<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>
|
<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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<DeleteApiTokenModal isOpen={deleteModalOpen} onClose={() => setDeleteModalOpen(false)} tokenId={token.id} />
|
<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}>
|
<Tooltip tooltipContent="Delete token" isMobile={isMobile}>
|
||||||
<button
|
<button
|
||||||
onClick={() => setDeleteModalOpen(true)}
|
onClick={() => setDeleteModalOpen(true)}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ export const AutoArchiveAutomation: React.FC<Props> = observer((props) => {
|
||||||
handleClose={() => setmonthModal(false)}
|
handleClose={() => setmonthModal(false)}
|
||||||
handleChange={handleChange}
|
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-center justify-between">
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
<div className="flex items-center justify-center rounded bg-custom-background-90 p-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 ? (
|
||||||
currentProjectDetails.archive_in !== 0 && (
|
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="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 text-sm font-medium">Auto-archive issues that are closed for</div>
|
||||||
<div className="w-1/2">
|
<div className="w-1/2">
|
||||||
|
|
@ -104,7 +104,7 @@ export const AutoArchiveAutomation: React.FC<Props> = observer((props) => {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
<Loader className="ml-12">
|
<Loader className="mx-6">
|
||||||
<Loader.Item height="50px" />
|
<Loader.Item height="50px" />
|
||||||
</Loader>
|
</Loader>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
|
||||||
handleClose={() => setmonthModal(false)}
|
handleClose={() => setmonthModal(false)}
|
||||||
handleChange={handleChange}
|
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-center justify-between">
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
<div className="flex items-center justify-center rounded bg-custom-background-90 p-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 ? (
|
||||||
currentProjectDetails.close_in !== 0 && (
|
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 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="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>
|
<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
|
||||||
? 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>
|
</div>
|
||||||
}
|
}
|
||||||
onChange={(val: string) => {
|
onChange={(val: string) => {
|
||||||
|
|
@ -171,7 +171,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
<Loader className="ml-12">
|
<Loader className="mx-6">
|
||||||
<Loader.Item height="50px" />
|
<Loader.Item height="50px" />
|
||||||
</Loader>
|
</Loader>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ export const WidgetIssuesList: React.FC<WidgetIssuesListProps> = (props) => {
|
||||||
</div>
|
</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 === "assigned" && <AssignedIssuesEmptyState type={tab} />}
|
||||||
{type === "created" && <CreatedIssuesEmptyState type={tab} />}
|
{type === "created" && <CreatedIssuesEmptyState type={tab} />}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,10 @@ export const EstimateRoot: FC<TEstimateRoot> = observer((props) => {
|
||||||
{loader === "init-loader" || isSWRLoading ? (
|
{loader === "init-loader" || isSWRLoading ? (
|
||||||
<EstimateLoaderScreen />
|
<EstimateLoaderScreen />
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-12">
|
<div className="space-y-2">
|
||||||
{/* header */}
|
{/* header */}
|
||||||
<div className="text-xl font-medium text-custom-text-100 border-b border-custom-border-200 py-3.5">
|
<div className="flex flex-col items-start border-b border-custom-border-100 pb-3.5">
|
||||||
Estimates
|
<h3 className="text-xl font-medium leading-normal">Estimates</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* current active estimate section */}
|
{/* current active estimate section */}
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ const IntegrationGuide = observer(() => {
|
||||||
{EXPORTERS_LIST.map((service) => (
|
{EXPORTERS_LIST.map((service) => (
|
||||||
<div
|
<div
|
||||||
key={service.provider}
|
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="flex w-full items-start justify-between gap-4">
|
||||||
<div className="item-center flex gap-2.5">
|
<div className="item-center flex gap-2.5">
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ const smallButton = <ListFilter className="h-3 " />;
|
||||||
const largeButton = (
|
const largeButton = (
|
||||||
<div className={cn(getButtonStyling("neutral-primary", "sm"), "text-custom-text-300")}>
|
<div className={cn(getButtonStyling("neutral-primary", "sm"), "text-custom-text-300")}>
|
||||||
<ListFilter className="h-3 " />
|
<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} />
|
<ChevronDown className="h-3 w-3" strokeWidth={2} />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -21,8 +21,8 @@ export const FiltersRoot: FC = () => (
|
||||||
<FiltersDropdown
|
<FiltersDropdown
|
||||||
menuButton={
|
menuButton={
|
||||||
<>
|
<>
|
||||||
<div className="hidden 2xl:flex">{largeButton}</div>
|
<div className="hidden xl:flex">{largeButton}</div>
|
||||||
<div className="flex 2xl:hidden">{smallButton}</div>
|
<div className="flex xl:hidden">{smallButton}</div>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
title=""
|
title=""
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ export const InboxIssueOrderByDropdown: FC = observer(() => {
|
||||||
<CustomMenu
|
<CustomMenu
|
||||||
customButton={
|
customButton={
|
||||||
<>
|
<>
|
||||||
<div className="hidden 2xl:flex">{largeButton}</div>
|
<div className="hidden xl:flex">{largeButton}</div>
|
||||||
<div className="flex 2xl:hidden">{smallButton}</div>
|
<div className="flex xl:hidden">{smallButton}</div>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
placement="bottom-end"
|
placement="bottom-end"
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ export const InboxSidebar: FC<IInboxSidebarProps> = observer((props) => {
|
||||||
<div
|
<div
|
||||||
key={option?.key}
|
key={option?.key}
|
||||||
className={cn(
|
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`
|
currentTab === option?.key ? `text-custom-primary-100` : `hover:text-custom-text-200`
|
||||||
)}
|
)}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||||
const isGroupByCreatedBy = group_by === "created_by";
|
const isGroupByCreatedBy = group_by === "created_by";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContentWrapper className={`flex-row relative gap-4`}>
|
<ContentWrapper className={`flex-row relative gap-4 py-4`}>
|
||||||
{list &&
|
{list &&
|
||||||
list.length > 0 &&
|
list.length > 0 &&
|
||||||
list.map((subList: IGroupByColumn) => {
|
list.map((subList: IGroupByColumn) => {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ export const HeaderSubGroupByCard: FC<IHeaderSubGroupByCard> = observer((props)
|
||||||
const { icon, title, count, column_id, kanbanFilters, handleKanbanFilters } = props;
|
const { icon, title, count, column_id, kanbanFilters, handleKanbanFilters } = props;
|
||||||
return (
|
return (
|
||||||
<div
|
<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)}
|
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">
|
<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,
|
TIssueGroupByOptions,
|
||||||
TIssueOrderByOptions,
|
TIssueOrderByOptions,
|
||||||
} from "@plane/types";
|
} from "@plane/types";
|
||||||
|
// UI
|
||||||
|
import { Row } from "@plane/ui";
|
||||||
// hooks
|
// hooks
|
||||||
import { useCycle, useLabel, useMember, useModule, useProject, useProjectState } from "@/hooks/store";
|
import { useCycle, useLabel, useMember, useModule, useProject, useProjectState } from "@/hooks/store";
|
||||||
import { useIssueStoreType } from "@/hooks/use-issue-layout-store";
|
import { useIssueStoreType } from "@/hooks/use-issue-layout-store";
|
||||||
|
|
@ -160,7 +162,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
|
||||||
return (
|
return (
|
||||||
<div key={_list.id} className="flex flex-shrink-0 flex-col">
|
<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 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
|
<HeaderSubGroupByCard
|
||||||
column_id={_list.id}
|
column_id={_list.id}
|
||||||
icon={_list.icon}
|
icon={_list.icon}
|
||||||
|
|
@ -169,7 +171,7 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
|
||||||
kanbanFilters={kanbanFilters}
|
kanbanFilters={kanbanFilters}
|
||||||
handleKanbanFilters={handleKanbanFilters}
|
handleKanbanFilters={handleKanbanFilters}
|
||||||
/>
|
/>
|
||||||
</div>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{subGroupByVisibilityToggle.showIssues && (
|
{subGroupByVisibilityToggle.showIssues && (
|
||||||
|
|
@ -295,7 +297,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<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
|
<SubGroupSwimlaneHeader
|
||||||
getGroupIssueCount={getGroupIssueCount}
|
getGroupIssueCount={getGroupIssueCount}
|
||||||
group_by={group_by}
|
group_by={group_by}
|
||||||
|
|
@ -305,7 +307,7 @@ export const KanBanSwimLanes: React.FC<IKanBanSwimLanes> = observer((props) => {
|
||||||
list={groupByList}
|
list={groupByList}
|
||||||
showEmptyGroup={showEmptyGroup}
|
showEmptyGroup={showEmptyGroup}
|
||||||
/>
|
/>
|
||||||
</div>
|
</Row>
|
||||||
|
|
||||||
{sub_group_by && (
|
{sub_group_by && (
|
||||||
<SubGroupSwimlane
|
<SubGroupSwimlane
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ export const KanbanQuickAddIssueButton: FC<TQuickAddIssueButton> = observer((pro
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<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}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
<PlusIcon className="h-3.5 w-3.5 stroke-2" />
|
<PlusIcon className="h-3.5 w-3.5 stroke-2" />
|
||||||
|
|
|
||||||
|
|
@ -63,13 +63,13 @@ export const ProjectSettingsLabelList: React.FC = observer(() => {
|
||||||
data={selectDeleteLabel ?? null}
|
data={selectDeleteLabel ?? null}
|
||||||
onClose={() => setSelectDeleteLabel(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>
|
<h3 className="text-xl font-medium">Labels</h3>
|
||||||
<Button variant="primary" onClick={newLabel} size="sm">
|
<Button variant="primary" onClick={newLabel} size="sm">
|
||||||
Add label
|
Add label
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full py-8">
|
<div className="w-full py-2">
|
||||||
{showLabelForm && (
|
{showLabelForm && (
|
||||||
<div className="my-2 w-full rounded border border-custom-border-200 px-3.5 py-2">
|
<div className="my-2 w-full rounded border border-custom-border-200 px-3.5 py-2">
|
||||||
<CreateUpdateLabelInline
|
<CreateUpdateLabelInline
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ export const ProfileStateDistribution: React.FC<Props> = ({ stateDistribution, u
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col space-y-2">
|
<div className="flex flex-col space-y-2">
|
||||||
<h3 className="text-lg font-medium">Issues by state</h3>
|
<h3 className="text-lg font-medium">Issues by state</h3>
|
||||||
<Card>
|
<Card className="h-full">
|
||||||
{userProfile.state_distribution.length > 0 ? (
|
{userProfile.state_distribution.length > 0 ? (
|
||||||
<div className="grid grid-cols-1 gap-x-6 md:grid-cols-2">
|
<div className="grid grid-cols-1 gap-x-6 md:grid-cols-2">
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ export const ProjectDetailsForm: FC<IProjectDetailsForm> = (props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<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" />
|
<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" />
|
<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">
|
<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");
|
setTrackElement("Projects page");
|
||||||
toggleCreateProjectModal(true);
|
toggleCreateProjectModal(true);
|
||||||
}}
|
}}
|
||||||
className="items-center gap-1 my-auto"
|
className="items-center gap-1"
|
||||||
>
|
>
|
||||||
<span className="hidden sm:inline-block">Add</span> Project
|
<span className="hidden sm:inline-block">Add</span> Project
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -67,9 +67,9 @@ export const ProjectSettingsMemberDefaults: React.FC = observer(() => {
|
||||||
default_assignee:
|
default_assignee:
|
||||||
formData.default_assignee === "none"
|
formData.default_assignee === "none"
|
||||||
? null
|
? null
|
||||||
: formData.default_assignee ?? currentProjectDetails?.default_assignee,
|
: (formData.default_assignee ?? currentProjectDetails?.default_assignee),
|
||||||
project_lead:
|
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(() => {
|
.then(() => {
|
||||||
setToast({
|
setToast({
|
||||||
|
|
@ -85,12 +85,12 @@ export const ProjectSettingsMemberDefaults: React.FC = observer(() => {
|
||||||
|
|
||||||
return (
|
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>
|
<h3 className="text-xl font-medium">Defaults</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex w-full flex-col gap-2 pb-4">
|
<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">
|
<div className="flex w-1/2 flex-col gap-2">
|
||||||
<h4 className="text-sm">Project Lead</h4>
|
<h4 className="text-sm">Project Lead</h4>
|
||||||
<div className="">
|
<div className="">
|
||||||
|
|
|
||||||
|
|
@ -56,12 +56,12 @@ export const ProjectFeaturesList: FC<Props> = observer((props) => {
|
||||||
if (!currentUser) return <></>;
|
if (!currentUser) return <></>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-4 space-y-6">
|
<div className="space-y-6">
|
||||||
{Object.keys(PROJECT_FEATURES_LIST).map((featureSectionKey) => {
|
{Object.keys(PROJECT_FEATURES_LIST).map((featureSectionKey) => {
|
||||||
const feature = PROJECT_FEATURES_LIST[featureSectionKey];
|
const feature = PROJECT_FEATURES_LIST[featureSectionKey];
|
||||||
return (
|
return (
|
||||||
<div key={featureSectionKey} className="">
|
<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>
|
<h3 className="text-xl font-medium">{feature.title}</h3>
|
||||||
<h4 className="text-sm leading-5 text-custom-text-200">{feature.description}</h4>
|
<h4 className="text-sm leading-5 text-custom-text-200">{feature.description}</h4>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { forwardRef } from "react";
|
||||||
import { ContentWrapper } from "@plane/ui";
|
import { ContentWrapper } from "@plane/ui";
|
||||||
|
|
||||||
export const KanbanIssueBlockLoader = forwardRef<HTMLSpanElement>((props, ref) => (
|
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";
|
KanbanIssueBlockLoader.displayName = "KanbanIssueBlockLoader";
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export const ViewOrderByDropdown: React.FC<Props> = (props) => {
|
||||||
];
|
];
|
||||||
|
|
||||||
const buttonClassName = isMobile
|
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`;
|
: `${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";
|
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}>
|
<span className={buttonClassName}>
|
||||||
{!isMobile && <ArrowDownWideNarrow className="h-3 w-3" />}
|
{!isMobile && <ArrowDownWideNarrow className="h-3 w-3" />}
|
||||||
<span className="flex-shrink-0"> {orderByDetails?.label}</span>
|
<span className="flex-shrink-0"> {orderByDetails?.label}</span>
|
||||||
<ChevronDown className={chevronClassName} strokeWidth={1} />
|
<ChevronDown className={chevronClassName} strokeWidth={2} />
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
placement="bottom-end"
|
placement="bottom-end"
|
||||||
className="w-full"
|
className="w-full flex justify-center"
|
||||||
maxHeight="lg"
|
maxHeight="lg"
|
||||||
closeOnSelect
|
closeOnSelect
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ export const WebhookForm: FC<Props> = observer((props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(handleFormSubmit)}>
|
<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="text-xl font-medium text-custom-text-200">{data ? "Webhook details" : "Create webhook"}</div>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
|
|
@ -85,7 +85,7 @@ export const WebhookForm: FC<Props> = observer((props) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{data ? (
|
{data ? (
|
||||||
<div className="p-5 pt-0 space-y-5">
|
<div className="pt-0 space-y-5">
|
||||||
<WebhookSecretKey data={data} />
|
<WebhookSecretKey data={data} />
|
||||||
<Button type="submit" loading={isSubmitting}>
|
<Button type="submit" loading={isSubmitting}>
|
||||||
{isSubmitting ? "Updating" : "Update"}
|
{isSubmitting ? "Updating" : "Update"}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ export const WebhooksListItem: FC<IWebhookListItem> = (props) => {
|
||||||
return (
|
return (
|
||||||
<div className="border-b border-custom-border-200">
|
<div className="border-b border-custom-border-200">
|
||||||
<Link href={`/${workspaceSlug}/settings/webhooks/${webhook?.id}`}>
|
<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>
|
<h5 className="truncate text-base font-medium">{webhook.url}</h5>
|
||||||
<ToggleSwitch value={webhook.is_active} onChange={handleToggle} />
|
<ToggleSwitch value={webhook.is_active} onChange={handleToggle} />
|
||||||
</span>
|
</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={`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">
|
<div className="flex flex-col gap-1">
|
||||||
<button type="button" onClick={() => setIsImageUploadModalOpen(true)} disabled={!isAdmin}>
|
<button type="button" onClick={() => setIsImageUploadModalOpen(true)} disabled={!isAdmin}>
|
||||||
{watch("logo") && watch("logo") !== null && watch("logo") !== "" ? (
|
{watch("logo") && watch("logo") !== null && watch("logo") !== "" ? (
|
||||||
|
|
@ -190,7 +190,7 @@ export const WorkspaceDetails: FC = observer(() => {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-1">
|
<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">{`${
|
<button type="button" onClick={handleCopyUrl} className="text-sm tracking-tight text-left">{`${
|
||||||
typeof window !== "undefined" && window.location.origin.replace("http://", "").replace("https://", "")
|
typeof window !== "undefined" && window.location.origin.replace("http://", "").replace("https://", "")
|
||||||
}/${currentWorkspace.slug}`}</button>
|
}/${currentWorkspace.slug}`}</button>
|
||||||
|
|
@ -212,7 +212,7 @@ export const WorkspaceDetails: FC = observer(() => {
|
||||||
</div>
|
</div>
|
||||||
</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="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">
|
<div className="flex flex-col gap-1">
|
||||||
<h4 className="text-sm">Workspace name</h4>
|
<h4 className="text-sm">Workspace name</h4>
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ export const GlobalViewsHeader: React.FC = observer(() => {
|
||||||
const isAuthorizedUser = !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER;
|
const isAuthorizedUser = !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Header variant={EHeaderVariant.SECONDARY}>
|
<Header variant={EHeaderVariant.SECONDARY} className="min-h-[44px]">
|
||||||
<CreateUpdateWorkspaceViewModal isOpen={createViewModal} onClose={() => setCreateViewModal(false)} />
|
<CreateUpdateWorkspaceViewModal isOpen={createViewModal} onClose={() => setCreateViewModal(false)} />
|
||||||
<div
|
<div
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue