diff --git a/client/admin/apps/AppMenu.js b/client/admin/apps/AppMenu.js index c0030011bfc5..a7cb1fbe3cc4 100644 --- a/client/admin/apps/AppMenu.js +++ b/client/admin/apps/AppMenu.js @@ -174,7 +174,7 @@ function AppMenu({ app, ...props }) { handleUninstall, ]); - return ; + return ; } export default AppMenu; diff --git a/client/admin/apps/AppProvider.tsx b/client/admin/apps/AppProvider.tsx index 5c4b6b76d4e6..2cb3ab67eaf9 100644 --- a/client/admin/apps/AppProvider.tsx +++ b/client/admin/apps/AppProvider.tsx @@ -24,11 +24,13 @@ type App = { export type AppDataContextValue = { data: App[]; dataCache: any; + finishedLoading: boolean; } export const AppDataContext = createContext({ data: [], dataCache: [], + finishedLoading: false, }); type ListenersMapping = { @@ -51,6 +53,7 @@ const registerListeners = (listeners: ListenersMapping): (() => void) => { const AppProvider: FunctionComponent = ({ children }) => { const [data, setData] = useState(() => []); + const [finishedLoading, setFinishedLoading] = useState(() => false); const [dataCache, setDataCache] = useState(() => []); const ref = useRef(data); @@ -63,12 +66,17 @@ const AppProvider: FunctionComponent = ({ children }) => { const getDataCopy = (): typeof ref.current => ref.current.slice(0); useEffect(() => { + const updateData = (data: App[]): void => { + setData(data.sort((a, b) => (a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1))); + invalidateData(); + }; + const handleAppAddedOrUpdated = async (appId: string): Promise => { try { const { status, version } = await Apps.getApp(appId); const app = await Apps.getAppFromMarketplace(appId, version); const updatedData = getDataCopy(); - const index = updatedData.findIndex(({ id }) => id === appId); + const index = updatedData.findIndex(({ id }: {id: string}) => id === appId); updatedData[index] = { ...app, installed: true, @@ -88,7 +96,7 @@ const AppProvider: FunctionComponent = ({ children }) => { APP_UPDATED: handleAppAddedOrUpdated, APP_REMOVED: (appId: string): void => { const updatedData = getDataCopy(); - const index = updatedData.findIndex(({ id }) => id === appId); + const index = updatedData.findIndex(({ id }: {id: string}) => id === appId); if (!updatedData[index]) { return; } @@ -106,7 +114,7 @@ const AppProvider: FunctionComponent = ({ children }) => { }, APP_STATUS_CHANGE: ({ appId, status }: {appId: string; status: unknown}): void => { const updatedData = getDataCopy(); - const app = updatedData.find(({ id }) => id === appId); + const app = updatedData.find(({ id }: {id: string}) => id === appId); if (!app) { return; @@ -124,11 +132,18 @@ const AppProvider: FunctionComponent = ({ children }) => { (async (): Promise => { try { - const [marketplaceApps, installedApps] = await Promise.all([ - Apps.getAppsFromMarketplace() as Promise, - Apps.getApps() as Promise, - ]); - const appsData = marketplaceApps.map((app) => { + const installedApps = await Apps.getApps().then((result) => { + let apps: App[] = []; + if (result.length) { + apps = result.map((current: App) => ({ ...current, installed: true, marketplace: false })); + updateData(apps); + } + return apps; + }) as App[]; + + const marketplaceApps = await Apps.getAppsFromMarketplace() as App[]; + + const appsData = marketplaceApps.length ? marketplaceApps.map((app) => { const appIndex = installedApps.findIndex(({ id }) => id === app.id); if (!installedApps[appIndex]) { return { @@ -148,14 +163,14 @@ const AppProvider: FunctionComponent = ({ children }) => { bundledIn: app.bundledIn, marketplaceVersion: app.version, }; - }); + }) : []; if (installedApps.length) { - appsData.push(...installedApps.map((current) => ({ ...current, installed: true, marketplace: false }))); + appsData.push(...installedApps); } - setData(appsData.sort((a, b) => (a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1))); - invalidateData(); + updateData(appsData); + setFinishedLoading(true); } catch (e) { handleAPIError(e); unregisterListeners(); @@ -163,9 +178,9 @@ const AppProvider: FunctionComponent = ({ children }) => { })(); return unregisterListeners; - }, []); + }, [setData, setFinishedLoading]); - return ; + return ; }; export default AppProvider; diff --git a/client/admin/apps/MarketplaceTable.js b/client/admin/apps/MarketplaceTable.js index b6d20c43f679..8e7f6a6936eb 100644 --- a/client/admin/apps/MarketplaceTable.js +++ b/client/admin/apps/MarketplaceTable.js @@ -124,7 +124,7 @@ function MarketplaceTable() { const [sort, setSort] = useState(['name', 'asc']); const { text, current, itemsPerPage } = params; - const { data, dataCache } = useContext(AppDataContext); + const { data, dataCache, finishedLoading } = useContext(AppDataContext); const [filteredApps, filteredAppsCount] = useFilteredApps({ filterFunction: useCallback( (text) => ({ name, marketplace }) => marketplace !== false && name.toLowerCase().indexOf(text.toLowerCase()) > -1, @@ -174,7 +174,7 @@ function MarketplaceTable() { {t('Status')} } - results={filteredApps} + results={(filteredApps?.length || finishedLoading) && filteredApps} total={filteredAppsCount} setParams={setParams} params={params} diff --git a/client/admin/users/UserInfoActions.js b/client/admin/users/UserInfoActions.js index 2f210645da4c..c02fc692c611 100644 --- a/client/admin/users/UserInfoActions.js +++ b/client/admin/users/UserInfoActions.js @@ -256,7 +256,7 @@ export const UserInfoActions = ({ username, _id, isActive, isAdmin, onChange, .. { actions && actions.map((action, index) => ())} - { moreActions && } + { moreActions && } { modal } diff --git a/client/fuselage-hooks.d.ts b/client/fuselage-hooks.d.ts deleted file mode 100644 index 2bef8fec95ab..000000000000 --- a/client/fuselage-hooks.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '@rocket.chat/fuselage-hooks' { - export const useDebouncedCallback: (fn: (...args: any[]) => any, ms: number, deps: any[]) => (...args: any[]) => any; - export const useMutableCallback: (fn: (...args: any[]) => any) => (...args: any[]) => any; -} diff --git a/package-lock.json b/package-lock.json index 4e2a525f86f3..1c8ef9a9592d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2728,9 +2728,9 @@ } }, "@rocket.chat/css-in-js": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/css-in-js/-/css-in-js-0.10.0.tgz", - "integrity": "sha512-Zo/18kmiRtuGGzFtCYJz1DGs1+j6MBTKWM/n6+bmgw3ubCuSsG1t12KtJl87BBwVnJwC7W+oxqesM8llUF5Odw==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/css-in-js/-/css-in-js-0.13.0.tgz", + "integrity": "sha512-WnwjR1Ye7bGuj2YOaaros9IqDRpLFC8mBShoQ5vpV5MvBaNHDUu9l94pAoeSqkl5r7LMkLiVCFbMVUBivWaTqQ==", "requires": { "@emotion/hash": "^0.8.0", "@emotion/stylis": "^0.8.5" @@ -2746,25 +2746,36 @@ } }, "@rocket.chat/fuselage": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage/-/fuselage-0.10.0.tgz", - "integrity": "sha512-P2LO5g6pQvUfE1Or1AjgFZWV45v+6htGejwRovPtZRbRAngHT9dJcTfDfykjncCEptZi6xBvEh+pkCgcZ1fCng==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage/-/fuselage-0.13.0.tgz", + "integrity": "sha512-FB3usvEBHuoJYwEW/tCRNRjKxiiWEwx3SKrn11FsVCEuUluk7a4HtaY73TOSVd1/3nv3AzMYFG1DZde1TGixTA==", "requires": { - "@rocket.chat/css-in-js": "^0.10.0", - "@rocket.chat/fuselage-tokens": "^0.10.0", + "@rocket.chat/css-in-js": "^0.13.0", + "@rocket.chat/fuselage-tokens": "^0.13.0", "invariant": "^2.2.4", "react-keyed-flatten-children": "^1.2.0" } }, "@rocket.chat/fuselage-hooks": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-hooks/-/fuselage-hooks-0.10.0.tgz", - "integrity": "sha512-oU3MgNakM32yqwXVS7lXnOvYjwNtkOpext1NMsAsirjfvhFz+CwdFEqLgn6uGVohoiR3KvV4xJSN/ZaF5WhRCQ==" + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-hooks/-/fuselage-hooks-0.13.0.tgz", + "integrity": "sha512-d+IH+WEwjduGSfuIyAeXCGIyj7xypLNGEMEeNeNbmmCk7FBtK5pz4TCa2Hzx+2hAzQptPJOVWR1oKWMps4d7lA==", + "requires": { + "@rocket.chat/fuselage-tokens": "^0.13.0", + "use-subscription": "^1.4.1" + }, + "dependencies": { + "@rocket.chat/fuselage-tokens": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-tokens/-/fuselage-tokens-0.13.0.tgz", + "integrity": "sha512-C0BCyt+k0ZPU31LZNPoxnIaH08OCNNJa8nHoky7SR95Tq/Y9U6I42Yh11q9lc05KhoOGcVkenm4k+v8eBP5ARw==" + } + } }, "@rocket.chat/fuselage-polyfills": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-polyfills/-/fuselage-polyfills-0.10.0.tgz", - "integrity": "sha512-WmWLWXed4vKySWtvDr9umFBcZ7tk0MWL7gFGsDV0tSuQpBjRGW3gfOBkGnvay0DG+UzJbw9pLUWXAbArBNDCNw==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-polyfills/-/fuselage-polyfills-0.13.0.tgz", + "integrity": "sha512-moaIdPj9G4xWKu8bkXJaXiLOHOSkLVXJ+zciOKyD8Vet1D8bFqNdSgRC6nc50CXtW6Imk98bl/as/M228gOAfw==", "requires": { "@juggle/resize-observer": "^3.1.2", "clipboard-polyfill": "^2.8.6", @@ -2772,22 +2783,22 @@ } }, "@rocket.chat/fuselage-tokens": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-tokens/-/fuselage-tokens-0.10.0.tgz", - "integrity": "sha512-q7LHbeGHqOt+6g05FNAPkR8hEknxHrhvIp4K4DlLWaPrLCySdPp1lmXZuSO+AoGl69Y/e8BdWmK46K2PAhzwGw==" + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-tokens/-/fuselage-tokens-0.13.0.tgz", + "integrity": "sha512-C0BCyt+k0ZPU31LZNPoxnIaH08OCNNJa8nHoky7SR95Tq/Y9U6I42Yh11q9lc05KhoOGcVkenm4k+v8eBP5ARw==" }, "@rocket.chat/fuselage-ui-kit": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-ui-kit/-/fuselage-ui-kit-0.10.0.tgz", - "integrity": "sha512-2wrJjcKUN0fOPUhllMA/+nJkJLlz7GZ5NI+eG2snUjuaEyi8LUWGqdd7Xqx4hZOxm4wG24hFJaxc4WQb4kCO2Q==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-ui-kit/-/fuselage-ui-kit-0.13.0.tgz", + "integrity": "sha512-mXWJMuQ3HU8Jfq28MUS9flLOi0yBBndF3ZZg8MszLJA9xI8r8hls6edGP1S0Hd6GzKDxI3pEIrJSRQbpAX9+ug==", "requires": { - "@rocket.chat/ui-kit": "^0.10.0" + "@rocket.chat/ui-kit": "^0.13.0" } }, "@rocket.chat/icons": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/icons/-/icons-0.10.0.tgz", - "integrity": "sha512-gtXIIQf8pCLVLcUtd7cbt/OukM9XlnmK9+du4utc5LIvuNHJaaekSFv9Bg3URy41P/8Ss9dc6FmDnlPna4F19g==" + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/icons/-/icons-0.13.0.tgz", + "integrity": "sha512-gZ9ydWhmSLU29PmRX5p3mFS5wwAKYf/dwUaqyoPWXAwehiZGAj5SDFcWDKeqkh5FH9D8lCRMHVNBLBVZI5xrKw==" }, "@rocket.chat/livechat": { "version": "1.6.0", @@ -2896,9 +2907,9 @@ } }, "@rocket.chat/ui-kit": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/ui-kit/-/ui-kit-0.10.0.tgz", - "integrity": "sha512-zCMDsxdmUvKD9zzyskiV8kThIcsAaXvZT1LzFk4yLq2Wh5meTJ+TClgt9Zn3pBdO/2mwdjBueiGc+k+vqNIqRg==" + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/ui-kit/-/ui-kit-0.13.0.tgz", + "integrity": "sha512-xY8xc98KGshyOJM2GCLnYE9TTevViO7bVeY1HVRB2anDutgHRFgt6qFW1eiaB8s+6J+5I6VTE3k0jzQeaRsAeg==" }, "@samverschueren/stream-to-observable": { "version": "0.3.0", diff --git a/package.json b/package.json index 800cc6dbf783..a2da8316fb7c 100644 --- a/package.json +++ b/package.json @@ -129,14 +129,13 @@ "@nivo/line": "^0.61.1", "@nivo/pie": "^0.61.1", "@rocket.chat/apps-engine": "1.16.0-alpha.3466", - "@rocket.chat/css-in-js": "^0.10.0", - "@rocket.chat/fuselage": "^0.10.0", - "@rocket.chat/fuselage-hooks": "^0.10.0", - "@rocket.chat/fuselage-polyfills": "^0.10.0", - "@rocket.chat/fuselage-ui-kit": "^0.10.0", - "@rocket.chat/icons": "^0.10.0", - "@rocket.chat/mp3-encoder": "^0.13.0", - "@rocket.chat/ui-kit": "^0.10.0", + "@rocket.chat/css-in-js": "^0.13.0", + "@rocket.chat/fuselage": "^0.13.0", + "@rocket.chat/fuselage-hooks": "^0.13.0", + "@rocket.chat/fuselage-polyfills": "^0.13.0", + "@rocket.chat/fuselage-ui-kit": "^0.13.0", + "@rocket.chat/icons": "^0.13.0", + "@rocket.chat/ui-kit": "^0.13.0", "@slack/client": "^4.8.0", "@types/fibers": "^3.1.0", "@types/underscore.string": "0.0.38",