mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: UI/UX improvements (#3319)
* chore: add proper message for cycle/ module having start & end date but isn't active yet. * fix: infinite loader after updating workspace settings. * fix: user profile icon dropdown doesn't closes automatically. * style: fix inconsistent padding in cycle empty state. * chore: remove multiple `empty state` in labels settings and improve add label logic. * style: fix inconsistent padding in project label, integration and estimates empty state. * style: fix integrations settings breadcrumb title. * style: add proper `disabled` styles for email field in profile settings. * style: fix cycle layout height.
This commit is contained in:
parent
d98b688342
commit
9dd8c8ba14
@ -43,7 +43,7 @@ export const NewEmptyState: React.FC<Props> = ({
|
|||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center overflow-y-auto">
|
<div className="flex items-center justify-center overflow-y-auto">
|
||||||
<div className=" flex h-full w-full flex-col items-center justify-center ">
|
<div className=" flex h-full w-full flex-col items-center justify-center ">
|
||||||
<div className="m-5 flex max-w-6xl flex-col gap-5 rounded-xl border border-custom-border-200 px-10 py-7 shadow-sm md:m-16">
|
<div className="m-5 flex max-w-6xl flex-col gap-5 rounded-xl border border-custom-border-200 px-10 py-7 shadow-sm md:m-8">
|
||||||
<h3 className="text-2xl font-semibold">{title}</h3>
|
<h3 className="text-2xl font-semibold">{title}</h3>
|
||||||
{description && <p className=" text-lg">{description}</p>}
|
{description && <p className=" text-lg">{description}</p>}
|
||||||
<div className="relative w-full max-w-6xl">
|
<div className="relative w-full max-w-6xl">
|
||||||
|
@ -539,7 +539,9 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<AlertCircle height={14} width={14} className="text-custom-text-200" />
|
<AlertCircle height={14} width={14} className="text-custom-text-200" />
|
||||||
<span className="text-xs italic text-custom-text-200">
|
<span className="text-xs italic text-custom-text-200">
|
||||||
Invalid date. Please enter valid date.
|
{cycleDetails?.start_date && cycleDetails?.end_date
|
||||||
|
? "This cycle isn't active yet."
|
||||||
|
: "Invalid date. Please enter valid date."}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -102,7 +102,7 @@ export const EstimatesList: React.FC = observer(() => {
|
|||||||
))}
|
))}
|
||||||
</section>
|
</section>
|
||||||
) : (
|
) : (
|
||||||
<div className="h-full w-full overflow-y-auto">
|
<div className="w-full py-8">
|
||||||
<EmptyState
|
<EmptyState
|
||||||
title="No estimates yet"
|
title="No estimates yet"
|
||||||
description="Estimates help you communicate the complexity of an issue."
|
description="Estimates help you communicate the complexity of an issue."
|
||||||
|
@ -96,9 +96,9 @@ export const ProjectSettingsLabelList: React.FC = observer(() => {
|
|||||||
Add label
|
Add label
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full py-8">
|
||||||
{showLabelForm && (
|
{showLabelForm && (
|
||||||
<div className="w-full rounded border border-custom-border-200 px-3.5 py-2">
|
<div className="w-full rounded border border-custom-border-200 px-3.5 py-2 my-2">
|
||||||
<CreateUpdateLabelInline
|
<CreateUpdateLabelInline
|
||||||
labelForm={showLabelForm}
|
labelForm={showLabelForm}
|
||||||
setLabelForm={setLabelForm}
|
setLabelForm={setLabelForm}
|
||||||
@ -112,7 +112,7 @@ export const ProjectSettingsLabelList: React.FC = observer(() => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{projectLabels ? (
|
{projectLabels ? (
|
||||||
projectLabels.length === 0 ? (
|
projectLabels.length === 0 && !showLabelForm ? (
|
||||||
<EmptyState
|
<EmptyState
|
||||||
title="No labels yet"
|
title="No labels yet"
|
||||||
description="Create labels to help organize and filter issues in you project"
|
description="Create labels to help organize and filter issues in you project"
|
||||||
@ -203,25 +203,14 @@ export const ProjectSettingsLabelList: React.FC = observer(() => {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
|
!showLabelForm && (
|
||||||
<Loader className="space-y-5">
|
<Loader className="space-y-5">
|
||||||
<Loader.Item height="42px" />
|
<Loader.Item height="42px" />
|
||||||
<Loader.Item height="42px" />
|
<Loader.Item height="42px" />
|
||||||
<Loader.Item height="42px" />
|
<Loader.Item height="42px" />
|
||||||
<Loader.Item height="42px" />
|
<Loader.Item height="42px" />
|
||||||
</Loader>
|
</Loader>
|
||||||
)}
|
)
|
||||||
|
|
||||||
{/* empty state */}
|
|
||||||
{projectLabels && projectLabels.length === 0 && (
|
|
||||||
<EmptyState
|
|
||||||
title="No labels yet"
|
|
||||||
description="Create labels to help organize and filter issues in your project."
|
|
||||||
image={emptyLabel}
|
|
||||||
primaryButton={{
|
|
||||||
text: "Add label",
|
|
||||||
onClick: () => newLabel(),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -550,7 +550,9 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<AlertCircle height={14} width={14} className="text-custom-text-200" />
|
<AlertCircle height={14} width={14} className="text-custom-text-200" />
|
||||||
<span className="text-xs italic text-custom-text-200">
|
<span className="text-xs italic text-custom-text-200">
|
||||||
Invalid date. Please enter valid date.
|
{moduleDetails?.start_date && moduleDetails?.target_date
|
||||||
|
? "This module isn't active yet."
|
||||||
|
: "Invalid date. Please enter valid date."}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -278,14 +278,14 @@ export const WorkspaceSidebarDropdown = observer(() => {
|
|||||||
<div className="flex flex-col gap-2.5 pb-2">
|
<div className="flex flex-col gap-2.5 pb-2">
|
||||||
<span className="px-2 text-custom-sidebar-text-200">{currentUser?.email}</span>
|
<span className="px-2 text-custom-sidebar-text-200">{currentUser?.email}</span>
|
||||||
{profileLinks(workspaceSlug?.toString() ?? "", currentUser?.id ?? "").map((link, index) => (
|
{profileLinks(workspaceSlug?.toString() ?? "", currentUser?.id ?? "").map((link, index) => (
|
||||||
<Menu.Item key={index} as="button" type="button">
|
<Link key={index} href={link.link}>
|
||||||
<Link href={link.link}>
|
<Menu.Item key={index} as="div">
|
||||||
<span className="flex w-full items-center gap-2 rounded px-2 py-1 hover:bg-custom-sidebar-background-80">
|
<span className="flex w-full items-center gap-2 rounded px-2 py-1 hover:bg-custom-sidebar-background-80">
|
||||||
<link.icon className="h-4 w-4 stroke-[1.5]" />
|
<link.icon className="h-4 w-4 stroke-[1.5]" />
|
||||||
{link.name}
|
{link.name}
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
</Link>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className={`pt-2 ${isUserInstanceAdmin ? "pb-2" : ""}`}>
|
<div className={`pt-2 ${isUserInstanceAdmin ? "pb-2" : ""}`}>
|
||||||
@ -301,13 +301,13 @@ export const WorkspaceSidebarDropdown = observer(() => {
|
|||||||
</div>
|
</div>
|
||||||
{isUserInstanceAdmin && (
|
{isUserInstanceAdmin && (
|
||||||
<div className="p-2 pb-0">
|
<div className="p-2 pb-0">
|
||||||
<Menu.Item as="button" type="button" className="w-full">
|
|
||||||
<Link href="/god-mode">
|
<Link href="/god-mode">
|
||||||
|
<Menu.Item as="button" type="button" className="w-full">
|
||||||
<span className="flex w-full items-center justify-center rounded bg-custom-primary-100/20 px-2 py-1 text-sm font-medium text-custom-primary-100 hover:bg-custom-primary-100/30 hover:text-custom-primary-200">
|
<span className="flex w-full items-center justify-center rounded bg-custom-primary-100/20 px-2 py-1 text-sm font-medium text-custom-primary-100 hover:bg-custom-primary-100/30 hover:text-custom-primary-200">
|
||||||
Enter God Mode
|
Enter God Mode
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Menu.Items>
|
</Menu.Items>
|
||||||
|
@ -59,7 +59,7 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
|
|||||||
if (!workspaceSlug || !projectId) return null;
|
if (!workspaceSlug || !projectId) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="w-full h-full">
|
||||||
<CycleCreateUpdateModal
|
<CycleCreateUpdateModal
|
||||||
workspaceSlug={workspaceSlug.toString()}
|
workspaceSlug={workspaceSlug.toString()}
|
||||||
projectId={projectId.toString()}
|
projectId={projectId.toString()}
|
||||||
@ -67,7 +67,7 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
|
|||||||
handleClose={() => setCreateModal(false)}
|
handleClose={() => setCreateModal(false)}
|
||||||
/>
|
/>
|
||||||
{totalCycles === 0 ? (
|
{totalCycles === 0 ? (
|
||||||
<div className="grid h-full place-items-center">
|
<div className="h-full place-items-center">
|
||||||
<NewEmptyState
|
<NewEmptyState
|
||||||
title="Group and timebox your work in Cycles."
|
title="Group and timebox your work in Cycles."
|
||||||
description="Break work down by timeboxed chunks, work backwards from your project deadline to set dates, and make tangible progress as a team."
|
description="Break work down by timeboxed chunks, work backwards from your project deadline to set dates, and make tangible progress as a team."
|
||||||
@ -194,7 +194,7 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
|
|||||||
</Tab.Panels>
|
</Tab.Panels>
|
||||||
</Tab.Group>
|
</Tab.Group>
|
||||||
)}
|
)}
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ const ProjectIntegrationsPage: NextPageWithLayout = () => {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
<div className="w-full py-8">
|
||||||
<EmptyState
|
<EmptyState
|
||||||
title="You haven't configured integrations"
|
title="You haven't configured integrations"
|
||||||
description="Configure GitHub and other integrations to sync your project issues."
|
description="Configure GitHub and other integrations to sync your project issues."
|
||||||
@ -64,6 +65,7 @@ const ProjectIntegrationsPage: NextPageWithLayout = () => {
|
|||||||
}}
|
}}
|
||||||
disabled={!isAdmin}
|
disabled={!isAdmin}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
<Loader className="space-y-5">
|
<Loader className="space-y-5">
|
||||||
|
@ -65,7 +65,7 @@ const WorkspaceIntegrationsPage: NextPageWithLayout = observer(() => {
|
|||||||
|
|
||||||
WorkspaceIntegrationsPage.getLayout = function getLayout(page: ReactElement) {
|
WorkspaceIntegrationsPage.getLayout = function getLayout(page: ReactElement) {
|
||||||
return (
|
return (
|
||||||
<AppLayout header={<WorkspaceSettingHeader title="Export Settings" />}>
|
<AppLayout header={<WorkspaceSettingHeader title="Integrations Settings" />}>
|
||||||
<WorkspaceSettingLayout>{page}</WorkspaceSettingLayout>
|
<WorkspaceSettingLayout>{page}</WorkspaceSettingLayout>
|
||||||
</AppLayout>
|
</AppLayout>
|
||||||
);
|
);
|
||||||
|
@ -218,7 +218,7 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => {
|
|||||||
<div className="grid grid-cols-1 gap-6 px-8 lg:grid-cols-2 2xl:grid-cols-3">
|
<div className="grid grid-cols-1 gap-6 px-8 lg: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">
|
<h4 className="text-sm">
|
||||||
First name <span className="text-red-500">*</span>
|
First name<span className="text-red-500">*</span>
|
||||||
</h4>
|
</h4>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
@ -275,17 +275,16 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => {
|
|||||||
rules={{
|
rules={{
|
||||||
required: "Email is required.",
|
required: "Email is required.",
|
||||||
}}
|
}}
|
||||||
render={({ field: { value, onChange, ref } }) => (
|
render={({ field: { value, ref } }) => (
|
||||||
<Input
|
<Input
|
||||||
id="email"
|
id="email"
|
||||||
name="email"
|
name="email"
|
||||||
type="email"
|
type="email"
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
|
||||||
ref={ref}
|
ref={ref}
|
||||||
hasError={Boolean(errors.email)}
|
hasError={Boolean(errors.email)}
|
||||||
placeholder="Enter your email"
|
placeholder="Enter your email"
|
||||||
className={`w-full rounded-md ${errors.email ? "border-red-500" : ""}`}
|
className={`w-full rounded-md cursor-not-allowed !bg-custom-background-80 ${errors.email ? "border-red-500" : ""}`}
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -14,10 +14,9 @@ import {
|
|||||||
IWorkspaceBulkInviteFormData,
|
IWorkspaceBulkInviteFormData,
|
||||||
IWorkspaceViewProps,
|
IWorkspaceViewProps,
|
||||||
IUserProjectsRole,
|
IUserProjectsRole,
|
||||||
TIssueMap,
|
|
||||||
TIssue,
|
TIssue,
|
||||||
|
IWorkspaceView,
|
||||||
} from "@plane/types";
|
} from "@plane/types";
|
||||||
import { IWorkspaceView } from "@plane/types";
|
|
||||||
|
|
||||||
export class WorkspaceService extends APIService {
|
export class WorkspaceService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -135,7 +135,7 @@ export class WorkspaceRootStore implements IWorkspaceRootStore {
|
|||||||
updateWorkspace = async (workspaceSlug: string, data: Partial<IWorkspace>) =>
|
updateWorkspace = async (workspaceSlug: string, data: Partial<IWorkspace>) =>
|
||||||
await this.workspaceService.updateWorkspace(workspaceSlug, data).then((response) => {
|
await this.workspaceService.updateWorkspace(workspaceSlug, data).then((response) => {
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
set(this.workspaces, response.id, data);
|
set(this.workspaces, response.id, response);
|
||||||
});
|
});
|
||||||
return response;
|
return response;
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user