From ff595b52995738224e685f4b4598ea7e63aaf32c Mon Sep 17 00:00:00 2001 From: Paula Stachova Date: Mon, 5 May 2025 15:27:54 +0200 Subject: [PATCH 1/6] wip --- .../src/components/empty-content.tsx | 27 ++++-- .../icons/General_CONTENT_Collaborate.svg | 10 +++ .../icons/General_FEATURES_Flexibility.svg | 8 ++ .../icons/General_FEATURES_Insight.svg | 11 +++ .../Technical_MDB_SchemaVisualization.svg | 13 +++ .../src/components/icons/collaborate.tsx | 49 +++++++++++ .../src/components/icons/flexibility.tsx | 35 ++++++++ .../src/components/icons/insight.tsx | 39 ++++++++ .../components/icons/schema-visualization.tsx | 88 +++++++++++++++++++ .../src/components/saved-diagrams-list.tsx | 88 ++++++++++++++++++- 10 files changed, 357 insertions(+), 11 deletions(-) create mode 100644 packages/compass-data-modeling/src/components/icons/General_CONTENT_Collaborate.svg create mode 100644 packages/compass-data-modeling/src/components/icons/General_FEATURES_Flexibility.svg create mode 100644 packages/compass-data-modeling/src/components/icons/General_FEATURES_Insight.svg create mode 100644 packages/compass-data-modeling/src/components/icons/Technical_MDB_SchemaVisualization.svg create mode 100644 packages/compass-data-modeling/src/components/icons/collaborate.tsx create mode 100644 packages/compass-data-modeling/src/components/icons/flexibility.tsx create mode 100644 packages/compass-data-modeling/src/components/icons/insight.tsx create mode 100644 packages/compass-data-modeling/src/components/icons/schema-visualization.tsx diff --git a/packages/compass-components/src/components/empty-content.tsx b/packages/compass-components/src/components/empty-content.tsx index beef022bb10..dc0ecc81f7a 100644 --- a/packages/compass-components/src/components/empty-content.tsx +++ b/packages/compass-components/src/components/empty-content.tsx @@ -44,32 +44,45 @@ const callToActionLinkContainerStyles = css({ }); type EmptyContentProps = { - icon: React.FunctionComponent; + icon?: React.FunctionComponent; title: string; + titleClassName?: string; subTitle: React.ReactNode; + subTitleClassName?: string; callToAction?: React.ReactNode; callToActionLink?: React.ReactNode; }; const EmptyContent: React.FunctionComponent< EmptyContentProps & React.HTMLProps -> = ({ icon: Icon, title, subTitle, callToAction, callToActionLink }) => { +> = ({ + icon: Icon, + title, + subTitle, + callToAction, + callToActionLink, + titleClassName, + subTitleClassName, +}) => { const darkMode = useDarkMode(); return (
-
- -
+ {Icon && ( +
+ +
+ )} {title} - {subTitle} + {subTitle} {!!callToAction && (
{typeof callToAction === 'string' ? ( diff --git a/packages/compass-data-modeling/src/components/icons/General_CONTENT_Collaborate.svg b/packages/compass-data-modeling/src/components/icons/General_CONTENT_Collaborate.svg new file mode 100644 index 00000000000..b9f7b9540c9 --- /dev/null +++ b/packages/compass-data-modeling/src/components/icons/General_CONTENT_Collaborate.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/packages/compass-data-modeling/src/components/icons/General_FEATURES_Flexibility.svg b/packages/compass-data-modeling/src/components/icons/General_FEATURES_Flexibility.svg new file mode 100644 index 00000000000..59218ec5cd7 --- /dev/null +++ b/packages/compass-data-modeling/src/components/icons/General_FEATURES_Flexibility.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/packages/compass-data-modeling/src/components/icons/General_FEATURES_Insight.svg b/packages/compass-data-modeling/src/components/icons/General_FEATURES_Insight.svg new file mode 100644 index 00000000000..e2b22a240be --- /dev/null +++ b/packages/compass-data-modeling/src/components/icons/General_FEATURES_Insight.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/packages/compass-data-modeling/src/components/icons/Technical_MDB_SchemaVisualization.svg b/packages/compass-data-modeling/src/components/icons/Technical_MDB_SchemaVisualization.svg new file mode 100644 index 00000000000..9f99b51f67c --- /dev/null +++ b/packages/compass-data-modeling/src/components/icons/Technical_MDB_SchemaVisualization.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/packages/compass-data-modeling/src/components/icons/collaborate.tsx b/packages/compass-data-modeling/src/components/icons/collaborate.tsx new file mode 100644 index 00000000000..3273d0402e3 --- /dev/null +++ b/packages/compass-data-modeling/src/components/icons/collaborate.tsx @@ -0,0 +1,49 @@ +import React, { useMemo } from 'react'; +import { palette, useDarkMode } from '@mongodb-js/compass-components'; + +const Collaborate: React.FunctionComponent = () => { + const darkMode = useDarkMode(); + const strokeColor = useMemo( + () => (darkMode ? palette.white : palette.black), + [darkMode] + ); + + return ( + + + + + + + + + + + ); +}; + +export default Collaborate; diff --git a/packages/compass-data-modeling/src/components/icons/flexibility.tsx b/packages/compass-data-modeling/src/components/icons/flexibility.tsx new file mode 100644 index 00000000000..2774c8249c4 --- /dev/null +++ b/packages/compass-data-modeling/src/components/icons/flexibility.tsx @@ -0,0 +1,35 @@ +import React, { useMemo } from 'react'; +import { palette, useDarkMode } from '@mongodb-js/compass-components'; + +const Flexibility: React.FunctionComponent = () => { + const darkMode = useDarkMode(); + const strokeColor = useMemo( + () => (darkMode ? palette.white : palette.black), + [darkMode] + ); + // Using green that doesn't change with dark mode + const fillColor = palette.green.base; + + return ( + + + + + ); +}; + +export default Flexibility; diff --git a/packages/compass-data-modeling/src/components/icons/insight.tsx b/packages/compass-data-modeling/src/components/icons/insight.tsx new file mode 100644 index 00000000000..6da69cbcf22 --- /dev/null +++ b/packages/compass-data-modeling/src/components/icons/insight.tsx @@ -0,0 +1,39 @@ +import React, { useMemo } from 'react'; +import { palette, useDarkMode } from '@mongodb-js/compass-components'; + +const Insight: React.FunctionComponent = () => { + const darkMode = useDarkMode(); + const strokeColor = useMemo( + () => (darkMode ? palette.white : palette.black), + [darkMode] + ); + // Green color that doesn't change with dark mode + const fillColor = palette.green.base; + + return ( + + + + + + ); +}; + +export default Insight; diff --git a/packages/compass-data-modeling/src/components/icons/schema-visualization.tsx b/packages/compass-data-modeling/src/components/icons/schema-visualization.tsx new file mode 100644 index 00000000000..58450582d25 --- /dev/null +++ b/packages/compass-data-modeling/src/components/icons/schema-visualization.tsx @@ -0,0 +1,88 @@ +import React, { useMemo } from 'react'; +import { palette, useDarkMode } from '@mongodb-js/compass-components'; + +const SchemaVisualization: React.FunctionComponent = () => { + const darkMode = useDarkMode(); + const strokeColor = useMemo( + () => (darkMode ? palette.white : palette.black), + [darkMode] + ); + // Using green that doesn't change with dark mode + const fillColor = palette.green.base; + + return ( + + + + + + + + + + + + + + ); +}; + +export default SchemaVisualization; diff --git a/packages/compass-data-modeling/src/components/saved-diagrams-list.tsx b/packages/compass-data-modeling/src/components/saved-diagrams-list.tsx index 45d471f1aac..f67d2466ed3 100644 --- a/packages/compass-data-modeling/src/components/saved-diagrams-list.tsx +++ b/packages/compass-data-modeling/src/components/saved-diagrams-list.tsx @@ -4,14 +4,83 @@ import { createNewDiagram } from '../store/generate-diagram-wizard'; import { Button, Card, + css, EmptyContent, - Icon, ItemActionMenu, + Link, WorkspaceContainer, } from '@mongodb-js/compass-components'; import { useDataModelSavedItems } from '../provider'; import { deleteDiagram, openDiagram, renameDiagram } from '../store/diagram'; import type { MongoDBDataModelDescription } from '../services/data-model-storage'; +import CollaborateIcon from './icons/Collaborate'; +import SchemaVisualizationIcon from './icons/schema-visualization'; +import FlexibilityIcon from './icons/flexibility'; +import InsightIcon from './icons/insight'; + +const subTitleStyles = css({ + maxWidth: '750px', +}); + +type Feature = 'visualization' | 'collaboration' | 'interactive' | 'insights'; +const featureDescription: Record< + Feature, + { icon: React.FunctionComponent; title: string; subtitle: string } +> = { + visualization: { + icon: SchemaVisualizationIcon, + title: 'Quick Visualization & Refactoring', + subtitle: 'Instantly visualize and refactor data models', + }, + collaboration: { + icon: CollaborateIcon, + title: 'Collaboration & Sharing with your team', + subtitle: 'Collaborate and share schemas across teams', + }, + interactive: { + icon: FlexibilityIcon, + title: 'Interactive Diagram Analysis', + subtitle: 'Explore and annotate interactive diagrams', + }, + insights: { + icon: InsightIcon, + title: 'Performance Insights & Optimization', + subtitle: 'Uncover performance insights & best practices', + }, +}; + +const featuresListStyles = css({ + display: 'grid', + gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))', + gap: '16px', + marginTop: '16px', +}); + +const FeaturesList: React.FunctionComponent<{ features: Feature[] }> = ({ + features, +}) => { + return ( +
+ {features.map((feature, key) => { + const { icon: Icon, title, subtitle } = featureDescription[feature]; + return ( +
+ +

{title}

+

{subtitle}

+
+ ); + })} +
+ ); +}; const SavedDiagramsList: React.FunctionComponent<{ onCreateDiagramClick: () => void; @@ -72,7 +141,6 @@ const SavedDiagramsList: React.FunctionComponent<{ } else { content = ( } title="Design, Visualize, and Evolve your Data Model" subTitle={ <> @@ -80,15 +148,27 @@ const SavedDiagramsList: React.FunctionComponent<{ applications evolve, so must your schema—intelligently and strategically. Minimize complexity, prevent performance bottlenecks, and keep your development agile. + + + Data Modeling Documentation + } + subTitleClassName={subTitleStyles} callToAction={ } > @@ -106,7 +186,7 @@ const SavedDiagramsList: React.FunctionComponent<{ size="xsmall" data-testid="create-diagram-button" > - Create diagram + Generate new diagram ) : null; From 5681224dbdbcc43daea23731d23e867cb1b96310 Mon Sep 17 00:00:00 2001 From: Paula Stachova Date: Tue, 6 May 2025 11:21:32 +0200 Subject: [PATCH 2/6] fix: empty diagram list view COMPASS-9310 --- .../src/components/saved-diagrams-list.tsx | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/packages/compass-data-modeling/src/components/saved-diagrams-list.tsx b/packages/compass-data-modeling/src/components/saved-diagrams-list.tsx index f67d2466ed3..0110de17464 100644 --- a/packages/compass-data-modeling/src/components/saved-diagrams-list.tsx +++ b/packages/compass-data-modeling/src/components/saved-diagrams-list.tsx @@ -9,11 +9,12 @@ import { ItemActionMenu, Link, WorkspaceContainer, + spacing, } from '@mongodb-js/compass-components'; import { useDataModelSavedItems } from '../provider'; import { deleteDiagram, openDiagram, renameDiagram } from '../store/diagram'; import type { MongoDBDataModelDescription } from '../services/data-model-storage'; -import CollaborateIcon from './icons/Collaborate'; +import CollaborateIcon from './icons/collaborate'; import SchemaVisualizationIcon from './icons/schema-visualization'; import FlexibilityIcon from './icons/flexibility'; import InsightIcon from './icons/insight'; @@ -22,6 +23,20 @@ const subTitleStyles = css({ maxWidth: '750px', }); +const featuresListStyles = css({ + display: 'flex', + justifyContent: 'center', + gap: spacing[600], + marginTop: spacing[400], +}); + +const featureItemStyles = css({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: spacing[400], +}); + type Feature = 'visualization' | 'collaboration' | 'interactive' | 'insights'; const featureDescription: Record< Feature, @@ -49,13 +64,6 @@ const featureDescription: Record< }, }; -const featuresListStyles = css({ - display: 'grid', - gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))', - gap: '16px', - marginTop: '16px', -}); - const FeaturesList: React.FunctionComponent<{ features: Feature[] }> = ({ features, }) => { @@ -64,14 +72,7 @@ const FeaturesList: React.FunctionComponent<{ features: Feature[] }> = ({ {features.map((feature, key) => { const { icon: Icon, title, subtitle } = featureDescription[feature]; return ( -
+

{title}

{subtitle}

@@ -82,7 +83,7 @@ const FeaturesList: React.FunctionComponent<{ features: Feature[] }> = ({ ); }; -const SavedDiagramsList: React.FunctionComponent<{ +export const SavedDiagramsList: React.FunctionComponent<{ onCreateDiagramClick: () => void; onOpenDiagramClick: (diagram: MongoDBDataModelDescription) => void; onDiagramDeleteClick: (id: string) => void; From 44f2dca724fae96e15171cb3c75934aea88c912b Mon Sep 17 00:00:00 2001 From: Paula Stachova Date: Wed, 7 May 2025 17:17:05 +0200 Subject: [PATCH 3/6] wip --- packages/compass-data-modeling/src/provider/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/compass-data-modeling/src/provider/index.tsx b/packages/compass-data-modeling/src/provider/index.tsx index 716756627a9..ec5b683ac66 100644 --- a/packages/compass-data-modeling/src/provider/index.tsx +++ b/packages/compass-data-modeling/src/provider/index.tsx @@ -5,7 +5,7 @@ import type { } from '../services/data-model-storage'; import { createServiceLocator } from 'hadron-app-registry'; -type DataModelStorageServiceState = { +export type DataModelStorageServiceState = { status: 'INITIAL' | 'LOADING' | 'REFRESHING' | 'READY' | 'ERROR'; error: Error | null; items: MongoDBDataModelDescription[]; From c1c94db80bafb6ab57b7db7f4ed6a113d96172b3 Mon Sep 17 00:00:00 2001 From: Paula Stachova Date: Wed, 7 May 2025 17:32:55 +0200 Subject: [PATCH 4/6] adding tests --- .../components/saved-diagrams-list.spec.tsx | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 packages/compass-data-modeling/src/components/saved-diagrams-list.spec.tsx diff --git a/packages/compass-data-modeling/src/components/saved-diagrams-list.spec.tsx b/packages/compass-data-modeling/src/components/saved-diagrams-list.spec.tsx new file mode 100644 index 00000000000..9f304bea6bc --- /dev/null +++ b/packages/compass-data-modeling/src/components/saved-diagrams-list.spec.tsx @@ -0,0 +1,100 @@ +import React from 'react'; +import { expect } from 'chai'; +import { screen, userEvent } from '@mongodb-js/testing-library-compass'; +import SavedDiagramsList from './saved-diagrams-list'; +import { renderWithStore } from '../../test/setup-store'; +import type { DataModelingStore } from '../../test/setup-store'; +import { DataModelStorageServiceProvider } from '../provider'; +import type { MongoDBDataModelDescription } from '../services/data-model-storage'; + +describe('SavedDiagramsList', function () { + const renderSavedDiagramsList = ({ + loadAll = () => Promise.resolve([]), + }: { + loadAll?: () => Promise; + } = {}) => { + const mockDataModelStorage = { + status: 'READY', + error: null, + items: [], + save: () => { + return Promise.resolve(false); + }, + delete: () => { + return Promise.resolve(false); + }, + loadAll, + load: () => { + return Promise.resolve(null); + }, + }; + return renderWithStore( + + + , + { + services: { + dataModelStorage: mockDataModelStorage, + }, + } + ); + }; + + context('when there are no saved diagrams', function () { + let store: DataModelingStore; + + beforeEach(function () { + const result = renderSavedDiagramsList(); + store = result.store; + }); + + it('shows the empty state', function () { + expect( + screen.getByText( + 'No saved Design, Visualize, and Evolve your Data Model' + ) + ).to.exist; + }); + + it('allows to start adding diagrams', function () { + const createDiagramButton = screen.getByRole('button', { + name: 'Generate new diagram', + }); + expect(store.getState().generateDiagramWizard.inProgress).to.be.false; + expect(createDiagramButton).to.be.visible; + userEvent.click(createDiagramButton); + expect(store.getState().generateDiagramWizard.inProgress).to.be.true; + }); + }); + + context('when there are diagrams', function () { + let store: DataModelingStore; + + beforeEach(function () { + const result = renderSavedDiagramsList({ + loadAll: () => + Promise.resolve([ + { + id: 'diagram-1', + name: 'Diagram 1', + }, + ]), + }); + store = result.store; + }); + + it('shows the list of diagrams', function () { + expect(screen.getByText('Diagram 1')).to.exist; + }); + + it('allows to add another diagram', function () { + const createDiagramButton = screen.getByRole('button', { + name: 'Generate diagram', + }); + expect(store.getState().generateDiagramWizard.inProgress).to.be.false; + expect(createDiagramButton).to.be.visible; + userEvent.click(createDiagramButton); + expect(store.getState().generateDiagramWizard.inProgress).to.be.true; + }); + }); +}); From f4f0c886784ebbbc43ae28ce62e0b3894fd9a77b Mon Sep 17 00:00:00 2001 From: Paula Stachova Date: Fri, 9 May 2025 13:26:21 +0200 Subject: [PATCH 5/6] finish tests --- .../components/saved-diagrams-list.spec.tsx | 32 +++++++++++++------ .../src/components/saved-diagrams-list.tsx | 2 +- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/packages/compass-data-modeling/src/components/saved-diagrams-list.spec.tsx b/packages/compass-data-modeling/src/components/saved-diagrams-list.spec.tsx index 9f304bea6bc..85fbf76bee5 100644 --- a/packages/compass-data-modeling/src/components/saved-diagrams-list.spec.tsx +++ b/packages/compass-data-modeling/src/components/saved-diagrams-list.spec.tsx @@ -1,6 +1,10 @@ import React from 'react'; import { expect } from 'chai'; -import { screen, userEvent } from '@mongodb-js/testing-library-compass'; +import { + screen, + userEvent, + waitFor, +} from '@mongodb-js/testing-library-compass'; import SavedDiagramsList from './saved-diagrams-list'; import { renderWithStore } from '../../test/setup-store'; import type { DataModelingStore } from '../../test/setup-store'; @@ -43,22 +47,25 @@ describe('SavedDiagramsList', function () { context('when there are no saved diagrams', function () { let store: DataModelingStore; - beforeEach(function () { + beforeEach(async function () { const result = renderSavedDiagramsList(); store = result.store; + + // wait till the empty list is loaded + await waitFor(() => { + expect(screen.getByTestId('empty-content')).to.be.visible; + }); }); it('shows the empty state', function () { expect( - screen.getByText( - 'No saved Design, Visualize, and Evolve your Data Model' - ) - ).to.exist; + screen.getByText('Design, Visualize, and Evolve your Data Model') + ).to.be.visible; }); it('allows to start adding diagrams', function () { const createDiagramButton = screen.getByRole('button', { - name: 'Generate new diagram', + name: 'Generate diagram', }); expect(store.getState().generateDiagramWizard.inProgress).to.be.false; expect(createDiagramButton).to.be.visible; @@ -70,17 +77,22 @@ describe('SavedDiagramsList', function () { context('when there are diagrams', function () { let store: DataModelingStore; - beforeEach(function () { + beforeEach(async function () { const result = renderSavedDiagramsList({ loadAll: () => Promise.resolve([ { id: 'diagram-1', name: 'Diagram 1', - }, + } as MongoDBDataModelDescription, ]), }); store = result.store; + + // wait till the list is loaded + await waitFor(() => { + expect(screen.getByTestId('saved-diagram-list')).to.be.visible; + }); }); it('shows the list of diagrams', function () { @@ -89,7 +101,7 @@ describe('SavedDiagramsList', function () { it('allows to add another diagram', function () { const createDiagramButton = screen.getByRole('button', { - name: 'Generate diagram', + name: 'Generate new diagram', }); expect(store.getState().generateDiagramWizard.inProgress).to.be.false; expect(createDiagramButton).to.be.visible; diff --git a/packages/compass-data-modeling/src/components/saved-diagrams-list.tsx b/packages/compass-data-modeling/src/components/saved-diagrams-list.tsx index 0110de17464..0d4878a949a 100644 --- a/packages/compass-data-modeling/src/components/saved-diagrams-list.tsx +++ b/packages/compass-data-modeling/src/components/saved-diagrams-list.tsx @@ -106,7 +106,7 @@ export const SavedDiagramsList: React.FunctionComponent<{ if (showList) { content = ( -
+
{items.map((diagram) => { return ( Date: Fri, 9 May 2025 13:27:16 +0200 Subject: [PATCH 6/6] cleanup --- .../icons/General_CONTENT_Collaborate.svg | 10 ---------- .../icons/General_FEATURES_Flexibility.svg | 8 -------- .../components/icons/General_FEATURES_Insight.svg | 11 ----------- .../icons/Technical_MDB_SchemaVisualization.svg | 13 ------------- 4 files changed, 42 deletions(-) delete mode 100644 packages/compass-data-modeling/src/components/icons/General_CONTENT_Collaborate.svg delete mode 100644 packages/compass-data-modeling/src/components/icons/General_FEATURES_Flexibility.svg delete mode 100644 packages/compass-data-modeling/src/components/icons/General_FEATURES_Insight.svg delete mode 100644 packages/compass-data-modeling/src/components/icons/Technical_MDB_SchemaVisualization.svg diff --git a/packages/compass-data-modeling/src/components/icons/General_CONTENT_Collaborate.svg b/packages/compass-data-modeling/src/components/icons/General_CONTENT_Collaborate.svg deleted file mode 100644 index b9f7b9540c9..00000000000 --- a/packages/compass-data-modeling/src/components/icons/General_CONTENT_Collaborate.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/packages/compass-data-modeling/src/components/icons/General_FEATURES_Flexibility.svg b/packages/compass-data-modeling/src/components/icons/General_FEATURES_Flexibility.svg deleted file mode 100644 index 59218ec5cd7..00000000000 --- a/packages/compass-data-modeling/src/components/icons/General_FEATURES_Flexibility.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/packages/compass-data-modeling/src/components/icons/General_FEATURES_Insight.svg b/packages/compass-data-modeling/src/components/icons/General_FEATURES_Insight.svg deleted file mode 100644 index e2b22a240be..00000000000 --- a/packages/compass-data-modeling/src/components/icons/General_FEATURES_Insight.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/packages/compass-data-modeling/src/components/icons/Technical_MDB_SchemaVisualization.svg b/packages/compass-data-modeling/src/components/icons/Technical_MDB_SchemaVisualization.svg deleted file mode 100644 index 9f99b51f67c..00000000000 --- a/packages/compass-data-modeling/src/components/icons/Technical_MDB_SchemaVisualization.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - -