import React, { useState, useEffect, useContext, useCallback, memo, useMemo, useRef } from "react";
import theme from "../theme.jsx";
import { isMobile } from "react-device-detect";
import AppGrid from "../components/AppGrid.jsx";
import { useLocation, useNavigate } from "react-router-dom";
import {
TextField, Button, Typography, MenuItem, Select, Tabs, Tab, Zoom,
Grid,
Paper,
ButtonBase,
Tooltip,
Box,
CircularProgress,
Checkbox,
Skeleton,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
IconButton,
} from "@mui/material";
import { Context } from "../context/ContextApi.jsx";
import Add from '@mui/icons-material/Add';
import CachedIcon from '@mui/icons-material/Cached';
import CloudDownloadIcon from '@mui/icons-material/CloudDownload';
import EditIcon from '@mui/icons-material/Edit';
import InputAdornment from '@mui/material/InputAdornment';
import Search from '@mui/icons-material/Search';
import ClearIcon from '@mui/icons-material/Clear';
import CloseIcon from '@mui/icons-material/Close';
import { ClearRefinements, connectHits, connectSearchBox, connectStateResults, InstantSearch, RefinementList, connectRefinementList, Configure } from "react-instantsearch-dom";
import { removeQuery } from "../components/ScrollToTop.jsx";
import { toast } from "react-toastify";
import algoliasearch from "algoliasearch/lite";
import { debounce } from "lodash";
import AppSelection from "../components/AppSelection.jsx";
import AppModal from "../components/AppModal.jsx";
import AppCreationModal from "../components/AppCreationModal.jsx";
const searchClient = algoliasearch(
"JNSS5CFDZZ",
"db08e40265e2941b9a7d8f644b6e5240"
);
// AppCard Component
const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl, deactivatedIndexes, currTab, handleAppClick, leftSideBarOpenByClick, userdata }) => {
const navigate = useNavigate();
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}`;
var canEditApp = userdata.admin === "true" || userdata.id === data?.owner || data?.owner === "" || (userdata.admin === "true" && userdata.active_org.id === data?.reference_org) || !data?.generated
const paperStyle = {
backgroundColor: mouseHoverIndex === index ? "rgba(26, 26, 26, 1)" : "#212121",
color: "rgba(241, 241, 241, 1)",
cursor: "pointer",
fontFamily: theme?.typography?.fontFamily,
// position: "relative",
width: "100%",
height: 96,
borderRadius: 8,
boxShadow: "0px 0px 10px 0px rgba(0, 0, 0, 0.1)",
marginBottom: 20,
transition: "width 0.3s ease",
};
return (
setMouseHoverIndex(index)}
onMouseOut={() => setMouseHoverIndex(-1)}
>
{
handleAppClick(data);
}}
>
{data.name.replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase())}
{data.categories ? data.categories.join(", ") : "NA"}
{data.generated !== true && data.tags && data.tags.slice(0, 2).map((tag, tagIndex) => (
{tag}
{tagIndex < data.tags.length - 1 ? ", " : ""}
))}
{/* Deactivate button */}
{currTab === 0 && !deactivatedIndexes.includes(index) && mouseHoverIndex === index && data.generated === true && (
{
canEditApp && (
)
}
)}
);
};
// Component to fetch all public app from the algolia.
const Hits = ({
userdata,
hits,
handleAppClick,
setIsAnyAppActivated,
searchQuery,
globalUrl,
isLoggedIn,
currTab,
leftSideBarOpenByClick
}) => {
const [hoverEffect, setHoverEffect] = useState(-1);
const [allActivatedAppIds, setAllActivatedAppIds] = useState([]);
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
const [deactivatedIndexes, setDeactivatedIndexes] = React.useState([]);
const [isLoading, setIsLoading] = useState(true)
useEffect(() => {
var baseurl = globalUrl;
fetch(baseurl + "/api/v1/me", {
credentials: "include",
headers: {
'Content-Type': 'application/json',
},
})
.then(response => response.json())
.then(responseJson => {
if (responseJson.success) {
setAllActivatedAppIds(responseJson.active_apps)
}
setIsLoading(false)
})
.catch(error => {
console.log("Failed login check: ", error);
});
}, [currTab]);
const normalizedString = (name) => {
if (typeof name === 'string') {
return name.replace(/_/g, ' ');
} else {
return name;
}
};
useEffect(() => {
if (userdata && userdata.active_apps) {
setAllActivatedAppIds(userdata.active_apps);
}
}, [currTab, window.location]);
//Function for activation and deactivation of app
const handleActivateButton = (event, data, type) => {
//use prevent default so it will stop redirection to the app page
event.preventDefault();
event.stopPropagation();
if (!isLoggedIn) {
toast.error("Please log in to your account to activate the app.")
return;
}
if (type === "activate") {
toast.success(`The ${normalizedString(data.name)} app is activating. Please wait...`);
}
if (type === "deactivate") {
toast.success(`The ${normalizedString(data.name)} app is deactivating. Please wait...`);
}
const baseURL = globalUrl;
const url = `${baseURL}/api/v1/apps/${data.objectID}/${type}`;
fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
credentials: "include",
})
.then((response) => response.json())
.then((responseJson) => {
if (responseJson.success === false) {
toast.error(responseJson.reason);
} else {
//toast.success(`App ${type}d Successfully!`);
if (type === 'activate') {
setAllActivatedAppIds(prev => [...prev, data.objectID]);
setIsAnyAppActivated(true);
}
if (type === 'deactivate') {
const updatedIds = allActivatedAppIds.filter(id => id !== data.objectID);
setAllActivatedAppIds(updatedIds);
}
}
})
.catch(error => {
console.log("app error: ", error.toString());
});
}
let workflowDelay = 0;
const isHeader = true;
return (
{!isLoading ?
(
{hits?.length === 0 && searchQuery.length >= 0 ? (
No apps found
) : (
{hits?.map((data, index) => {
const appUrl =
isCloud
? `/apps/${data.objectID}?queryID=${data.__queryID}`
: `https://shuffler.io/apps/${data.objectID}?queryID=${data.__queryID}`;
return (
{
setHoverEffect(index);
}}
onMouseLeave={() => {
setHoverEffect(-1);
}}
>
{
console.log("App modal", data)
handleAppClick(data);
}}
>
{(allActivatedAppIds && allActivatedAppIds.includes(data.objectID)) && }
{normalizedString(data.name)}
{data.categories !== null
? normalizedString(data.categories).join(", ")
: "NA"}
{hoverEffect === index && isCloud ? (
{data.tags && (
{data.tags.slice(0, 1).map((tag, tagIndex) => (
{normalizedString(tag)}
{tagIndex < 1 ? ", " : ""}
))}
)}
) : (
{data.tags &&
data.tags.map((tag, tagIndex) => (
{normalizedString(tag)}
{tagIndex < data.tags.length - 1 ? ", " : ""}
))}
)}
{hoverEffect === index && isCloud && (
{allActivatedAppIds && allActivatedAppIds.includes(data.objectID) ? (
) : (
)}
)}
);
})}
)}
) : (
)
}
);
}
// Custom SearchBox Component
const SearchBox = ({ refine, searchQuery, setSearchQuery }) => {
const inputRef = useRef(null);
const [localQuery, setLocalQuery] = useState(searchQuery);
const location = useLocation();
// Initialize search when component mounts or when switching to Discover tab
useEffect(() => {
if (searchQuery) {
setLocalQuery(searchQuery);
refine(searchQuery); // This will trigger the Algolia search
}
}, [searchQuery, refine]);
// Debounced function to refine search
const debouncedRefine = useRef(
debounce((value) => {
setSearchQuery(value);
removeQuery("q");
refine(value);
}, 300)
).current;
useEffect(() => {
const urlSearchParams = new URLSearchParams(window.location.search);
const params = Object.fromEntries(urlSearchParams.entries());
const foundQuery = params["q"];
if (foundQuery) {
setLocalQuery(foundQuery);
debouncedRefine(foundQuery);
}
}, [debouncedRefine]);
useEffect(() => {
if (searchQuery === "") {
return;
}
if (inputRef.current) {
inputRef.current.focus();
}
}, [searchQuery]);
const handleChange = (event) => {
const value = event.target.value;
setLocalQuery(value);
debouncedRefine(value);
};
return (
{
if (event.key === "Enter") {
event.preventDefault();
}
}}
style={{ borderRadius: 8, height: 45, fontFamily: theme?.typography?.fontFamily, flex: 1 }}
InputProps={{
style: {
borderRadius: 8,
height: 45
},
endAdornment: (
{localQuery?.length === 0 ? : (
{
setLocalQuery('');
debouncedRefine('');
const queryParams = new URLSearchParams(location.search);
queryParams.delete('q');
window.history.replaceState({}, '', `${location.pathname}?${queryParams.toString()}`);
}}
/>
)}
),
}}
/>
);
};
const CustomSearchBox = connectSearchBox(SearchBox);
const CustomHits = connectHits(Hits);
// Custom Category Dropdown Component
const CategoryDropdown = ({ items, currentRefinement, refine }) => {
const handleChange = (event) => {
const value = event.target.value;
refine(value);
};
return (
{currentRefinement.length > 0 && (
refine([])}
/>
)}
);
};
const CustomCategoryDropdown = connectRefinementList(CategoryDropdown);
// Custom Label Dropdown Component
const LabelDropdown = ({ items, currentRefinement, refine }) => {
const handleChange = (event) => {
const value = event.target.value;
refine(value);
};
return (
{currentRefinement.length > 0 && (
refine([])}
/>
)}
);
};
const CustomLabelDropdown = connectRefinementList(LabelDropdown);
// New filter function
const filterApps = (apps, searchQuery, selectedCategory, selectedLabel) => {
if (!Array.isArray(apps)) return [];
return apps.filter((app) => {
const matchesSearchQuery = (
searchQuery === "" || // If searchQuery is empty, match all apps
app.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
(app.tags && app.tags.some(tag =>
tag.toLowerCase().includes(searchQuery.toLowerCase())
)) ||
(app.categories && app.categories.some((category) =>
category.toLowerCase().includes(searchQuery.toLowerCase())
))
);
const matchesSelectedCategories = (
selectedCategory.length === 0 || // If no category is selected, match all apps
(app.categories && app.categories.some(category =>
selectedCategory.includes(category)
))
);
const matchesSelectedTags = (
selectedLabel.length === 0 || // If no label is selected, match all apps
(app.tags && app.tags.some(tag =>
selectedLabel.includes(tag)
))
);
return matchesSearchQuery && matchesSelectedCategories && matchesSelectedTags;
});
};
// Add this new component for the app skeleton
const AppSkeleton = () => {
return (
);
};
// Replace the loading sections in the main component with this
const LoadingGrid = () => {
return (
{[...Array(7)].map((_, index) => (
))}
);
};
// Main Apps Component
const Apps2 = (props) => {
const { globalUrl, isLoaded, serverside, userdata, isLoggedIn, checkLogin } = props;
let navigate = useNavigate();
const { leftSideBarOpenByClick } = useContext(Context);
const location = useLocation();
const [searchQuery, setSearchQuery] = useState("");
const [selectedCategory, setSelectedCategory] = useState([]);
const [selectedLabel, setSelectedLabel] = useState([]);
const [currTab, setCurrTab] = useState(0);
const [categories, setCategories] = useState([]);
const [labels, setLabels] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [userApps, setUserApps] = useState([]);
const [orgApps, setOrgApps] = useState([]);
const [appsToShow, setAppsToShow] = useState([]);
const [deactivatedIndexes, setDeactivatedIndexes] = React.useState([]);
const [IsAnyAppActivated, setIsAnyAppActivated] = useState(false);
const [mouseHoverIndex, setMouseHoverIndex] = useState(-1);
var counted = 0;
const [showNoAppFound, setShowNoAppFound] = useState(false);
const [openModal, setOpenModal] = useState(false);
const [selectedApp, setSelectedApp] = useState(null);
const [appFramework, setAppFramework] = useState(undefined);
const [defaultSearch, setDefaultSearch] = useState("");
const [apps, setApps] = useState([]);
const [filteredApps, setFilteredApps] = useState([]);
const [appSearchLoading, setAppSearchLoading] = useState(false);
const [creatorProfile, setCreatorProfile] = useState({});
const [openApi, setOpenApi] = React.useState("");
const [loadAppsModalOpen, setLoadAppsModalOpen] = useState(false);
const [downloadBranch, setDownloadBranch] = useState("master");
const [field1, setField1] = useState("");
const [field2, setField2] = useState("");
const [validation, setValidation] = useState(null);
const [createAppModalOpen, setCreateAppModalOpen] = useState(false);
const baseRepository = "https://github.com/frikky/shuffle-apps";
const isCloud =
window.location.host === "localhost:3002" ||
window.location.host === "shuffler.io"
? true
: false;
// Set the current tab based on the query parameter
useEffect(() => {
const queryParams = new URLSearchParams(location.search);
const tabParam = queryParams.get('tab');
if (tabParam !== null && tabParam !== undefined) {
if (tabParam === 'org_apps') {
setCurrTab(0);
} else if (tabParam === 'my_apps') {
setCurrTab(1);
} else {
setCurrTab(2);
}
}
}, [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
useEffect(() => {
const fetchApps = async () => {
const baseUrl = globalUrl;
let url;
setIsLoading(true);
const userId = userdata?.id;
if (currTab === 1 && userId) {
url = `${baseUrl}/api/v1/users/${userId}/apps`;
} else if (currTab === 0) {
url = `${baseUrl}/api/v1/apps`;
}
try {
const response = await fetch(url, {
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
});
const data = await response.json();
if (currTab === 1) {
setAppsToShow(data);
setUserApps(data);
} else if (currTab === 0) {
setAppsToShow(data);
setOrgApps(data);
// For testing the empty state
// setAppsToShow([]);
// setOrgApps([]);
}
setIsLoading(false);
} catch (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();
}
}, [currTab, globalUrl, userdata?.id]); // Remove location.search dependency
// useEffect(() => {
// // setSearchQuery("");
// setSelectedCategory([]);
// setSelectedLabel([]);
// }, [currTab])
// Find top categories and tags based on the current tab
useEffect(() => {
if (currTab === 0 || currTab === 1) {
setCategories(findTopCategories());
setLabels(findTopTags());
}
}, [currTab, appsToShow])
const getUserProfile = (username) => {
if (serverside === true || !isCloud) {
setCreatorProfile({})
return;
}
fetch(`${globalUrl}/api/v1/users/creators/${username}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200 for WORKFLOW EXECUTION :O!");
}
return response.json();
})
.then((responseJson) => {
if (responseJson.success !== false) {
console.log("creator profile: ", responseJson)
setCreatorProfile(responseJson);
} else {
setCreatorProfile({})
}
})
.catch((error) => {
console.log(error);
setCreatorProfile({})
});
};
useEffect(() => {
if (serverside) {
return null;
}
}, [serverside]);
const getApps = () => {
// Get apps from localstorage
var storageApps = []
try {
const appstorage = localStorage.getItem("apps")
storageApps = JSON.parse(appstorage)
if (storageApps === null || storageApps === undefined || storageApps.length === 0) {
storageApps = []
} else {
setAppsToShow(storageApps)
setOrgApps(storageApps)
setApps(storageApps)
// setFilteredApps(storageApps)
// setAppSearchLoading(false)
}
} catch (e) {
//console.log("Failed to get apps from localstorage: ", e)
}
fetch(globalUrl + "/api/v1/apps", {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
})
.then((response) => {
setIsLoading(false);
if (response.status !== 200) {
console.log("Status not 200 for apps :O!");
//if (isCloud) {
// window.location.pathname = "/search";
//}
}
return response.json();
})
.then((responseJson) => {
//responseJson = sortByKey(responseJson, "large_image")
//responseJson = sortByKey(responseJson, "is_valid")
//setFilteredApps(responseJson.filter(app => !internalIds.includes(app.name) && !(!app.activated && app.generated)))
console.log("responseJson: from getApps ", responseJson)
var privateapps = [];
var valid = [];
var invalid = [];
for (var key in responseJson) {
const app = responseJson[key];
if (app.is_valid && !(!app.activated && app.generated)) {
privateapps.push(app);
} else if (
app.private_id !== undefined &&
app.private_id.length > 0
) {
valid.push(app);
} else {
invalid.push(app);
}
}
//console.log(privateapps)
//console.log(valid)
//console.log(invalid)
//console.log(privateapps)
//privateapps.reverse()
privateapps.push(...valid);
privateapps.push(...invalid);
console.log("privateapps: setting apps ", privateapps)
setAppsToShow(privateapps);
setOrgApps(privateapps);
setApps(privateapps);
// setCursearch("");
//handleSearchChange(event.target.value)
//setCursearch(event.target.value)
// setFilteredApps(privateapps);
if (privateapps.length > 0) {
if (selectedApp.id === undefined || selectedApp.id === null) {
if (privateapps[0].owner !== undefined && privateapps[0].owner !== null) {
getUserProfile(privateapps[0].owner);
}
// setContact(privateapps[0].contact_info)
// setSelectedApp(privateapps[0]);
// setSharingConfiguration(privateapps[0].sharing === true ? "public" : "you")
}
// if (
// privateapps[0].actions !== null &&
// privateapps[0].actions.length > 0
// ) {
// setSelectedAction(privateapps[0].actions[0]);
// } else {
// setSelectedAction({});
// }
}
if (privateapps.length > 0 && storageApps.length === 0) {
try {
localStorage.setItem("apps", JSON.stringify(privateapps))
} catch (e) {
console.log("Failed to set apps in localstorage: ", e)
}
}
//setTimeout(() => {
// setFirstLoad(false)
//}, 5000)
})
.catch((error) => {
toast(error.toString());
setIsLoading(false);
});
};
// Locally hotloads app from folder
const hotloadApps = () => {
toast("Hotloading apps from location in .env");
setIsLoading(true);
fetch(globalUrl + "/api/v1/apps/run_hotload", {
method: "POST",
mode: "cors",
headers: {
Accept: "application/json",
},
credentials: "include",
})
.then((response) => {
setIsLoading(false);
if (response.status === 200) {
//toast("Hotloaded apps!")
getApps();
}
return response.json();
})
.then((responseJson) => {
if (responseJson.success === true) {
toast("Successfully finished hotload");
} else {
console.log("failed hotload: ", responseJson)
// toast(`Failed hotload: ${responseJson.reason}`);
//(responseJson.reason !== undefined && responseJson.reason.length > 0) {
}
})
.catch((error) => {
toast(`Failed hotload: ${error.toString()}`);
});
};
// Load data e.g. from github
const getSpecificApps = (url, forceUpdate) => {
setValidation(true);
setIsLoading(true);
//start()
const parsedData = {
url: url,
branch: downloadBranch || "master",
};
if (field1.length > 0) {
parsedData["field_1"] = field1;
}
if (field2.length > 0) {
parsedData["field_2"] = field2;
}
parsedData["force_update"] = forceUpdate;
toast("Getting specific apps from your URL.");
var cors = "cors";
fetch(globalUrl + "/api/v1/apps/get_existing", {
method: "POST",
mode: "cors",
headers: {
Accept: "application/json",
},
body: JSON.stringify(parsedData),
credentials: "include",
})
.then((response) => {
if (response.status === 200) {
toast("Loaded existing apps!");
}
//stop()
setIsLoading(false);
setValidation(false);
return response.json();
})
.then((responseJson) => {
console.log("DATA: ", responseJson);
if (responseJson.reason !== undefined) {
toast("Failed loading: " + responseJson.reason);
}
})
.catch((error) => {
console.log("ERROR: ", error.toString());
//toast(error.toString());
//stop()
setIsLoading(false);
setValidation(false);
});
};
const handleGithubValidation = (forceUpdate) => {
getSpecificApps(openApi, forceUpdate);
setLoadAppsModalOpen(false);
};
const appsModalLoad = loadAppsModalOpen ? (
) : null;
const findTopCategories = () => {
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
if (Array.isArray(apps)) {
apps.forEach((app) => {
const categories = app.categories;
if (categories && categories.length > 0) {
categories.forEach((category) => {
categoryCountMap[category] = (categoryCountMap[category] || 0) + 1;
});
}
});
const categoryArray = Object.keys(categoryCountMap).map((category) => ({
category,
count: categoryCountMap[category],
}));
categoryArray.sort((a, b) => b.count - a.count);
const topCategories = categoryArray.slice(0, 7);
return topCategories;
}
};
const findTopTags = () => {
const tagCountMap = {};
const apps = currTab === 1 ? userApps : orgApps;
if (Array.isArray(apps)) {
apps.forEach((app) => {
const tags = app.tags;
if (tags && tags.length > 0) {
tags.forEach((tag) => {
tagCountMap[tag] = (tagCountMap[tag] || 0) + 1;
});
}
});
}
const tagArray = Object.keys(tagCountMap).map((tag) => ({
tag,
count: tagCountMap[tag],
}));
tagArray.sort((a, b) => b.count - a.count);
const topTags = tagArray.slice(0, 8);
return topTags;
};
const handleCreateApp = (e) => {
e.preventDefault();
setCreateAppModalOpen(true);
// setOpenModal(true);
};
useEffect(() => {
const apps = currTab === 1 ? userApps : orgApps;
const filteredUserAppdata = filterApps(apps, searchQuery, selectedCategory, selectedLabel);
setAppsToShow(filteredUserAppdata);
}, [searchQuery, selectedCategory, selectedLabel, currTab]);
const handleTabChange = (event, newTab) => {
setCurrTab(newTab);
// Apply filters immediately when changing tabs
if (newTab === 0) {
const filteredOrgApps = filterApps(orgApps, searchQuery, selectedCategory, selectedLabel);
setAppsToShow(filteredOrgApps);
} else if (newTab === 1) {
const filteredUserApps = filterApps(userApps, searchQuery, selectedCategory, selectedLabel);
setAppsToShow(filteredUserApps);
}
// Update URL query params based on tab index
const tabMapping = {
0: 'org_apps',
1: 'my_apps',
2: 'all_apps'
};
const queryParams = new URLSearchParams(location.search);
queryParams.set('tab', tabMapping[newTab]);
// Maintain search query in URL regardless of tab
if (searchQuery) {
queryParams.set('q', searchQuery);
} else {
queryParams.delete('q');
}
navigate(`${location.pathname}?${queryParams.toString()}`);
};
// Update useEffect for filtering without URL manipulation
useEffect(() => {
if (currTab === 2) return; // Skip for "Discover Apps" tab as it uses Algolia
const apps = currTab === 1 ? userApps : orgApps;
const filteredApps = filterApps(apps, searchQuery, selectedCategory, selectedLabel);
setAppsToShow(filteredApps);
}, [searchQuery, selectedCategory, selectedLabel, currTab, userApps, orgApps]);
// Add URL update only when search is performed
const handleSearchChange = (event) => {
const newSearchQuery = event.target.value;
setSearchQuery(newSearchQuery);
// Update URL only when user performs search
const queryParams = new URLSearchParams(location.search);
if (newSearchQuery) {
queryParams.set('q', newSearchQuery);
} else {
queryParams.delete('q');
}
window.history.replaceState({}, '', `${location.pathname}?${queryParams.toString()}`);
};
const boxStyle = {
color: "white",
display: "flex",
flexDirection: "column",
height: "100%",
width: "100%",
margin: "auto",
maxWidth: "70%",
fontFamily: theme?.typography?.fontFamily,
// padding: '20px 380px',
};
const handleCategoryChange = (event) => {
const value = event.target.value;
setSelectedCategory(value);
};
const handleLabelChange = (event) => {
const value = event.target.value;
setSelectedLabel(value);
};
const handleAppClick = (app) => {
setSelectedApp(app);
setOpenModal(true);
}
const handleAppModalClose = () => {
setOpenModal(false)
}
return (
setCreateAppModalOpen(false)}
theme={theme}
globalUrl={globalUrl}
isCloud={isCloud}
/>
{appsModalLoad}
Apps
{isCloud ? null : (
{userdata === undefined || userdata === null || isLoading ? null : (
)}
{userdata === undefined || userdata === null || userdata.admin === "false" ? null :
}
)}
handleTabChange(event, newTab)}
TabIndicatorProps={{ style: { height: '3px', borderRadius: 10, backgroundColor: "#FF8544" } }}
style={{ fontFamily: theme?.typography?.fontFamily }}
>
{(currTab === 0 || currTab === 1) ? (
{
if (event.key === "Enter") {
event.preventDefault();
}
}}
limit={5}
InputProps={{
style: {
borderRadius: 8,
height: 45
},
endAdornment: (
{searchQuery.length === 0 ? : (
{
setSearchQuery("")
const queryParams = new URLSearchParams(location.search);
queryParams.delete('q');
window.history.replaceState({}, '', `${location.pathname}?${queryParams.toString()}`);
}}
/>
)}
),
}}
/>
) : (
)}
{currTab === 2 ? (
) : (
<>
{selectedCategory.length > 0 && (
setSelectedCategory([])}
/>
)}
>
)}
{currTab === 2 ? (
) : (
<>
{selectedLabel.length > 0 && (
setSelectedLabel([])}
/>
)}
>
)}
}
>
Create an App
{
currTab === 0 && (
{isLoading ? (
) : (
<>
{appsToShow?.length > 0 && appsToShow !== undefined && !isLoading ? (
{appsToShow.map((data, index) => (
))}
) : (
)}
>
)}
)
}
{
currTab === 1 && (
{isLoading ? (
) : (
<>
{appsToShow?.length > 0 && appsToShow !== undefined ? (
{appsToShow.map((data, index) => (
))}
) : (
)}
>
)}
)
}
{
currTab === 2 &&
}
);
};
export default Apps2;