Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WEB-3203] fix: dashboard widgets' empty state content and assets #6450

Merged
merged 2 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions packages/editor/src/styles/editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,14 @@ ul[data-type="taskList"] li > div {
}

ul[data-type="taskList"] li > label input[type="checkbox"] {
border: 1px solid rgba(var(--color-border-300)) !important;
border: 1px solid rgba(var(--color-text-100), 0.2) !important;
outline: none;
border-radius: 2px;
transform: scale(1.05);
}

.ProseMirror[contenteditable="true"] input[type="checkbox"]:hover {
background-color: rgba(var(--color-background-80));
background-color: rgba(var(--color-text-100), 0.1);
}

.ProseMirror[contenteditable="false"] input[type="checkbox"] {
Expand Down
4 changes: 2 additions & 2 deletions web/core/components/editor/sticky-editor/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { getEditorFileHandlers } from "@/helpers/editor.helper";
// plane web hooks
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
import { useFileSize } from "@/plane-web/hooks/use-file-size";
import { Toolbar } from "./toolbar";
import { StickyEditorToolbar } from "./toolbar";

interface StickyEditorWrapperProps
extends Omit<ILiteTextEditor, "disabledExtensions" | "fileHandler" | "mentionHandler"> {
Expand Down Expand Up @@ -87,7 +87,7 @@ export const StickyEditor = React.forwardRef<EditorRefApi, StickyEditorWrapperPr
isFocused ? "max-h-[200px] opacity-100 scale-y-100 mt-3" : "max-h-0 opacity-0 scale-y-0 invisible"
)}
>
<Toolbar
<StickyEditorToolbar
executeCommand={(item) => {
// TODO: update this while toolbar homogenization
// @ts-expect-error type mismatch here
Expand Down
12 changes: 8 additions & 4 deletions web/core/components/editor/sticky-editor/toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type Props = {

const toolbarItems = TOOLBAR_ITEMS.sticky;

export const Toolbar: React.FC<Props> = (props) => {
export const StickyEditorToolbar: React.FC<Props> = (props) => {
const { executeCommand, editorRef, handleColorChange, handleDelete } = props;

// State to manage active states of toolbar items
Expand Down Expand Up @@ -69,7 +69,11 @@ export const Toolbar: React.FC<Props> = (props) => {
</p>
}
>
<button onClick={() => setShowColorPalette(!showColorPalette)} className="flex text-custom-text-300">
<button
type="button"
onClick={() => setShowColorPalette(!showColorPalette)}
className="flex text-custom-text-100/50"
>
<Palette className="size-4 my-auto" />
</button>
</Tooltip>
Expand All @@ -95,7 +99,7 @@ export const Toolbar: React.FC<Props> = (props) => {
type="button"
onClick={() => executeCommand(item)}
className={cn(
"grid place-items-center aspect-square rounded-sm p-0.5 text-custom-text-300",
"grid place-items-center aspect-square rounded-sm p-0.5 text-custom-text-100/50",
{}
)}
>
Expand All @@ -122,7 +126,7 @@ export const Toolbar: React.FC<Props> = (props) => {
</p>
}
>
<button onClick={handleDelete} className="my-auto text-custom-text-300">
<button type="button" onClick={handleDelete} className="my-auto text-custom-text-100/50">
<Trash2 className="size-4" />
</button>
</Tooltip>
Expand Down
2 changes: 1 addition & 1 deletion web/core/components/home/home-dashboard-widgets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const HOME_WIDGETS_LIST: {
quick_links: {
component: DashboardQuickLinks,
fullWidth: false,
title: "Quick links",
title: "Quicklinks",
},
recents: {
component: RecentActivityWidget,
Expand Down
5 changes: 4 additions & 1 deletion web/core/components/home/widgets/empty-states/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export * from "./root";
export * from "./links";
export * from "./no-projects";
export * from "./recents";
export * from "./stickies";
14 changes: 6 additions & 8 deletions web/core/components/home/widgets/empty-states/links.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { Link2 } from "lucide-react";

export const LinksEmptyState = () => (
<div className="min-h-[110px] flex w-full justify-center py-6 bg-custom-border-100 rounded">
<div className="m-auto flex gap-2">
<Link2 size={30} className="text-custom-text-400/40 -rotate-45" />
<div className="text-custom-text-400 text-sm text-center my-auto">
Add any links you need for quick access to your work.
</div>
</div>
<div className="min-h-[110px] w-full flex items-center justify-center gap-2 py-6 bg-custom-background-90 text-custom-text-400 rounded">
<div className="flex-shrink-0 size-[30px] grid place-items-center">
<Link2 className="size-6 -rotate-45" />
</div>
);
<p className="text-sm text-center font-medium">Save links to work things that you{"'"}d like handy.</p>
</div>
);
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ import React from "react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { Briefcase, Hotel, Users } from "lucide-react";
// plane ui
import { Avatar } from "@plane/ui";
// helpers
import { getFileURL } from "@/helpers/file.helper";
// hooks
import { useCommandPalette, useEventTracker, useUser, useUserPermissions } from "@/hooks/store";
// plane web constants
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants";

export const EmptyWorkspace = () => {
export const NoProjectsEmptyState = () => {
// navigation
const { workspaceSlug } = useParams();
// store hooks
Expand All @@ -26,11 +28,11 @@ export const EmptyWorkspace = () => {
const EMPTY_STATE_DATA = [
{
id: "create-project",
title: "Create a project",
description: "Create your first project now to get started",
icon: <Briefcase className="w-[40px] h-[40px] text-custom-primary-100" />,
title: "Create a project.",
description: "Most things start with a project in Plane.",
icon: <Briefcase className="size-12 text-custom-primary-100" />,
cta: {
text: "Create Project",
text: "Get started",
onClick: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
if (!canCreateProject) return;
e.preventDefault();
Expand All @@ -42,66 +44,56 @@ export const EmptyWorkspace = () => {
},
{
id: "invite-team",
title: "Invite your team",
description: "The sub text will be of two lines and that will be placed.",
icon: <Users className="w-[40px] h-[40px] text-custom-primary-100" />,
title: "Invite your team.",
description: "Build, ship, and manage with coworkers.",
icon: <Users className="size-12 text-custom-primary-100" />,
cta: {
text: "Invite now",
text: "Get them in",
link: `/${workspaceSlug}/settings/members`,
},
},
{
id: "configure-workspace",
title: "Configure your workspace",
description: "The sub text will be of two lines and that will be placed.",
icon: <Hotel className="w-[40px] h-[40px] text-custom-primary-100" />,
title: "Set up your workspace.",
description: "Turn features on or off or go beyond that.",
icon: <Hotel className="size-12 text-custom-primary-100" />,
cta: {
text: "Configure workspace",
text: "Configure this workspace",
link: "settings",
},
},
{
id: "personalize-account",
title: "Personalize your account",
description: "The sub text will be of two lines and that will be placed.",
icon:
currentUser?.avatar_url && currentUser?.avatar_url.trim() !== "" ? (
<Link href={`/${workspaceSlug}/profile/${currentUser?.id}`}>
<span className="relative flex h-6 w-6 items-center justify-center rounded-full p-4 capitalize text-white">
<img
src={getFileURL(currentUser?.avatar_url)}
className="absolute left-0 top-0 h-full w-full rounded-full object-cover"
alt={currentUser?.display_name || currentUser?.email}
/>
</span>
</Link>
) : (
<Link href={`/${workspaceSlug}/profile/${currentUser?.id}`}>
<span className="relative flex h-6 w-6 items-center justify-center rounded-full bg-gray-700 p-4 capitalize text-white text-sm">
{(currentUser?.email ?? currentUser?.display_name ?? "?")[0]}
</span>
</Link>
),
title: "Make Plane yours.",
description: "Choose your picture, colors, and more.",
icon: (
<Avatar
src={getFileURL(currentUser?.avatar_url ?? "")}
name={currentUser?.display_name}
size={48}
className="text-xl"
showTooltip={false}
/>
),
cta: {
text: "Personalize account",
text: "Personalize now",
link: "/profile",
},
},
];

return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4">
{EMPTY_STATE_DATA.map((item) => (
<div
key={item.id}
className="flex flex-col items-center justify-center py-8 bg-custom-background-100 rounded-lg text-center border border-custom-border-200/40"
className="flex flex-col items-center justify-center p-6 bg-custom-background-100 rounded-lg text-center border border-custom-border-200/40"
>
<div className="flex items-center justify-center bg-custom-primary-100/10 rounded-full w-[80px] h-[80px] mb-4">
<div className="grid place-items-center bg-custom-primary-100/10 rounded-full size-24 mb-3">
<span className="text-3xl my-auto">{item.icon}</span>
</div>
<h3 className="text-lg font-medium text-custom-text-100 mb-2">{item.title}</h3>
<p className="text-sm text-custom-text-200 mb-4 w-[80%] flex-1">{item.description}</p>

<h3 className="text-base font-medium text-custom-text-100 mb-2">{item.title}</h3>
<p className="text-sm text-custom-text-300 mb-2">{item.description}</p>
{item.cta.link ? (
<Link
href={item.cta.link}
Expand All @@ -111,6 +103,7 @@ export const EmptyWorkspace = () => {
</Link>
) : (
<button
type="button"
className="text-custom-primary-100 hover:text-custom-primary-200 text-sm font-medium"
onClick={item.cta.onClick}
>
Expand Down
59 changes: 31 additions & 28 deletions web/core/components/home/widgets/empty-states/recents.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,41 @@
import { Briefcase, FileText, History } from "lucide-react";
// plane ui
import { LayersIcon } from "@plane/ui";

const getDisplayContent = (type: string) => {
switch (type) {
case "project":
return {
icon: Briefcase,
text: "Projects you go into or have assigned work in will show up here.",
};
case "page":
return {
icon: FileText,
text: "Create, see, or change something on pages you have access to and see them here.",
};
case "issue":
return {
icon: LayersIcon,
text: "Let's see some issues to see them show up here.",
};
default:
return {
icon: History,
text: "Whatever you see and act on in Plane will show up here.",
};
}
};

export const RecentsEmptyState = ({ type }: { type: string }) => {
const getDisplayContent = () => {
switch (type) {
case "project":
return {
icon: <Briefcase size={30} className="text-custom-text-400/40" />,
text: "Your recent projects will appear here once you visit one.",
};
case "page":
return {
icon: <FileText size={30} className="text-custom-text-400/40" />,
text: "Your recent pages will appear here once you visit one.",
};
case "issue":
return {
icon: <LayersIcon className="text-custom-text-400/40 w-[30px] h-[30px]" />,
text: "Your recent issues will appear here once you visit one.",
};
default:
return {
icon: <History size={30} className="text-custom-text-400/40" />,
text: "You don’t have any recent items yet.",
};
}
};
const { icon, text } = getDisplayContent();
const displayContent = getDisplayContent(type);

return (
<div className="min-h-[120px] flex w-full justify-center py-6 bg-custom-border-100 rounded">
<div className="m-auto flex gap-2">
{icon} <div className="text-custom-text-400 text-sm text-center my-auto">{text}</div>
<div className="min-h-[110px] w-full flex items-center justify-center gap-2 py-6 bg-custom-background-90 text-custom-text-400 rounded">
<div className="flex-shrink-0 size-[30px] grid place-items-center">
<displayContent.icon className="size-6" />
</div>
<p className="text-sm text-center font-medium">{displayContent.text}</p>
</div>
);
};
12 changes: 6 additions & 6 deletions web/core/components/home/widgets/empty-states/stickies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
import { RecentStickyIcon } from "@plane/ui";

export const StickiesEmptyState = () => (
<div className="min-h-[110px] flex w-full justify-center py-6 bg-custom-border-100 rounded">
<div className="m-auto flex gap-2">
<RecentStickyIcon className="h-[30px] w-[30px] text-custom-text-400/40" />
<div className="text-custom-text-400 text-sm text-center my-auto">
No stickies yet. Add one to start making quick notes.
</div>
<div className="min-h-[110px] w-full flex items-center justify-center gap-2 py-6 bg-custom-background-90 text-custom-text-400 rounded">
<div className="flex-shrink-0 size-[30px] grid place-items-center">
<RecentStickyIcon className="size-6" />
</div>
<p className="text-sm text-center font-medium">
Jot down an idea, capture an aha, or record a brainwave. Add a sticky to get started.
</p>
</div>
);
2 changes: 1 addition & 1 deletion web/core/components/home/widgets/links/action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const AddLink = (props: TProps) => {
<div className="rounded p-2 bg-custom-background-80/40 w-8 h-8 my-auto">
<PlusIcon className="h-4 w-4 stroke-2 text-custom-text-350" />
</div>
<div className="text-sm font-medium my-auto">Add quick Link</div>
<div className="text-sm font-medium my-auto">Add quicklink</div>
</button>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,7 @@ export const LinkCreateUpdateModal: FC<TLinkCreateEditModal> = observer((props)
<ModalCore isOpen={isModalOpen} handleClose={onClose}>
<form onSubmit={handleSubmit(handleFormSubmit)}>
<div className="space-y-5 p-5">
<h3 className="text-xl font-medium text-custom-text-200">
{preloadedData?.id ? "Update" : "Add"} quick link
</h3>
<h3 className="text-xl font-medium text-custom-text-200">{preloadedData?.id ? "Update" : "Add"} quicklink</h3>
<div className="mt-2 space-y-3">
<div>
<label htmlFor="url" className="mb-2 text-custom-text-200 text-base font-medium">
Expand Down Expand Up @@ -124,7 +122,7 @@ export const LinkCreateUpdateModal: FC<TLinkCreateEditModal> = observer((props)
Cancel
</Button>
<Button variant="primary" size="sm" type="submit" loading={isSubmitting}>
{preloadedData?.id ? (isSubmitting ? "Updating" : "Update") : isSubmitting ? "Adding" : "Add"} quick link
{preloadedData?.id ? (isSubmitting ? "Updating" : "Update") : isSubmitting ? "Adding" : "Add"} quicklink
</Button>
</div>
</form>
Expand Down
Loading
Loading