From 97b8fce043fdeabf48b0f75a888e2ebbec66a511 Mon Sep 17 00:00:00 2001 From: Janhvi Patil Date: Fri, 14 Jun 2024 17:15:13 +0530 Subject: [PATCH 1/5] feat: added base setup for settings page --- frontend/src/App.tsx | 5 +- .../feature/userSettings/UserSettings.tsx | 26 ++++++++ .../layout/Sidebar/SidebarFooter.tsx | 62 ++++++++++--------- 3 files changed, 62 insertions(+), 31 deletions(-) create mode 100644 frontend/src/components/feature/userSettings/UserSettings.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 43a875c5e..fbc134ea4 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -23,9 +23,10 @@ const router = createBrowserRouter( } > } /> import('./components/feature/saved-messages/SavedMessages')} /> + import('./components/feature/userSettings/UserSettings')} /> import('@/pages/ChatSpace')} /> - import('./pages/settings/Settings')}> + {/* import('./pages/settings/Settings')}> import('./pages/settings/Webhooks/WebhookList')} /> import('./pages/settings/Webhooks/CreateWebhook')} /> @@ -34,7 +35,7 @@ const router = createBrowserRouter( import('./pages/settings/ServerScripts/SchedulerEvents/CreateSchedulerEvent')} /> import('./pages/settings/ServerScripts/SchedulerEvents/ViewSchedulerEvent')} /> - + */} diff --git a/frontend/src/components/feature/userSettings/UserSettings.tsx b/frontend/src/components/feature/userSettings/UserSettings.tsx new file mode 100644 index 000000000..02766471d --- /dev/null +++ b/frontend/src/components/feature/userSettings/UserSettings.tsx @@ -0,0 +1,26 @@ +import { PageHeader } from '@/components/layout/Heading/PageHeader' +import { Box, Flex, Heading, Text } from '@radix-ui/themes' +import { BiChevronLeft } from 'react-icons/bi' +import { Link } from 'react-router-dom' + +const UserSettings = () => { + return ( + <> + + + + + + Settings + + + + + Make changes to your account. + + + + ) +} + +export const Component = UserSettings \ No newline at end of file diff --git a/frontend/src/components/layout/Sidebar/SidebarFooter.tsx b/frontend/src/components/layout/Sidebar/SidebarFooter.tsx index 5d5fd2c97..222e3a305 100644 --- a/frontend/src/components/layout/Sidebar/SidebarFooter.tsx +++ b/frontend/src/components/layout/Sidebar/SidebarFooter.tsx @@ -2,7 +2,7 @@ import { useContext, useState } from 'react' import { UserContext } from '../../../utils/auth/UserProvider' import { useUserData } from '@/hooks/useUserData' import { AddRavenUsers } from '@/components/feature/raven-users/AddRavenUsers' -import { DropdownMenu, Flex, IconButton, Link, Separator, Text } from '@radix-ui/themes' +import { DropdownMenu, Flex, IconButton, Separator, Text } from '@radix-ui/themes' import { BiDotsHorizontalRounded } from 'react-icons/bi' import { UserAvatar } from '@/components/common/UserAvatar' import { isSystemManager } from '@/utils/roles' @@ -15,6 +15,8 @@ import { SlSettings } from 'react-icons/sl' import { TbUsersPlus } from 'react-icons/tb' import PushNotificationToggle from '@/components/feature/userSettings/PushNotificationToggle' import { useIsUserActive } from '@/hooks/useIsUserActive' +import { MdOutlineExitToApp } from 'react-icons/md' +import { useNavigate } from 'react-router-dom' export const SidebarFooter = ({ isSettingsPage = false }: { isSettingsPage?: boolean }) => { @@ -30,12 +32,12 @@ export const SidebarFooter = ({ isSettingsPage = false }: { isSettingsPage?: boo const isActive = useIsUserActive(userData.name) const isDesktop = useIsDesktop() + const navigate = useNavigate() return ( {userData.full_name} - - - - - - - - - setUserStatusModalOpen(true)}> - Set custom status - - {canAddUsers && - - } - - - {canAddUsers && isDesktop && - setIsAddUserModalOpen(true)} className={'flex justify-normal gap-2'}> - Add users to Raven + + navigate('/channel/settings')}> + + + + + + + + + + + setUserStatusModalOpen(true)}> + Set custom status - } - {!isSettingsPage && isDesktop && + {canAddUsers && } + + {canAddUsers && isDesktop && + setIsAddUserModalOpen(true)} className={'flex justify-normal gap-2'}> + Add users to Raven + + } + {/* {!isSettingsPage && isDesktop && Settings - } - - Log Out - - - + } */} + + Log Out + + + + From a11805d5eacbccf547abcf9badba87c282a53a85 Mon Sep 17 00:00:00 2001 From: Janhvi Patil Date: Fri, 14 Jun 2024 17:29:18 +0530 Subject: [PATCH 2/5] chore: file restructure - user settings --- frontend/src/components/common/UserAvatar.tsx | 2 +- .../feature/chat/ChatMessage/MessageItem.tsx | 2 +- .../Renderers/TiptapRenderer/Mention.tsx | 2 +- .../SetUserAvailabilityMenu.tsx | 0 .../SetCustomStatusContent.tsx | 0 .../SetCustomStatusModal.tsx | 0 .../PushNotificationToggle.tsx | 0 .../{ => UploadImage}/DeleteImageModal.tsx | 0 .../{ => UploadImage}/FileUploadBox.tsx | 6 ++--- .../{ => UploadImage}/ImageUploader.tsx | 2 +- .../{ => UploadImage}/UploadImageModal.tsx | 2 +- .../feature/userSettings/UserSettings.tsx | 2 ++ .../userSettings/UserSettingsModal.tsx | 22 ------------------- .../userSettings/UserSettingsModalContent.tsx | 18 --------------- .../layout/Sidebar/SidebarFooter.tsx | 7 +++--- 15 files changed, 13 insertions(+), 52 deletions(-) rename frontend/src/components/feature/userSettings/{ => AvailabilityStatus}/SetUserAvailabilityMenu.tsx (100%) rename frontend/src/components/feature/userSettings/{ => CustomStatus}/SetCustomStatusContent.tsx (100%) rename frontend/src/components/feature/userSettings/{ => CustomStatus}/SetCustomStatusModal.tsx (100%) rename frontend/src/components/feature/userSettings/{ => PushNotifications}/PushNotificationToggle.tsx (100%) rename frontend/src/components/feature/userSettings/{ => UploadImage}/DeleteImageModal.tsx (100%) rename frontend/src/components/feature/userSettings/{ => UploadImage}/FileUploadBox.tsx (96%) rename frontend/src/components/feature/userSettings/{ => UploadImage}/ImageUploader.tsx (98%) rename frontend/src/components/feature/userSettings/{ => UploadImage}/UploadImageModal.tsx (97%) delete mode 100644 frontend/src/components/feature/userSettings/UserSettingsModal.tsx delete mode 100644 frontend/src/components/feature/userSettings/UserSettingsModalContent.tsx diff --git a/frontend/src/components/common/UserAvatar.tsx b/frontend/src/components/common/UserAvatar.tsx index 265309a2a..68a36ebd8 100644 --- a/frontend/src/components/common/UserAvatar.tsx +++ b/frontend/src/components/common/UserAvatar.tsx @@ -5,7 +5,7 @@ import { clsx } from 'clsx' import { generateAvatarColor } from '../feature/select-member/GenerateAvatarColor' import { RiRobot2Fill } from 'react-icons/ri' import { useMemo } from 'react' -import { AvailabilityStatus } from '../feature/userSettings/SetUserAvailabilityMenu' +import { AvailabilityStatus } from '../feature/userSettings/AvailabilityStatus/SetUserAvailabilityMenu' interface UserAvatarProps extends Partial { alt?: string, diff --git a/frontend/src/components/feature/chat/ChatMessage/MessageItem.tsx b/frontend/src/components/feature/chat/ChatMessage/MessageItem.tsx index dcb604a72..26c43f4b8 100644 --- a/frontend/src/components/feature/chat/ChatMessage/MessageItem.tsx +++ b/frontend/src/components/feature/chat/ChatMessage/MessageItem.tsx @@ -24,7 +24,7 @@ import { RiRobot2Fill } from 'react-icons/ri' import { useIsDesktop } from '@/hooks/useMediaQuery' import { useDoubleTap } from 'use-double-tap' import useOutsideClick from '@/hooks/useOutsideClick' -import { getStatusText } from '../../userSettings/SetUserAvailabilityMenu' +import { getStatusText } from '../../userSettings/AvailabilityStatus/SetUserAvailabilityMenu' interface MessageBlockProps { message: Message, diff --git a/frontend/src/components/feature/chat/ChatMessage/Renderers/TiptapRenderer/Mention.tsx b/frontend/src/components/feature/chat/ChatMessage/Renderers/TiptapRenderer/Mention.tsx index 6d9784969..a9194f738 100644 --- a/frontend/src/components/feature/chat/ChatMessage/Renderers/TiptapRenderer/Mention.tsx +++ b/frontend/src/components/feature/chat/ChatMessage/Renderers/TiptapRenderer/Mention.tsx @@ -1,5 +1,5 @@ import { UserAvatar } from '@/components/common/UserAvatar'; -import { getStatusText } from '@/components/feature/userSettings/SetUserAvailabilityMenu'; +import { getStatusText } from '@/components/feature/userSettings/AvailabilityStatus/SetUserAvailabilityMenu'; import { useGetUser } from '@/hooks/useGetUser'; import { useIsUserActive } from '@/hooks/useIsUserActive'; import { Flex, HoverCard, Link, Text } from '@radix-ui/themes'; diff --git a/frontend/src/components/feature/userSettings/SetUserAvailabilityMenu.tsx b/frontend/src/components/feature/userSettings/AvailabilityStatus/SetUserAvailabilityMenu.tsx similarity index 100% rename from frontend/src/components/feature/userSettings/SetUserAvailabilityMenu.tsx rename to frontend/src/components/feature/userSettings/AvailabilityStatus/SetUserAvailabilityMenu.tsx diff --git a/frontend/src/components/feature/userSettings/SetCustomStatusContent.tsx b/frontend/src/components/feature/userSettings/CustomStatus/SetCustomStatusContent.tsx similarity index 100% rename from frontend/src/components/feature/userSettings/SetCustomStatusContent.tsx rename to frontend/src/components/feature/userSettings/CustomStatus/SetCustomStatusContent.tsx diff --git a/frontend/src/components/feature/userSettings/SetCustomStatusModal.tsx b/frontend/src/components/feature/userSettings/CustomStatus/SetCustomStatusModal.tsx similarity index 100% rename from frontend/src/components/feature/userSettings/SetCustomStatusModal.tsx rename to frontend/src/components/feature/userSettings/CustomStatus/SetCustomStatusModal.tsx diff --git a/frontend/src/components/feature/userSettings/PushNotificationToggle.tsx b/frontend/src/components/feature/userSettings/PushNotifications/PushNotificationToggle.tsx similarity index 100% rename from frontend/src/components/feature/userSettings/PushNotificationToggle.tsx rename to frontend/src/components/feature/userSettings/PushNotifications/PushNotificationToggle.tsx diff --git a/frontend/src/components/feature/userSettings/DeleteImageModal.tsx b/frontend/src/components/feature/userSettings/UploadImage/DeleteImageModal.tsx similarity index 100% rename from frontend/src/components/feature/userSettings/DeleteImageModal.tsx rename to frontend/src/components/feature/userSettings/UploadImage/DeleteImageModal.tsx diff --git a/frontend/src/components/feature/userSettings/FileUploadBox.tsx b/frontend/src/components/feature/userSettings/UploadImage/FileUploadBox.tsx similarity index 96% rename from frontend/src/components/feature/userSettings/FileUploadBox.tsx rename to frontend/src/components/feature/userSettings/UploadImage/FileUploadBox.tsx index 01c49f942..2f32733b6 100644 --- a/frontend/src/components/feature/userSettings/FileUploadBox.tsx +++ b/frontend/src/components/feature/userSettings/UploadImage/FileUploadBox.tsx @@ -3,12 +3,12 @@ import { FlexProps } from "@radix-ui/themes/dist/cjs/components/flex"; import { forwardRef, useImperativeHandle, useState } from "react"; import { Accept, useDropzone } from "react-dropzone"; import { toast } from "sonner"; -import { CustomFile } from "../file-upload/FileDrop"; -import { FileUploadProgress } from "../chat/ChatInput/FileInput/useFileUpload"; -import { getFileSize } from "../file-upload/FileListItem"; import { useGetFilePreviewUrl } from "@/hooks/useGetFilePreviewUrl"; import { Loader } from "@/components/common/Loader"; import { BiTrash } from "react-icons/bi"; +import { CustomFile } from "../../file-upload/FileDrop"; +import { FileUploadProgress } from "../../chat/ChatInput/FileInput/useFileUpload"; +import { getFileSize } from "../../file-upload/FileListItem"; export interface FileUploadBoxProps extends FlexProps { /** File to be uploaded */ diff --git a/frontend/src/components/feature/userSettings/ImageUploader.tsx b/frontend/src/components/feature/userSettings/UploadImage/ImageUploader.tsx similarity index 98% rename from frontend/src/components/feature/userSettings/ImageUploader.tsx rename to frontend/src/components/feature/userSettings/UploadImage/ImageUploader.tsx index 98a1b5430..f7a501018 100644 --- a/frontend/src/components/feature/userSettings/ImageUploader.tsx +++ b/frontend/src/components/feature/userSettings/UploadImage/ImageUploader.tsx @@ -6,7 +6,7 @@ import { DIALOG_CONTENT_CLASS } from "@/utils/layout/dialog" import { DeleteImageModal } from "./DeleteImageModal" import { useUserData } from "@/hooks/useUserData" import { toast } from "sonner" -import { CustomFile } from "../file-upload/FileDrop" +import { CustomFile } from "../../file-upload/FileDrop" import { UploadImageModal } from "./UploadImageModal" import { BiTrash } from "react-icons/bi" import { LuUpload } from "react-icons/lu" diff --git a/frontend/src/components/feature/userSettings/UploadImageModal.tsx b/frontend/src/components/feature/userSettings/UploadImage/UploadImageModal.tsx similarity index 97% rename from frontend/src/components/feature/userSettings/UploadImageModal.tsx rename to frontend/src/components/feature/userSettings/UploadImage/UploadImageModal.tsx index dc4cb8f0c..31c407955 100644 --- a/frontend/src/components/feature/userSettings/UploadImageModal.tsx +++ b/frontend/src/components/feature/userSettings/UploadImage/UploadImageModal.tsx @@ -1,7 +1,7 @@ import { Loader } from "@/components/common/Loader" import { useUserData } from "@/hooks/useUserData" import { Button, Dialog, Flex } from "@radix-ui/themes" -import { CustomFile } from "../file-upload/FileDrop" +import { CustomFile } from "../../file-upload/FileDrop" import { ErrorBanner } from "@/components/layout/AlertBanner" import { useState } from "react" import { FrappeError, useFrappeFileUpload } from "frappe-react-sdk" diff --git a/frontend/src/components/feature/userSettings/UserSettings.tsx b/frontend/src/components/feature/userSettings/UserSettings.tsx index 02766471d..afef36240 100644 --- a/frontend/src/components/feature/userSettings/UserSettings.tsx +++ b/frontend/src/components/feature/userSettings/UserSettings.tsx @@ -2,6 +2,7 @@ import { PageHeader } from '@/components/layout/Heading/PageHeader' import { Box, Flex, Heading, Text } from '@radix-ui/themes' import { BiChevronLeft } from 'react-icons/bi' import { Link } from 'react-router-dom' +import { ImageUploader } from './UploadImage/ImageUploader' const UserSettings = () => { return ( @@ -17,6 +18,7 @@ const UserSettings = () => { Make changes to your account. + diff --git a/frontend/src/components/feature/userSettings/UserSettingsModal.tsx b/frontend/src/components/feature/userSettings/UserSettingsModal.tsx deleted file mode 100644 index c9a2372c6..000000000 --- a/frontend/src/components/feature/userSettings/UserSettingsModal.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { Loader } from "@/components/common/Loader" -import { DIALOG_CONTENT_CLASS } from "@/utils/layout/dialog" -import { Dialog, Flex } from "@radix-ui/themes" -import { lazy, Suspense } from "react" - -const UserSettingsModalContent = lazy(() => import('./UserSettingsModalContent')) - -export const UserSettingsModal = ({ isOpen, onOpenChange }: { isOpen: boolean, onOpenChange: (open: boolean) => void }) => { - - const onClose = () => { - onOpenChange(false) - } - - return - - }> - - - - - -} \ No newline at end of file diff --git a/frontend/src/components/feature/userSettings/UserSettingsModalContent.tsx b/frontend/src/components/feature/userSettings/UserSettingsModalContent.tsx deleted file mode 100644 index 29017f51c..000000000 --- a/frontend/src/components/feature/userSettings/UserSettingsModalContent.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Dialog } from "@radix-ui/themes" -import { ImageUploader } from "./ImageUploader" - -const UserSettingsModalContent = ({ onClose }: { onClose: VoidFunction }) => { - - return ( -
- User Settings - - Set your preferences and manage your account - - - -
- ) -} - -export default UserSettingsModalContent \ No newline at end of file diff --git a/frontend/src/components/layout/Sidebar/SidebarFooter.tsx b/frontend/src/components/layout/Sidebar/SidebarFooter.tsx index 222e3a305..70755a129 100644 --- a/frontend/src/components/layout/Sidebar/SidebarFooter.tsx +++ b/frontend/src/components/layout/Sidebar/SidebarFooter.tsx @@ -7,16 +7,16 @@ import { BiDotsHorizontalRounded } from 'react-icons/bi' import { UserAvatar } from '@/components/common/UserAvatar' import { isSystemManager } from '@/utils/roles' import { BsEmojiSmile } from 'react-icons/bs' -import { SetCustomStatusModal } from '@/components/feature/userSettings/SetCustomStatusModal' -import { SetUserAvailabilityMenu } from '@/components/feature/userSettings/SetUserAvailabilityMenu' import useCurrentRavenUser from '@/hooks/useCurrentRavenUser' import { useIsDesktop } from '@/hooks/useMediaQuery' import { SlSettings } from 'react-icons/sl' import { TbUsersPlus } from 'react-icons/tb' -import PushNotificationToggle from '@/components/feature/userSettings/PushNotificationToggle' +import PushNotificationToggle from '@/components/feature/userSettings/PushNotifications/PushNotificationToggle' import { useIsUserActive } from '@/hooks/useIsUserActive' import { MdOutlineExitToApp } from 'react-icons/md' import { useNavigate } from 'react-router-dom' +import { SetUserAvailabilityMenu } from '@/components/feature/userSettings/AvailabilityStatus/SetUserAvailabilityMenu' +import { SetCustomStatusModal } from '@/components/feature/userSettings/CustomStatus/SetCustomStatusModal' export const SidebarFooter = ({ isSettingsPage = false }: { isSettingsPage?: boolean }) => { @@ -87,7 +87,6 @@ export const SidebarFooter = ({ isSettingsPage = false }: { isSettingsPage?: boo - {/* */} From 1cbeb93f79d3c6003adf7090882b1b3662db2d0b Mon Sep 17 00:00:00 2001 From: Janhvi Patil Date: Mon, 17 Jun 2024 10:58:31 +0530 Subject: [PATCH 3/5] feat: added settings sidebar and settings page to add users --- frontend/src/App.tsx | 8 +- .../feature/raven-users/AddRavenUsers.tsx | 22 ------ .../{UserSettings.tsx => Settings.tsx} | 17 ++-- .../feature/userSettings/SettingsSidebar.tsx | 79 +++++++++++++++++++ .../UploadImage/ImageUploader.tsx | 9 ++- .../userSettings/UserProfile/UserProfile.tsx | 77 ++++++++++++++++++ .../Users/AddUsers.tsx} | 51 ++++++------ .../Users}/UsersTable.tsx | 0 .../layout/Sidebar/SidebarFooter.tsx | 16 +--- frontend/src/pages/AddRavenUsersPage.tsx | 2 +- 10 files changed, 207 insertions(+), 74 deletions(-) delete mode 100644 frontend/src/components/feature/raven-users/AddRavenUsers.tsx rename frontend/src/components/feature/userSettings/{UserSettings.tsx => Settings.tsx} (63%) create mode 100644 frontend/src/components/feature/userSettings/SettingsSidebar.tsx create mode 100644 frontend/src/components/feature/userSettings/UserProfile/UserProfile.tsx rename frontend/src/components/feature/{raven-users/AddRavenUsersContent.tsx => userSettings/Users/AddUsers.tsx} (82%) rename frontend/src/components/feature/{raven-users => userSettings/Users}/UsersTable.tsx (100%) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index fbc134ea4..34aec2448 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -9,6 +9,7 @@ import { ThemeProvider } from './ThemeProvider' import { Toaster } from 'sonner' import { useStickyState } from './hooks/useStickyState' import MobileTabsPage from './pages/MobileTabsPage' +import { UserProfile } from './components/feature/userSettings/UserProfile/UserProfile' const router = createBrowserRouter( @@ -23,7 +24,12 @@ const router = createBrowserRouter( } > } /> import('./components/feature/saved-messages/SavedMessages')} /> - import('./components/feature/userSettings/UserSettings')} /> + import('./components/feature/userSettings/Settings')}> + } /> + } /> + import('./components/feature/userSettings/Users/AddUsers')} /> + {/* import('./components/feature/userSettings/Bots')} /> */} + import('@/pages/ChatSpace')} /> {/* import('./pages/settings/Settings')}> diff --git a/frontend/src/components/feature/raven-users/AddRavenUsers.tsx b/frontend/src/components/feature/raven-users/AddRavenUsers.tsx deleted file mode 100644 index 5010384d8..000000000 --- a/frontend/src/components/feature/raven-users/AddRavenUsers.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { Loader } from "@/components/common/Loader" -import { DIALOG_CONTENT_CLASS } from "@/utils/layout/dialog" -import { Dialog, Flex } from "@radix-ui/themes" -import { lazy, Suspense } from "react" - -const AddRavenUsersContent = lazy(() => import("./AddRavenUsersContent")) - -export const AddRavenUsers = ({ isOpen, onOpenChange }: any) => { - - const onClose = () => { - onOpenChange(false) - } - return - - }> - - - - - - -} \ No newline at end of file diff --git a/frontend/src/components/feature/userSettings/UserSettings.tsx b/frontend/src/components/feature/userSettings/Settings.tsx similarity index 63% rename from frontend/src/components/feature/userSettings/UserSettings.tsx rename to frontend/src/components/feature/userSettings/Settings.tsx index afef36240..816e8a684 100644 --- a/frontend/src/components/feature/userSettings/UserSettings.tsx +++ b/frontend/src/components/feature/userSettings/Settings.tsx @@ -1,8 +1,9 @@ import { PageHeader } from '@/components/layout/Heading/PageHeader' -import { Box, Flex, Heading, Text } from '@radix-ui/themes' +import { Box, Flex, Heading } from '@radix-ui/themes' import { BiChevronLeft } from 'react-icons/bi' import { Link } from 'react-router-dom' -import { ImageUploader } from './UploadImage/ImageUploader' +import { SettingsSidebar } from './SettingsSidebar' +import { Outlet } from "react-router-dom" const UserSettings = () => { return ( @@ -15,12 +16,12 @@ const UserSettings = () => { Settings - - - Make changes to your account. - - - + + + + + + ) } diff --git a/frontend/src/components/feature/userSettings/SettingsSidebar.tsx b/frontend/src/components/feature/userSettings/SettingsSidebar.tsx new file mode 100644 index 000000000..1d419520c --- /dev/null +++ b/frontend/src/components/feature/userSettings/SettingsSidebar.tsx @@ -0,0 +1,79 @@ +import { useIsDesktop } from '@/hooks/useMediaQuery' +import { Box, Flex, Separator, Text } from '@radix-ui/themes' +import clsx from 'clsx' +import { PropsWithChildren, createElement } from 'react' +import { IconType } from 'react-icons' +import { BiBuildings } from 'react-icons/bi' +import { BsBoxes } from 'react-icons/bs' +import { LuUserCircle2 } from 'react-icons/lu' +import { NavLink } from 'react-router-dom' + +export const SettingsSidebar = () => { + + const isDesktop = useIsDesktop() + + return ( + + + + + {/* */} + + + + + + + {/* + + + + + + */} + + + ) +} + +const SettingsGroup = ({ title, icon, children }: PropsWithChildren<{ title: string, icon: IconType }>) => { + return + + {children} + +} + +const SettingsSeparator = () => { + return +} +const SettingsSidebarGroupHeader = ({ title, icon }: { title: string, icon: IconType }) => { + return ( + + {createElement(icon, { size: 15 })} + {title} + + ) +} + +const SettingsSidebarItem = ({ title, to, end }: { title: string, to: string, end?: boolean }) => { + + const activeClass = "bg-slate-3 dark:bg-slate-4 hover:bg-slate-3 hover:dark:bg-slate-4" + + return ( + + {({ isActive }) => { + return ( + + + {title} + + + ) + }} + + ) +} \ No newline at end of file diff --git a/frontend/src/components/feature/userSettings/UploadImage/ImageUploader.tsx b/frontend/src/components/feature/userSettings/UploadImage/ImageUploader.tsx index f7a501018..863ce19d1 100644 --- a/frontend/src/components/feature/userSettings/UploadImage/ImageUploader.tsx +++ b/frontend/src/components/feature/userSettings/UploadImage/ImageUploader.tsx @@ -8,7 +8,6 @@ import { useUserData } from "@/hooks/useUserData" import { toast } from "sonner" import { CustomFile } from "../../file-upload/FileDrop" import { UploadImageModal } from "./UploadImageModal" -import { BiTrash } from "react-icons/bi" import { LuUpload } from "react-icons/lu" interface ImageUploaderProps { @@ -72,7 +71,9 @@ export const UploadImage = ({ open, setOpen, uploadImage }: { open: boolean, set return ( - + @@ -92,8 +93,8 @@ export const DeleteImage = ({ open, setOpen }: { open: boolean, setOpen: (open: return ( - diff --git a/frontend/src/components/feature/userSettings/UserProfile/UserProfile.tsx b/frontend/src/components/feature/userSettings/UserProfile/UserProfile.tsx new file mode 100644 index 000000000..b39bb73d7 --- /dev/null +++ b/frontend/src/components/feature/userSettings/UserProfile/UserProfile.tsx @@ -0,0 +1,77 @@ +import { ErrorText, Label } from "@/components/common/Form" +import { Loader } from "@/components/common/Loader" +import { ErrorBanner } from "@/components/layout/AlertBanner" +import { useUserData } from "@/hooks/useUserData" +import { Box, Button, Flex, TextField, Text } from "@radix-ui/themes" +import { useFrappeUpdateDoc } from "frappe-react-sdk" +import { FormProvider, useForm } from "react-hook-form" +import { toast } from 'sonner' +import { ImageUploader } from "../UploadImage/ImageUploader" + +type UserProfile = { + full_name?: string, + user_image?: string, +} + +export const UserProfile = () => { + + const methods = useForm() + const { register, handleSubmit, formState: { errors } } = methods + const { updateDoc, loading: updatingDoc, error } = useFrappeUpdateDoc() + + const currentUser = useUserData() + + const onSubmit = (data: UserProfile) => { + updateDoc("Raven User", currentUser?.name ?? null, { + full_name: data.full_name, + user_image: data.user_image + }).then(() => { + toast.success("Profile updated") + }).catch(() => { + toast.error("Profile update failed") + }) + } + + return ( + + +
+ + + + + Your Profile + + + + + + + + + {errors?.full_name && {errors.full_name?.message}} + + + + + + +
+
+
+ ) +} \ No newline at end of file diff --git a/frontend/src/components/feature/raven-users/AddRavenUsersContent.tsx b/frontend/src/components/feature/userSettings/Users/AddUsers.tsx similarity index 82% rename from frontend/src/components/feature/raven-users/AddRavenUsersContent.tsx rename to frontend/src/components/feature/userSettings/Users/AddUsers.tsx index 0058b696c..6e450aa35 100644 --- a/frontend/src/components/feature/raven-users/AddRavenUsersContent.tsx +++ b/frontend/src/components/feature/userSettings/Users/AddUsers.tsx @@ -3,24 +3,26 @@ import { usePaginationWithDoctype } from "@/hooks/usePagination" import { User } from "@/types/Core/User" import { Filter, useFrappeGetDocList, useFrappePostCall, useSWRConfig } from "frappe-react-sdk" import { ChangeEvent, useContext, useState } from "react" -import { Sort } from "../sorting" -import { PageLengthSelector } from "../pagination/PageLengthSelector" -import { PageSelector } from "../pagination/PageSelector" import { ErrorBanner } from "@/components/layout/AlertBanner" import { TableLoader } from "@/components/layout/Loaders/TableLoader" -import { UsersTable } from "./UsersTable" import { UserListContext } from "@/utils/users/UserListProvider" -import { Button, Dialog, Em, Flex, Strong, Text, TextField } from "@radix-ui/themes" +import { Button, Flex, Strong, Text, TextField } from "@radix-ui/themes" import { Loader } from "@/components/common/Loader" import { BiSearch } from "react-icons/bi" import { ErrorCallout } from "@/components/common/Callouts/ErrorCallouts" import { toast } from "sonner" +import { Sort } from "../../sorting" +import { PageLengthSelector } from "../../pagination/PageLengthSelector" +import { PageSelector } from "../../pagination/PageSelector" +import { UsersTable } from "./UsersTable" +import { isSystemManager } from "@/utils/roles" interface AddUsersResponse { failed_users: User[], success_users: User[] } -const AddRavenUsersContent = ({ onClose }: { onClose: VoidFunction }) => { + +const AddUsers = () => { const { mutate } = useSWRConfig() const [searchText, setSearchText] = useState("") @@ -68,7 +70,6 @@ const AddRavenUsersContent = ({ onClose }: { onClose: VoidFunction }) => { mutate('raven.api.raven_users.get_list') if (res.message.failed_users.length === 0) { - onClose() setSelected([]) } else { setFailedUsers(res.message.failed_users) @@ -78,16 +79,29 @@ const AddRavenUsersContent = ({ onClose }: { onClose: VoidFunction }) => { } } + const canAddRavenUsers = isSystemManager() + return ( -
- Add users to Raven + + + + + Add users to Raven + Only System managers have the ability to add users; users you add will be given the "Raven User" role. + + + - + + placeholder='Search for user'> @@ -132,19 +146,8 @@ const AddRavenUsersContent = ({ onClose }: { onClose: VoidFunction }) => { {data && data.length !== 0 && } - - - - - - -
+ ) } -export default AddRavenUsersContent \ No newline at end of file +export const Component = AddUsers \ No newline at end of file diff --git a/frontend/src/components/feature/raven-users/UsersTable.tsx b/frontend/src/components/feature/userSettings/Users/UsersTable.tsx similarity index 100% rename from frontend/src/components/feature/raven-users/UsersTable.tsx rename to frontend/src/components/feature/userSettings/Users/UsersTable.tsx diff --git a/frontend/src/components/layout/Sidebar/SidebarFooter.tsx b/frontend/src/components/layout/Sidebar/SidebarFooter.tsx index 70755a129..6124357c8 100644 --- a/frontend/src/components/layout/Sidebar/SidebarFooter.tsx +++ b/frontend/src/components/layout/Sidebar/SidebarFooter.tsx @@ -1,33 +1,27 @@ import { useContext, useState } from 'react' import { UserContext } from '../../../utils/auth/UserProvider' import { useUserData } from '@/hooks/useUserData' -import { AddRavenUsers } from '@/components/feature/raven-users/AddRavenUsers' import { DropdownMenu, Flex, IconButton, Separator, Text } from '@radix-ui/themes' import { BiDotsHorizontalRounded } from 'react-icons/bi' import { UserAvatar } from '@/components/common/UserAvatar' -import { isSystemManager } from '@/utils/roles' import { BsEmojiSmile } from 'react-icons/bs' import useCurrentRavenUser from '@/hooks/useCurrentRavenUser' import { useIsDesktop } from '@/hooks/useMediaQuery' import { SlSettings } from 'react-icons/sl' -import { TbUsersPlus } from 'react-icons/tb' -import PushNotificationToggle from '@/components/feature/userSettings/PushNotifications/PushNotificationToggle' import { useIsUserActive } from '@/hooks/useIsUserActive' import { MdOutlineExitToApp } from 'react-icons/md' import { useNavigate } from 'react-router-dom' import { SetUserAvailabilityMenu } from '@/components/feature/userSettings/AvailabilityStatus/SetUserAvailabilityMenu' import { SetCustomStatusModal } from '@/components/feature/userSettings/CustomStatus/SetCustomStatusModal' +import PushNotificationToggle from '@/components/feature/userSettings/PushNotifications/PushNotificationToggle' export const SidebarFooter = ({ isSettingsPage = false }: { isSettingsPage?: boolean }) => { const userData = useUserData() const { logout } = useContext(UserContext) - const [isAddUserModalOpen, setIsAddUserModalOpen] = useState(false) const [isUserStatusModalOpen, setUserStatusModalOpen] = useState(false) - const canAddUsers = isSystemManager() - const { myProfile } = useCurrentRavenUser() const isActive = useIsUserActive(userData.name) @@ -64,13 +58,7 @@ export const SidebarFooter = ({ isSettingsPage = false }: { isSettingsPage?: boo setUserStatusModalOpen(true)}> Set custom status - {canAddUsers && } - {canAddUsers && isDesktop && - setIsAddUserModalOpen(true)} className={'flex justify-normal gap-2'}> - Add users to Raven - - } {/* {!isSettingsPage && isDesktop && @@ -78,6 +66,7 @@ export const SidebarFooter = ({ isSettingsPage = false }: { isSettingsPage?: boo } */} + Log Out @@ -88,7 +77,6 @@ export const SidebarFooter = ({ isSettingsPage = false }: { isSettingsPage?: boo - ) diff --git a/frontend/src/pages/AddRavenUsersPage.tsx b/frontend/src/pages/AddRavenUsersPage.tsx index ab81ee99a..cf2f4558f 100644 --- a/frontend/src/pages/AddRavenUsersPage.tsx +++ b/frontend/src/pages/AddRavenUsersPage.tsx @@ -8,7 +8,6 @@ import { ChangeEvent, useContext, useState } from 'react' import { FaInfo } from 'react-icons/fa' import { PageLengthSelector } from '@/components/feature/pagination/PageLengthSelector' import { PageSelector } from '@/components/feature/pagination/PageSelector' -import { UsersTable } from '@/components/feature/raven-users/UsersTable' import { Sort } from '@/components/feature/sorting' import { ErrorBanner } from '@/components/layout/AlertBanner' import { TableLoader } from '@/components/layout/Loaders/TableLoader' @@ -17,6 +16,7 @@ import { UserContext } from '@/utils/auth/UserProvider' import { Loader } from '@/components/common/Loader' import { toast } from 'sonner' import { User } from '@/types/Core/User' +import { UsersTable } from '@/components/feature/userSettings/Users/UsersTable' const AddRavenUsersPage = () => { From 281dac5e645cbcf7f7c951da8ba4e2216fca0734 Mon Sep 17 00:00:00 2001 From: Janhvi Patil Date: Tue, 18 Jun 2024 11:43:47 +0530 Subject: [PATCH 4/5] feat: updated styles for user profile page --- frontend/src/App.tsx | 2 +- .../feature/userSettings/Settings.tsx | 29 ---- .../UploadImage/DeleteImageModal.tsx | 14 +- .../UploadImage/ImageUploader.tsx | 58 ++++--- .../userSettings/UserProfile/UserProfile.tsx | 141 ++++++++++++++---- .../layout/Sidebar/SidebarFooter.tsx | 2 +- frontend/src/pages/settings/Settings.tsx | 23 ++- .../raven/doctype/raven_user/raven_user.json | 8 +- 8 files changed, 173 insertions(+), 104 deletions(-) delete mode 100644 frontend/src/components/feature/userSettings/Settings.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 34aec2448..4b69f1898 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -24,7 +24,7 @@ const router = createBrowserRouter( } > } /> import('./components/feature/saved-messages/SavedMessages')} /> - import('./components/feature/userSettings/Settings')}> + import('./pages/settings/Settings')}> } /> } /> import('./components/feature/userSettings/Users/AddUsers')} /> diff --git a/frontend/src/components/feature/userSettings/Settings.tsx b/frontend/src/components/feature/userSettings/Settings.tsx deleted file mode 100644 index 816e8a684..000000000 --- a/frontend/src/components/feature/userSettings/Settings.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { PageHeader } from '@/components/layout/Heading/PageHeader' -import { Box, Flex, Heading } from '@radix-ui/themes' -import { BiChevronLeft } from 'react-icons/bi' -import { Link } from 'react-router-dom' -import { SettingsSidebar } from './SettingsSidebar' -import { Outlet } from "react-router-dom" - -const UserSettings = () => { - return ( - <> - - - - - - Settings - - - - - - - - - - ) -} - -export const Component = UserSettings \ No newline at end of file diff --git a/frontend/src/components/feature/userSettings/UploadImage/DeleteImageModal.tsx b/frontend/src/components/feature/userSettings/UploadImage/DeleteImageModal.tsx index fce945189..6fca1d5fd 100644 --- a/frontend/src/components/feature/userSettings/UploadImage/DeleteImageModal.tsx +++ b/frontend/src/components/feature/userSettings/UploadImage/DeleteImageModal.tsx @@ -14,24 +14,24 @@ export const DeleteImageModal = ({ onClose }: DeleteImageModalProps) => { const { updateDoc, error, loading } = useFrappeUpdateDoc() const userData = useUserData() - const deleteImage = () => { + const removeImage = () => { updateDoc('Raven User', userData.name, { 'user_image': null }).then(() => { onClose() - toast.success("Image deleted successfully") + toast.success("Image removed successfully") }).catch(() => { - toast("Could not delete image") + toast("Could not remove image") }) } return ( <> - Delete Image + Remove Image - Are you sure you want to delete this image? + Are you sure you want to remove this image? @@ -41,9 +41,9 @@ export const DeleteImageModal = ({ onClose }: DeleteImageModalProps) => { - diff --git a/frontend/src/components/feature/userSettings/UploadImage/ImageUploader.tsx b/frontend/src/components/feature/userSettings/UploadImage/ImageUploader.tsx index 863ce19d1..c26ac3ca9 100644 --- a/frontend/src/components/feature/userSettings/UploadImage/ImageUploader.tsx +++ b/frontend/src/components/feature/userSettings/UploadImage/ImageUploader.tsx @@ -1,14 +1,16 @@ import { useFrappeUpdateDoc } from "frappe-react-sdk" import { Accept } from "react-dropzone" import { useState } from "react" -import { AlertDialog, Box, Button, Dialog, Flex } from "@radix-ui/themes" +import { AlertDialog, Box, Dialog, Flex, IconButton, Tooltip } from "@radix-ui/themes" import { DIALOG_CONTENT_CLASS } from "@/utils/layout/dialog" import { DeleteImageModal } from "./DeleteImageModal" import { useUserData } from "@/hooks/useUserData" import { toast } from "sonner" import { CustomFile } from "../../file-upload/FileDrop" import { UploadImageModal } from "./UploadImageModal" -import { LuUpload } from "react-icons/lu" +import { FiCamera } from "react-icons/fi" +import { BiSolidTrash } from "react-icons/bi" +import { UserAvatar, getInitials } from "@/components/common/UserAvatar" interface ImageUploaderProps { /** Takes input MIME type as 'key' & array of extensions as 'value'; empty array - all extensions supported */ @@ -39,29 +41,17 @@ export const ImageUploader = ({ icon, accept = { 'image/*': ['.jpeg', '.jpg', '. const [isDeleteImageModalOpen, setDeleteImageModalOpen] = useState(false) return ( - - - {userData.user_image && } - - + + + {userData.user_image ? {'User + : } - - + {userData.user_image && } + ) } - - -export interface ImagePreviewProps { - file: string -} - -export const ImagePreview = ({ file }: ImagePreviewProps) => { - return {'User -} - - export const UploadImage = ({ open, setOpen, uploadImage }: { open: boolean, setOpen: (open: boolean) => void, uploadImage: (file: CustomFile) => void }) => { const onClose = () => { @@ -70,11 +60,14 @@ export const UploadImage = ({ open, setOpen, uploadImage }: { open: boolean, set return ( - - - + + + + + + + @@ -82,8 +75,6 @@ export const UploadImage = ({ open, setOpen, uploadImage }: { open: boolean, set ) } - - export const DeleteImage = ({ open, setOpen }: { open: boolean, setOpen: (open: boolean) => void }) => { const onClose = () => { @@ -92,11 +83,14 @@ export const DeleteImage = ({ open, setOpen }: { open: boolean, setOpen: (open: return ( - - - + + + + + + + diff --git a/frontend/src/components/feature/userSettings/UserProfile/UserProfile.tsx b/frontend/src/components/feature/userSettings/UserProfile/UserProfile.tsx index b39bb73d7..8e2214a7f 100644 --- a/frontend/src/components/feature/userSettings/UserProfile/UserProfile.tsx +++ b/frontend/src/components/feature/userSettings/UserProfile/UserProfile.tsx @@ -1,16 +1,23 @@ import { ErrorText, Label } from "@/components/common/Form" import { Loader } from "@/components/common/Loader" import { ErrorBanner } from "@/components/layout/AlertBanner" -import { useUserData } from "@/hooks/useUserData" -import { Box, Button, Flex, TextField, Text } from "@radix-ui/themes" +import { Box, Button, Flex, TextField, Text, DropdownMenu, Card, IconButton, Separator } from "@radix-ui/themes" import { useFrappeUpdateDoc } from "frappe-react-sdk" import { FormProvider, useForm } from "react-hook-form" import { toast } from 'sonner' import { ImageUploader } from "../UploadImage/ImageUploader" +import { getStatusText } from "../AvailabilityStatus/SetUserAvailabilityMenu" +import useCurrentRavenUser from "@/hooks/useCurrentRavenUser" +import { useState } from "react" +import { GrPowerReset } from "react-icons/gr" +import { BiSmile } from "react-icons/bi" +import EmojiPicker from "@/components/common/EmojiPicker/EmojiPicker" type UserProfile = { full_name?: string, user_image?: string, + availability_status?: string, + custom_status?: string } export const UserProfile = () => { @@ -18,11 +25,12 @@ export const UserProfile = () => { const methods = useForm() const { register, handleSubmit, formState: { errors } } = methods const { updateDoc, loading: updatingDoc, error } = useFrappeUpdateDoc() + const { myProfile, mutate } = useCurrentRavenUser() - const currentUser = useUserData() + const [availabilityStatus, setAvailabilityStatus] = useState(myProfile?.availability_status ?? '') const onSubmit = (data: UserProfile) => { - updateDoc("Raven User", currentUser?.name ?? null, { + updateDoc("Raven User", myProfile?.name ?? null, { full_name: data.full_name, user_image: data.user_image }).then(() => { @@ -32,42 +40,123 @@ export const UserProfile = () => { }) } + const [isEmojiPickerOpen, setEmojiPickerOpen] = useState(false) + const onEmojiSelect = (emoji: string) => { + methods.setValue('custom_status', `${methods.getValues('custom_status')} ${emoji}`) + } + return ( +
- - Your Profile + + Profile + Manage your Raven profile + - - - - - - {errors?.full_name && {errors.full_name?.message}} - - + + + + + + + + + + + + + + + {errors?.full_name && {errors.full_name?.message}} + + + + + + + + + {getStatusText(availabilityStatus)} + + + setAvailabilityStatus('Available')}> + {getStatusText('Available')} + + setAvailabilityStatus('Away')}> + {getStatusText('Away')} + + setAvailabilityStatus('Do not disturb')}> + {getStatusText('Do not disturb')} + + setAvailabilityStatus('Invisible')}> + {getStatusText('Invisible')} + + setAvailabilityStatus('')}> + Reset + + + + + + + + + + + Share what you are up to + + + + - + + setEmojiPickerOpen(!isEmojiPickerOpen)} variant='ghost' color='gray'> + + + + + {errors.custom_status && {errors.custom_status.message}} + + {isEmojiPickerOpen && } + + + + +
diff --git a/frontend/src/components/layout/Sidebar/SidebarFooter.tsx b/frontend/src/components/layout/Sidebar/SidebarFooter.tsx index 6124357c8..e8858e750 100644 --- a/frontend/src/components/layout/Sidebar/SidebarFooter.tsx +++ b/frontend/src/components/layout/Sidebar/SidebarFooter.tsx @@ -44,7 +44,7 @@ export const SidebarFooter = ({ isSettingsPage = false }: { isSettingsPage?: boo {userData.full_name}
- navigate('/channel/settings')}> + navigate('/channel/settings/profile')}> diff --git a/frontend/src/pages/settings/Settings.tsx b/frontend/src/pages/settings/Settings.tsx index 3fb4ff48d..a63b5987c 100644 --- a/frontend/src/pages/settings/Settings.tsx +++ b/frontend/src/pages/settings/Settings.tsx @@ -1,15 +1,24 @@ -import { Sidebar } from "@/components/layout/Settings/SettingsSidebar" -import { Flex, Box } from "@radix-ui/themes" +import { SettingsSidebar } from '@/components/feature/userSettings/SettingsSidebar' +import { PageHeader } from '@/components/layout/Heading/PageHeader' +import { Box, Flex, Heading } from '@radix-ui/themes' +import { BiChevronLeft } from 'react-icons/bi' +import { Link } from 'react-router-dom' import { Outlet } from "react-router-dom" const Settings = () => { return ( <> - - - - - + + + + + + Settings + + + + + diff --git a/raven/raven/doctype/raven_user/raven_user.json b/raven/raven/doctype/raven_user/raven_user.json index 3df35c9a6..0f2f2c3f7 100644 --- a/raven/raven/doctype/raven_user/raven_user.json +++ b/raven/raven/doctype/raven_user/raven_user.json @@ -18,6 +18,7 @@ "html_xuuw", "pinned_channels_section", "pinned_channels", + "user_status_section", "availability_status", "custom_status" ], @@ -110,11 +111,16 @@ "fieldname": "custom_status", "fieldtype": "Data", "label": "Custom Status" + }, + { + "fieldname": "user_status_section", + "fieldtype": "Section Break", + "label": "User Status" } ], "image_field": "user_image", "links": [], - "modified": "2024-05-24 15:23:40.547992", + "modified": "2024-06-17 11:04:12.713868", "modified_by": "Administrator", "module": "Raven", "name": "Raven User", From 1e9fa4abeba490f2aa1664015d971fc1ecd45c8d Mon Sep 17 00:00:00 2001 From: Janhvi Patil Date: Fri, 21 Jun 2024 18:16:37 +0530 Subject: [PATCH 5/5] fix: image upload modal --- .../feature/userSettings/SettingsSidebar.tsx | 2 +- .../UploadImage/DeleteImageModal.tsx | 24 ++++++----- .../UploadImage/FileUploadBox.tsx | 21 +++++----- .../UploadImage/ImageUploader.tsx | 31 +++++++------- .../UploadImage/UploadImageModal.tsx | 9 ++--- .../userSettings/UserProfile/UserProfile.tsx | 40 ++++++++++++++----- .../layout/Sidebar/SidebarFooter.tsx | 4 +- raven/raven/doctype/raven_user/raven_user.py | 2 +- 8 files changed, 76 insertions(+), 57 deletions(-) diff --git a/frontend/src/components/feature/userSettings/SettingsSidebar.tsx b/frontend/src/components/feature/userSettings/SettingsSidebar.tsx index 1d419520c..844667388 100644 --- a/frontend/src/components/feature/userSettings/SettingsSidebar.tsx +++ b/frontend/src/components/feature/userSettings/SettingsSidebar.tsx @@ -22,7 +22,7 @@ export const SettingsSidebar = () => { - + {/* */} {/* diff --git a/frontend/src/components/feature/userSettings/UploadImage/DeleteImageModal.tsx b/frontend/src/components/feature/userSettings/UploadImage/DeleteImageModal.tsx index 6fca1d5fd..da78964cc 100644 --- a/frontend/src/components/feature/userSettings/UploadImage/DeleteImageModal.tsx +++ b/frontend/src/components/feature/userSettings/UploadImage/DeleteImageModal.tsx @@ -1,9 +1,9 @@ -import { useFrappeUpdateDoc } from 'frappe-react-sdk' -import { AlertDialog, Button, Flex, Text } from '@radix-ui/themes' -import { Loader } from '@/components/common/Loader' +import { useFrappePostCall } from 'frappe-react-sdk' import { toast } from 'sonner' +import { AlertDialog, Button, Flex, Text } from '@radix-ui/themes' import { ErrorBanner } from '@/components/layout/AlertBanner' -import { useUserData } from '@/hooks/useUserData' +import { Loader } from '@/components/common/Loader' +import useCurrentRavenUser from '@/hooks/useCurrentRavenUser' interface DeleteImageModalProps { onClose: () => void @@ -11,17 +11,19 @@ interface DeleteImageModalProps { export const DeleteImageModal = ({ onClose }: DeleteImageModalProps) => { - const { updateDoc, error, loading } = useFrappeUpdateDoc() - const userData = useUserData() + const { call, error, loading } = useFrappePostCall('frappe.client.set_value') + const { myProfile, mutate } = useCurrentRavenUser() const removeImage = () => { - updateDoc('Raven User', userData.name, { - 'user_image': null + call({ + doctype: 'Raven User', + name: myProfile?.name, + fieldname: 'user_image', + value: '' }).then(() => { + toast.success("User status updated") + mutate() onClose() - toast.success("Image removed successfully") - }).catch(() => { - toast("Could not remove image") }) } diff --git a/frontend/src/components/feature/userSettings/UploadImage/FileUploadBox.tsx b/frontend/src/components/feature/userSettings/UploadImage/FileUploadBox.tsx index 2f32733b6..66eacc71c 100644 --- a/frontend/src/components/feature/userSettings/UploadImage/FileUploadBox.tsx +++ b/frontend/src/components/feature/userSettings/UploadImage/FileUploadBox.tsx @@ -37,13 +37,12 @@ export const FileUploadBox = forwardRef((props: FileUploadBoxProps, ref) => { } const { getRootProps, getInputProps, open } = useDropzone({ - onDrop: (receivedFiles) => { + onDrop: (receivedFiles: File[]) => { if (receivedFiles.length > 0) { - onFileChange({ - ...receivedFiles[0], - fileID: receivedFiles[0].name + Date.now(), - uploadProgress: 0, - }) + const f: CustomFile = receivedFiles[0] as CustomFile + f.uploadProgress = 0 + f.fileID = f.name + Date.now() + onFileChange(f) } }, maxFiles: 1, @@ -116,8 +115,6 @@ interface FileItemProps { const FileItem = ({ file, removeFile, uploadProgress }: FileItemProps) => { - console.log('file', file) - const previewURL = useGetFilePreviewUrl(file) const fileSizeString = getFileSize(file) const isUploadComplete = uploadProgress?.[file.fileID]?.isComplete ?? false @@ -126,13 +123,13 @@ const FileItem = ({ file, removeFile, uploadProgress }: FileItemProps) => { return ( - + {previewURL && File preview} - - {file.name} - + + {file.name} + {fileSizeString} diff --git a/frontend/src/components/feature/userSettings/UploadImage/ImageUploader.tsx b/frontend/src/components/feature/userSettings/UploadImage/ImageUploader.tsx index c26ac3ca9..c5e984f12 100644 --- a/frontend/src/components/feature/userSettings/UploadImage/ImageUploader.tsx +++ b/frontend/src/components/feature/userSettings/UploadImage/ImageUploader.tsx @@ -1,16 +1,15 @@ -import { useFrappeUpdateDoc } from "frappe-react-sdk" +import { useFrappePostCall } from "frappe-react-sdk" import { Accept } from "react-dropzone" import { useState } from "react" import { AlertDialog, Box, Dialog, Flex, IconButton, Tooltip } from "@radix-ui/themes" import { DIALOG_CONTENT_CLASS } from "@/utils/layout/dialog" import { DeleteImageModal } from "./DeleteImageModal" -import { useUserData } from "@/hooks/useUserData" import { toast } from "sonner" -import { CustomFile } from "../../file-upload/FileDrop" import { UploadImageModal } from "./UploadImageModal" import { FiCamera } from "react-icons/fi" import { BiSolidTrash } from "react-icons/bi" import { UserAvatar, getInitials } from "@/components/common/UserAvatar" +import useCurrentRavenUser from "@/hooks/useCurrentRavenUser" interface ImageUploaderProps { /** Takes input MIME type as 'key' & array of extensions as 'value'; empty array - all extensions supported */ @@ -22,17 +21,21 @@ interface ImageUploaderProps { export const ImageUploader = ({ icon, accept = { 'image/*': ['.jpeg', '.jpg', '.png'] }, maxFileSize, ...props }: ImageUploaderProps) => { - const { updateDoc, error: updateDocError } = useFrappeUpdateDoc() - const userData = useUserData() + const { call, error } = useFrappePostCall('frappe.client.set_value') + const { myProfile, mutate } = useCurrentRavenUser() - const uploadImage = (file: CustomFile) => { + const uploadImage = (file: string) => { if (file) { - updateDoc('Raven User', userData.name, { - 'user_image': file + call({ + doctype: 'Raven User', + name: myProfile?.name, + fieldname: 'user_image', + value: file }).then(() => { toast("Image uploaded successfully.") + mutate() }).catch(() => { - toast(`There was an error while uploading the image. ${updateDocError ? updateDocError.exception ?? updateDocError.httpStatusText : null}`) + toast(`There was an error while uploading the image. ${error ? error.exception ?? error.httpStatusText : null}`) }) } } @@ -43,16 +46,16 @@ export const ImageUploader = ({ icon, accept = { 'image/*': ['.jpeg', '.jpg', '. return ( - {userData.user_image ? {'User - : } + {myProfile?.user_image ? {'User + : } - {userData.user_image && } + {myProfile?.user_image && } ) } -export const UploadImage = ({ open, setOpen, uploadImage }: { open: boolean, setOpen: (open: boolean) => void, uploadImage: (file: CustomFile) => void }) => { +export const UploadImage = ({ open, setOpen, uploadImage }: { open: boolean, setOpen: (open: boolean) => void, uploadImage: (file: string) => void }) => { const onClose = () => { setOpen(false) @@ -86,7 +89,7 @@ export const DeleteImage = ({ open, setOpen }: { open: boolean, setOpen: (open: + className={'absolute -right-2 bottom-6 rounded-md bg-white dark:bg-slate-4 shadow-md'}> diff --git a/frontend/src/components/feature/userSettings/UploadImage/UploadImageModal.tsx b/frontend/src/components/feature/userSettings/UploadImage/UploadImageModal.tsx index 31c407955..f3a5fc2b1 100644 --- a/frontend/src/components/feature/userSettings/UploadImage/UploadImageModal.tsx +++ b/frontend/src/components/feature/userSettings/UploadImage/UploadImageModal.tsx @@ -9,7 +9,7 @@ import { FileUploadBox } from "./FileUploadBox" interface UploadImageModalProps { onClose: () => void, - uploadImage: (file: CustomFile) => void + uploadImage: (file: string) => void } export const UploadImageModal = ({ onClose, uploadImage }: UploadImageModalProps) => { @@ -32,11 +32,10 @@ export const UploadImageModal = ({ onClose, uploadImage }: UploadImageModalProps docname: userData.name, fieldname: 'user_image', isPrivate: true, - }).then(() => { - uploadImage(file) + }).then((res) => { + uploadImage(res.file_url) onClose() - } - ).catch((e) => { + }).catch((e) => { setFileError(e) }) } diff --git a/frontend/src/components/feature/userSettings/UserProfile/UserProfile.tsx b/frontend/src/components/feature/userSettings/UserProfile/UserProfile.tsx index 8e2214a7f..f36b6c3f6 100644 --- a/frontend/src/components/feature/userSettings/UserProfile/UserProfile.tsx +++ b/frontend/src/components/feature/userSettings/UserProfile/UserProfile.tsx @@ -1,7 +1,7 @@ import { ErrorText, Label } from "@/components/common/Form" import { Loader } from "@/components/common/Loader" import { ErrorBanner } from "@/components/layout/AlertBanner" -import { Box, Button, Flex, TextField, Text, DropdownMenu, Card, IconButton, Separator } from "@radix-ui/themes" +import { Box, Button, Flex, TextField, Text, DropdownMenu, Card, IconButton, Separator, Popover } from "@radix-ui/themes" import { useFrappeUpdateDoc } from "frappe-react-sdk" import { FormProvider, useForm } from "react-hook-form" import { toast } from 'sonner' @@ -22,19 +22,29 @@ type UserProfile = { export const UserProfile = () => { - const methods = useForm() + const { myProfile, mutate } = useCurrentRavenUser() + const methods = useForm({ + defaultValues: { + full_name: myProfile?.full_name ?? '', + user_image: myProfile?.user_image ?? '', + availability_status: myProfile?.availability_status ?? '', + custom_status: myProfile?.custom_status ?? '' + } + }) const { register, handleSubmit, formState: { errors } } = methods const { updateDoc, loading: updatingDoc, error } = useFrappeUpdateDoc() - const { myProfile, mutate } = useCurrentRavenUser() const [availabilityStatus, setAvailabilityStatus] = useState(myProfile?.availability_status ?? '') const onSubmit = (data: UserProfile) => { updateDoc("Raven User", myProfile?.name ?? null, { full_name: data.full_name, - user_image: data.user_image + user_image: data.user_image, + availability_status: availabilityStatus, + custom_status: data.custom_status }).then(() => { toast.success("Profile updated") + mutate() }).catch(() => { toast.error("Profile update failed") }) @@ -66,13 +76,13 @@ export const UserProfile = () => { - + - + @@ -99,7 +109,9 @@ export const UserProfile = () => { - {getStatusText(availabilityStatus)} + {availabilityStatus ? getStatusText(availabilityStatus) : + Set Availability + } setAvailabilityStatus('Available')}> @@ -144,14 +156,20 @@ export const UserProfile = () => { aria-invalid={errors.custom_status ? 'true' : 'false'}> - setEmojiPickerOpen(!isEmojiPickerOpen)} variant='ghost' color='gray'> - - + + + setEmojiPickerOpen(!isEmojiPickerOpen)} variant='ghost' color='gray'> + + + + + + + {errors.custom_status && {errors.custom_status.message}} - {isEmojiPickerOpen && } diff --git a/frontend/src/components/layout/Sidebar/SidebarFooter.tsx b/frontend/src/components/layout/Sidebar/SidebarFooter.tsx index e8858e750..2612d4a92 100644 --- a/frontend/src/components/layout/Sidebar/SidebarFooter.tsx +++ b/frontend/src/components/layout/Sidebar/SidebarFooter.tsx @@ -40,8 +40,8 @@ export const SidebarFooter = ({ isSettingsPage = false }: { isSettingsPage?: boo - - {userData.full_name} + + {myProfile?.full_name ?? userData.full_name} navigate('/channel/settings/profile')}> diff --git a/raven/raven/doctype/raven_user/raven_user.py b/raven/raven/doctype/raven_user/raven_user.py index d00fbfd2f..71f3a280e 100644 --- a/raven/raven/doctype/raven_user/raven_user.py +++ b/raven/raven/doctype/raven_user/raven_user.py @@ -48,7 +48,7 @@ def validate(self): if self.type == "User" and not self.user: frappe.throw(_("User is mandatory")) - def before_save(self): + def before_insert(self): if self.type != "Bot": self.update_photo_from_user()