done with orgApps section

This commit is contained in:
monilprajapati
2024-11-15 12:30:24 +05:30
parent 39e3218533
commit 2bf969bd14
+233 -68
View File
@@ -29,6 +29,7 @@ const searchClient = algoliasearch(
"db08e40265e2941b9a7d8f644b6e5240" "db08e40265e2941b9a7d8f644b6e5240"
); );
// AppCard Component
const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl, deactivatedIndexes }) => { const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl, deactivatedIndexes }) => {
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}`;
@@ -42,7 +43,7 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
height: 96, height: 96,
borderRadius: 8, borderRadius: 8,
boxShadow: "0px 0px 10px 0px rgba(0, 0, 0, 0.1)", boxShadow: "0px 0px 10px 0px rgba(0, 0, 0, 0.1)",
// marginBottom: 20, marginBottom: 20,
}; };
return ( return (
@@ -169,13 +170,13 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
// Component to fetch all public app from the algolia. // Component to fetch all public app from the algolia.
const Hits = memo(({ const Hits = ({
userdata, userdata,
hits, hits,
algoliaSelectedCategories,
setIsAnyAppActivated, setIsAnyAppActivated,
searchQuery, searchQuery,
globalUrl, globalUrl,
setIsLoggedIn,
isLoading, isLoading,
isLoggedIn, isLoggedIn,
}) => { }) => {
@@ -193,6 +194,16 @@ const Hits = memo(({
} }
}; };
useEffect(() => {
console.log("searchQuery", searchQuery)
console.log("hits", hits)
}, [searchQuery, hits])
const filteredHits = hits?.filter(hit => {
if (algoliaSelectedCategories?.length === 0) return true; // If no categories are selected, show all hits
return hit.categories?.some(category => algoliaSelectedCategories.includes(category));
});
// const fetchUserData = useCallback(async () => { // const fetchUserData = useCallback(async () => {
// try { // try {
@@ -281,33 +292,37 @@ const Hits = memo(({
return () => clearTimeout(timer); return () => clearTimeout(timer);
}, []); }, []);
const memoizedHits = useMemo(() => hits, [hits]);
return ( return (
<div> <div>
{!isLoading ? ( {!isLoading ? (
<div> <div>
{memoizedHits?.length === 0 && searchQuery.length >= 0 && showNoAppFound ? ( {filteredHits?.length === 0 && searchQuery.length >= 0 && showNoAppFound ? (
<Typography variant="body1" style={{ marginTop: '30%' }}>No Apps Found</Typography> <Typography variant="body1" style={{ marginTop: '30%' }}>No Apps Found</Typography>
) : ( ) : (
<Grid item spacing={2} justifyContent="flex-start"> <Grid item spacing={2} justifyContent="flex-start">
<div <div
style={{ style={{
gap: 16, minHeight: 570,
overflowY: "auto",
overflowX: "hidden",
}}>
<div
style={{
rowGap: 16,
columnGap: 16,
marginTop: 16, marginTop: 16,
display: "flex", display: "flex",
flexWrap: "wrap", flexWrap: "wrap",
justifyContent: "flex-start", justifyContent: "flex-start",
marginLeft: 24, // marginLeft: 24,
overflowY: "auto",
overflowX: "hidden",
maxHeight: 570, maxHeight: 570,
scrollbarWidth: "thin", scrollbarWidth: "thin",
scrollbarColor: "#494949 #2f2f2f", scrollbarColor: "#494949 #2f2f2f",
}} }}
> >
{memoizedHits.map((data, index) => { {filteredHits?.map((data, index) => {
const appUrl = const appUrl =
isCloud isCloud
? `/apps/${data.objectID}?queryID=${data.__queryID}` ? `/apps/${data.objectID}?queryID=${data.__queryID}`
@@ -513,6 +528,7 @@ const Hits = memo(({
}) })
} }
</div> </div>
</div>
</Grid > </Grid >
)} )}
</div> </div>
@@ -521,8 +537,9 @@ const Hits = memo(({
)} )}
</div> </div>
); );
}); }
// Main Apps Component
const Apps2 = (props) => { const Apps2 = (props) => {
const { globalUrl, isLoaded, serverside, userdata, isLoggedIn } = props; const { globalUrl, isLoaded, serverside, userdata, isLoggedIn } = props;
let navigate = useNavigate(); let navigate = useNavigate();
@@ -530,11 +547,13 @@ const Apps2 = (props) => {
const location = useLocation(); const location = useLocation();
const [searchQuery, setSearchQuery] = useState(""); const [searchQuery, setSearchQuery] = useState("");
const [selectedCategory, setSelectedCategory] = useState(""); const [selectedCategory, setSelectedCategory] = useState("");
const [algoliaSelectedCategories, setAlgoliaSelectedCategories] = 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(true); 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 [selectedCategoryForUsersAndOgsApps, setselectedCategoryForUsersAndOgsApps] = useState([]);
@@ -542,13 +561,12 @@ const Apps2 = (props) => {
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);
const [mouseHoverIndex, setMouseHoverIndex] = useState(-1); const [mouseHoverIndex, setMouseHoverIndex] = useState(-1);
var counted = 0; var counted = 0;
const [showNoAppFound, setShowNoAppFound] = useState(false); const [showNoAppFound, setShowNoAppFound] = useState(false);
const CustomHits = connectHits(Hits)
// Set the current tab based on the query parameter
useEffect(() => { useEffect(() => {
const queryParams = new URLSearchParams(location.search); const queryParams = new URLSearchParams(location.search);
const tabParam = queryParams.get('tab'); const tabParam = queryParams.get('tab');
@@ -560,10 +578,13 @@ const Apps2 = (props) => {
} else { } else {
setCurrTab(2); setCurrTab(2);
} }
} else {
setCurrTab(0);
} }
}, [location.search]); }, [location.search]);
// Fetch apps based on the current tab : 0 -> org_apps, 1 -> my_apps, 2 -> all_apps
useEffect(() => { useEffect(() => {
const fetchApps = async () => { const fetchApps = async () => {
const baseUrl = globalUrl; const baseUrl = globalUrl;
@@ -589,9 +610,12 @@ 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) console.log("data from userApps", data)
setAppsToShow(data);
setUserApps(data); setUserApps(data);
setIsLoading(false); setIsLoading(false);
} else if (currTab === 0) { } else if (currTab === 0) {
console.log("data from orgApps", data)
setAppsToShow(data);
setOrgApps(data); setOrgApps(data);
setIsLoading(false); setIsLoading(false);
} }
@@ -601,9 +625,20 @@ const Apps2 = (props) => {
}; };
fetchApps(); fetchApps();
}, [currTab, globalUrl]); // Added globalUrl to dependencies to avoid stale closures }, [currTab, globalUrl, location.search]); // Added globalUrl to dependencies to avoid stale closures
useEffect(() => {
setSearchQuery("");
}, [currTab])
// Find top categories and tags based on the current tab
useEffect(() => {
if (currTab === 0) {
setCategories(findTopCategories());
setLabels(findTopTags());
}
}, [currTab, appsToShow])
useEffect(() => { useEffect(() => {
@@ -615,10 +650,10 @@ const Apps2 = (props) => {
const findTopCategories = () => { const findTopCategories = () => {
const categoryCountMap = {}; const categoryCountMap = {};
const apps = currTab === 1 ? userApps : orgApps;
// Check if userAndOrgsApp is an array before iterating over it and Find top 10 Category from the apps // Check if userAndOrgsApp is an array before iterating over it and Find top 10 Category from the apps
if (Array.isArray(appsToShow)) { if (Array.isArray(apps)) {
appsToShow.forEach((app) => { apps.forEach((app) => {
const categories = app.categories; const categories = app.categories;
if (categories && categories.length > 0) { if (categories && categories.length > 0) {
@@ -643,9 +678,10 @@ const Apps2 = (props) => {
const findTopTags = () => { const findTopTags = () => {
const tagCountMap = {}; const tagCountMap = {};
const apps = currTab === 1 ? userApps : orgApps;
if (Array.isArray(appsToShow)) { if (Array.isArray(apps)) {
appsToShow.forEach((app) => { apps.forEach((app) => {
const tags = app.tags; const tags = app.tags;
if (tags && tags.length > 0) { if (tags && tags.length > 0) {
tags.forEach((tag) => { tags.forEach((tag) => {
@@ -672,10 +708,13 @@ const Apps2 = (props) => {
}; };
//Search app base on app name, category and tag useEffect(() => {
const filteredUserAppdata = Array.isArray(appsToShow) ? appsToShow.filter((app) => { const apps = currTab === 1 ? userApps : orgApps;
// Search app based on app name, category, and tag
const filteredUserAppdata = Array.isArray(apps) ? apps.filter((app) => {
const matchesSearchQuery = ( const matchesSearchQuery = (
searchQuery === "" || searchQuery === "" || // If searchQuery is empty, match all apps
app.name.toLowerCase().includes(searchQuery.toLowerCase()) || app.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
(app.tags && app.tags.some(tag => (app.tags && app.tags.some(tag =>
tag.toLowerCase().includes(searchQuery.toLowerCase()) tag.toLowerCase().includes(searchQuery.toLowerCase())
@@ -686,23 +725,25 @@ const Apps2 = (props) => {
); );
const matchesSelectedCategories = ( const matchesSelectedCategories = (
selectedCategoryForUsersAndOgsApps.length === 0 || selectedCategory === "" || // If no category is selected, match all apps
(app.categories && app.categories.some(category => (app.categories && app.categories.some(category =>
selectedCategoryForUsersAndOgsApps.includes(category) selectedCategory.includes(category)
)) ))
); );
const matchesSelectedTags = ( const matchesSelectedTags = (
selectedTagsForUserAndOrgApps.length === 0 || selectedLabel === "" || // If no label is selected, match all apps
(app.tags && selectedTagsForUserAndOrgApps.some(tag => (app.tags && app.tags.some(tag =>
app.tags.includes(tag) tag.toLowerCase().includes(selectedLabel.toLowerCase())
)) ))
); );
return matchesSearchQuery && matchesSelectedCategories && matchesSelectedTags; return matchesSearchQuery && matchesSelectedCategories && matchesSelectedTags;
}) : []; }) : [];
setAppsToShow(filteredUserAppdata);
}, [searchQuery, selectedCategory, selectedLabel]);
const handleTabChange = (newTab) => { const handleTabChange = (newTab) => {
console.log("Current Tab", newTab) console.log("Current Tab", newTab)
@@ -746,6 +787,104 @@ const Apps2 = (props) => {
const SearchBox = ({ refine, searchQuery, setSearchQuery }) => {
const inputRef = React.useRef(null); // Create a ref for the input field
// Check for query in URL and set it
React.useEffect(() => {
if (
window !== undefined &&
window.location !== undefined &&
window.location.search !== undefined &&
window.location.search !== null
) {
const urlSearchParams = new URLSearchParams(window.location.search);
const params = Object.fromEntries(urlSearchParams.entries());
const foundQuery = params["q"];
if (foundQuery !== null && foundQuery !== undefined) {
console.log("Got query: ", foundQuery);
refine(foundQuery);
setSearchQuery(foundQuery); // Use setSearchQuery to update state
}
}
}, [refine, setSearchQuery]); // Add dependencies
// Use useEffect to focus the input when it mounts or when searchQuery changes
React.useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, [searchQuery]); // Focus whenever searchQuery changes
console.log("searchQuery", searchQuery);
return (
<TextField
fullWidth
variant="outlined"
placeholder="Search for apps"
value={searchQuery}
id="shuffle_search_field"
inputRef={inputRef} // Attach the ref to the input field
onChange={(event) => {
setSearchQuery(event.target.value); // Update the search query
removeQuery("q");
refine(event.target.value); // Refine the search
}}
onKeyDown={(event) => {
if (event.key === "Enter") {
event.preventDefault();
}
}}
limit={5}
style={{ width: '100%', borderRadius: '7px', fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)" }}
InputProps={{
style: {
borderRadius: 8,
},
endAdornment: (
<InputAdornment position="end">
{searchQuery?.length === 0 ? <Search /> : (
<ClearIcon
style={{
cursor: "pointer",
marginRight: 10
}}
onClick={() => {
setSearchQuery(''); // Clear the search query
removeQuery("q");
refine(''); // Clear the refinement
}}
/>
)}
</InputAdornment>
),
}}
/>
);
};
const CustomSearchBox = connectSearchBox(SearchBox);
const CustomHits = connectHits(Hits)
const handleCategoryChange = (selectedValue) => {
setAlgoliaSelectedCategories(prev => {
if (prev.includes(selectedValue)) {
// If the category is already selected, remove it
return prev.filter(category => category !== selectedValue);
} else {
// Otherwise, add it to the selected categories
return [...prev, selectedValue];
}
});
};
useEffect(() => {
console.log("algoliaSelectedCategories", algoliaSelectedCategories)
}, [algoliaSelectedCategories])
return ( return (
<InstantSearch searchClient={searchClient} indexName="appsearch"> <InstantSearch searchClient={searchClient} indexName="appsearch">
<div style={boxStyle}> <div style={boxStyle}>
@@ -765,6 +904,8 @@ const Apps2 = (props) => {
</div> </div>
<div style={{ display: "flex", justifyContent: "space-between", marginBottom: 20 }}> <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 20 }}>
<div style={{ flex: 1, marginRight: 10 }}> <div style={{ flex: 1, marginRight: 10 }}>
{
(currTab === 0 || currTab === 1) &&
<TextField <TextField
fullWidth fullWidth
variant="outlined" variant="outlined"
@@ -772,9 +913,7 @@ const Apps2 = (props) => {
value={searchQuery} value={searchQuery}
id="shuffle_search_field" id="shuffle_search_field"
onChange={(event) => { onChange={(event) => {
setSearchQuery(event.currentTarget.value); setSearchQuery(event.target.value);
removeQuery("q");
// refine(event.currentTarget.value);
}} }}
onKeyDown={(event) => { onKeyDown={(event) => {
if (event.key === "Enter") { if (event.key === "Enter") {
@@ -796,7 +935,11 @@ const Apps2 = (props) => {
), ),
}} }}
/> />
{/* <CustomSearchBox searchQuery={searchQuery} setSearchQuery={setSearchQuery} /> */} }
{
currTab === 2 &&
<CustomSearchBox searchQuery={searchQuery} setSearchQuery={setSearchQuery} />
}
</div> </div>
<div style={{ flex: 1, marginRight: 10 }}> <div style={{ flex: 1, marginRight: 10 }}>
<Select <Select
@@ -807,14 +950,14 @@ const Apps2 = (props) => {
displayEmpty displayEmpty
style={{ width: '100%', borderRadius: '7px', fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)" }} style={{ width: '100%', borderRadius: '7px', fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)" }}
> >
<MenuItem value="" > <MenuItem value="">
All Categories All Categories
</MenuItem> </MenuItem>
{ {
currTab === 0 && currTab === 0 &&
( (
categories?.map((category) => ( categories?.map((category) => (
<MenuItem value={category.category}> <MenuItem key={category.category} value={category.category}>
{category.category} {category.category}
</MenuItem> </MenuItem>
)) ))
@@ -824,11 +967,20 @@ const Apps2 = (props) => {
currTab === 2 && currTab === 2 &&
( (
<div style={{ padding: "5px 10px" }}> <div style={{ padding: "5px 10px" }}>
<RefinementList attribute="categories" /> <RefinementList
attribute="categories"
defaultRefinement={algoliaSelectedCategories}
onChange={(selectedItems) => {
handleCategoryChange(selectedItems);
}}
transformItems={(items) => {
console.log("items", items)
return items;
}}
/>
</div> </div>
) )
} }
</Select> </Select>
</div> </div>
<div style={{ flex: 1, marginRight: 10 }}> <div style={{ flex: 1, marginRight: 10 }}>
@@ -878,42 +1030,50 @@ const Apps2 = (props) => {
<div> <div>
{ {
currTab === 0 && currTab === 0 && (
(orgApps.length > 0 ? ( <div style={{ minHeight: 570, overflowY: "auto", overflowX: "hidden" }}>
<div style={{ rowGap: 16, columnGap: 16, marginTop: 16, display: "flex", flexWrap: "wrap", justifyContent: "flex-start", overflowY: "auto", overflowX: "hidden", maxHeight: 570, scrollbarWidth: "thin", scrollbarColor: "#494949 #2f2f2f", maxHeight: 570, minHeight: 570 }}> {isLoading ? (
{ <div style={{ width: "100%", height: "100%", display: "flex", justifyContent: "center", alignItems: "center" }}>
isLoading ? <div <CircularProgress />
style={{ </div>
width: "100%", ) : (
height: "100%", <>
display: "flex", {appsToShow?.length > 0 && appsToShow !== undefined && !isLoading ? (
justifyContent: "center", <div style={{ rowGap: 16, columnGap: 16, marginTop: 16, display: "flex", flexWrap: "wrap", justifyContent: "flex-start", maxHeight: 570, scrollbarWidth: "thin", scrollbarColor: "#494949 #2f2f2f" }}>
alignItems: "center", {appsToShow.map((data, index) => (
}} <AppCard key={index} data={data} index={index} mouseHoverIndex={mouseHoverIndex} setMouseHoverIndex={setMouseHoverIndex} globalUrl={globalUrl} deactivatedIndexes={deactivatedIndexes} />
> <CircularProgress /></div> ))}
: </div>
( ) : (
filteredUserAppdata?.map((data, index) => ( <div style={{ marginTop: 100, fontSize: 20, fontWeight: 500, width: "100%", textAlign: "center" }}>
<AppCard key={index} data={data} index={index} mouseHoverIndex={mouseHoverIndex} setMouseHoverIndex={setMouseHoverIndex} globalUrl={globalUrl} deactivatedIndexes={deactivatedIndexes} /> No apps found
)) </div>
) )}
} </>
)}
</div> </div>
) : <div
style={{
marginTop: 100,
fontSize: 20,
fontWeight: 500,
width: "100%",
textAlign: "center",
}}
>No apps found</div>
) )
} }
{ {
currTab === 1 && currTab === 1 &&
(userApps.length > 0 ? ( (userApps.length > 0 ? (
<div style={{ rowGap: 16, columnGap: 16, marginTop: 16, display: "flex", flexWrap: "wrap", justifyContent: "flex-start", overflowY: "auto", overflowX: "hidden", maxHeight: 570, scrollbarWidth: "thin", scrollbarColor: "#494949 #2f2f2f", maxHeight: 570 }}> <div style={{
minHeight: 570,
overflowY: "auto",
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 isLoading ? <div
style={{ style={{
@@ -932,7 +1092,9 @@ const Apps2 = (props) => {
) )
} }
</div> </div>
) : <div </div>
) : !isLoading && (
<div
style={{ style={{
marginTop: 100, marginTop: 100,
fontSize: 20, fontSize: 20,
@@ -942,10 +1104,12 @@ const Apps2 = (props) => {
}} }}
>No apps found</div> >No apps found</div>
) )
)
} }
{ {
currTab === 2 && currTab === 2 &&
<CustomHits <CustomHits
isLoggedIn={isLoggedIn} isLoggedIn={isLoggedIn}
userdata={userdata} userdata={userdata}
@@ -953,6 +1117,7 @@ const Apps2 = (props) => {
hitsPerPage={5} hitsPerPage={5}
globalUrl={globalUrl} globalUrl={globalUrl}
searchQuery={searchQuery} searchQuery={searchQuery}
algoliaSelectedCategories={algoliaSelectedCategories}
mouseHoverIndex={mouseHoverIndex} mouseHoverIndex={mouseHoverIndex}
setMouseHoverIndex={setMouseHoverIndex} setMouseHoverIndex={setMouseHoverIndex}
/> />