mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fix: added image popover for settings cover (#737)
* fix: added popover for profile cover * fix:removed comments
This commit is contained in:
parent
35f9876981
commit
a68d94c33f
@ -59,7 +59,7 @@ export const ImagePickerPopover: React.FC<Props> = ({ label, value, onChange })
|
|||||||
return (
|
return (
|
||||||
<Popover className="relative z-[2]" ref={ref}>
|
<Popover className="relative z-[2]" ref={ref}>
|
||||||
<Popover.Button
|
<Popover.Button
|
||||||
className="rounded-md border border-gray-500 bg-white px-2 py-1 text-xs text-gray-700"
|
className="rounded border border-gray-500 bg-white px-2 py-1 text-xs text-gray-700"
|
||||||
onClick={() => setIsOpen((prev) => !prev)}
|
onClick={() => setIsOpen((prev) => !prev)}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
@ -92,11 +92,7 @@ export const ImagePickerPopover: React.FC<Props> = ({ label, value, onChange })
|
|||||||
</Tab.List>
|
</Tab.List>
|
||||||
<Tab.Panels className="h-full w-full flex-1 overflow-y-auto overflow-x-hidden">
|
<Tab.Panels className="h-full w-full flex-1 overflow-y-auto overflow-x-hidden">
|
||||||
<Tab.Panel className="h-full w-full space-y-4">
|
<Tab.Panel className="h-full w-full space-y-4">
|
||||||
<form
|
<div
|
||||||
onSubmit={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
setSearchParams(formData.search);
|
|
||||||
}}
|
|
||||||
className="flex gap-x-2 pt-7"
|
className="flex gap-x-2 pt-7"
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
@ -107,10 +103,10 @@ export const ImagePickerPopover: React.FC<Props> = ({ label, value, onChange })
|
|||||||
onChange={(e) => setFormData({ ...formData, search: e.target.value })}
|
onChange={(e) => setFormData({ ...formData, search: e.target.value })}
|
||||||
placeholder="Search for images"
|
placeholder="Search for images"
|
||||||
/>
|
/>
|
||||||
<PrimaryButton type="submit" className="bg-indigo-600" size="sm">
|
<PrimaryButton type="button" onClick={()=>setSearchParams(formData.search)} className="bg-indigo-600" size="sm">
|
||||||
Search
|
Search
|
||||||
</PrimaryButton>
|
</PrimaryButton>
|
||||||
</form>
|
</div>
|
||||||
{images ? (
|
{images ? (
|
||||||
<div className="grid grid-cols-4 gap-4">
|
<div className="grid grid-cols-4 gap-4">
|
||||||
{images.map((image) => (
|
{images.map((image) => (
|
||||||
|
@ -82,7 +82,7 @@ const EmojiIconPicker: React.FC<Props> = ({
|
|||||||
setOpenColorPicker(false);
|
setOpenColorPicker(false);
|
||||||
}}
|
}}
|
||||||
className={`-my-1 w-1/2 border-b pb-2 text-center text-sm font-medium outline-none transition-colors ${
|
className={`-my-1 w-1/2 border-b pb-2 text-center text-sm font-medium outline-none transition-colors ${
|
||||||
selected ? "border-theme" : "border-transparent"
|
selected ? "border-theme text-theme" : "border-transparent text-gray-500"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{tab.title}
|
{tab.title}
|
||||||
@ -95,12 +95,12 @@ const EmojiIconPicker: React.FC<Props> = ({
|
|||||||
<Tab.Panel>
|
<Tab.Panel>
|
||||||
{recentEmojis.length > 0 && (
|
{recentEmojis.length > 0 && (
|
||||||
<div className="py-2">
|
<div className="py-2">
|
||||||
{/* <h3 className="mb-2">Recent Emojis</h3> */}
|
<h3 className="mb-2 ml-1 text-xs text-gray-400">Recent</h3>
|
||||||
<div className="grid grid-cols-10">
|
<div className="grid grid-cols-8 gap-2">
|
||||||
{recentEmojis.map((emoji) => (
|
{recentEmojis.map((emoji) => (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="h-4 w-4 select-none text-sm hover:bg-hover-gray flex items-center justify-between"
|
className="h-4 w-4 select-none text-base hover:bg-hover-gray flex items-center justify-between"
|
||||||
key={emoji}
|
key={emoji}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onChange(emoji);
|
onChange(emoji);
|
||||||
@ -115,12 +115,11 @@ const EmojiIconPicker: React.FC<Props> = ({
|
|||||||
)}
|
)}
|
||||||
<hr className="w-full h-[1px] mb-2" />
|
<hr className="w-full h-[1px] mb-2" />
|
||||||
<div>
|
<div>
|
||||||
{/* <h3 className="mb-1">All Emojis</h3> */}
|
<div className="grid grid-cols-8 gap-x-2 gap-y-3">
|
||||||
<div className="grid grid-cols-10 gap-y-1">
|
|
||||||
{emojis.map((emoji) => (
|
{emojis.map((emoji) => (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="h-4 w-4 mb-1 select-none text-sm hover:bg-hover-gray flex items-center"
|
className="h-4 w-4 ml-1 select-none text-base hover:bg-hover-gray flex justify-center items-center"
|
||||||
key={emoji}
|
key={emoji}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onChange(emoji);
|
onChange(emoji);
|
||||||
@ -135,54 +134,53 @@ const EmojiIconPicker: React.FC<Props> = ({
|
|||||||
</div>
|
</div>
|
||||||
</Tab.Panel>
|
</Tab.Panel>
|
||||||
<div className="py-2">
|
<div className="py-2">
|
||||||
<div className="relative">
|
|
||||||
<div className="pb-2 flex items-center justify-between">
|
|
||||||
{[
|
|
||||||
"#D687FF",
|
|
||||||
"#F7AE59",
|
|
||||||
"#FF6B00",
|
|
||||||
"#8CC1FF",
|
|
||||||
"#FCBE1D",
|
|
||||||
"#18904F",
|
|
||||||
"#ADF672",
|
|
||||||
"#05C3FF",
|
|
||||||
"#000000",
|
|
||||||
].map((curCol) => (
|
|
||||||
<span
|
|
||||||
className="w-4 h-4 rounded-full cursor-pointer"
|
|
||||||
style={{ backgroundColor: curCol }}
|
|
||||||
onClick={() => setActiveColor(curCol)}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => setOpenColorPicker((prev) => !prev)}
|
|
||||||
className="flex items-center gap-1"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="w-4 h-4 rounded-full conical-gradient"
|
|
||||||
style={{ backgroundColor: activeColor }}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<TwitterPicker
|
|
||||||
className={`m-2 !absolute top-4 left-4 z-10 ${
|
|
||||||
openColorPicker ? "block" : "hidden"
|
|
||||||
}`}
|
|
||||||
color={activeColor}
|
|
||||||
onChange={(color) => {
|
|
||||||
setActiveColor(color.hex);
|
|
||||||
if (onIconColorChange) onIconColorChange(color.hex);
|
|
||||||
}}
|
|
||||||
triangle="hide"
|
|
||||||
width="205px"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr className="w-full h-[1px] mb-1" />
|
|
||||||
<Tab.Panel className="flex h-full w-full flex-col justify-center">
|
<Tab.Panel className="flex h-full w-full flex-col justify-center">
|
||||||
<div className="grid grid-cols-10 mt-1 ml-1 gap-1">
|
<div className="relative">
|
||||||
|
<div className="pb-2 px-1 flex items-center justify-between">
|
||||||
|
{[
|
||||||
|
"#FF6B00",
|
||||||
|
"#8CC1FF",
|
||||||
|
"#FCBE1D",
|
||||||
|
"#18904F",
|
||||||
|
"#ADF672",
|
||||||
|
"#05C3FF",
|
||||||
|
"#000000",
|
||||||
|
].map((curCol) => (
|
||||||
|
<span
|
||||||
|
className="w-4 h-4 rounded-full cursor-pointer"
|
||||||
|
style={{ backgroundColor: curCol }}
|
||||||
|
onClick={() => setActiveColor(curCol)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setOpenColorPicker((prev) => !prev)}
|
||||||
|
className="flex items-center gap-1"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="w-4 h-4 rounded-full conical-gradient"
|
||||||
|
style={{ backgroundColor: activeColor }}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<TwitterPicker
|
||||||
|
className={`m-2 !absolute top-4 left-4 z-10 ${
|
||||||
|
openColorPicker ? "block" : "hidden"
|
||||||
|
}`}
|
||||||
|
color={activeColor}
|
||||||
|
onChange={(color) => {
|
||||||
|
setActiveColor(color.hex);
|
||||||
|
if (onIconColorChange) onIconColorChange(color.hex);
|
||||||
|
}}
|
||||||
|
triangle="hide"
|
||||||
|
width="205px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr className="w-full h-[1px] mb-1" />
|
||||||
|
|
||||||
|
<div className="grid grid-cols-8 mt-1 ml-1 gap-x-2 gap-y-3">
|
||||||
{icons.material_rounded.map((icon) => (
|
{icons.material_rounded.map((icon) => (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@ -195,7 +193,7 @@ const EmojiIconPicker: React.FC<Props> = ({
|
|||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
style={{ color: activeColor }}
|
style={{ color: activeColor }}
|
||||||
className="material-symbols-rounded text-base"
|
className="material-symbols-rounded text-lg"
|
||||||
>
|
>
|
||||||
{icon.name}
|
{icon.name}
|
||||||
</span>
|
</span>
|
||||||
|
@ -16,7 +16,7 @@ import AppLayout from "layouts/app-layout";
|
|||||||
import projectService from "services/project.service";
|
import projectService from "services/project.service";
|
||||||
// components
|
// components
|
||||||
import { DeleteProjectModal } from "components/project";
|
import { DeleteProjectModal } from "components/project";
|
||||||
import { ImageUploadModal } from "components/core";
|
import { ImagePickerPopover } from "components/core";
|
||||||
import EmojiIconPicker from "components/emoji-icon-picker";
|
import EmojiIconPicker from "components/emoji-icon-picker";
|
||||||
// hooks
|
// hooks
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
@ -157,17 +157,6 @@ const GeneralSettings: NextPage<UserAuth> = ({ isMember, isOwner, isViewer, isGu
|
|||||||
router.push(`/${workspaceSlug}/projects`);
|
router.push(`/${workspaceSlug}/projects`);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ImageUploadModal
|
|
||||||
isOpen={isImageUploadModalOpen}
|
|
||||||
onClose={() => setIsImageUploadModalOpen(false)}
|
|
||||||
onSuccess={(imageUrl) => {
|
|
||||||
setIsImageUploading(true);
|
|
||||||
setValue("cover_image", imageUrl);
|
|
||||||
setIsImageUploadModalOpen(false);
|
|
||||||
handleSubmit(onSubmit)().then(() => setIsImageUploading(false));
|
|
||||||
}}
|
|
||||||
value={watch("cover_image")}
|
|
||||||
/>
|
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="space-y-8 sm:space-y-12">
|
<div className="space-y-8 sm:space-y-12">
|
||||||
<div className="grid grid-cols-12 items-start gap-4 sm:gap-16">
|
<div className="grid grid-cols-12 items-start gap-4 sm:gap-16">
|
||||||
@ -241,23 +230,23 @@ const GeneralSettings: NextPage<UserAuth> = ({ isMember, isOwner, isViewer, isGu
|
|||||||
</div>
|
</div>
|
||||||
<div className="col-span-12 sm:col-span-6">
|
<div className="col-span-12 sm:col-span-6">
|
||||||
{watch("cover_image") ? (
|
{watch("cover_image") ? (
|
||||||
<div className="w-32 h-32 rounded border p-1">
|
<div className="w-full h-32 rounded border p-1">
|
||||||
<div className="w-full h-full relative rounded">
|
<div className="w-full h-full relative rounded">
|
||||||
<Image
|
<Image
|
||||||
src={watch("cover_image")!}
|
src={watch("cover_image")!}
|
||||||
alt={projectDetails?.name ?? "Cover image"}
|
alt={projectDetails?.name ?? "Cover image"}
|
||||||
objectFit="cover"
|
objectFit="cover"
|
||||||
layout="fill"
|
layout="fill"
|
||||||
|
className="rounded"
|
||||||
/>
|
/>
|
||||||
<div className="absolute bottom-1 w-full flex justify-center">
|
<div className="absolute bottom-0 w-full flex justify-end">
|
||||||
<button
|
<ImagePickerPopover
|
||||||
type="button"
|
label={"Change cover"}
|
||||||
disabled={isImageUploading}
|
onChange={(imageUrl) => {
|
||||||
onClick={() => setIsImageUploadModalOpen(true)}
|
setValue("cover_image", imageUrl);
|
||||||
className="bg-white rounded text-sm border-2 border-gray-300 text-gray-400 p-1 py-0.5"
|
}}
|
||||||
>
|
value={watch("cover_image")}
|
||||||
{isImageUploading ? "Uploading..." : "Change Cover"}
|
/>
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user