diff --git a/client/src/components/Home/Home.tsx b/client/src/components/Home/Home.tsx index fc154724..4e3c4784 100644 --- a/client/src/components/Home/Home.tsx +++ b/client/src/components/Home/Home.tsx @@ -52,13 +52,6 @@ const Home = (props: ComponentProps): JSX.Element => { // Local search query const [localSearch, setLocalSearch] = useState(null); - // Load app categories - useEffect(() => { - if (appCategories.length === 0) { - getAppCategories(); - } - }, [getAppCategories]); - // Load apps useEffect(() => { if (apps.length === 0) { @@ -66,13 +59,6 @@ const Home = (props: ComponentProps): JSX.Element => { } }, [getApps]); - // Load bookmark categories - useEffect(() => { - if (bookmarkCategories.length === 0) { - getBookmarkCategories(); - } - }, [getBookmarkCategories]); - // Load bookmarks useEffect(() => { if (bookmarks.length === 0) { @@ -120,10 +106,11 @@ const Home = (props: ComponentProps): JSX.Element => { return [category]; }; - const categoryContainsItems = (category: Category, allItems: App[] | Bookmark[]): boolean => { - if (category.apps?.length > 0) return true; + const categoryContainsPinnedItems = (category: Category, allItems: App[] | Bookmark[]): boolean => { + if (category.apps?.filter((app: App) => app.isPinned).length > 0) return true; + if (category.bookmarks?.filter((bookmark: Bookmark) => bookmark.isPinned).length > 0) return true; if (category.id < 0) { // Is a default category - return allItems.findIndex((item: App | Bookmark) => item.categoryId === category.id) >= 0; + return allItems.findIndex((item: App | Bookmark) => item.categoryId === category.id && item.isPinned) >= 0; } return false; }; @@ -160,7 +147,7 @@ const Home = (props: ComponentProps): JSX.Element => { category.isPinned && categoryContainsItems(category, apps)) + ? appCategories.filter((category: Category) => category.isPinned && categoryContainsPinnedItems(category, apps)) : searchInCategories(localSearch, appCategories) } apps={ @@ -189,7 +176,7 @@ const Home = (props: ComponentProps): JSX.Element => { category.isPinned && categoryContainsItems(category, bookmarks)) + ? bookmarkCategories.filter((category: Category) => category.isPinned && categoryContainsPinnedItems(category, bookmarks)) : searchInCategories(localSearch, bookmarkCategories) } bookmarks={ diff --git a/client/src/store/actions/app.ts b/client/src/store/actions/app.ts index 58d0f0ea..8d616ac7 100644 --- a/client/src/store/actions/app.ts +++ b/client/src/store/actions/app.ts @@ -26,6 +26,8 @@ export const getApps = () => async (dispatch: Dispatch) => { type: ActionTypes.getAppsSuccess, payload: res.data.data, }); + + await getCategories(dispatch); } catch (err) { console.log(err); } @@ -49,17 +51,21 @@ export const getAppCategories = () => async (dispatch: Dispatch) => { }); try { - const res = await axios.get>("/api/categories/apps"); - - dispatch>({ - type: ActionTypes.getAppCategoriesSuccess, - payload: res.data.data - }); + await getCategories(dispatch); } catch (err) { console.log(err); } }; +async function getCategories(dispatch: Dispatch) { + const res = await axios.get>("/api/categories/apps"); + + dispatch>({ + type: ActionTypes.getAppCategoriesSuccess, + payload: res.data.data + }); +} + /** * ADD CATEGORY */ diff --git a/client/src/store/actions/bookmark.ts b/client/src/store/actions/bookmark.ts index 658f002c..fc5256a4 100644 --- a/client/src/store/actions/bookmark.ts +++ b/client/src/store/actions/bookmark.ts @@ -26,6 +26,8 @@ export const getBookmarks = () => async (dispatch: Dispatch) => { type: ActionTypes.getBookmarksSuccess, payload: res.data.data, }); + + await getCategories(dispatch); } catch (err) { console.log(err); } @@ -49,17 +51,21 @@ export const getBookmarkCategories = () => async (dispatch: Dispatch) => { }); try { - const res = await axios.get>("/api/categories/bookmarks"); - - dispatch>({ - type: ActionTypes.getBookmarkCategoriesSuccess, - payload: res.data.data - }); + await getCategories(dispatch); } catch (err) { console.log(err); } }; +async function getCategories(dispatch: Dispatch) { + const res = await axios.get>("/api/categories/bookmarks"); + + dispatch>({ + type: ActionTypes.getBookmarkCategoriesSuccess, + payload: res.data.data + }); +} + /** * ADD CATEGORY */ @@ -473,3 +479,4 @@ export const reorderBookmarkCategories = console.log(err); } }; + diff --git a/controllers/apps.js b/controllers/apps.js index 86fdd097..f880a079 100644 --- a/controllers/apps.js +++ b/controllers/apps.js @@ -217,6 +217,12 @@ async function retrieveDockerApps(apps, orderType, unpinStoppedApps) { for (let i = 0; i < names.length; i++) { const category = categoriesLabels[i] ? categories.find(category => category.name.toUpperCase() === categoriesLabels[i].toUpperCase()) : dockerDefaultCategory; + if (!category) { + category = await createNewCategory(categoriesLabels[i]); + if (category) { + categories.push(category); + } + } dockerApps.push({ name: names[i] || names[0], @@ -250,6 +256,15 @@ async function retrieveDockerApps(apps, orderType, unpinStoppedApps) { return apps; } +async function createNewCategory(newCategoryName) { + return await Category.create({ + name: newCategoryName, + type: 'apps', + isPinned: true, + orderId: Number.MAX_SAFE_INTEGER //New category will always be last and can then be re-ordered manually by user + }); +} + async function retrieveKubernetesApps(apps, orderType, unpinStoppedApps) { let ingresses = null; @@ -295,6 +310,12 @@ async function retrieveKubernetesApps(apps, orderType, unpinStoppedApps) { for (let i = 0; i < names.length; i++) { const category = categoriesLabels[i] ? categories.find(category => category.name.toUpperCase() === categoriesLabels[i].toUpperCase()) : kubernetesDefaultCategory; + if (!category) { + category = await createNewCategory(categoriesLabels[i]); + if (category) { + categories.push(category); + } + } kubernetesApps.push({ name: names[i] || names[0],