mirror of
https://github.com/makeplane/plane.git
synced 2026-02-08 23:19:22 -06:00
[WEB-3998] fix: minor empty states changes + refactoring (#7151)
This commit is contained in:
@@ -15,7 +15,7 @@ export default function SettingsLayout({ children }: { children: React.ReactNode
|
||||
{/* Header */}
|
||||
<SettingsHeader />
|
||||
{/* Content */}
|
||||
<ContentWrapper className="px-4 md:pl-12 md:py-page-y md:flex w-full">
|
||||
<ContentWrapper className="px-4 md:pl-12 md:pt-page-y md:flex w-full">
|
||||
<SettingsContentLayout>{children}</SettingsContentLayout>
|
||||
</ContentWrapper>
|
||||
</main>
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
|
||||
import { FC, ReactNode } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
// components
|
||||
import { usePathname } from "next/navigation";
|
||||
// constants
|
||||
import { EUserWorkspaceRoles, WORKSPACE_SETTINGS_ACCESS } from "@plane/constants";
|
||||
// hooks
|
||||
// components
|
||||
import { NotAuthorizedView } from "@/components/auth-screens";
|
||||
import { CommandPalette } from "@/components/command-palette";
|
||||
import { SettingsMobileNav } from "@/components/settings";
|
||||
import { getWorkspaceActivePath, pathnameToAccessKey } from "@/components/settings/helper";
|
||||
// hooks
|
||||
import { useUserPermissions } from "@/hooks/store";
|
||||
// local components
|
||||
import { WorkspaceSettingsSidebar } from "./sidebar";
|
||||
|
||||
@@ -82,9 +82,9 @@ const WebhooksListPage = observer(() => {
|
||||
<div className="flex h-full w-full flex-col">
|
||||
<div className="h-full w-full flex items-center justify-center">
|
||||
<DetailedEmptyState
|
||||
className="!px-0 py-5"
|
||||
title={t("workspace_settings.empty_state.webhooks.title")}
|
||||
description={t("workspace_settings.empty_state.webhooks.description")}
|
||||
className="!p-0"
|
||||
title=""
|
||||
description=""
|
||||
assetPath={resolvedPath}
|
||||
size="md"
|
||||
primaryButton={{
|
||||
|
||||
@@ -57,10 +57,10 @@ const ProfileActivityPage = observer(() => {
|
||||
description={t("account_settings.activity.description")}
|
||||
/>
|
||||
<DetailedEmptyState
|
||||
title={t("profile.empty_state.activity.title")}
|
||||
description={t("profile.empty_state.activity.description")}
|
||||
title={""}
|
||||
description={""}
|
||||
assetPath={resolvedPath}
|
||||
className="w-full !px-0 justify-center mx-auto min-h-fit"
|
||||
className="w-full !p-0 justify-center mx-auto min-h-fit"
|
||||
size="md"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -88,10 +88,10 @@ const ApiTokensPage = observer(() => {
|
||||
/>
|
||||
<div className="h-full w-full flex items-center justify-center">
|
||||
<DetailedEmptyState
|
||||
title={t("workspace_settings.empty_state.api_tokens.title")}
|
||||
description={t("workspace_settings.empty_state.api_tokens.description")}
|
||||
title=""
|
||||
description=""
|
||||
assetPath={resolvedPath}
|
||||
className="w-full !px-0 justify-center mx-auto"
|
||||
className="w-full !p-0 justify-center mx-auto"
|
||||
size="md"
|
||||
primaryButton={{
|
||||
text: t("workspace_settings.settings.api_tokens.add_token"),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { IWorkspace } from "@plane/types";
|
||||
|
||||
type TProps = {
|
||||
workspace: IWorkspace;
|
||||
workspace?: IWorkspace;
|
||||
};
|
||||
|
||||
export const SubscriptionPill = (props: TProps) => <></>;
|
||||
|
||||
@@ -20,10 +20,10 @@ export const EstimateEmptyScreen: FC<TEstimateEmptyScreen> = (props) => {
|
||||
const resolvedPath = `/empty-state/project-settings/estimates-${resolvedTheme === "light" ? "light" : "dark"}.png`;
|
||||
return (
|
||||
<DetailedEmptyState
|
||||
title={t("project_settings.empty_state.estimates.title")}
|
||||
description={t("project_settings.empty_state.estimates.description")}
|
||||
title={""}
|
||||
description={""}
|
||||
assetPath={resolvedPath}
|
||||
className="w-full !px-0 !py-4"
|
||||
className="w-full !px-0 !py-0"
|
||||
primaryButton={{
|
||||
text: t("project_settings.empty_state.estimates.primary_button"),
|
||||
onClick: onButtonClick,
|
||||
|
||||
@@ -106,10 +106,15 @@ export const ProjectSettingsLabelList: React.FC = observer(() => {
|
||||
projectLabels.length === 0 && !showLabelForm ? (
|
||||
<div className="flex items-center justify-center h-full w-full">
|
||||
<DetailedEmptyState
|
||||
title={t("project_settings.empty_state.labels.title")}
|
||||
description={t("project_settings.empty_state.labels.description")}
|
||||
title={""}
|
||||
description={""}
|
||||
primaryButton={{
|
||||
text: "Create your first label",
|
||||
onClick: newLabel,
|
||||
}}
|
||||
assetPath={resolvedPath}
|
||||
className="w-full !px-0 !py-4"
|
||||
className="w-full !px-0 !py-0"
|
||||
size="md"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -32,7 +32,7 @@ export const SettingsHeader = observer(() => {
|
||||
getButtonStyling("neutral-primary", "sm"),
|
||||
"md:absolute left-2 top-9 group flex gap-2 text-custom-text-300 mb-4 border border-transparent w-fit rounded-lg ",
|
||||
"h-6 w-6 rounded-lg p-1 bg-custom-background-100 border-custom-border-200 ",
|
||||
isScrolled ? "-mt-1 " : "hidden p-0 overflow-hidden items-center pr-2 border-none"
|
||||
isScrolled ? "-mt-2 " : "hidden p-0 overflow-hidden items-center pr-2 border-none"
|
||||
)}
|
||||
>
|
||||
<ChevronLeftIcon className={cn("h-4 w-4", !isScrolled ? "my-auto h-0" : "")} />
|
||||
|
||||
@@ -5,18 +5,27 @@ type Props = {
|
||||
description?: string;
|
||||
appendToRight?: React.ReactNode;
|
||||
showButton?: boolean;
|
||||
customButton?: React.ReactNode;
|
||||
button?: {
|
||||
label: string;
|
||||
onClick: () => void;
|
||||
};
|
||||
};
|
||||
|
||||
export const SettingsHeading = ({ title, description, button, appendToRight, showButton = true }: Props) => (
|
||||
export const SettingsHeading = ({
|
||||
title,
|
||||
description,
|
||||
button,
|
||||
appendToRight,
|
||||
customButton,
|
||||
showButton = true,
|
||||
}: Props) => (
|
||||
<div className="flex items-center justify-between border-b border-custom-border-100 pb-3.5">
|
||||
<div className="flex flex-col items-start gap-1">
|
||||
{typeof title === "string" ? <h3 className="text-xl font-medium">{title}</h3> : title}
|
||||
{description && <div className="text-sm text-custom-text-300">{description}</div>}
|
||||
</div>
|
||||
{showButton && customButton}
|
||||
{button && showButton && (
|
||||
<Button variant="primary" onClick={button.onClick} size="sm">
|
||||
{button.label}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { observer } from "mobx-react";
|
||||
import { WorkspaceLogo } from "@/components/workspace";
|
||||
import { getUserRole } from "@/helpers/user.helper";
|
||||
import { useWorkspace } from "@/hooks/store/use-workspace";
|
||||
import { SubscriptionPill } from "@/plane-web/components/common";
|
||||
|
||||
export const SettingsSidebarHeader = (props: { customHeader?: React.ReactNode }) => {
|
||||
export const SettingsSidebarHeader = observer((props: { customHeader?: React.ReactNode }) => {
|
||||
const { customHeader } = props;
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
return customHeader
|
||||
@@ -26,8 +27,8 @@ export const SettingsSidebarHeader = (props: { customHeader?: React.ReactNode })
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-shrink-0">
|
||||
<SubscriptionPill workspace={currentWorkspace} />
|
||||
<SubscriptionPill />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import Link from "next/link";
|
||||
import { useParams } from "next/navigation";
|
||||
import { Disclosure } from "@headlessui/react";
|
||||
@@ -23,7 +24,7 @@ export type TSettingsSidebarNavItemProps = {
|
||||
renderChildren?: (key: string) => React.ReactNode;
|
||||
};
|
||||
|
||||
const SettingsSidebarNavItem = (props: TSettingsSidebarNavItemProps) => {
|
||||
const SettingsSidebarNavItem = observer((props: TSettingsSidebarNavItemProps) => {
|
||||
const { workspaceSlug, setting, isActive, actionIcons, appendItemsToTitle, renderChildren } = props;
|
||||
// router
|
||||
const { projectId } = useParams();
|
||||
@@ -88,6 +89,6 @@ const SettingsSidebarNavItem = (props: TSettingsSidebarNavItemProps) => {
|
||||
)}
|
||||
</Disclosure>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export default SettingsSidebarNavItem;
|
||||
|
||||
@@ -87,7 +87,7 @@ export const WorkspaceMembersListItem: FC<Props> = observer((props) => {
|
||||
if (isEmpty(columns)) return <MembersLayoutLoader />;
|
||||
|
||||
return (
|
||||
<div className="border-t border-custom-border-100">
|
||||
<div className="border-t border-custom-border-100 grid">
|
||||
{removeMemberModal && (
|
||||
<ConfirmWorkspaceMemberRemove
|
||||
isOpen={removeMemberModal.member.id.length > 0}
|
||||
|
||||
@@ -62,7 +62,7 @@ export const WorkspaceMembersList: FC<{ searchQuery: string; isAdmin: boolean }>
|
||||
isOpen={showPendingInvites}
|
||||
onToggle={() => setShowPendingInvites((prev) => !prev)}
|
||||
buttonClassName="w-full"
|
||||
className="h-full"
|
||||
className=""
|
||||
title={
|
||||
<div className="flex w-full items-center justify-between pt-4">
|
||||
<div className="flex">
|
||||
|
||||
@@ -367,7 +367,7 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
|
||||
setIsMenuActive(false);
|
||||
}}
|
||||
>
|
||||
<Link href={`/${workspaceSlug}/projects/${project?.id}/settings`}>
|
||||
<Link href={`/${workspaceSlug}/settings/projects/${project?.id}`}>
|
||||
<div className="flex items-center justify-start gap-2">
|
||||
<Settings className="h-3.5 w-3.5 stroke-[1.5]" />
|
||||
<span>{t("settings")}</span>
|
||||
|
||||
Reference in New Issue
Block a user