Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
95e2ed1
setup data for the feature
mabaasit Jan 27, 2025
4678b4d
update sidebar
mabaasit Jan 27, 2025
8c3489b
update database-collection
mabaasit Jan 27, 2025
ad89873
correct icon
mabaasit Jan 28, 2025
a387b72
update workspace tabs
mabaasit Jan 28, 2025
32f9ae5
rename property
mabaasit Jan 28, 2025
52bfd4f
fetch collstats only if db exists
mabaasit Jan 28, 2025
f421be4
clean up
mabaasit Jan 28, 2025
f7c760f
checks and lint
mabaasit Jan 28, 2025
1d245e5
Merge branch 'main' into COMPASS-5750-non-existent-ns
mabaasit Jan 28, 2025
8e3506e
fix log id and message
mabaasit Jan 28, 2025
1d119f7
tests
mabaasit Jan 29, 2025
6d132b2
correcct comment
mabaasit Jan 29, 2025
9e31ef5
correct color on grid
mabaasit Jan 29, 2025
4cf633a
rename prop
mabaasit Jan 29, 2025
79e2ca7
also handle non-existent collections
mabaasit Jan 29, 2025
5a0ec67
fix check
mabaasit Jan 29, 2025
731ac2d
react to changes
mabaasit Jan 29, 2025
fdcfb42
do mix with adapt ns info
mabaasit Jan 29, 2025
bd05401
border on hover
mabaasit Jan 30, 2025
3740848
Merge branch 'main' into COMPASS-5750-non-existent-ns
mabaasit Jan 30, 2025
6b44ac1
use spacing nums
mabaasit Jan 30, 2025
c671c7c
Merge branch 'COMPASS-5750-non-existent-ns' of https://github.com/mon…
mabaasit Jan 30, 2025
523154c
text change
mabaasit Jan 30, 2025
fab0289
Merge branch 'main' into COMPASS-5750-non-existent-ns
mabaasit Jan 30, 2025
df696e1
Merge remote-tracking branch 'origin' into COMPASS-5750-non-existent-ns
mabaasit Jan 31, 2025
dc52d8e
install
mabaasit Jan 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion packages/collection-model/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@ interface CollectionProps {
index_size: number;
isTimeSeries: boolean;
isView: boolean;
/** Only relevant for a view and identifies collection/view from which this view was created. */
sourceName: string | null;
source: Collection;
properties: { id: string; options?: unknown }[];
properties: { id: string; options?: Record<string, unknown> }[];
is_non_existent: boolean;
}

type CollectionDataService = Pick<DataService, 'collectionStats' | 'collectionInfo' | 'listCollections' | 'isListSearchIndexesSupported'>;
Expand Down
14 changes: 13 additions & 1 deletion packages/collection-model/lib/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,9 @@ function pickCollectionInfo({
validation,
clustered,
fle2,
is_non_existent,
}) {
return { type, readonly, view_on, collation, pipeline, validation, clustered, fle2 };
return { type, readonly, view_on, collation, pipeline, validation, clustered, fle2, is_non_existent };
}

/**
Expand All @@ -124,6 +125,7 @@ const CollectionModel = AmpersandModel.extend(debounceActions(['fetch']), {
statusError: { type: 'string', default: null },

// Normalized values from collectionInfo command
is_non_existent: 'boolean',
readonly: 'boolean',
clustered: 'boolean',
fle2: 'boolean',
Expand Down Expand Up @@ -250,6 +252,16 @@ const CollectionModel = AmpersandModel.extend(debounceActions(['fetch']), {
...collStats,
...(collectionInfo && pickCollectionInfo(collectionInfo)),
});
// If the collection is not unprovisioned `is_non_existent` anymore,
// let's update the parent database model to reflect the change.
// This happens when a user tries to insert first document into a
// collection that doesn't exist yet or creates a new collection
// for an unprovisioned database.
if (!this.is_non_existent) {
getParentByType(this, 'Database').set({
is_non_existent: false,
});
}
Comment on lines +255 to +264
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is the right place for this, but if you feel it does not belong here, let me know

} catch (err) {
this.set({ status: 'error', statusError: err.message });
throw err;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ function Tab({
tabContentId,
iconGlyph,
tabTheme,
className: tabClassName,
...props
}: TabProps & React.HTMLProps<HTMLDivElement>) {
const darkMode = useDarkMode();
Expand Down Expand Up @@ -250,7 +251,8 @@ function Tab({
themeClass,
isSelected && selectedTabStyles,
isSelected && tabTheme && selectedThemedTabStyles,
isDragging && draggingTabStyles
isDragging && draggingTabStyles,
tabClassName
)}
aria-selected={isSelected}
role="tab"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React from 'react';
import type { SidebarTreeItem } from './tree-data';
import { css, Icon, ServerIcon, Tooltip } from '@mongodb-js/compass-components';
import type { GlyphName } from '@mongodb-js/compass-components';
import { WithStatusMarker } from './with-status-marker';
import { isLocalhost } from 'mongodb-build-info';

const NON_EXISTANT_NAMESPACE_TEXT =
'You have privileges to this namespace, but it is not in your list of current namespaces';

const tooltipTriggerStyles = css({
display: 'flex',
});
const IconWithTooltip = ({
text,
glyph,
}: {
text: string;
glyph: GlyphName;
}) => {
return (
<Tooltip
align="bottom"
justify="start"
trigger={
<div className={tooltipTriggerStyles}>
<Icon glyph={glyph} />
</div>
}
>
{text}
</Tooltip>
);
};

export const NavigationItemIcon = ({ item }: { item: SidebarTreeItem }) => {
if (item.type === 'database') {
if (item.isNonExistent) {
return (
<IconWithTooltip
text={NON_EXISTANT_NAMESPACE_TEXT}
glyph="EmptyDatabase"
/>
);
}
return <Icon glyph="Database" />;
}
if (item.type === 'collection') {
if (item.isNonExistent) {
return (
<IconWithTooltip
text={NON_EXISTANT_NAMESPACE_TEXT}
glyph="EmptyFolder"
/>
);
}
return <Icon glyph="Folder" />;
}
if (item.type === 'view') {
return <Icon glyph="Visibility" />;
}
if (item.type === 'timeseries') {
return <Icon glyph="TimeSeries" />;
}
if (item.type === 'connection') {
const isFavorite = item.connectionInfo.savedConnectionType === 'favorite';
if (isFavorite) {
return (
<WithStatusMarker status={item.connectionStatus}>
<Icon glyph="Favorite" />
</WithStatusMarker>
);
}
if (isLocalhost(item.connectionInfo.connectionOptions.connectionString)) {
return (
<WithStatusMarker status={item.connectionStatus}>
<Icon glyph="Laptop" />
</WithStatusMarker>
);
}
return (
<WithStatusMarker status={item.connectionStatus}>
<ServerIcon />
</WithStatusMarker>
);
}
return null;
};
44 changes: 2 additions & 42 deletions packages/compass-connections-navigation/src/navigation-item.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import React, { useCallback, useMemo } from 'react';
import { isLocalhost } from 'mongodb-build-info';
import {
Icon,
ServerIcon,
cx,
css,
palette,
Expand All @@ -17,8 +14,8 @@ import type { NavigationItemActions } from './item-actions';
import type { SidebarTreeItem, SidebarActionableItem } from './tree-data';
import { getTreeItemStyles } from './utils';
import { ConnectionStatus } from '@mongodb-js/compass-connections/provider';
import { WithStatusMarker } from './with-status-marker';
import type { Actions } from './constants';
import { NavigationItemIcon } from './navigation-item-icon';

const nonGenuineBtnStyles = css({
color: palette.yellow.dark2,
Expand Down Expand Up @@ -115,43 +112,6 @@ export function NavigationItem({
getItemActions,
}: NavigationItemProps) {
const isDarkMode = useDarkMode();
const itemIcon = useMemo(() => {
if (item.type === 'database') {
return <Icon glyph="Database" />;
}
if (item.type === 'collection') {
return <Icon glyph="Folder" />;
}
if (item.type === 'view') {
return <Icon glyph="Visibility" />;
}
if (item.type === 'timeseries') {
return <Icon glyph="TimeSeries" />;
}
if (item.type === 'connection') {
const isFavorite = item.connectionInfo.savedConnectionType === 'favorite';
if (isFavorite) {
return (
<WithStatusMarker status={item.connectionStatus}>
<Icon glyph="Favorite" />
</WithStatusMarker>
);
}
if (isLocalhost(item.connectionInfo.connectionOptions.connectionString)) {
return (
<WithStatusMarker status={item.connectionStatus}>
<Icon glyph="Laptop" />
</WithStatusMarker>
);
}
return (
<WithStatusMarker status={item.connectionStatus}>
<ServerIcon />
</WithStatusMarker>
);
}
}, [item]);

const onAction = useCallback(
(action: Actions) => {
if (item.type !== 'placeholder') {
Expand Down Expand Up @@ -258,7 +218,7 @@ export function NavigationItem({
hasDefaultAction={
item.type !== 'connection' || item.connectionStatus === 'connected'
}
icon={itemIcon}
icon={<NavigationItemIcon item={item} />}
name={item.name}
style={style}
dataAttributes={itemDataProps}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import {
} from '@mongodb-js/connection-form';
import { palette, useDarkMode } from '@mongodb-js/compass-components';
import type { SidebarTreeItem } from './tree-data';
import { ConnectionStatus } from '@mongodb-js/compass-connections/provider';

type AcceptedStyles = {
'--item-bg-color'?: string;
'--item-bg-color-hover'?: string;
'--item-bg-color-active'?: string;
'--item-color'?: string;
'--item-color-active'?: string;
};

export default function StyledNavigationItem({
Expand All @@ -25,28 +25,37 @@ export default function StyledNavigationItem({
const { connectionColorToHex, connectionColorToHexActive } =
useConnectionColor();
const { colorCode } = item;
const isDisconnectedConnection =
item.type === 'connection' &&
item.connectionStatus !== ConnectionStatus.Connected;
const inactiveColor = useMemo(
() => (isDarkMode ? palette.gray.light1 : palette.gray.dark1),
[isDarkMode]
);

const style: React.CSSProperties & AcceptedStyles = useMemo(() => {
const style: AcceptedStyles = {};
const isDisconnectedConnection =
item.type === 'connection' && item.connectionStatus !== 'connected';
const isNonExistentNamespace =
(item.type === 'database' || item.type === 'collection') &&
item.isNonExistent;

if (colorCode && colorCode !== DefaultColorCode) {
style['--item-bg-color'] = connectionColorToHex(colorCode);
style['--item-bg-color-hover'] = connectionColorToHexActive(colorCode);
style['--item-bg-color-active'] = connectionColorToHexActive(colorCode);
}

if (isDisconnectedConnection) {
style['--item-color'] = isDarkMode
? palette.gray.light1
: palette.gray.dark1;
if (isDisconnectedConnection || isNonExistentNamespace) {
style['--item-color'] = inactiveColor;
}

// For a non-existent namespace, even if its active, we show it as inactive
if (isNonExistentNamespace) {
style['--item-color-active'] = inactiveColor;
}
return style;
}, [
isDarkMode,
isDisconnectedConnection,
inactiveColor,
item,
colorCode,
connectionColorToHex,
connectionColorToHexActive,
Expand Down
35 changes: 22 additions & 13 deletions packages/compass-connections-navigation/src/tree-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export type Database = {
collectionsStatus: DatabaseOrCollectionStatus;
collectionsLength: number;
collections: Collection[];
isNonExistent: boolean;
};

type PlaceholderTreeItem = VirtualPlaceholderItem & {
Expand All @@ -67,6 +68,7 @@ export type Collection = {
type: 'view' | 'collection' | 'timeseries';
sourceName: string | null;
pipeline: unknown[];
isNonExistent: boolean;
};

export type NotConnectedConnectionTreeItem = VirtualTreeItem & {
Expand Down Expand Up @@ -100,6 +102,7 @@ export type DatabaseTreeItem = VirtualTreeItem & {
connectionId: string;
dbName: string;
hasWriteActionsDisabled: boolean;
isNonExistent: boolean;
};

export type CollectionTreeItem = VirtualTreeItem & {
Expand All @@ -110,6 +113,7 @@ export type CollectionTreeItem = VirtualTreeItem & {
connectionId: string;
namespace: string;
hasWriteActionsDisabled: boolean;
isNonExistent: boolean;
};

export type SidebarActionableItem =
Expand Down Expand Up @@ -245,6 +249,7 @@ const databaseToItems = ({
collections,
collectionsLength,
collectionsStatus,
isNonExistent,
},
connectionId,
expandedItems = {},
Expand Down Expand Up @@ -277,6 +282,7 @@ const databaseToItems = ({
dbName: id,
isExpandable: true,
hasWriteActionsDisabled,
isNonExistent,
};

const sidebarData: SidebarTreeItem[] = [databaseTI];
Expand Down Expand Up @@ -304,19 +310,22 @@ const databaseToItems = ({
}

return sidebarData.concat(
collections.map(({ _id: id, name, type }, collectionIndex) => ({
id: `${connectionId}.${id}`, // id is the namespace of the collection, so includes db as well
level: level + 1,
name,
type,
setSize: collectionsLength,
posInSet: collectionIndex + 1,
colorCode,
connectionId,
namespace: id,
hasWriteActionsDisabled,
isExpandable: false,
}))
collections.map(
({ _id: id, name, type, isNonExistent }, collectionIndex) => ({
id: `${connectionId}.${id}`, // id is the namespace of the collection, so includes db as well
level: level + 1,
name,
type,
setSize: collectionsLength,
posInSet: collectionIndex + 1,
colorCode,
connectionId,
namespace: id,
hasWriteActionsDisabled,
isExpandable: false,
isNonExistent,
})
)
);
};

Expand Down
Loading
Loading