Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
edbb983
feat: add navigation dropdown component
prateekshourya29 Dec 11, 2024
1ccbf6a
chore: enhance title/ description loader and componenet modularity
prateekshourya29 Dec 11, 2024
6a27815
chore: issue store filter update
prateekshourya29 Dec 11, 2024
738f0ec
chore: added few icons to ui package
prateekshourya29 Dec 11, 2024
16b9776
chore: improvements for tabs componenet
prateekshourya29 Dec 11, 2024
6ee99a2
chore: enhance sidebar modularity
prateekshourya29 Dec 11, 2024
34ea342
chore: update issue and router store to add support for additional is…
prateekshourya29 Dec 11, 2024
e430730
chore: enhanced cycle componenets modularity
prateekshourya29 Dec 11, 2024
abbb15f
feat: added project grouping header for cycles list
prateekshourya29 Dec 11, 2024
43c2069
chore: enhanced project dropdown componenet by adding multiple select…
prateekshourya29 Dec 11, 2024
fe27e91
chore: enhanced rich text editor modularity by taking members ids as …
prateekshourya29 Dec 11, 2024
4340ec8
chore: added functionality to filter disabled layouts in issue-layout…
prateekshourya29 Dec 11, 2024
0151d32
chore: added support to pass project ids as props in project card list
prateekshourya29 Dec 11, 2024
a57f81a
feat: multi select project modal
prateekshourya29 Dec 11, 2024
50988f5
chore: seperate out project componenet for reusability
prateekshourya29 Dec 11, 2024
30fa748
chore: command pallete store improvements
prateekshourya29 Dec 11, 2024
3e31994
fix: build errors
prateekshourya29 Dec 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/constants/src/issue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export enum EIssueGroupByToServerOptions {
"target_date" = "target_date",
"project" = "project_id",
"created_by" = "created_by",
"team_project" = "project_id",
}

export enum EIssueGroupBYServerToProperty {
Expand Down
2 changes: 2 additions & 0 deletions packages/types/src/common.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ export type TLogoProps = {
background_color?: string;
};
};

export type TNameDescriptionLoader = "submitting" | "submitted" | "saved";
1 change: 1 addition & 0 deletions packages/types/src/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,5 @@ export enum EFileAssetType {
USER_AVATAR = "USER_AVATAR",
USER_COVER = "USER_COVER",
WORKSPACE_LOGO = "WORKSPACE_LOGO",
TEAM_SPACE_DESCRIPTION = "TEAM_SPACE_DESCRIPTION",
}
3 changes: 2 additions & 1 deletion packages/types/src/issues.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,8 @@ export type GroupByColumnTypes =
| "priority"
| "labels"
| "assignees"
| "created_by";
| "created_by"
| "team_project";

export interface IGroupByColumn {
id: string;
Expand Down
3 changes: 3 additions & 0 deletions packages/types/src/view-props.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type TIssueGroupByOptions =
| "cycle"
| "module"
| "target_date"
| "team_project"
| null;

export type TIssueOrderByOptions =
Expand Down Expand Up @@ -69,6 +70,7 @@ export type TIssueParams =
| "start_date"
| "target_date"
| "project"
| "team_project"
| "group_by"
| "sub_group_by"
| "order_by"
Expand All @@ -92,6 +94,7 @@ export interface IIssueFilterOptions {
cycle?: string[] | null;
module?: string[] | null;
project?: string[] | null;
team_project?: string[] | null;
start_date?: string[] | null;
state?: string[] | null;
state_group?: string[] | null;
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/breadcrumbs/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./breadcrumbs";
export * from "./navigation-dropdown";
96 changes: 96 additions & 0 deletions packages/ui/src/breadcrumbs/navigation-dropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
"use client";

import * as React from "react";
import { CheckIcon, ChevronDownIcon } from "lucide-react";
// ui
import { CustomMenu, TContextMenuItem } from "../dropdowns";
// helpers
import { cn } from "../../helpers";

type TBreadcrumbNavigationDropdownProps = {
selectedItemKey: string;
navigationItems: TContextMenuItem[];
navigationDisabled?: boolean;
};

export const BreadcrumbNavigationDropdown = (props: TBreadcrumbNavigationDropdownProps) => {
const { selectedItemKey, navigationItems, navigationDisabled = false } = props;
// derived values
const selectedItem = navigationItems.find((item) => item.key === selectedItemKey);
const selectedItemIcon = selectedItem?.icon ? (
<selectedItem.icon className={cn("size-3.5", selectedItem.iconClassName)} />
) : undefined;

// if no selected item, return null
if (!selectedItem) return null;

const NavigationButton = ({ className }: { className?: string }) => (
<li
className={cn(
"flex items-center justify-center cursor-default text-sm font-medium text-custom-text-200 group-hover:text-custom-text-100 outline-none",
className
)}
tabIndex={-1}
>
{selectedItemIcon && (
<div className="flex h-5 w-5 items-center justify-start overflow-hidden">{selectedItemIcon}</div>
)}
<div className="relative line-clamp-1 block max-w-[150px] overflow-hidden truncate">{selectedItem.title}</div>
</li>
);

if (navigationDisabled) {
return <NavigationButton />;
}

return (
<CustomMenu
customButton={
<div className="group flex items-center gap-1.5">
<NavigationButton className="cursor-pointer" />
<ChevronDownIcon className="size-4 text-custom-text-200 group-hover:text-custom-text-100" />
</div>
}
placement="bottom-start"
closeOnSelect
>
{navigationItems.map((item) => {
if (item.shouldRender === false) return null;
return (
<CustomMenu.MenuItem
key={item.key}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
if (item.key === selectedItemKey) return;
item.action();
}}
className={cn(
"flex items-center gap-2",
{
"text-custom-text-400": item.disabled,
},
item.className
)}
disabled={item.disabled}
>
{item.icon && <item.icon className={cn("size-3.5", item.iconClassName)} />}
<div className="w-full">
<h5>{item.title}</h5>
{item.description && (
<p
className={cn("text-custom-text-300 whitespace-pre-line", {
"text-custom-text-400": item.disabled,
})}
>
{item.description}
</p>
)}
</div>
{item.key === selectedItemKey && <CheckIcon className="flex-shrink-0 size-3.5" />}
</CustomMenu.MenuItem>
);
})}
</CustomMenu>
);
};
3 changes: 3 additions & 0 deletions packages/ui/src/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export * from "./epic-icon";
export * from "./full-screen-panel-icon";
export * from "./github-icon";
export * from "./gitlab-icon";
export * from "./info-fill-icon";
export * from "./info-icon";
export * from "./layer-stack";
export * from "./layers-icon";
Expand All @@ -38,3 +39,5 @@ export * from "./done-icon";
export * from "./pending-icon";
export * from "./pi-chat";
export * from "./workspace-icon";
export * from "./teams";
export * from "./lead-icon";
26 changes: 26 additions & 0 deletions packages/ui/src/icons/lead-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from "react";

import { ISvgIcons } from "./type";

export const LeadIcon: React.FC<ISvgIcons> = ({ className = "text-current", ...rest }) => (
<svg className={className} viewBox="0 0 19 18" fill="none" xmlns="http://www.w3.org/2000/svg" {...rest}>
<path
d="M0.571533 9C0.571533 4.02944 4.60097 0 9.57153 0C14.5421 0 18.5715 4.02944 18.5715 9C18.5715 13.9706 14.5421 18 9.57153 18C4.60097 18 0.571533 13.9706 0.571533 9Z"
fill="#3372FF"
/>
<g clip-path="url(#clip0_8992_2377)">
<circle cx="9.57153" cy="6.5" r="2.5" fill="#F5F5FF" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M8.94653 9.625C6.53029 9.625 4.57153 11.5838 4.57153 14H9.57153H14.5715C14.5715 11.5838 12.6128 9.625 10.1965 9.625H9.82153L10.8215 13.0278L9.57153 14L8.32153 13.0278L9.32153 9.625H8.94653Z"
fill="#F5F5FF"
/>
</g>
<defs>
<clipPath id="clip0_8992_2377">
<rect width="10" height="10" fill="white" transform="translate(4.57153 4)" />
</clipPath>
</defs>
</svg>
);
19 changes: 19 additions & 0 deletions packages/ui/src/icons/teams.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as React from "react";

import { ISvgIcons } from "./type";

export const TeamsIcon: React.FC<ISvgIcons> = ({ className = "text-current", ...rest }) => (
<svg className={className} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M8.25 6.75C8.25 5.75544 8.64509 4.80161 9.34835 4.09835C10.0516 3.39509 11.0054 3 12 3C12.9946 3 13.9484 3.39509 14.6517 4.09835C15.3549 4.80161 15.75 5.75544 15.75 6.75C15.75 7.74456 15.3549 8.69839 14.6517 9.40165C13.9484 10.1049 12.9946 10.5 12 10.5C11.0054 10.5 10.0516 10.1049 9.34835 9.40165C8.64509 8.69839 8.25 7.74456 8.25 6.75ZM15.75 9.75C15.75 8.95435 16.0661 8.19129 16.6287 7.62868C17.1913 7.06607 17.9544 6.75 18.75 6.75C19.5456 6.75 20.3087 7.06607 20.8713 7.62868C21.4339 8.19129 21.75 8.95435 21.75 9.75C21.75 10.5456 21.4339 11.3087 20.8713 11.8713C20.3087 12.4339 19.5456 12.75 18.75 12.75C17.9544 12.75 17.1913 12.4339 16.6287 11.8713C16.0661 11.3087 15.75 10.5456 15.75 9.75ZM2.25 9.75C2.25 8.95435 2.56607 8.19129 3.12868 7.62868C3.69129 7.06607 4.45435 6.75 5.25 6.75C6.04565 6.75 6.80871 7.06607 7.37132 7.62868C7.93393 8.19129 8.25 8.95435 8.25 9.75C8.25 10.5456 7.93393 11.3087 7.37132 11.8713C6.80871 12.4339 6.04565 12.75 5.25 12.75C4.45435 12.75 3.69129 12.4339 3.12868 11.8713C2.56607 11.3087 2.25 10.5456 2.25 9.75ZM6.31 15.117C6.91995 14.161 7.76108 13.3743 8.75562 12.8294C9.75016 12.2846 10.866 11.9994 12 12C12.9498 11.9991 13.8891 12.1989 14.7564 12.5862C15.6237 12.9734 16.3994 13.5395 17.0327 14.2474C17.6661 14.9552 18.1428 15.7888 18.4317 16.6936C18.7205 17.5985 18.815 18.5541 18.709 19.498C18.696 19.6153 18.6556 19.7278 18.591 19.8265C18.5263 19.9252 18.4393 20.0073 18.337 20.066C16.4086 21.1725 14.2233 21.7532 12 21.75C9.695 21.75 7.53 21.138 5.663 20.066C5.56069 20.0073 5.47368 19.9252 5.40904 19.8265C5.34441 19.7278 5.30396 19.6153 5.291 19.498C5.12305 17.9646 5.48246 16.4198 6.31 15.118V15.117Z"
fill="currentColor"
{...rest}
/>
<path
d="M5.08208 14.2539C4.09584 15.7763 3.63633 17.5802 3.77408 19.3889C3.17359 19.2979 2.58299 19.1505 2.01008 18.9489L1.89508 18.9089C1.79248 18.8725 1.70263 18.8071 1.63643 18.7207C1.57023 18.6342 1.53051 18.5305 1.52208 18.4219L1.51208 18.3009C1.47169 17.7989 1.53284 17.2938 1.69188 16.816C1.85093 16.3381 2.10462 15.8971 2.4378 15.5194C2.77099 15.1417 3.17685 14.835 3.63116 14.6176C4.08547 14.4001 4.57893 14.2765 5.08208 14.2539ZM20.2261 19.3889C20.3638 17.5802 19.9043 15.7763 18.9181 14.2539C19.4212 14.2765 19.9147 14.4001 20.369 14.6176C20.8233 14.835 21.2292 15.1417 21.5624 15.5194C21.8955 15.8971 22.1492 16.3381 22.3083 16.816C22.4673 17.2938 22.5285 17.7989 22.4881 18.3009L22.4781 18.4219C22.4695 18.5303 22.4297 18.6338 22.3635 18.7201C22.2973 18.8063 22.2075 18.8716 22.1051 18.9079L21.9901 18.9479C21.4231 19.1479 20.8341 19.2969 20.2261 19.3889Z"
fill="currentColor"
/>
</svg>
);
32 changes: 27 additions & 5 deletions packages/ui/src/tabs/tabs.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC, Fragment } from "react";
import React, { FC, Fragment, useEffect, useState } from "react";
import { Tab } from "@headlessui/react";
import { LucideProps } from "lucide-react";
// helpers
Expand All @@ -11,18 +11,21 @@ type TabItem = {
label?: React.ReactNode;
content: React.ReactNode;
disabled?: boolean;
onClick?: () => void;
};

type TTabsProps = {
tabs: TabItem[];
storageKey: string;
storageKey?: string;
actions?: React.ReactNode;
defaultTab?: string;
containerClassName?: string;
tabListContainerClassName?: string;
tabListClassName?: string;
tabClassName?: string;
tabPanelClassName?: string;
size?: "sm" | "md" | "lg";
storeInLocalStorage?: boolean;
};

export const Tabs: FC<TTabsProps> = (props: TTabsProps) => {
Expand All @@ -36,15 +39,28 @@ export const Tabs: FC<TTabsProps> = (props: TTabsProps) => {
tabListClassName = "",
tabClassName = "",
tabPanelClassName = "",
size = "md",
storeInLocalStorage = true,
} = props;
// local storage
const { storedValue, setValue } = useLocalStorage(`tab-${storageKey}`, defaultTab);
const { storedValue, setValue } = useLocalStorage(
storeInLocalStorage && storageKey ? `tab-${storageKey}` : `tab-${tabs[0]?.key}`,
defaultTab
);
// state
const [selectedTab, setSelectedTab] = useState(storedValue ?? defaultTab);

useEffect(() => {
if (storeInLocalStorage) {
setValue(selectedTab);
}
}, [selectedTab, setValue, storeInLocalStorage, storageKey]);

const currentTabIndex = (tabKey: string): number => tabs.findIndex((tab) => tab.key === tabKey);

return (
<div className="flex flex-col w-full h-full">
<Tab.Group defaultIndex={currentTabIndex(storedValue ?? defaultTab)}>
<Tab.Group defaultIndex={currentTabIndex(selectedTab)}>
<div className={cn("flex flex-col w-full h-full gap-2", containerClassName)}>
<div className={cn("flex w-full items-center gap-4", tabListContainerClassName)}>
<Tab.List
Expand All @@ -64,12 +80,18 @@ export const Tabs: FC<TTabsProps> = (props: TTabsProps) => {
: tab.disabled
? "text-custom-text-400 cursor-not-allowed"
: "text-custom-text-400 hover:text-custom-text-300 hover:bg-custom-background-80/60",
{
"text-xs": size === "sm",
"text-sm": size === "md",
"text-base": size === "lg",
},
tabClassName
)
}
key={tab.key}
onClick={() => {
if (!tab.disabled) setValue(tab.key);
if (!tab.disabled) setSelectedTab(tab.key);
tab.onClick?.();
}}
disabled={tab.disabled}
>
Expand Down
2 changes: 1 addition & 1 deletion space/core/store/helpers/base-issues.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { CoreRootStore } from "../root.store";
// constants
// helpers

export type TIssueDisplayFilterOptions = Exclude<TIssueGroupByOptions, null> | "target_date";
export type TIssueDisplayFilterOptions = Exclude<TIssueGroupByOptions, null | "team_project"> | "target_date";

export enum EIssueGroupedAction {
ADD = "ADD",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,12 @@ const CycleDetailPage = observer(() => {
"0px 1px 4px 0px rgba(0, 0, 0, 0.06), 0px 2px 4px 0px rgba(16, 24, 40, 0.06), 0px 1px 8px -1px rgba(16, 24, 40, 0.06)",
}}
>
<CycleDetailsSidebar handleClose={toggleSidebar} />
<CycleDetailsSidebar
handleClose={toggleSidebar}
cycleId={cycleId.toString()}
projectId={projectId.toString()}
workspaceSlug={workspaceSlug.toString()}
/>
</div>
)}
</div>
Expand Down
17 changes: 13 additions & 4 deletions web/app/[workspaceSlug]/(projects)/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { useFavorite } from "@/hooks/store/use-favorite";
import useSize from "@/hooks/use-window-size";
// plane web components
import { SidebarAppSwitcher } from "@/plane-web/components/sidebar";
import { SidebarTeamsList } from "@/plane-web/components/workspace/sidebar/teams-sidebar-list";
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";

export const AppSidebar: FC = observer(() => {
Expand All @@ -47,7 +48,7 @@ export const AppSidebar: FC = observer(() => {
});

useEffect(() => {
if (windowSize[0] < 768) !sidebarCollapsed && toggleSidebar();
if (windowSize[0] < 768 && !sidebarCollapsed) toggleSidebar();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [windowSize]);

Expand All @@ -73,9 +74,12 @@ export const AppSidebar: FC = observer(() => {
"px-4": !sidebarCollapsed,
})}
>
{/* Workspace switcher and settings */}
<SidebarDropdown />
<div className="flex-shrink-0 h-4" />
<SidebarAppSwitcher />
{/* App switcher */}
{canPerformWorkspaceMemberActions && <SidebarAppSwitcher />}
{/* Quick actions */}
<SidebarQuickActions />
</div>
<hr
Expand All @@ -88,18 +92,23 @@ export const AppSidebar: FC = observer(() => {
"vertical-scrollbar px-4": !sidebarCollapsed,
})}
>
{/* User Menu */}
<SidebarUserMenu />

{/* Workspace Menu */}
<SidebarWorkspaceMenu />
<hr
className={cn("flex-shrink-0 border-custom-sidebar-border-300 h-[0.5px] w-3/5 mx-auto my-1", {
"opacity-0": !sidebarCollapsed,
})}
/>
{/* Favorites Menu */}
{canPerformWorkspaceMemberActions && !isFavoriteEmpty && <SidebarFavoritesMenu />}

{/* Teams List */}
<SidebarTeamsList />
{/* Projects List */}
<SidebarProjectsList />
</div>
{/* Help Section */}
<SidebarHelpSection />
</div>
</div>
Expand Down
Loading