forked from github/plane
chore: added icon field for objects
This commit is contained in:
parent
5dc9e00c3d
commit
e94fb40602
@ -94,7 +94,7 @@ export const CustomRelationAttribute: React.FC<Props> = ({
|
||||
{({ open }: { open: boolean }) => (
|
||||
<>
|
||||
<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}`}
|
||||
</Combobox.Button>
|
||||
|
@ -15,6 +15,8 @@ import { Loader, PrimaryButton, SecondaryButton } from "components/ui";
|
||||
import { ICustomAttribute, TCustomAttributeTypes } from "types";
|
||||
// constants
|
||||
import { CUSTOM_ATTRIBUTES_LIST } from "constants/custom-attributes";
|
||||
import { renderEmoji } from "helpers/emoji.helper";
|
||||
import EmojiIconPicker from "components/emoji-icon-picker";
|
||||
|
||||
type Props = {
|
||||
objectIdToEdit?: string | null;
|
||||
@ -53,6 +55,7 @@ export const ObjectModal: React.FC<Props> = observer(
|
||||
const payload: Partial<ICustomAttribute> = {
|
||||
description: object.description ?? "",
|
||||
display_name: object.display_name ?? "",
|
||||
icon: object.icon ?? "",
|
||||
project: projectId.toString(),
|
||||
type: "entity",
|
||||
};
|
||||
@ -74,6 +77,7 @@ export const ObjectModal: React.FC<Props> = observer(
|
||||
const payload: Partial<ICustomAttribute> = {
|
||||
description: object.description ?? "",
|
||||
display_name: object.display_name ?? "",
|
||||
icon: object.icon ?? "",
|
||||
};
|
||||
|
||||
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="space-y-4 px-6">
|
||||
<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>
|
||||
<Input
|
||||
placeholder="Enter Object Title"
|
||||
|
@ -13,6 +13,7 @@ import { CustomMenu, Loader } from "components/ui";
|
||||
import { TableProperties } from "lucide-react";
|
||||
// types
|
||||
import { ICustomAttribute } from "types";
|
||||
import { renderEmoji } from "helpers/emoji.helper";
|
||||
|
||||
type Props = {
|
||||
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 className="flex gap-4">
|
||||
<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>
|
||||
<h5 className="text-sm font-medium">{entity.display_name}</h5>
|
||||
|
@ -7,6 +7,8 @@ import { observer } from "mobx-react-lite";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// ui
|
||||
import { CustomSearchSelect } from "components/ui";
|
||||
import { renderEmoji } from "helpers/emoji.helper";
|
||||
import { TableProperties } from "lucide-react";
|
||||
|
||||
type Props = {
|
||||
onChange: (val: string | null) => void;
|
||||
@ -25,14 +27,28 @@ export const ObjectsSelect: React.FC<Props> = observer(({ onChange, projectId, v
|
||||
| {
|
||||
value: any;
|
||||
query: string;
|
||||
content: string;
|
||||
content: JSX.Element;
|
||||
}[]
|
||||
| undefined = entities?.map((entity) => ({
|
||||
value: entity.id,
|
||||
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(() => {
|
||||
if (!workspaceSlug) return;
|
||||
@ -40,9 +56,22 @@ export const ObjectsSelect: React.FC<Props> = observer(({ onChange, projectId, v
|
||||
if (!entities) fetchEntities(workspaceSlug.toString(), projectId);
|
||||
}, [entities, fetchEntities, projectId, workspaceSlug]);
|
||||
|
||||
const selectedEntity = entities?.find((e) => e.id === value);
|
||||
|
||||
return (
|
||||
<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}
|
||||
maxHeight="md"
|
||||
optionsClassName="!min-w-[10rem]"
|
||||
|
@ -31,6 +31,8 @@ const EmojiIconPicker: React.FC<Props> = ({
|
||||
onChange,
|
||||
onIconColorChange,
|
||||
disabled = false,
|
||||
showEmojiPicker = true,
|
||||
showIconPicker = true,
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = 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.List className="flex-0 -mx-2 flex justify-around gap-1 p-1">
|
||||
{tabOptions.map((tab) => (
|
||||
<Tab key={tab.key} as={React.Fragment}>
|
||||
{({ selected }) => (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setOpenColorPicker(false);
|
||||
}}
|
||||
className={`-my-1 w-1/2 border-b pb-2 text-center text-sm font-medium outline-none transition-colors ${
|
||||
selected ? "" : "border-transparent text-custom-text-200"
|
||||
}`}
|
||||
>
|
||||
{tab.title}
|
||||
</button>
|
||||
)}
|
||||
</Tab>
|
||||
))}
|
||||
{tabOptions.map((tab) => {
|
||||
if (!showEmojiPicker && tab.key === "emoji") return null;
|
||||
if (!showIconPicker && tab.key === "icon") return null;
|
||||
|
||||
return (
|
||||
<Tab key={tab.key} as={React.Fragment}>
|
||||
{({ selected }) => (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setOpenColorPicker(false);
|
||||
}}
|
||||
className={`-my-1 w-1/2 border-b pb-2 text-center text-sm font-medium outline-none transition-colors ${
|
||||
selected ? "" : "border-transparent text-custom-text-200"
|
||||
}`}
|
||||
>
|
||||
{tab.title}
|
||||
</button>
|
||||
)}
|
||||
</Tab>
|
||||
);
|
||||
})}
|
||||
</Tab.List>
|
||||
<Tab.Panels className="flex-1 overflow-y-auto">
|
||||
<Tab.Panel>
|
||||
|
2
web/components/emoji-icon-picker/types.d.ts
vendored
2
web/components/emoji-icon-picker/types.d.ts
vendored
@ -11,4 +11,6 @@ export type Props = {
|
||||
) => void;
|
||||
onIconColorChange?: (data: any) => void;
|
||||
disabled?: boolean;
|
||||
showEmojiPicker?: boolean;
|
||||
showIconPicker?: boolean;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user