Done with myApps section

This commit is contained in:
monilprajapati
2024-11-15 17:02:43 +05:30
parent d9b3acd27c
commit 0e1a86c90b
3 changed files with 285 additions and 214 deletions
+1
View File
@@ -418,6 +418,7 @@ const App = (message, props) => {
serverside={false} serverside={false}
isLoaded={isLoaded} isLoaded={isLoaded}
isLoggedIn={isLoggedIn} isLoggedIn={isLoggedIn}
checkLogin={checkLogin}
userdata={userdata} userdata={userdata}
globalUrl={globalUrl} globalUrl={globalUrl}
surfaceColor={theme.palette.surfaceColor} surfaceColor={theme.palette.surfaceColor}
+7 -1
View File
@@ -47,6 +47,7 @@ const AppSelection = props => {
defaultSearch, defaultSearch,
setDefaultSearch, setDefaultSearch,
checkLogin, checkLogin,
isAppPage=false
} = props; } = props;
const [discoveryData, setDiscoveryData] = React.useState({}) const [discoveryData, setDiscoveryData] = React.useState({})
@@ -507,11 +508,13 @@ const AppSelection = props => {
})} })}
</Grid> </Grid>
</div> </div>
{
!isAppPage && (
<>
{!moreButton ? ( {!moreButton ? (
<div style={{ width: "100%", marginLeft: isMobile ? 80 : 200, marginBottom: 20, textAlign: isMobile ? "center" : null }}> <div style={{ width: "100%", marginLeft: isMobile ? 80 : 200, marginBottom: 20, textAlign: isMobile ? "center" : null }}>
<Link style={{ color: "#FF8444" }} onClick={() => { <Link style={{ color: "#FF8444" }} onClick={() => {
setMoreButton(true) setMoreButton(true)
setTimeout(() => { setTimeout(() => {
navigate("/welcome?tab=2") navigate("/welcome?tab=2")
}, 250) }, 250)
@@ -527,6 +530,9 @@ const AppSelection = props => {
See usecases See usecases
</Button> </Button>
</div> </div>
</>
)
}
</div> </div>
</Fade> </Fade>
) )
+163 -99
View File
@@ -24,6 +24,7 @@ import { removeQuery } from "../components/ScrollToTop.jsx";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import algoliasearch from "algoliasearch/lite"; import algoliasearch from "algoliasearch/lite";
import { debounce } from "lodash"; import { debounce } from "lodash";
import AppSelection from "../components/AppSelection.jsx";
const searchClient = algoliasearch( const searchClient = algoliasearch(
@@ -32,7 +33,7 @@ const searchClient = algoliasearch(
); );
// AppCard Component // AppCard Component
const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl, deactivatedIndexes }) => { const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl, deactivatedIndexes, currTab }) => {
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" || window.location.host === "localhost:3000"; const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" || window.location.host === "localhost:3000";
const appUrl = isCloud ? `/apps/${data.id}` : `https://shuffler.io/apps/${data.id}`; const appUrl = isCloud ? `/apps/${data.id}` : `https://shuffler.io/apps/${data.id}`;
@@ -50,9 +51,13 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
return ( return (
<Grid item xs={12} key={index}> <Grid item xs={12} key={index}>
<a href={appUrl} rel="noopener noreferrer" style={{ textDecoration: "none", color: "#f85a3e" }}> <Paper elevation={0}
<Paper elevation={0} style={paperStyle} onMouseOver={() => setMouseHoverIndex(index)} onMouseOut={() => setMouseHoverIndex(-1)}> style={paperStyle}
<ButtonBase style={{ onMouseOver={() => setMouseHoverIndex(index)}
onMouseOut={() => setMouseHoverIndex(-1)}
>
<ButtonBase
style={{
borderRadius: 6, borderRadius: 6,
fontSize: 16, fontSize: 16,
overflow: "hidden", overflow: "hidden",
@@ -60,7 +65,14 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
alignItems: "flex-start", alignItems: "flex-start",
width: '100%', width: '100%',
backgroundColor: mouseHoverIndex === index ? "#2F2F2F" : "#212121" backgroundColor: mouseHoverIndex === index ? "#2F2F2F" : "#212121"
}}> }}
onClick={(event) => {
// if (!event.target.closest('.deactivate-button')) {
// window.location.href = appUrl;
// }
console.log("clicked");
}}
>
<img <img
alt={data.name} alt={data.name}
src={data.small_image || data.large_image ? (data.small_image || data.large_image) : "/images/no_image.png"} src={data.small_image || data.large_image ? (data.small_image || data.large_image) : "/images/no_image.png"}
@@ -122,9 +134,11 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
</span> </span>
))} ))}
</div> </div>
{/* Deactivate button logic */} {/* Deactivate button */}
{mouseHoverIndex === index ? {currTab === 0 && !deactivatedIndexes.includes(index) && mouseHoverIndex === index && data.generated === true && (
<Button style={{ <Button
className="deactivate-button"
style={{
marginLeft: 15, marginLeft: 15,
width: 102, width: 102,
height: 35, height: 35,
@@ -134,7 +148,6 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
textTransform: "none", textTransform: "none",
}} }}
onClick={(event) => { onClick={(event) => {
event.preventDefault();
event.stopPropagation(); event.stopPropagation();
const url = `${globalUrl}/api/v1/apps/${data.id}/deactivate`; const url = `${globalUrl}/api/v1/apps/${data.id}/deactivate`;
@@ -157,15 +170,15 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
.catch(error => { .catch(error => {
console.log("app error: ", error.toString()); console.log("app error: ", error.toString());
}); });
}}> }}
>
Deactivate Deactivate
</Button> </Button>
: null} )}
</div> </div>
</div> </div>
</ButtonBase> </ButtonBase>
</Paper> </Paper>
</a>
</Grid> </Grid>
); );
}; };
@@ -183,7 +196,7 @@ const Hits = ({
}) => { }) => {
const [hoverEffect, setHoverEffect] = useState(-1); const [hoverEffect, setHoverEffect] = useState(-1);
const [allActivatedAppIds, setAllActivatedAppIds] = useState(userdata?.active_apps); const [allActivatedAppIds, setAllActivatedAppIds] = useState(userdata?.active_apps);
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" || window.location.host === "localhost:3000"; const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
const [deactivatedIndexes, setDeactivatedIndexes] = React.useState([]); const [deactivatedIndexes, setDeactivatedIndexes] = React.useState([]);
const normalizedString = (name) => { const normalizedString = (name) => {
@@ -194,12 +207,6 @@ const Hits = ({
} }
}; };
useEffect(() => {
console.log("searchQuery", searchQuery)
console.log("hits", hits)
}, [searchQuery, hits])
//Function for activation and deactivation of app //Function for activation and deactivation of app
@@ -270,7 +277,9 @@ const Hits = ({
{!isLoading ? ( {!isLoading ? (
<div> <div>
{hits?.length === 0 && searchQuery.length >= 0 && showNoAppFound ? ( {hits?.length === 0 && searchQuery.length >= 0 && showNoAppFound ? (
<Typography variant="body1" style={{ marginTop: '30%' }}>No Apps Found</Typography> <div style={{ marginTop: 100, fontSize: 20, fontWeight: 500, width: "100%", textAlign: "center" }}>
<Typography variant="body1">No Apps Found</Typography>
</div>
) : ( ) : (
<Grid item spacing={2} justifyContent="flex-start"> <Grid item spacing={2} justifyContent="flex-start">
<div <div
@@ -574,6 +583,9 @@ const SearchBox = ({ refine, searchQuery, setSearchQuery }) => {
}, [debouncedRefine]); }, [debouncedRefine]);
useEffect(() => { useEffect(() => {
if (searchQuery === "") {
return;
}
if (inputRef.current) { if (inputRef.current) {
inputRef.current.focus(); inputRef.current.focus();
} }
@@ -628,24 +640,62 @@ const SearchBox = ({ refine, searchQuery, setSearchQuery }) => {
const CustomSearchBox = connectSearchBox(SearchBox); const CustomSearchBox = connectSearchBox(SearchBox);
const CustomHits = connectHits(Hits); const CustomHits = connectHits(Hits);
// Custom Label Dropdown Component
const LabelDropdown = ({ items, currentRefinement, refine }) => {
const handleChange = (event) => {
const value = event.target.value;
refine(value);
};
return (
<Select
fullWidth
variant="outlined"
value={currentRefinement}
onChange={handleChange}
displayEmpty
multiple
style={{
width: '100%',
maxWidth: '300px',
borderRadius: '7px',
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)",
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
renderValue={(selected) => selected.length ? selected.join(', ') : 'All Labels'}
>
<MenuItem disabled value="">
All Labels
</MenuItem>
{items.map(item => (
<MenuItem key={item.label} value={item.label}>
<Checkbox checked={currentRefinement.includes(item.label)} />
{item.label} ({item.count})
</MenuItem>
))}
</Select>
);
};
const CustomLabelDropdown = connectRefinementList(LabelDropdown);
// Main Apps Component // Main Apps Component
const Apps2 = (props) => { const Apps2 = (props) => {
const { globalUrl, isLoaded, serverside, userdata, isLoggedIn } = props; const { globalUrl, isLoaded, serverside, userdata, isLoggedIn, checkLogin } = props;
let navigate = useNavigate(); let navigate = useNavigate();
const { leftSideBarOpenByClick } = useContext(Context); const { leftSideBarOpenByClick } = useContext(Context);
const location = useLocation(); const location = useLocation();
const [searchQuery, setSearchQuery] = useState(""); const [searchQuery, setSearchQuery] = useState("");
const [selectedCategory, setSelectedCategory] = useState([]); const [selectedCategory, setSelectedCategory] = useState([]);
const [selectedLabel, setSelectedLabel] = useState([]); const [selectedLabel, setSelectedLabel] = useState([]);
const [algoliaSelectedLabels, setAlgoliaSelectedLabels] = useState([]);
const [currTab, setCurrTab] = useState(0); const [currTab, setCurrTab] = useState(0);
const [categories, setCategories] = useState([]); const [categories, setCategories] = useState([]);
const [labels, setLabels] = useState([]); const [labels, setLabels] = useState([]);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [userApps, setUserApps] = useState([]); const [userApps, setUserApps] = useState([]);
const [orgApps, setOrgApps] = useState([]); const [orgApps, setOrgApps] = useState([]);
const [selectedCategoryForUsersAndOgsApps, setselectedCategoryForUsersAndOgsApps] = useState([]);
const [selectedTagsForUserAndOrgApps, setSelectedTagsForUserAndOrgApps] = useState([]);
const [appsToShow, setAppsToShow] = useState([]); const [appsToShow, setAppsToShow] = useState([]);
const [deactivatedIndexes, setDeactivatedIndexes] = React.useState([]); const [deactivatedIndexes, setDeactivatedIndexes] = React.useState([]);
const [IsAnyAppActivated, setIsAnyAppActivated] = useState(false); const [IsAnyAppActivated, setIsAnyAppActivated] = useState(false);
@@ -654,6 +704,8 @@ const Apps2 = (props) => {
const [showNoAppFound, setShowNoAppFound] = useState(false); const [showNoAppFound, setShowNoAppFound] = useState(false);
const [appFramework, setAppFramework] = useState(undefined);
const [defaultSearch, setDefaultSearch] = useState("");
// Set the current tab based on the query parameter // Set the current tab based on the query parameter
useEffect(() => { useEffect(() => {
const queryParams = new URLSearchParams(location.search); const queryParams = new URLSearchParams(location.search);
@@ -666,11 +718,47 @@ const Apps2 = (props) => {
} else { } else {
setCurrTab(2); setCurrTab(2);
} }
} else {
setCurrTab(0);
} }
}, [location.search]); }, [location.search]);
useEffect(() => {
const getFramework = () => {
fetch(globalUrl + "/api/v1/apps/frameworkConfiguration", {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200 for framework!");
}
return response.json();
})
.then((responseJson) => {
if (responseJson.success === false) {
setAppFramework({})
if (responseJson.reason !== undefined) {
//toast("Failed loading: " + responseJson.reason)
} else {
//toast("Failed to load framework for your org.")
}
} else {
setAppFramework(responseJson)
}
})
.catch((error) => {
console.log("err in framework: ", error.toString());
})
}
getFramework();
}, []);
// Fetch apps based on the current tab : 0 -> org_apps, 1 -> my_apps, 2 -> all_apps // Fetch apps based on the current tab : 0 -> org_apps, 1 -> my_apps, 2 -> all_apps
useEffect(() => { useEffect(() => {
@@ -695,23 +783,27 @@ const Apps2 = (props) => {
}); });
const data = await response.json(); const data = await response.json();
if (currTab === 1) { if (currTab === 1) {
console.log("data from userApps", data)
setAppsToShow(data); setAppsToShow(data);
setUserApps(data); setUserApps(data);
setIsLoading(false);
} else if (currTab === 0) { } else if (currTab === 0) {
console.log("data from orgApps", data)
setAppsToShow(data); setAppsToShow(data);
setOrgApps(data); setOrgApps(data);
setIsLoading(false); // For testing the empty state
// setAppsToShow([]);
// setOrgApps([]);
} }
setIsLoading(false);
} catch (err) { } catch (err) {
console.error("Error fetching apps:", err); console.error("Error fetching apps:", err);
setIsLoading(false);
} }
}; };
// Only fetch if we have required data
if (globalUrl && (currTab === 0 || (currTab === 1 && userdata?.id))) {
fetchApps(); fetchApps();
}, [currTab, globalUrl, location.search]); // Added globalUrl to dependencies to avoid stale closures }
}, [currTab, globalUrl, userdata?.id]); // Remove location.search dependency
useEffect(() => { useEffect(() => {
setSearchQuery(""); setSearchQuery("");
@@ -789,8 +881,9 @@ const Apps2 = (props) => {
return topTags; return topTags;
}; };
const handleCreateApp = () => { const handleCreateApp = (e) => {
navigate('/create-app'); e.preventDefault();
console.log("Create app clicked")
}; };
@@ -832,7 +925,6 @@ const Apps2 = (props) => {
const handleTabChange = (newTab) => { const handleTabChange = (newTab) => {
console.log("Current Tab", newTab)
setCurrTab(newTab); setCurrTab(newTab);
if (newTab === 0) { if (newTab === 0) {
setAppsToShow(orgApps) setAppsToShow(orgApps)
@@ -956,17 +1048,13 @@ const Apps2 = (props) => {
{category.category} {category.category}
</MenuItem> </MenuItem>
))} ))}
{
selectedCategory.length > 0 && (
<MenuItem onClick={() => setSelectedCategory([])} style={{ display: 'flex', justifyContent: 'center', padding: '10px', backgroundColor: '#212121', color: '#fff', marginTop: '10px', cursor: 'pointer' }}>
<Typography style={{ textAlign: 'center', width: '100%', fontWeight: 'bold' }}>Remove All Categories</Typography>
</MenuItem>
)
}
</Select> </Select>
)} )}
</div> </div>
<div style={{ flex: 1, marginRight: 10 }}> <div style={{ flex: 1, marginRight: 10 }}>
{currTab === 2 ? (
<CustomLabelDropdown attribute="action_labels" />
) : (
<Select <Select
fullWidth fullWidth
variant="outlined" variant="outlined"
@@ -986,14 +1074,8 @@ const Apps2 = (props) => {
{tag.tag} {tag.tag}
</MenuItem> </MenuItem>
))} ))}
{
selectedLabel.length > 0 && (
<MenuItem onClick={() => setSelectedCategory([])} style={{ display: 'flex', justifyContent: 'center', padding: '10px', backgroundColor: '#212121', color: '#fff', marginTop: '10px', cursor: 'pointer' }}>
<Typography style={{ textAlign: 'center', width: '100%', fontWeight: 'bold' }}>Remove All Labels</Typography>
</MenuItem>
)
}
</Select> </Select>
)}
</div> </div>
<div style={{ flex: 1, marginRight: 10 }}> <div style={{ flex: 1, marginRight: 10 }}>
<Button <Button
@@ -1013,7 +1095,7 @@ const Apps2 = (props) => {
currTab === 0 && ( currTab === 0 && (
<div style={{ minHeight: 570, overflowY: "auto", overflowX: "hidden" }}> <div style={{ minHeight: 570, overflowY: "auto", overflowX: "hidden" }}>
{isLoading ? ( {isLoading ? (
<div style={{ width: "100%", height: "100%", display: "flex", justifyContent: "center", alignItems: "center" }}> <div style={{ width: "100%", textAlign: "center", display: "flex", justifyContent: "center", alignItems: "center" }}>
<CircularProgress /> <CircularProgress />
</div> </div>
) : ( ) : (
@@ -1021,12 +1103,21 @@ const Apps2 = (props) => {
{appsToShow?.length > 0 && appsToShow !== undefined && !isLoading ? ( {appsToShow?.length > 0 && appsToShow !== undefined && !isLoading ? (
<div style={{ rowGap: 16, columnGap: 16, marginTop: 16, display: "flex", flexWrap: "wrap", justifyContent: "flex-start", maxHeight: 570, scrollbarWidth: "thin", scrollbarColor: "#494949 #2f2f2f" }}> <div style={{ rowGap: 16, columnGap: 16, marginTop: 16, display: "flex", flexWrap: "wrap", justifyContent: "flex-start", maxHeight: 570, scrollbarWidth: "thin", scrollbarColor: "#494949 #2f2f2f" }}>
{appsToShow.map((data, index) => ( {appsToShow.map((data, index) => (
<AppCard key={index} data={data} index={index} mouseHoverIndex={mouseHoverIndex} setMouseHoverIndex={setMouseHoverIndex} globalUrl={globalUrl} deactivatedIndexes={deactivatedIndexes} /> <AppCard key={index} data={data} index={index} mouseHoverIndex={mouseHoverIndex} setMouseHoverIndex={setMouseHoverIndex} globalUrl={globalUrl} deactivatedIndexes={deactivatedIndexes} currTab={currTab} />
))} ))}
</div> </div>
) : ( ) : (
<div style={{ marginTop: 100, fontSize: 20, fontWeight: 500, width: "100%", textAlign: "center" }}> <div style={{ width: "100%", marginTop: 60, textAlign: "center", display: "flex", justifyContent: "center", alignItems: "center" }}>
No apps found <AppSelection
userdata={userdata}
globalUrl={globalUrl}
appFramework={appFramework}
setAppFramework={setAppFramework}
defaultSearch={defaultSearch}
setDefaultSearch={setDefaultSearch}
checkLogin={checkLogin}
isAppPage={true}
/>
</div> </div>
)} )}
</> </>
@@ -1035,55 +1126,28 @@ const Apps2 = (props) => {
) )
} }
{ {
currTab === 1 && currTab === 1 && (
(userApps.length > 0 ? ( <div style={{ minHeight: 570, overflowY: "auto", overflowX: "hidden" }}>
<div style={{ {isLoading ? (
minHeight: 570, <div style={{ width: "100%", textAlign: "center", display: "flex", justifyContent: "center", alignItems: "center" }}>
overflowY: "auto", <CircularProgress />
overflowX: "hidden",
}}>
<div style={{
rowGap: 16,
columnGap: 16,
marginTop: 16,
display: "flex",
flexWrap: "wrap",
justifyContent: "flex-start",
maxHeight: 570,
scrollbarWidth: "thin",
scrollbarColor: "#494949 #2f2f2f",
// minHeight: 570
}}>
{
isLoading ? <div
style={{
width: "100%",
height: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
> <CircularProgress /></div>
:
(
userApps.map((data, index) => (
<AppCard key={index} data={data} index={index} mouseHoverIndex={mouseHoverIndex} setMouseHoverIndex={setMouseHoverIndex} globalUrl={globalUrl} deactivatedIndexes={deactivatedIndexes} />
))
)
}
</div> </div>
) : (
<>
{appsToShow?.length > 0 && appsToShow !== undefined ? (
<div style={{ rowGap: 16, columnGap: 16, marginTop: 16, display: "flex", flexWrap: "wrap", justifyContent: "flex-start", maxHeight: 570, scrollbarWidth: "thin", scrollbarColor: "#494949 #2f2f2f" }}>
{appsToShow.map((data, index) => (
<AppCard key={index} data={data} index={index} mouseHoverIndex={mouseHoverIndex} setMouseHoverIndex={setMouseHoverIndex} globalUrl={globalUrl} deactivatedIndexes={deactivatedIndexes} currTab={currTab} />
))}
</div>
) : (
<div style={{ width: "100%", marginTop: 60, textAlign: "center", display: "flex", justifyContent: "center", alignItems: "center" }}>
<Typography variant="body1">No Apps Found</Typography>
</div>
)}
</>
)}
</div> </div>
) : !isLoading && (
<div
style={{
marginTop: 100,
fontSize: 20,
fontWeight: 500,
width: "100%",
textAlign: "center",
}}
>No apps found</div>
)
) )
} }