Skip to content

Commit 87f6468

Browse files
authored
feat(compass-workspaces): introduce workspaces plugin; implement single top level tabs COMPASS-7354 (#5169)
* feat(compass-workspaces): introduce workspaces plugin; implement single top level tabs * chore(compass-components): redesign workspace tabs * chore(sidebar): add Performance item to the sidebar * chore(workspaces): workspace type based on tab plugins * chore: depcheck * chore: more depcheck * chore: lint and broken unit test fixes * chore(workspaces): add missing event listeners * chore(app-registry): add activate helpers * chore(e2e): update e2e tests for the new workspace tabs * chore(workspaces): empty state and plus button behavior * chore(workspaces): add tabs tests * chore(components): fix tab focus state and visible focus color * chore(components): update tab test * chore(app-stores): show error toast if failed to get instance info on first try * chore(collection): remove duplicated prop from expression * chore(sidebar): be more explicit about default value for instance props * fix(workspaces): when opening an existing workspace, prioritize current active one when selecting * fix(workspaces): handle empty tabs state on namespace remove
1 parent f93ded3 commit 87f6468

File tree

112 files changed

+2570
-3158
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+2570
-3158
lines changed

package-lock.json

Lines changed: 340 additions & 91 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/collection-model/index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ interface Collection {
8888
dataService: DataService;
8989
}): Promise<CollectionMetadata>;
9090
on(evt: string, fn: (...args: any) => void);
91+
off(evt: string, fn: (...args: any) => void);
92+
removeListener(evt: string, fn: (...args: any) => void);
9193
toJSON(opts?: { derived: boolean }): this;
9294
}
9395

packages/compass-app-stores/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,14 @@
7676
"xvfb-maybe": "^0.2.1"
7777
},
7878
"dependencies": {
79+
"@mongodb-js/compass-components": "^1.19.0",
7980
"@mongodb-js/compass-logging": "^1.2.6",
8081
"hadron-app-registry": "^9.0.14",
8182
"mongodb-data-service": "^22.15.1",
8283
"mongodb-instance-model": "^12.15.1"
8384
},
8485
"peerDependencies": {
86+
"@mongodb-js/compass-components": "^1.19.0",
8587
"@mongodb-js/compass-logging": "^1.2.6",
8688
"hadron-app-registry": "^9.0.14",
8789
"mongodb-data-service": "^22.15.1",

packages/compass-app-stores/src/stores/instance-store.ts

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import toNS from 'mongodb-ns';
44
import type { DataService } from 'mongodb-data-service';
55
import type { AppRegistry } from 'hadron-app-registry';
66
import type { LoggerAndTelemetry } from '@mongodb-js/compass-logging/provider';
7+
import { openToast } from '@mongodb-js/compass-components';
78

89
function serversArray(
910
serversMap: NonNullable<
@@ -57,6 +58,8 @@ export function createInstanceStore({
5758
'dataService'
5859
> = {}
5960
) {
61+
const isFirstRun = instance.status === 'initial';
62+
6063
try {
6164
await instance.refresh({ dataService, ...refreshOptions });
6265

@@ -71,6 +74,26 @@ export function createInstanceStore({
7174
dataService,
7275
errorMessage: err.message,
7376
});
77+
78+
// The `instance.refresh` method is catching all expected errors: we treat
79+
// a lot of metadata as optional so failing to fetch it shouldn't throw.
80+
// In most cases if this failed on subsequent runs, user is probably
81+
// already in a state that will show them a more specified error (like
82+
// seeing some server error trying to refresh collection list in cases
83+
// that something happened with the server after connection). However if
84+
// we are fetching instance info for the first time (as indicated by the
85+
// initial instance status) and we ended up here, there might be no other
86+
// place for the user to see the error. This is a very rare case, but we
87+
// don't want to leave the user without any indication that something went
88+
// wrong and so we show an toast with the error message
89+
if (isFirstRun) {
90+
const { name, message } = err as Error;
91+
openToast('instance-refresh-failed', {
92+
title: 'Failed to retrieve server info',
93+
description: `${name}: ${message}`,
94+
variant: 'important',
95+
});
96+
}
7497
}
7598
}
7699

@@ -268,13 +291,6 @@ export function createInstanceStore({
268291

269292
const onCollectionRenamed = voidify(
270293
async ({ from, to }: { from: string; to: string }) => {
271-
// we must fetch the old collection's metadata before refreshing because refreshing the
272-
// collection metadata will remove the old collection from the model.
273-
const metadata = await fetchCollectionMetadata(from);
274-
appRegistry.emit('refresh-collection-tabs', {
275-
metadata,
276-
newNamespace: to,
277-
});
278294
const { database } = toNS(from);
279295
await refreshNamespace({
280296
ns: to,
@@ -315,31 +331,6 @@ export function createInstanceStore({
315331
});
316332
onAppRegistryEvent('collection-created', onCollectionCreated);
317333

318-
const onActiveCollectionDropped = (ns: string) => {
319-
// This callback will fire after drop collection happened, we force it into
320-
// a microtask to allow drop collections event handler to force start
321-
// databases and collections list update before we run our check here
322-
queueMicrotask(
323-
voidify(async () => {
324-
const { database } = toNS(ns);
325-
await instance.fetchDatabases({ dataService });
326-
const db = instance.databases.get(database);
327-
await db?.fetchCollections({ dataService });
328-
if (db?.collectionsLength) {
329-
appRegistry.emit('select-database', database);
330-
} else {
331-
appRegistry.emit('open-instance-workspace', 'Databases');
332-
}
333-
})
334-
);
335-
};
336-
onAppRegistryEvent('active-collection-dropped', onActiveCollectionDropped);
337-
338-
const onActiveDatabaseDropped = () => {
339-
appRegistry.emit('open-instance-workspace', 'Databases');
340-
};
341-
onAppRegistryEvent('active-database-dropped', onActiveDatabaseDropped);
342-
343334
/**
344335
* Opens collection in the current active tab. No-op if currently open tab has
345336
* the same namespace. Additional `query` and `agrregation` props can be

packages/compass-collection/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,21 @@
5656
"reformat": "npm run eslint . -- --fix && npm run prettier -- --write ."
5757
},
5858
"peerDependencies": {
59+
"@mongodb-js/compass-app-stores": "^7.6.1",
5960
"@mongodb-js/compass-components": "^1.19.0",
6061
"@mongodb-js/compass-logging": "^1.2.6",
61-
"bson": "^6.2.0",
6262
"compass-preferences-model": "^2.15.6",
6363
"hadron-app-registry": "^9.0.14",
64+
"mongodb-data-service": "^22.15.1",
6465
"react": "^17.0.2"
6566
},
6667
"dependencies": {
68+
"@mongodb-js/compass-app-stores": "^7.6.1",
6769
"@mongodb-js/compass-components": "^1.19.0",
6870
"@mongodb-js/compass-logging": "^1.2.6",
69-
"bson": "^6.2.0",
7071
"compass-preferences-model": "^2.15.6",
71-
"hadron-app-registry": "^9.0.14"
72+
"hadron-app-registry": "^9.0.14",
73+
"mongodb-data-service": "^22.15.1"
7274
},
7375
"devDependencies": {
7476
"@mongodb-js/eslint-config-compass": "^1.0.11",
@@ -90,7 +92,6 @@
9092
"eslint": "^7.25.0",
9193
"mocha": "^10.2.0",
9294
"mongodb-collection-model": "^5.15.1",
93-
"mongodb-data-service": "^22.15.1",
9495
"mongodb-instance-model": "^12.15.1",
9596
"mongodb-ns": "^2.4.0",
9697
"numeral": "^2.0.6",

packages/compass-collection/src/components/collection-tab.tsx

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useEffect } from 'react';
2-
import { connect, Provider } from 'react-redux';
2+
import { connect } from 'react-redux';
33
import type { CollectionTabPluginMetadata } from '../modules/collection-tab';
44
import {
55
returnToView,
@@ -14,8 +14,8 @@ import {
1414
import { css, ErrorBoundary, TabNavBar } from '@mongodb-js/compass-components';
1515
import CollectionHeader from './collection-header';
1616
import { createLoggerAndTelemetry } from '@mongodb-js/compass-logging';
17-
import type { configureStore } from '../stores/collection-tab';
1817
import { useCollectionTabPlugins } from './collection-tab-provider';
18+
import type { CollectionTabOptions } from '../stores/collection-tab';
1919

2020
const { log, mongoLogId, track } = createLoggerAndTelemetry(
2121
'COMPASS-COLLECTION-TAB-UI'
@@ -59,13 +59,15 @@ const collectionModalContainerStyles = css({
5959
zIndex: 100,
6060
});
6161

62-
const CollectionTab: React.FunctionComponent<{
62+
type CollectionTabProps = {
6363
currentTab: string;
6464
collectionTabPluginMetadata: CollectionTabPluginMetadata;
6565
renderScopedModals(): React.ReactElement[];
6666
renderTabs(): { name: string; component: React.ReactElement }[];
6767
onTabClick(name: string): void;
68-
}> = ({
68+
};
69+
70+
const CollectionTab: React.FunctionComponent<CollectionTabProps> = ({
6971
currentTab,
7072
collectionTabPluginMetadata,
7173
renderScopedModals,
@@ -162,16 +164,6 @@ const ConnectedCollectionTab = connect(
162164
renderTabs: renderTabs,
163165
onTabClick: selectTab,
164166
}
165-
)(CollectionTab);
166-
167-
const CollectionTabPlugin: React.FunctionComponent<{
168-
store: ReturnType<typeof configureStore>;
169-
}> = ({ store }) => {
170-
return (
171-
<Provider store={store}>
172-
<ConnectedCollectionTab></ConnectedCollectionTab>
173-
</Provider>
174-
);
175-
};
167+
)(CollectionTab) as React.FunctionComponent<CollectionTabOptions>;
176168

177-
export default CollectionTabPlugin;
169+
export default ConnectedCollectionTab;

packages/compass-collection/src/components/workspace/index.ts

Lines changed: 0 additions & 2 deletions
This file was deleted.

packages/compass-collection/src/components/workspace/workspace.spec.tsx

Lines changed: 0 additions & 58 deletions
This file was deleted.

0 commit comments

Comments
 (0)