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 }) => (
|
{({ 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>
|
||||||
|
@ -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"
|
||||||
|
@ -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>
|
||||||
|
@ -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]"
|
||||||
|
@ -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>
|
||||||
|
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;
|
) => void;
|
||||||
onIconColorChange?: (data: any) => void;
|
onIconColorChange?: (data: any) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
showEmojiPicker?: boolean;
|
||||||
|
showIconPicker?: boolean;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user