chore: added icon field for objects

This commit is contained in:
Aaryan Khandelwal 2023-09-19 19:27:19 +05:30
parent 5dc9e00c3d
commit e94fb40602
6 changed files with 80 additions and 25 deletions

View File

@ -94,7 +94,7 @@ export const CustomRelationAttribute: React.FC<Props> = ({
{({ open }: { open: boolean }) => ( {({ open }: { open: boolean }) => (
<> <>
<Combobox.Button <Combobox.Button
className={`lex items-center text-xs rounded px-2.5 py-0.5 truncate w-min max-w-full text-left bg-custom-background-80 ${className}`} className={`flex items-center text-xs rounded px-2.5 py-0.5 truncate w-min max-w-full text-left bg-custom-background-80 ${className}`}
> >
{selectedOption?.label ?? `Select ${attributeDetails.unit}`} {selectedOption?.label ?? `Select ${attributeDetails.unit}`}
</Combobox.Button> </Combobox.Button>

View File

@ -15,6 +15,8 @@ import { Loader, PrimaryButton, SecondaryButton } from "components/ui";
import { ICustomAttribute, TCustomAttributeTypes } from "types"; import { ICustomAttribute, TCustomAttributeTypes } from "types";
// constants // constants
import { CUSTOM_ATTRIBUTES_LIST } from "constants/custom-attributes"; import { CUSTOM_ATTRIBUTES_LIST } from "constants/custom-attributes";
import { renderEmoji } from "helpers/emoji.helper";
import EmojiIconPicker from "components/emoji-icon-picker";
type Props = { type Props = {
objectIdToEdit?: string | null; objectIdToEdit?: string | null;
@ -53,6 +55,7 @@ export const ObjectModal: React.FC<Props> = observer(
const payload: Partial<ICustomAttribute> = { const payload: Partial<ICustomAttribute> = {
description: object.description ?? "", description: object.description ?? "",
display_name: object.display_name ?? "", display_name: object.display_name ?? "",
icon: object.icon ?? "",
project: projectId.toString(), project: projectId.toString(),
type: "entity", type: "entity",
}; };
@ -74,6 +77,7 @@ export const ObjectModal: React.FC<Props> = observer(
const payload: Partial<ICustomAttribute> = { const payload: Partial<ICustomAttribute> = {
description: object.description ?? "", description: object.description ?? "",
display_name: object.display_name ?? "", display_name: object.display_name ?? "",
icon: object.icon ?? "",
}; };
await customAttributes await customAttributes
@ -152,8 +156,16 @@ export const ObjectModal: React.FC<Props> = observer(
<div className="mt-5 space-y-5 h-full overflow-y-auto"> <div className="mt-5 space-y-5 h-full overflow-y-auto">
<div className="space-y-4 px-6"> <div className="space-y-4 px-6">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<div className="h-9 w-9 bg-custom-background-80 grid place-items-center rounded text-sm"> <div className="h-9 w-9 bg-custom-background-80 grid place-items-center rounded">
🚀 <EmojiIconPicker
label={object.icon ? renderEmoji(object.icon) : "Icon"}
onChange={(icon) => {
if (typeof icon === "string")
setObject((prevData) => ({ ...prevData, icon }));
}}
value={object.icon}
showIconPicker={false}
/>
</div> </div>
<Input <Input
placeholder="Enter Object Title" placeholder="Enter Object Title"

View File

@ -13,6 +13,7 @@ import { CustomMenu, Loader } from "components/ui";
import { TableProperties } from "lucide-react"; import { TableProperties } from "lucide-react";
// types // types
import { ICustomAttribute } from "types"; import { ICustomAttribute } from "types";
import { renderEmoji } from "helpers/emoji.helper";
type Props = { type Props = {
handleEditObject: (object: ICustomAttribute) => void; handleEditObject: (object: ICustomAttribute) => void;
@ -60,7 +61,11 @@ export const ObjectsList: React.FC<Props> = observer(({ handleEditObject, projec
<div key={entity.id} className="p-4 flex items-center justify-between gap-4"> <div key={entity.id} className="p-4 flex items-center justify-between gap-4">
<div className="flex gap-4"> <div className="flex gap-4">
<div className="bg-custom-background-80 h-10 w-10 grid place-items-center rounded"> <div className="bg-custom-background-80 h-10 w-10 grid place-items-center rounded">
<TableProperties size={20} strokeWidth={1.5} /> {entity.icon ? (
renderEmoji(entity.icon)
) : (
<TableProperties size={20} strokeWidth={1.5} />
)}
</div> </div>
<div> <div>
<h5 className="text-sm font-medium">{entity.display_name}</h5> <h5 className="text-sm font-medium">{entity.display_name}</h5>

View File

@ -7,6 +7,8 @@ import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
// ui // ui
import { CustomSearchSelect } from "components/ui"; import { CustomSearchSelect } from "components/ui";
import { renderEmoji } from "helpers/emoji.helper";
import { TableProperties } from "lucide-react";
type Props = { type Props = {
onChange: (val: string | null) => void; onChange: (val: string | null) => void;
@ -25,14 +27,28 @@ export const ObjectsSelect: React.FC<Props> = observer(({ onChange, projectId, v
| { | {
value: any; value: any;
query: string; query: string;
content: string; content: JSX.Element;
}[] }[]
| undefined = entities?.map((entity) => ({ | undefined = entities?.map((entity) => ({
value: entity.id, value: entity.id,
query: entity.display_name, query: entity.display_name,
content: entity.display_name, content: (
<div className="flex items-center gap-2 text-xs">
{entity.icon ? renderEmoji(entity.icon) : <TableProperties size={14} strokeWidth={1.5} />}
<span>{entity.display_name}</span>
</div>
),
})); }));
options?.unshift({ value: null, query: "default", content: "Default" }); options?.unshift({
value: null,
query: "default",
content: (
<div className="flex items-center gap-2">
<TableProperties size={14} strokeWidth={1.5} />
<span>Default</span>
</div>
),
});
useEffect(() => { useEffect(() => {
if (!workspaceSlug) return; if (!workspaceSlug) return;
@ -40,9 +56,22 @@ export const ObjectsSelect: React.FC<Props> = observer(({ onChange, projectId, v
if (!entities) fetchEntities(workspaceSlug.toString(), projectId); if (!entities) fetchEntities(workspaceSlug.toString(), projectId);
}, [entities, fetchEntities, projectId, workspaceSlug]); }, [entities, fetchEntities, projectId, workspaceSlug]);
const selectedEntity = entities?.find((e) => e.id === value);
return ( return (
<CustomSearchSelect <CustomSearchSelect
label={entities?.find((e) => e.id === value)?.display_name ?? "Default"} label={
<span className="flex items-center gap-2">
<div className="flex items-center gap-2 text-xs">
{selectedEntity?.icon ? (
renderEmoji(selectedEntity.icon)
) : (
<TableProperties size={14} strokeWidth={1.5} />
)}
<span>{selectedEntity?.display_name ?? "Default"}</span>
</div>
</span>
}
value={value} value={value}
maxHeight="md" maxHeight="md"
optionsClassName="!min-w-[10rem]" optionsClassName="!min-w-[10rem]"

View File

@ -31,6 +31,8 @@ const EmojiIconPicker: React.FC<Props> = ({
onChange, onChange,
onIconColorChange, onIconColorChange,
disabled = false, disabled = false,
showEmojiPicker = true,
showIconPicker = true,
}) => { }) => {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [openColorPicker, setOpenColorPicker] = useState(false); const [openColorPicker, setOpenColorPicker] = useState(false);
@ -75,23 +77,28 @@ const EmojiIconPicker: React.FC<Props> = ({
> >
<Tab.Group as="div" className="flex h-full w-full flex-col"> <Tab.Group as="div" className="flex h-full w-full flex-col">
<Tab.List className="flex-0 -mx-2 flex justify-around gap-1 p-1"> <Tab.List className="flex-0 -mx-2 flex justify-around gap-1 p-1">
{tabOptions.map((tab) => ( {tabOptions.map((tab) => {
<Tab key={tab.key} as={React.Fragment}> if (!showEmojiPicker && tab.key === "emoji") return null;
{({ selected }) => ( if (!showIconPicker && tab.key === "icon") return null;
<button
type="button" return (
onClick={() => { <Tab key={tab.key} as={React.Fragment}>
setOpenColorPicker(false); {({ selected }) => (
}} <button
className={`-my-1 w-1/2 border-b pb-2 text-center text-sm font-medium outline-none transition-colors ${ type="button"
selected ? "" : "border-transparent text-custom-text-200" onClick={() => {
}`} setOpenColorPicker(false);
> }}
{tab.title} className={`-my-1 w-1/2 border-b pb-2 text-center text-sm font-medium outline-none transition-colors ${
</button> selected ? "" : "border-transparent text-custom-text-200"
)} }`}
</Tab> >
))} {tab.title}
</button>
)}
</Tab>
);
})}
</Tab.List> </Tab.List>
<Tab.Panels className="flex-1 overflow-y-auto"> <Tab.Panels className="flex-1 overflow-y-auto">
<Tab.Panel> <Tab.Panel>

View File

@ -11,4 +11,6 @@ export type Props = {
) => void; ) => void;
onIconColorChange?: (data: any) => void; onIconColorChange?: (data: any) => void;
disabled?: boolean; disabled?: boolean;
showEmojiPicker?: boolean;
showIconPicker?: boolean;
}; };