Skip to content

Commit a387b72

Browse files
committed
update workspace tabs
1 parent ad89873 commit a387b72

File tree

4 files changed

+121
-9
lines changed

4 files changed

+121
-9
lines changed

packages/compass-components/src/components/workspace-tabs/tab.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ function Tab({
206206
tabContentId,
207207
iconGlyph,
208208
tabTheme,
209+
className: tabClassName,
209210
...props
210211
}: TabProps & React.HTMLProps<HTMLDivElement>) {
211212
const darkMode = useDarkMode();
@@ -250,7 +251,8 @@ function Tab({
250251
themeClass,
251252
isSelected && selectedTabStyles,
252253
isSelected && tabTheme && selectedThemedTabStyles,
253-
isDragging && draggingTabStyles
254+
isDragging && draggingTabStyles,
255+
tabClassName
254256
)}
255257
aria-selected={isSelected}
256258
role="tab"

packages/compass-workspaces/src/components/workspaces.tsx

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import {
55
MongoDBLogoMark,
66
WorkspaceTabs,
77
css,
8+
palette,
89
rafraf,
910
spacing,
1011
useDarkMode,
1112
} from '@mongodb-js/compass-components';
1213
import type {
1314
CollectionTabInfo,
15+
DatabaseTabInfo,
1416
OpenWorkspaceOptions,
1517
WorkspaceTab,
1618
WorkspacesState,
@@ -125,6 +127,7 @@ type CompassWorkspacesProps = {
125127
tabs: WorkspaceTab[];
126128
activeTab?: WorkspaceTab | null;
127129
collectionInfo: Record<string, CollectionTabInfo>;
130+
databaseInfo: Record<string, DatabaseTabInfo>;
128131
openOnEmptyWorkspace?: OpenWorkspaceOptions | null;
129132

130133
onSelectTab(at: number): void;
@@ -139,10 +142,15 @@ type CompassWorkspacesProps = {
139142
): void;
140143
};
141144

145+
const notProvisionedStyles = css({
146+
color: palette.gray.base,
147+
});
148+
142149
const CompassWorkspaces: React.FunctionComponent<CompassWorkspacesProps> = ({
143150
tabs,
144151
activeTab,
145152
collectionInfo,
153+
databaseInfo,
146154
openOnEmptyWorkspace,
147155
onSelectTab,
148156
onSelectNextTab,
@@ -223,6 +231,8 @@ const CompassWorkspaces: React.FunctionComponent<CompassWorkspacesProps> = ({
223231
const connectionName =
224232
getConnectionById(tab.connectionId)?.title || '';
225233
const database = tab.namespace;
234+
const namespaceId = `${tab.connectionId}.${database}`;
235+
const { ns_source } = databaseInfo[namespaceId] ?? {};
226236
return {
227237
id: tab.id,
228238
connectionName,
@@ -232,15 +242,20 @@ const CompassWorkspaces: React.FunctionComponent<CompassWorkspacesProps> = ({
232242
['Connection', connectionName || ''],
233243
['Database', database],
234244
] as Tooltip,
235-
iconGlyph: 'Database',
245+
iconGlyph:
246+
ns_source !== 'provisioned' ? 'EmptyDatabase' : 'Database',
236247
'data-namespace': tab.namespace,
237248
tabTheme: getThemeOf(tab.connectionId),
249+
...(ns_source !== 'provisioned' && {
250+
className: notProvisionedStyles,
251+
}),
238252
} as const;
239253
}
240254
case 'Collection': {
241255
const { database, collection, ns } = toNS(tab.namespace);
242-
const info = collectionInfo[ns] ?? {};
243-
const { isTimeSeries, isReadonly, sourceName } = info;
256+
const namespaceId = `${tab.connectionId}.${ns}`;
257+
const info = collectionInfo[namespaceId] ?? {};
258+
const { isTimeSeries, isReadonly, sourceName, ns_source } = info;
244259
const connectionName =
245260
getConnectionById(tab.connectionId)?.title || '';
246261
const collectionType = isTimeSeries
@@ -273,14 +288,19 @@ const CompassWorkspaces: React.FunctionComponent<CompassWorkspacesProps> = ({
273288
? 'Visibility'
274289
: collectionType === 'timeseries'
275290
? 'TimeSeries'
291+
: ns_source !== 'provisioned'
292+
? 'EmptyFolder'
276293
: 'Folder',
277294
'data-namespace': ns,
278295
tabTheme: getThemeOf(tab.connectionId),
296+
...(ns_source !== 'provisioned' && {
297+
className: notProvisionedStyles,
298+
}),
279299
} as const;
280300
}
281301
}
282302
});
283-
}, [tabs, collectionInfo, getThemeOf, getConnectionById]);
303+
}, [tabs, collectionInfo, databaseInfo, getThemeOf, getConnectionById]);
284304

285305
const activeTabIndex = tabs.findIndex((tab) => tab === activeTab);
286306

@@ -410,6 +430,7 @@ export default connect(
410430
tabs: state.tabs,
411431
activeTab: activeTab,
412432
collectionInfo: state.collectionInfo,
433+
databaseInfo: state.databaseInfo,
413434
};
414435
},
415436
{

packages/compass-workspaces/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export function configureStore(
6060
tabs: initialTabs,
6161
activeTabId: initialTabs[initialTabs.length - 1]?.id ?? null,
6262
collectionInfo: {},
63+
databaseInfo: {},
6364
},
6465
applyMiddleware(thunk.withExtraArgument(services))
6566
);

packages/compass-workspaces/src/stores/workspaces.ts

Lines changed: 92 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export enum WorkspacesActions {
7171
DatabaseRemoved = 'compass-workspaces/DatabaseRemoved',
7272
ConnectionDisconnected = 'compass-workspaces/ConnectionDisconnected',
7373
FetchCollectionTabInfo = 'compass-workspaces/FetchCollectionTabInfo',
74+
FetchDatabaseTabInfo = 'compass-workspaces/FetchDatabaseTabInfo',
7475
CollectionSubtabSelected = 'compass-workspaces/CollectionSubtabSelected',
7576
}
7677

@@ -100,6 +101,11 @@ export type CollectionTabInfo = {
100101
isTimeSeries: boolean;
101102
isReadonly: boolean;
102103
sourceName?: string | null;
104+
ns_source: 'provisioned' | 'privileges';
105+
};
106+
107+
export type DatabaseTabInfo = {
108+
ns_source: 'provisioned' | 'privileges' | 'roles';
103109
};
104110

105111
export type WorkspacesState = {
@@ -116,6 +122,11 @@ export type WorkspacesState = {
116122
* icon)
117123
*/
118124
collectionInfo: Record<string, CollectionTabInfo>;
125+
/**
126+
* Extra info for the collections tab namespace (where we show collections
127+
* of a database)
128+
*/
129+
databaseInfo: Record<string, DatabaseTabInfo>;
119130
};
120131

121132
const getTabId = () => {
@@ -236,6 +247,7 @@ const getInitialState = () => {
236247
tabs: [] as WorkspaceTab[],
237248
activeTabId: null,
238249
collectionInfo: {},
250+
databaseInfo: {},
239251
};
240252
};
241253

@@ -568,7 +580,22 @@ const reducer: Reducer<WorkspacesState, Action> = (
568580
...state,
569581
collectionInfo: {
570582
...state.collectionInfo,
571-
[action.namespace]: action.info,
583+
[action.namespaceId]: action.info,
584+
},
585+
};
586+
}
587+
588+
if (
589+
isAction<FetchDatabaseInfoAction>(
590+
action,
591+
WorkspacesActions.FetchDatabaseTabInfo
592+
)
593+
) {
594+
return {
595+
...state,
596+
databaseInfo: {
597+
...state.databaseInfo,
598+
[action.namespaceId]: action.info,
572599
},
573600
};
574601
}
@@ -639,10 +666,18 @@ type OpenWorkspaceAction = {
639666

640667
type FetchCollectionInfoAction = {
641668
type: WorkspacesActions.FetchCollectionTabInfo;
642-
namespace: string;
669+
// This uniquely identifies the collection tab for a given connection
670+
namespaceId: string;
643671
info: CollectionTabInfo;
644672
};
645673

674+
type FetchDatabaseInfoAction = {
675+
type: WorkspacesActions.FetchDatabaseTabInfo;
676+
// This uniquely identifies the database tab for a given connection
677+
namespaceId: string;
678+
info: DatabaseTabInfo;
679+
};
680+
646681
export type TabOptions = {
647682
/**
648683
* Optional. If set to `true`, always opens workspace in a new tab, otherwise
@@ -660,7 +695,8 @@ const fetchCollectionInfo = (
660695
getState,
661696
{ connections, instancesManager, logger }
662697
) => {
663-
if (getState().collectionInfo[workspaceOptions.namespace]) {
698+
const namespaceId = `${workspaceOptions.connectionId}.${workspaceOptions.namespace}`;
699+
if (getState().collectionInfo[namespaceId]) {
664700
return;
665701
}
666702

@@ -685,11 +721,58 @@ const fetchCollectionInfo = (
685721
await coll.fetch({ dataService });
686722
dispatch({
687723
type: WorkspacesActions.FetchCollectionTabInfo,
688-
namespace: workspaceOptions.namespace,
724+
namespaceId,
689725
info: {
690726
isTimeSeries: coll.isTimeSeries,
691727
isReadonly: coll.readonly ?? coll.isView,
692728
sourceName: coll.sourceName,
729+
ns_source: coll.ns_source,
730+
},
731+
});
732+
}
733+
} catch (err) {
734+
logger.debug(
735+
'Collection Metadata',
736+
logger.mongoLogId(1_001_000_306),
737+
'Error fetching collection metadata for tab',
738+
{ namespace: workspaceOptions.namespace },
739+
err
740+
);
741+
}
742+
};
743+
};
744+
745+
const fetchDatabaseInfo = (
746+
workspaceOptions: Extract<OpenWorkspaceOptions, { type: 'Collections' }>
747+
): WorkspacesThunkAction<Promise<void>, FetchDatabaseInfoAction> => {
748+
return async (
749+
dispatch,
750+
getState,
751+
{ connections, instancesManager, logger }
752+
) => {
753+
const { databaseInfo } = getState();
754+
const namespaceId = `${workspaceOptions.connectionId}.${workspaceOptions.namespace}`;
755+
if (databaseInfo[namespaceId]) {
756+
return;
757+
}
758+
759+
try {
760+
const dataService = connections.getDataServiceForConnection(
761+
workspaceOptions.connectionId
762+
);
763+
764+
const instance = instancesManager.getMongoDBInstanceForConnection(
765+
workspaceOptions.connectionId
766+
);
767+
768+
const db = instance.databases.get(workspaceOptions.namespace);
769+
if (db) {
770+
await db.fetch({ dataService });
771+
dispatch({
772+
type: WorkspacesActions.FetchDatabaseTabInfo,
773+
namespaceId,
774+
info: {
775+
ns_source: db.ns_source,
693776
},
694777
});
695778
}
@@ -717,6 +800,11 @@ export const openWorkspace = (
717800
void dispatch(fetchCollectionInfo(workspaceOptions));
718801
}
719802

803+
if (workspaceOptions.type === 'Collections') {
804+
// Fetching extra metadata for database should not block tab opening
805+
void dispatch(fetchDatabaseInfo(workspaceOptions));
806+
}
807+
720808
dispatch({
721809
type: WorkspacesActions.OpenWorkspace,
722810
workspace: workspaceOptions,

0 commit comments

Comments
 (0)