diff --git a/src/components/Apps/AppsDevModeNavBar.tsx b/src/components/Apps/AppsDevModeNavBar.tsx index 983aef3..15c22ab 100644 --- a/src/components/Apps/AppsDevModeNavBar.tsx +++ b/src/components/Apps/AppsDevModeNavBar.tsx @@ -1,51 +1,34 @@ -import React, { useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from 'react'; import { AppsNavBarLeft, AppsNavBarParent, AppsNavBarRight, -} from "./Apps-styles"; -import NavBack from "../../assets/svgs/NavBack.svg"; -import NavAdd from "../../assets/svgs/NavAdd.svg"; -import NavMoreMenu from "../../assets/svgs/NavMoreMenu.svg"; -import { - ButtonBase, - ListItemIcon, - ListItemText, - Menu, - MenuItem, - Tab, - Tabs, -} from "@mui/material"; +} from './Apps-styles'; +import { NavBack } from '../../assets/svgs/NavBack.tsx'; +import { NavAdd } from '../../assets/svgs/NavAdd.tsx'; +import { ButtonBase, Tab, Tabs } from '@mui/material'; import { executeEvent, subscribeToEvent, unsubscribeFromEvent, -} from "../../utils/events"; -import TabComponent from "./TabComponent"; -import PushPinIcon from "@mui/icons-material/PushPin"; -import RefreshIcon from "@mui/icons-material/Refresh"; -import { useRecoilState, useSetRecoilState } from "recoil"; -import { - navigationControllerAtom, - settingsLocalLastUpdatedAtom, - sortablePinnedAppsAtom, -} from "../../atoms/global"; -import { AppsDevModeTabComponent } from "./AppsDevModeTabComponent"; - - +} from '../../utils/events'; +import RefreshIcon from '@mui/icons-material/Refresh'; +import { useRecoilState } from 'recoil'; +import { navigationControllerAtom } from '../../atoms/global'; +import { AppsDevModeTabComponent } from './AppsDevModeTabComponent'; export const AppsDevModeNavBar = () => { const [tabs, setTabs] = useState([]); const [selectedTab, setSelectedTab] = useState(null); - const [navigationController, setNavigationController] = useRecoilState(navigationControllerAtom) + const [navigationController, setNavigationController] = useRecoilState( + navigationControllerAtom + ); const [isNewTabWindow, setIsNewTabWindow] = useState(false); const tabsRef = useRef(null); const [anchorEl, setAnchorEl] = useState(null); const open = Boolean(anchorEl); - - const handleClick = (event) => { setAnchorEl(event.currentTarget); }; @@ -57,27 +40,25 @@ export const AppsDevModeNavBar = () => { useEffect(() => { // Scroll to the last tab whenever the tabs array changes (e.g., when a new tab is added) if (tabsRef.current) { - const tabElements = tabsRef.current.querySelectorAll(".MuiTab-root"); + const tabElements = tabsRef.current.querySelectorAll('.MuiTab-root'); if (tabElements.length > 0) { const lastTab = tabElements[tabElements.length - 1]; lastTab.scrollIntoView({ - behavior: "smooth", - block: "nearest", - inline: "end", + behavior: 'smooth', + block: 'nearest', + inline: 'end', }); } } }, [tabs.length]); // Dependency on the number of tabs - - const isDisableBackButton = useMemo(()=> { - if(selectedTab && navigationController[selectedTab?.tabId]?.hasBack) return false - if(selectedTab && !navigationController[selectedTab?.tabId]?.hasBack) return true - return false - }, [navigationController, selectedTab]) - - - + const isDisableBackButton = useMemo(() => { + if (selectedTab && navigationController[selectedTab?.tabId]?.hasBack) + return false; + if (selectedTab && !navigationController[selectedTab?.tabId]?.hasBack) + return true; + return false; + }, [navigationController, selectedTab]); const setTabsToNav = (e) => { const { tabs, selectedTab, isNewTabWindow } = e.detail?.data; @@ -88,45 +69,43 @@ export const AppsDevModeNavBar = () => { }; useEffect(() => { - subscribeToEvent("appsDevModeSetTabsToNav", setTabsToNav); + subscribeToEvent('appsDevModeSetTabsToNav', setTabsToNav); return () => { - unsubscribeFromEvent("appsDevModeSetTabsToNav", setTabsToNav); + unsubscribeFromEvent('appsDevModeSetTabsToNav', setTabsToNav); }; }, []); - - - return ( { - executeEvent("devModeNavigateBack", selectedTab?.tabId); + executeEvent('devModeNavigateBack', selectedTab?.tabId); }} disabled={isDisableBackButton} sx={{ opacity: !isDisableBackButton ? 1 : 0.1, - cursor: !isDisableBackButton ? 'pointer': 'default' + cursor: !isDisableBackButton ? 'pointer' : 'default', }} > - + + { variant="scrollable" // Make tabs scrollable scrollButtons={true} sx={{ - "& .MuiTabs-indicator": { - backgroundColor: "white", + '& .MuiTabs-indicator': { + backgroundColor: 'white', }, maxHeight: `320px`, // Ensure the tabs container fits within the available space - overflow: "hidden", // Prevents overflow on small screens + overflow: 'hidden', // Prevents overflow on small screens }} > {tabs?.map((tab) => ( @@ -153,65 +132,61 @@ export const AppsDevModeNavBar = () => { /> } // Pass custom component sx={{ - "&.Mui-selected": { - color: "white", + '&.Mui-selected': { + color: 'white', }, - padding: "0px", - margin: "0px", - minWidth: "0px", - width: "50px", + padding: '0px', + margin: '0px', + minWidth: '0px', + width: '50px', }} /> ))} + {selectedTab && ( - { - setSelectedTab(null); - executeEvent("devModeNewTabWindow", {}); + sx={{ + gap: '10px', + flexDirection: 'column', }} > - { + setSelectedTab(null); + executeEvent('devModeNewTabWindow', {}); }} - src={NavAdd} - /> - - - { - if(selectedTab?.refreshFunc){ - selectedTab.refreshFunc(selectedTab?.tabId) - } else { - executeEvent("refreshApp", { - tabId: selectedTab?.tabId, - }); - } - - }} - > - + - - + + + { + if (selectedTab?.refreshFunc) { + selectedTab.refreshFunc(selectedTab?.tabId); + } else { + executeEvent('refreshApp', { + tabId: selectedTab?.tabId, + }); + } + }} + > + + + )} - - ); }; diff --git a/src/components/Apps/AppsLibrary.tsx b/src/components/Apps/AppsLibrary.tsx index 42a8658..e5cac4a 100644 --- a/src/components/Apps/AppsLibrary.tsx +++ b/src/components/Apps/AppsLibrary.tsx @@ -1,11 +1,4 @@ -import React, { - useCallback, - useContext, - useEffect, - useMemo, - useRef, - useState, -} from 'react'; +import { useContext, useEffect, useMemo, useRef, useState } from 'react'; import { AppCircle, AppCircleContainer, @@ -13,7 +6,6 @@ import { AppLibrarySubTitle, AppsContainer, AppsLibraryContainer, - AppsParent, AppsSearchContainer, AppsSearchLeft, AppsSearchRight, @@ -24,16 +16,22 @@ import { PublishQAppCTARight, PublishQAppDotsBG, } from './Apps-styles'; -import { Avatar, Box, ButtonBase, InputBase, styled } from '@mui/material'; -import { Add } from '@mui/icons-material'; +import { + Avatar, + Box, + ButtonBase, + InputBase, + styled, + useTheme, +} from '@mui/material'; import { MyContext, getBaseApiReact } from '../../App'; import LogoSelected from '../../assets/svgs/LogoSelected.svg'; import IconSearch from '../../assets/svgs/Search.svg'; import IconClearInput from '../../assets/svgs/ClearInput.svg'; import qappDevelopText from '../../assets/svgs/qappDevelopText.svg'; import qappDots from '../../assets/svgs/qappDots.svg'; +// import { Return } from './assets/svgs/Return.tsx'; import ReturnSVG from '../../assets/svgs/Return.svg'; - import { Spacer } from '../../common/Spacer'; import { AppInfoSnippet } from './AppInfoSnippet'; import { Virtuoso } from 'react-virtuoso'; @@ -43,6 +41,7 @@ import { MailIconImg, ShowMessageReturnButton, } from '../Group/Forum/Mail-styles'; + const officialAppList = [ 'q-tube', 'q-blog', @@ -59,8 +58,6 @@ const officialAppList = [ 'q-nodecontrol', ]; -// TODO: apply dark/light style - const ScrollerStyled = styled('div')({ // Hide scrollbar for WebKit browsers (Chrome, Safari) '::-webkit-scrollbar': { @@ -76,10 +73,10 @@ const ScrollerStyled = styled('div')({ }); const StyledVirtuosoContainer = styled('div')({ - position: 'relative', - width: '100%', display: 'flex', flexDirection: 'column', + position: 'relative', + width: '100%', // Hide scrollbar for WebKit browsers (Chrome, Safari) '::-webkit-scrollbar': { @@ -148,6 +145,8 @@ export const AppsLibrary = ({ ); }; + const theme = useTheme(); + return ( + setSearchValue(e.target.value)} @@ -191,7 +191,9 @@ export const AppsLibrary = ({ + + - + // TODO return icon Return to Apps Dashboard + + {searchedList?.length > 0 ? ( Official Apps + + {officialApps?.map((qapp) => { return ( @@ -271,6 +277,7 @@ export const AppsLibrary = ({ /> + {qapp?.metadata?.title || qapp?.name} @@ -279,20 +286,27 @@ export const AppsLibrary = ({ ); })} + + {hasPublishApp ? 'Update Apps!' : 'Create Apps!'} + + + + + { setMode('publish'); @@ -301,13 +315,18 @@ export const AppsLibrary = ({ {hasPublishApp ? 'Update' : 'Publish'} + + + Categories + + {category?.name} diff --git a/src/components/Apps/AppsNavBar.tsx b/src/components/Apps/AppsNavBar.tsx index 67786db..5546962 100644 --- a/src/components/Apps/AppsNavBar.tsx +++ b/src/components/Apps/AppsNavBar.tsx @@ -1,12 +1,12 @@ -import React, { useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from 'react'; import { AppsNavBarLeft, AppsNavBarParent, AppsNavBarRight, -} from "./Apps-styles"; -import NavBack from "../../assets/svgs/NavBack.svg"; -import NavAdd from "../../assets/svgs/NavAdd.svg"; -import NavMoreMenu from "../../assets/svgs/NavMoreMenu.svg"; +} from './Apps-styles'; +import { NavBack } from '../../assets/svgs/NavBack.tsx'; +import { NavAdd } from '../../assets/svgs/NavAdd.tsx'; +import { NavMoreMenu } from '../../assets/svgs/NavMoreMenu.tsx'; import { ButtonBase, ListItemIcon, @@ -15,27 +15,33 @@ import { MenuItem, Tab, Tabs, -} from "@mui/material"; +} from '@mui/material'; import { executeEvent, subscribeToEvent, unsubscribeFromEvent, -} from "../../utils/events"; -import TabComponent from "./TabComponent"; -import PushPinIcon from "@mui/icons-material/PushPin"; -import RefreshIcon from "@mui/icons-material/Refresh"; -import { useRecoilState, useSetRecoilState } from "recoil"; +} from '../../utils/events'; +import TabComponent from './TabComponent'; +import PushPinIcon from '@mui/icons-material/PushPin'; +import RefreshIcon from '@mui/icons-material/Refresh'; +import { useRecoilState, useSetRecoilState } from 'recoil'; import { navigationControllerAtom, settingsLocalLastUpdatedAtom, sortablePinnedAppsAtom, -} from "../../atoms/global"; +} from '../../atoms/global'; -export function saveToLocalStorage(key, subKey, newValue, otherRootData = {}, deleteWholeKey) { +export function saveToLocalStorage( + key, + subKey, + newValue, + otherRootData = {}, + deleteWholeKey +) { try { - if(deleteWholeKey){ + if (deleteWholeKey) { localStorage.setItem(key, null); - return + return; } // Fetch existing data const existingData = localStorage.getItem(key); @@ -64,7 +70,7 @@ export function saveToLocalStorage(key, subKey, newValue, otherRootData = {}, de const serializedValue = JSON.stringify(combinedData); localStorage.setItem(key, serializedValue); } catch (error) { - console.error("Error saving to localStorage:", error); + console.error('Error saving to localStorage:', error); } } @@ -78,13 +84,17 @@ export const AppsNavBar = () => { const [sortablePinnedApps, setSortablePinnedApps] = useRecoilState( sortablePinnedAppsAtom ); - const [navigationController, setNavigationController] = useRecoilState(navigationControllerAtom) + const [navigationController, setNavigationController] = useRecoilState( + navigationControllerAtom + ); - const isDisableBackButton = useMemo(()=> { - if(selectedTab && navigationController[selectedTab?.tabId]?.hasBack) return false - if(selectedTab && !navigationController[selectedTab?.tabId]?.hasBack) return true - return false - }, [navigationController, selectedTab]) + const isDisableBackButton = useMemo(() => { + if (selectedTab && navigationController[selectedTab?.tabId]?.hasBack) + return false; + if (selectedTab && !navigationController[selectedTab?.tabId]?.hasBack) + return true; + return false; + }, [navigationController, selectedTab]); const setSettingsLocalLastUpdated = useSetRecoilState( settingsLocalLastUpdatedAtom @@ -101,13 +111,13 @@ export const AppsNavBar = () => { useEffect(() => { // Scroll to the last tab whenever the tabs array changes (e.g., when a new tab is added) if (tabsRef.current) { - const tabElements = tabsRef.current.querySelectorAll(".MuiTab-root"); + const tabElements = tabsRef.current.querySelectorAll('.MuiTab-root'); if (tabElements.length > 0) { const lastTab = tabElements[tabElements.length - 1]; lastTab.scrollIntoView({ - behavior: "smooth", - block: "nearest", - inline: "end", + behavior: 'smooth', + block: 'nearest', + inline: 'end', }); } } @@ -122,10 +132,10 @@ export const AppsNavBar = () => { }; useEffect(() => { - subscribeToEvent("setTabsToNav", setTabsToNav); + subscribeToEvent('setTabsToNav', setTabsToNav); return () => { - unsubscribeFromEvent("setTabsToNav", setTabsToNav); + unsubscribeFromEvent('setTabsToNav', setTabsToNav); }; }, []); @@ -137,28 +147,29 @@ export const AppsNavBar = () => { { - executeEvent("navigateBack", selectedTab?.tabId); + onClick={() => { + executeEvent('navigateBack', selectedTab?.tabId); }} disabled={isDisableBackButton} sx={{ - opacity: !isDisableBackButton ? 1 : 0.1, - cursor: !isDisableBackButton ? 'pointer': 'default' + opacity: !isDisableBackButton ? 1 : 0.3, + cursor: !isDisableBackButton ? 'pointer' : 'default', }} > - + + {tabs?.map((tab) => ( @@ -173,83 +184,83 @@ export const AppsNavBar = () => { /> } // Pass custom component sx={{ - "&.Mui-selected": { - color: "white", + '&.Mui-selected': { + color: 'white', }, - padding: "0px", - margin: "0px", - minWidth: "0px", - width: "50px", + padding: '0px', + margin: '0px', + minWidth: '0px', + width: '50px', }} /> ))} + {selectedTab && ( - - { - setSelectedTab(null); - executeEvent("newTabWindow", {}); - }} - > - - - { - if (!selectedTab) return; - handleClick(e); - }} - > - - - + + { + setSelectedTab(null); + executeEvent('newTabWindow', {}); + }} + > + + + + { + if (!selectedTab) return; + handleClick(e); + }} + > + + + )} - + { } saveToLocalStorage( - "ext_saved_settings", - "sortablePinnedApps", + 'ext_saved_settings', + 'sortablePinnedApps', updatedApps ); return updatedApps; @@ -293,31 +304,33 @@ export const AppsNavBar = () => { > + + { - executeEvent("refreshApp", { + executeEvent('refreshApp', { tabId: selectedTab?.tabId, }); handleClose(); @@ -325,23 +338,24 @@ export const AppsNavBar = () => { > +