diff --git a/dist/MaterialsDesigner.d.ts b/dist/MaterialsDesigner.d.ts index e6c21c67..39627c97 100644 --- a/dist/MaterialsDesigner.d.ts +++ b/dist/MaterialsDesigner.d.ts @@ -5,8 +5,10 @@ declare class MaterialsDesigner { isVisibleItemsList: boolean; isVisibleSourceEditor: boolean; isVisibleThreeDEditorFullscreen: boolean; + isVisibleJupyterLiteSessionDrawer: boolean; importMaterialsDialogProps: null; }; + containerRef: React.RefObject; shouldComponentUpdate(nextProps: any, nextState: any): boolean; getGridConfig: () => any; checkIfOnlyOneGridItemIsVisible: () => boolean; @@ -46,5 +48,6 @@ declare namespace MaterialsDesigner { export { materialConfigs as defaultMaterialsSet }; } } +import React from "react"; import PropTypes from "prop-types"; declare const materialConfigs: any[]; diff --git a/dist/MaterialsDesigner.js b/dist/MaterialsDesigner.js index 085ccd90..7e87b031 100644 --- a/dist/MaterialsDesigner.js +++ b/dist/MaterialsDesigner.js @@ -18,6 +18,7 @@ import React from "react"; // import {MaterialSchema} from "@mat3ra/code/dist/js/types"; import { ThreeDEditorFullscreen } from "./components/3d_editor/ThreeDEditorFullscreen"; import EditorSelectionInfo, { FOOTER_HEIGHT, } from "./components/3d_editor_selection_info/EditorSelectionInfo"; +import JupyterLiteSessionDrawer from "./components/drawer_session/JupyterLiteSessionDrawer"; import HeaderMenuToolbar from "./components/header_menu/HeaderMenuToolbar"; import ItemsList from "./components/items_list/ItemsList"; import BasisEditor from "./components/source_editor/Basis"; @@ -100,8 +101,10 @@ class MaterialsDesigner extends mix(React.Component).with(FullscreenComponentMix isVisibleItemsList: true, isVisibleSourceEditor: true, isVisibleThreeDEditorFullscreen: true, + isVisibleJupyterLiteSessionDrawer: false, importMaterialsDialogProps: null, }; + this.containerRef = React.createRef(); } shouldComponentUpdate(nextProps, nextState) { const [nextProps_, thisProps_, nextState_, thisState_] = [ @@ -116,7 +119,7 @@ class MaterialsDesigner extends mix(React.Component).with(FullscreenComponentMix const { isVisibleItemsList, isVisibleSourceEditor, isVisibleThreeDEditorFullscreen } = this.state; const gridConfig = this.getGridConfig(); const mainContainerHeightDirective = `calc(100vh - ${APP_BAR_HEIGHT + FOOTER_HEIGHT - 8}px)`; // 8px is the padding + borders - return (_jsx(ThemeProvider, { theme: theme, children: _jsx(ScopedCssBaseline, { enableColorScheme: true, children: _jsxs(Paper, { id: "materials-designer", children: [_jsx(AppBar, { position: "static", className: setClass("", this.props.className), children: _jsx(HeaderMenuToolbar, { isLoading: this.props.isLoading, material: this.props.material, materials: this.props.materials, index: this.props.index, onUndo: this.props.onUndo, onRedo: this.props.onRedo, onReset: this.props.onReset, onClone: this.props.onClone, onToggleIsNonPeriodic: this.props.onToggleIsNonPeriodic, onUpdate: this.props.onUpdate, onAdd: this.props.onAdd, onExport: this.props.onExport, onSave: this.props.onSave, onExit: this.props.onExit, openImportModal: this.props.openImportModal, closeImportModal: this.props.closeImportModal, openSaveActionDialog: this.props.openSaveActionDialog, onGenerateSupercell: this.props.onGenerateSupercell, onGenerateSurface: this.props.onGenerateSurface, onSetBoundaryConditions: this.props.onSetBoundaryConditions, maxCombinatorialBasesCount: this.props.maxCombinatorialBasesCount, defaultMaterialsSet: this.props.defaultMaterialsSet, onSectionVisibilityToggle: this.onSectionVisibilityToggle, isVisibleItemsList: isVisibleItemsList, isVisibleSourceEditor: isVisibleSourceEditor, isVisibleThreeDEditorFullscreen: isVisibleThreeDEditorFullscreen, children: _jsx(IconButton, { color: "inherit", disabled: true, edge: "start", disableFocusRipple: true, disableRipple: true, sx: { mr: 0.75 }, children: _jsx(IconByName, { size: "large", edge: "start", color: "inherit", name: "entities.material", sx: { fontSize: "1.5rem" } }) }) }) }), _jsx(Box, { component: "main", sx: { + return (_jsx(ThemeProvider, { theme: theme, children: _jsx(ScopedCssBaseline, { enableColorScheme: true, children: _jsxs(Paper, { id: "materials-designer", children: [_jsx(AppBar, { position: "static", className: setClass("", this.props.className), children: _jsx(HeaderMenuToolbar, { isLoading: this.props.isLoading, material: this.props.material, materials: this.props.materials, index: this.props.index, onUndo: this.props.onUndo, onRedo: this.props.onRedo, onReset: this.props.onReset, onClone: this.props.onClone, onToggleIsNonPeriodic: this.props.onToggleIsNonPeriodic, onUpdate: this.props.onUpdate, onAdd: this.props.onAdd, onExport: this.props.onExport, onSave: this.props.onSave, onExit: this.props.onExit, openImportModal: this.props.openImportModal, closeImportModal: this.props.closeImportModal, openSaveActionDialog: this.props.openSaveActionDialog, onGenerateSupercell: this.props.onGenerateSupercell, onGenerateSurface: this.props.onGenerateSurface, onSetBoundaryConditions: this.props.onSetBoundaryConditions, maxCombinatorialBasesCount: this.props.maxCombinatorialBasesCount, defaultMaterialsSet: this.props.defaultMaterialsSet, onSectionVisibilityToggle: this.onSectionVisibilityToggle, isVisibleItemsList: isVisibleItemsList, isVisibleSourceEditor: isVisibleSourceEditor, isVisibleThreeDEditorFullscreen: isVisibleThreeDEditorFullscreen, isVisibleJupyterLiteSessionDrawer: this.state.isVisibleJupyterLiteSessionDrawer, children: _jsx(IconButton, { color: "inherit", disabled: true, edge: "start", disableFocusRipple: true, disableRipple: true, sx: { mr: 0.75 }, children: _jsx(IconByName, { size: "large", edge: "start", color: "inherit", name: "entities.material", sx: { fontSize: "1.5rem" } }) }) }) }), _jsx(Box, { component: "main", sx: { [theme.breakpoints.up("md")]: { height: mainContainerHeightDirective, }, @@ -124,7 +127,7 @@ class MaterialsDesigner extends mix(React.Component).with(FullscreenComponentMix maxHeight: mainContainerHeightDirective, }, overflowY: "auto", - }, children: _jsxs(Grid, { container: true, justifyContent: "flex-start", id: "materials-designer-container", sx: { height: "100%" }, children: [isVisibleItemsList && (_jsx(Grid, { item: true, ...gridConfig[1], sx: { + }, children: _jsxs(Grid, { container: true, justifyContent: "flex-start", id: "materials-designer-container", sx: { height: "100%" }, ref: this.containerRef, children: [isVisibleItemsList && (_jsx(Grid, { item: true, ...gridConfig[1], sx: { borderRight: `1px solid ${theme.palette.grey[800]}`, height: "100%", overflowY: "auto", @@ -141,7 +144,13 @@ class MaterialsDesigner extends mix(React.Component).with(FullscreenComponentMix newMaterial.metadata = this.props.material.metadata || {}; this.props.onUpdate(newMaterial); - } }) }))] }) }), _jsx(EditorSelectionInfo, {})] }) }) })); + } }) })), this.state.isVisibleJupyterLiteSessionDrawer && (_jsx(JupyterLiteSessionDrawer, { materials: this.props.materials, show: this.state.isVisibleJupyterLiteSessionDrawer, onMaterialsUpdate: (...args) => { + this.props.onAdd(...args); + }, onHide: () => { + this.setState({ + isVisibleJupyterLiteSessionDrawer: false, + }); + }, containerRef: this.containerRef }))] }) }), _jsx(EditorSelectionInfo, {})] }) }) })); } } MaterialsDesigner.propTypes = { diff --git a/dist/components/3d_editor/advanced_geometry/python_transformation/JupyterLiteTransformation.d.ts b/dist/components/3d_editor/advanced_geometry/python_transformation/JupyterLiteTransformation.d.ts index bb9ce094..3d3eab1c 100644 --- a/dist/components/3d_editor/advanced_geometry/python_transformation/JupyterLiteTransformation.d.ts +++ b/dist/components/3d_editor/advanced_geometry/python_transformation/JupyterLiteTransformation.d.ts @@ -1,220 +1,204 @@ -import MessageHandler from "@exabyte-io/cove.js/dist/other/iframe-messaging"; -import { MaterialSchema } from "@mat3ra/esse/dist/js/types"; import { Made } from "@mat3ra/made"; -import React from "react"; -interface JupyterLiteTransformationProps { - title: string; - materials: Made.Material[]; - show: boolean; - onSubmit: (newMaterials: Made.Material[]) => void; - onHide: () => void; -} -interface JupyterLiteTransformationState { - materials: Made.Material[]; +import BaseJupyterLiteSessionComponent, { BaseJupyterLiteProps } from "../../../include/jupyterlite/BaseJupyterLiteComponent"; +interface JupyterLiteTransformationDialogState { selectedMaterials: Made.Material[]; newMaterials: Made.Material[]; } -declare class JupyterLiteTransformation extends React.Component { - messageHandler: MessageHandler; - constructor(props: JupyterLiteTransformationProps); - componentDidMount(): void; - componentDidUpdate(prevProps: JupyterLiteTransformationProps): void; - returnSelectedMaterials: () => import("@mat3ra/made/dist/js/types").MaterialJSON[]; - validateMaterialConfigs: (configs: MaterialSchema[]) => { - validatedMaterials: ({ - _json: import("@mat3ra/made/dist/js/material").MaterialSchemaJSON; - toJSON(): import("@mat3ra/made/dist/js/types").MaterialJSON; - src: import("@mat3ra/esse/dist/js/types").FileSourceSchema; - updateFormula(): void; - isNonPeriodic: boolean; - getDerivedPropertyByName(name: string): { - name?: "volume" | undefined; - units?: "angstrom^3" | undefined; - value: number; - } | { - name?: "density" | undefined; - units?: "g/cm^3" | undefined; - value: number; - } | { - pointGroupSymbol?: string | undefined; - spaceGroupSymbol?: string | undefined; - tolerance?: { - units?: "angstrom" | undefined; - value: number; - } | undefined; - name?: "symmetry" | undefined; - } | { - name?: "elemental_ratio" | undefined; - value: number; - element?: string | undefined; - } | { - name?: "p-norm" | undefined; - degree?: number | undefined; +declare class JupyterLiteTransformationDialog extends BaseJupyterLiteSessionComponent { + constructor(props: BaseJupyterLiteProps); + componentDidUpdate(prevProps: BaseJupyterLiteProps, prevState: JupyterLiteTransformationDialogState): void; + handleSubmit: () => void; + setMaterials: (newMaterials: Made.Material[]) => void; + getMaterialsToUse: () => ({ + _json: import("@mat3ra/made/dist/js/material").MaterialSchemaJSON; + toJSON(): import("@mat3ra/made/dist/js/types").MaterialJSON; + src: import("@mat3ra/esse/dist/js/types").FileSourceSchema; + updateFormula(): void; + isNonPeriodic: boolean; + getDerivedPropertyByName(name: string): { + name?: "volume" | undefined; + units?: "angstrom^3" | undefined; + value: number; + } | { + name?: "density" | undefined; + units?: "g/cm^3" | undefined; + value: number; + } | { + pointGroupSymbol?: string | undefined; + spaceGroupSymbol?: string | undefined; + tolerance?: { + units?: "angstrom" | undefined; value: number; - } | { - name?: "inchi" | undefined; - value: string; - } | { - name?: "inchi_key" | undefined; - value: string; } | undefined; - getDerivedProperties(): import("@mat3ra/esse/dist/js/types").DerivedPropertiesSchema; - readonly formula: string; - readonly unitCellFormula: string; - setBasis(textOrObject: string | import("@mat3ra/made/dist/js/parsers/xyz").BasisConfig, format?: string | undefined, unitz?: string | undefined): void; - setBasisConstraints(constraints: import("@mat3ra/made/dist/js/constraints/constraints").Constraint[]): void; - readonly basis: import("@mat3ra/made/dist/js/parsers/xyz").BasisConfig; - readonly Basis: import("@mat3ra/made/dist/js/basis/constrained_basis").ConstrainedBasis; - readonly uniqueElements: string[]; - lattice: import("@mat3ra/made/dist/js/lattice/lattice_vectors").BravaisConfigProps | undefined; - readonly Lattice: Made.Lattice; - getInchiStringForHash(): string; - calculateHash(salt?: string | undefined, isScaled?: boolean | undefined, bypassNonPeriodicCheck?: boolean | undefined): string; - hash: string; - readonly scaledHash: string; - toCrystal(): void; - toCartesian(): void; - getBasisAsXyz(fractional?: boolean | undefined): string; - getAsQEFormat(): string; - getAsPOSCAR(ignoreOriginal?: boolean | undefined, omitConstraints?: boolean | undefined): string; - getACopyWithConventionalCell(): any; - getConsistencyChecks(): import("@mat3ra/esse/dist/js/types").ConsistencyCheck[]; - getBasisConsistencyChecks(): import("@mat3ra/esse/dist/js/types").ConsistencyCheck[]; - consistencyChecks: object[]; - addConsistencyChecks(array: object[]): void; - prop: { - (name: string, defaultValue: T): T; - (name: string): T_1 | undefined; - } & { - (name: string, defaultValue: T_2): T_2; - (name: string): T_1_1 | undefined; - } & { - (name: string, defaultValue: T_3): T_3; - (name: string): T_1_2 | undefined; - } & { - (name: string, defaultValue: T_4): T_4; - (name: string): T_1_3 | undefined; - } & { - (name: string, defaultValue: T_5): T_5; - (name: string): T_6 | undefined; - }; - setProp: ((name: string, value: unknown) => void) & ((name: string, value: unknown) => void) & ((name: string, value: unknown) => void) & ((name: string, value: unknown) => void) & ((name: string, value: unknown) => void); - unsetProp: ((name: string) => void) & ((name: string) => void) & ((name: string) => void) & ((name: string) => void) & ((name: string) => void); - setProps: ((json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined) => any) & ((json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined) => any) & ((json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined) => any) & ((json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined) => any) & ((json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined) => any); - toJSONSafe: ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject); - toJSONQuick: ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject); - clone: ((extraContext?: object | undefined) => any) & ((extraContext?: object | undefined) => any) & ((extraContext?: object | undefined) => any) & ((extraContext?: object | undefined) => any) & ((extraContext?: object | undefined) => any); - validate: (() => void) & (() => void) & (() => void) & (() => void) & (() => void); - clean: ((config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject); - isValid: (() => boolean) & (() => boolean) & (() => boolean) & (() => boolean) & (() => boolean); - id: string; - readonly cls: string; - getClsName: (() => string) & (() => string) & (() => string) & (() => string) & (() => string); - readonly slug: string; - readonly isSystemEntity: boolean; - getAsEntityReference: ((byIdOnly?: boolean | undefined) => import("@mat3ra/esse/dist/js/types").EntityReferenceSchema) & ((byIdOnly?: boolean | undefined) => import("@mat3ra/esse/dist/js/types").EntityReferenceSchema) & ((byIdOnly?: boolean | undefined) => import("@mat3ra/esse/dist/js/types").EntityReferenceSchema) & ((byIdOnly?: boolean | undefined) => import("@mat3ra/esse/dist/js/types").EntityReferenceSchema) & ((byIdOnly?: boolean | undefined) => import("@mat3ra/esse/dist/js/types").EntityReferenceSchema); - getEntityByName: ((entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string) => import("@mat3ra/code/dist/js/entity").InMemoryEntity) & ((entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string) => import("@mat3ra/code/dist/js/entity").InMemoryEntity) & ((entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string) => import("@mat3ra/code/dist/js/entity").InMemoryEntity) & ((entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string) => import("@mat3ra/code/dist/js/entity").InMemoryEntity) & ((entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string) => import("@mat3ra/code/dist/js/entity").InMemoryEntity); - metadata: object; - updateMetadata(object: object): void; - name: string; - setName(name: string): void; - readonly isDefault: boolean; + name?: "symmetry" | undefined; + } | { + name?: "elemental_ratio" | undefined; + value: number; + element?: string | undefined; + } | { + name?: "p-norm" | undefined; + degree?: number | undefined; + value: number; + } | { + name?: "inchi" | undefined; + value: string; + } | { + name?: "inchi_key" | undefined; + value: string; + } | undefined; + getDerivedProperties(): import("@mat3ra/esse/dist/js/types").DerivedPropertiesSchema; + readonly formula: string; + readonly unitCellFormula: string; + setBasis(textOrObject: string | import("@mat3ra/made/dist/js/parsers/xyz").BasisConfig, format?: string | undefined, unitz?: string | undefined): void; + setBasisConstraints(constraints: import("@mat3ra/made/dist/js/constraints/constraints").Constraint[]): void; + readonly basis: import("@mat3ra/made/dist/js/parsers/xyz").BasisConfig; + readonly Basis: import("@mat3ra/made/dist/js/basis/constrained_basis").ConstrainedBasis; + readonly uniqueElements: string[]; + lattice: import("@mat3ra/made/dist/js/lattice/lattice_vectors").BravaisConfigProps | undefined; + readonly Lattice: Made.Lattice; + getInchiStringForHash(): string; + calculateHash(salt?: string | undefined, isScaled?: boolean | undefined, bypassNonPeriodicCheck?: boolean | undefined): string; + hash: string; + readonly scaledHash: string; + toCrystal(): void; + toCartesian(): void; + getBasisAsXyz(fractional?: boolean | undefined): string; + getAsQEFormat(): string; + getAsPOSCAR(ignoreOriginal?: boolean | undefined, omitConstraints?: boolean | undefined): string; + getACopyWithConventionalCell(): any; + getConsistencyChecks(): import("@mat3ra/esse/dist/js/types").ConsistencyCheck[]; + getBasisConsistencyChecks(): import("@mat3ra/esse/dist/js/types").ConsistencyCheck[]; + consistencyChecks: object[]; + addConsistencyChecks(array: object[]): void; + prop: { + (name: string, defaultValue: T): T; + (name: string): T_1 | undefined; } & { - consistencyChecks: object[]; - addConsistencyChecks(array: object[]): void; - _json: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - prop(name: string, defaultValue: T_7): T_7; - prop(name: string): T_1_4 | undefined; - setProp(name: string, value: unknown): void; - unsetProp(name: string): void; - setProps(json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined): any; - toJSON(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - toJSONSafe(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - toJSONQuick(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - clone(extraContext?: object | undefined): any; - validate(): void; - clean(config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - isValid(): boolean; - id: string; - readonly cls: string; - getClsName(): string; - readonly slug: string; - readonly isSystemEntity: boolean; - getAsEntityReference(byIdOnly?: boolean | undefined): import("@mat3ra/esse/dist/js/types").EntityReferenceSchema; - getEntityByName(entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string): import("@mat3ra/code/dist/js/entity").InMemoryEntity; + (name: string, defaultValue: T_2): T_2; + (name: string): T_1_1 | undefined; } & { - metadata: object; - updateMetadata(object: object): void; - _json: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - prop(name: string, defaultValue: T_2_1): T_2_1; - prop(name: string): T_1_1_1 | undefined; - setProp(name: string, value: unknown): void; - unsetProp(name: string): void; - setProps(json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined): any; - toJSON(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - toJSONSafe(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - toJSONQuick(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - clone(extraContext?: object | undefined): any; - validate(): void; - clean(config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - isValid(): boolean; - id: string; - readonly cls: string; - getClsName(): string; - readonly slug: string; - readonly isSystemEntity: boolean; - getAsEntityReference(byIdOnly?: boolean | undefined): import("@mat3ra/esse/dist/js/types").EntityReferenceSchema; - getEntityByName(entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string): import("@mat3ra/code/dist/js/entity").InMemoryEntity; + (name: string, defaultValue: T_3): T_3; + (name: string): T_1_2 | undefined; } & { - name: string; - setName(name: string): void; - _json: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - prop(name: string, defaultValue: T_3_1): T_3_1; - prop(name: string): T_1_2_1 | undefined; - setProp(name: string, value: unknown): void; - unsetProp(name: string): void; - setProps(json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined): any; - toJSON(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - toJSONSafe(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - toJSONQuick(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - clone(extraContext?: object | undefined): any; - validate(): void; - clean(config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - isValid(): boolean; - id: string; - readonly cls: string; - getClsName(): string; - readonly slug: string; - readonly isSystemEntity: boolean; - getAsEntityReference(byIdOnly?: boolean | undefined): import("@mat3ra/esse/dist/js/types").EntityReferenceSchema; - getEntityByName(entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string): import("@mat3ra/code/dist/js/entity").InMemoryEntity; + (name: string, defaultValue: T_4): T_4; + (name: string): T_1_3 | undefined; } & { - readonly isDefault: boolean; - _json: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - prop(name: string, defaultValue: T_4_1): T_4_1; - prop(name: string): T_1_3_1 | undefined; - setProp(name: string, value: unknown): void; - unsetProp(name: string): void; - setProps(json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined): any; - toJSON(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - toJSONSafe(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - toJSONQuick(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - clone(extraContext?: object | undefined): any; - validate(): void; - clean(config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; - isValid(): boolean; - id: string; - readonly cls: string; - getClsName(): string; - readonly slug: string; - readonly isSystemEntity: boolean; - getAsEntityReference(byIdOnly?: boolean | undefined): import("@mat3ra/esse/dist/js/types").EntityReferenceSchema; - getEntityByName(entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string): import("@mat3ra/code/dist/js/entity").InMemoryEntity; - } & import("@mat3ra/code/dist/js/entity").InMemoryEntity)[]; - validationErrors: string[]; - }; - handleSetMaterials: (data: any) => void; - handleSubmit: () => Promise; + (name: string, defaultValue: T_5): T_5; + (name: string): T_6 | undefined; + }; + setProp: ((name: string, value: unknown) => void) & ((name: string, value: unknown) => void) & ((name: string, value: unknown) => void) & ((name: string, value: unknown) => void) & ((name: string, value: unknown) => void); + unsetProp: ((name: string) => void) & ((name: string) => void) & ((name: string) => void) & ((name: string) => void) & ((name: string) => void); + setProps: ((json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined) => any) & ((json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined) => any) & ((json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined) => any) & ((json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined) => any) & ((json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined) => any); + toJSONSafe: ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject); + toJSONQuick: ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject); + clone: ((extraContext?: object | undefined) => any) & ((extraContext?: object | undefined) => any) & ((extraContext?: object | undefined) => any) & ((extraContext?: object | undefined) => any) & ((extraContext?: object | undefined) => any); + validate: (() => void) & (() => void) & (() => void) & (() => void) & (() => void); + clean: ((config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject); + isValid: (() => boolean) & (() => boolean) & (() => boolean) & (() => boolean) & (() => boolean); + id: string; + readonly cls: string; + getClsName: (() => string) & (() => string) & (() => string) & (() => string) & (() => string); + readonly slug: string; + readonly isSystemEntity: boolean; + getAsEntityReference: ((byIdOnly?: boolean | undefined) => import("@mat3ra/esse/dist/js/types").EntityReferenceSchema) & ((byIdOnly?: boolean | undefined) => import("@mat3ra/esse/dist/js/types").EntityReferenceSchema) & ((byIdOnly?: boolean | undefined) => import("@mat3ra/esse/dist/js/types").EntityReferenceSchema) & ((byIdOnly?: boolean | undefined) => import("@mat3ra/esse/dist/js/types").EntityReferenceSchema) & ((byIdOnly?: boolean | undefined) => import("@mat3ra/esse/dist/js/types").EntityReferenceSchema); + getEntityByName: ((entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string) => import("@mat3ra/code/dist/js/entity").InMemoryEntity) & ((entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string) => import("@mat3ra/code/dist/js/entity").InMemoryEntity) & ((entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string) => import("@mat3ra/code/dist/js/entity").InMemoryEntity) & ((entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string) => import("@mat3ra/code/dist/js/entity").InMemoryEntity) & ((entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string) => import("@mat3ra/code/dist/js/entity").InMemoryEntity); + metadata: object; + updateMetadata(object: object): void; + name: string; + setName(name: string): void; + readonly isDefault: boolean; + } & { + consistencyChecks: object[]; + addConsistencyChecks(array: object[]): void; + _json: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + prop(name: string, defaultValue: T_7): T_7; + prop(name: string): T_1_4 | undefined; + setProp(name: string, value: unknown): void; + unsetProp(name: string): void; + setProps(json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined): any; + toJSON(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONSafe(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONQuick(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + clone(extraContext?: object | undefined): any; + validate(): void; + clean(config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + isValid(): boolean; + id: string; + readonly cls: string; + getClsName(): string; + readonly slug: string; + readonly isSystemEntity: boolean; + getAsEntityReference(byIdOnly?: boolean | undefined): import("@mat3ra/esse/dist/js/types").EntityReferenceSchema; + getEntityByName(entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string): import("@mat3ra/code/dist/js/entity").InMemoryEntity; + } & { + metadata: object; + updateMetadata(object: object): void; + _json: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + prop(name: string, defaultValue: T_2_1): T_2_1; + prop(name: string): T_1_1_1 | undefined; + setProp(name: string, value: unknown): void; + unsetProp(name: string): void; + setProps(json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined): any; + toJSON(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONSafe(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONQuick(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + clone(extraContext?: object | undefined): any; + validate(): void; + clean(config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + isValid(): boolean; + id: string; + readonly cls: string; + getClsName(): string; + readonly slug: string; + readonly isSystemEntity: boolean; + getAsEntityReference(byIdOnly?: boolean | undefined): import("@mat3ra/esse/dist/js/types").EntityReferenceSchema; + getEntityByName(entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string): import("@mat3ra/code/dist/js/entity").InMemoryEntity; + } & { + name: string; + setName(name: string): void; + _json: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + prop(name: string, defaultValue: T_3_1): T_3_1; + prop(name: string): T_1_2_1 | undefined; + setProp(name: string, value: unknown): void; + unsetProp(name: string): void; + setProps(json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined): any; + toJSON(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONSafe(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONQuick(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + clone(extraContext?: object | undefined): any; + validate(): void; + clean(config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + isValid(): boolean; + id: string; + readonly cls: string; + getClsName(): string; + readonly slug: string; + readonly isSystemEntity: boolean; + getAsEntityReference(byIdOnly?: boolean | undefined): import("@mat3ra/esse/dist/js/types").EntityReferenceSchema; + getEntityByName(entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string): import("@mat3ra/code/dist/js/entity").InMemoryEntity; + } & { + readonly isDefault: boolean; + _json: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + prop(name: string, defaultValue: T_4_1): T_4_1; + prop(name: string): T_1_3_1 | undefined; + setProp(name: string, value: unknown): void; + unsetProp(name: string): void; + setProps(json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined): any; + toJSON(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONSafe(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONQuick(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + clone(extraContext?: object | undefined): any; + validate(): void; + clean(config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + isValid(): boolean; + id: string; + readonly cls: string; + getClsName(): string; + readonly slug: string; + readonly isSystemEntity: boolean; + getAsEntityReference(byIdOnly?: boolean | undefined): import("@mat3ra/esse/dist/js/types").EntityReferenceSchema; + getEntityByName(entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string): import("@mat3ra/code/dist/js/entity").InMemoryEntity; + } & import("@mat3ra/code/dist/js/entity").InMemoryEntity)[]; render(): import("react/jsx-runtime").JSX.Element; } -export default JupyterLiteTransformation; +export default JupyterLiteTransformationDialog; diff --git a/dist/components/3d_editor/advanced_geometry/python_transformation/JupyterLiteTransformation.js b/dist/components/3d_editor/advanced_geometry/python_transformation/JupyterLiteTransformation.js index 0749a9a0..212a4639 100644 --- a/dist/components/3d_editor/advanced_geometry/python_transformation/JupyterLiteTransformation.js +++ b/dist/components/3d_editor/advanced_geometry/python_transformation/JupyterLiteTransformation.js @@ -1,82 +1,41 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import Dialog from "@exabyte-io/cove.js/dist/mui/components/dialog/Dialog"; -import MessageHandler from "@exabyte-io/cove.js/dist/other/iframe-messaging"; -import JupyterLiteSession from "@exabyte-io/cove.js/dist/other/jupyterlite/JupyterLiteSession"; -import { Made } from "@mat3ra/made"; import { darkScrollbar } from "@mui/material"; import Grid from "@mui/material/Grid"; import Paper from "@mui/material/Paper"; import Typography from "@mui/material/Typography"; -import { enqueueSnackbar } from "notistack"; -import React from "react"; import { theme } from "../../../../settings"; +import BaseJupyterLiteSessionComponent from "../../../include/jupyterlite/BaseJupyterLiteComponent"; import MaterialsSelector from "./MaterialsSelector"; -const DEFAULT_NOTEBOOK_PATH = "api-examples/other/materials_designer/Introduction.ipynb"; -class JupyterLiteTransformation extends React.Component { +class JupyterLiteTransformationDialog extends BaseJupyterLiteSessionComponent { constructor(props) { super(props); - this.messageHandler = new MessageHandler(); - this.returnSelectedMaterials = () => { - const { selectedMaterials } = this.state; - return selectedMaterials.map((material) => material.toJSON()); - }; - this.validateMaterialConfigs = (configs) => { - const validationErrors = []; - const validatedMaterials = configs.reduce((validMaterials, config) => { - try { - const material = new Made.Material(config); - material.validate(); - validMaterials.push(material); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } - catch (e) { - validationErrors.push(`Failed to create material ${config.name}: ${JSON.stringify(e.details.error[0])}`); - } - return validMaterials; - }, []); - return { validatedMaterials, validationErrors }; + this.handleSubmit = () => { + const { newMaterials } = this.state; + this.props.onMaterialsUpdate(newMaterials); }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - this.handleSetMaterials = (data) => { - const configs = data.materials; - if (Array.isArray(configs)) { - const { validatedMaterials, validationErrors } = this.validateMaterialConfigs(configs); - this.setState({ newMaterials: validatedMaterials }); - validationErrors.forEach((errorMessage) => { - enqueueSnackbar(errorMessage, { variant: "error" }); - }); - } - else { - enqueueSnackbar("Invalid material data received", { variant: "error" }); - } + this.setMaterials = (newMaterials) => { + this.setState({ newMaterials }); }; - this.handleSubmit = async () => { - const { onSubmit, materials } = this.props; - const { newMaterials } = this.state; - onSubmit(newMaterials); - this.setState({ selectedMaterials: [materials[0]], newMaterials: [] }); + this.getMaterialsToUse = () => { + return this.state.selectedMaterials; }; this.state = { - materials: props.materials, - selectedMaterials: [props.materials[0]], + selectedMaterials: [this.props.materials[0]], newMaterials: [], }; } - componentDidMount() { - this.messageHandler.addHandlers("set-data", [this.handleSetMaterials]); - this.messageHandler.addHandlers("get-data", [this.returnSelectedMaterials]); - } - componentDidUpdate(prevProps) { - const { materials } = this.props; - if (prevProps.materials !== materials) { - // eslint-disable-next-line react/no-did-update-set-state - this.setState({ materials }); + componentDidUpdate(prevProps, prevState) { + if (prevProps.materials !== this.props.materials) { + this.setState({ selectedMaterials: [this.props.materials[0]] }); + } + if (prevState.selectedMaterials !== this.state.selectedMaterials) { + this.sendMaterials(); } - this.messageHandler.sendData(this.returnSelectedMaterials()); } render() { - const { materials, selectedMaterials, newMaterials } = this.state; - const { title, show, onHide } = this.props; + const { title, show, onHide, materials } = this.props; + const { selectedMaterials, newMaterials } = this.state; return (_jsx(Dialog, { id: "jupyterlite-transformation-dialog", open: show, onClose: onHide, fullWidth: true, maxWidth: "xl", onSubmit: this.handleSubmit, title: title, isSubmitButtonDisabled: newMaterials.length === 0, children: _jsxs(Grid, { container: true, spacing: 1, id: "jupyterlite-transformation-dialog-content", sx: { height: "calc(100vh - 260px)", ...(theme.palette.mode === "dark" ? darkScrollbar() : null), @@ -85,7 +44,7 @@ class JupyterLiteTransformation extends React.Component { overflow: "hidden", }, children: _jsx(Paper, { sx: { height: "100%", - }, children: _jsx(JupyterLiteSession, { defaultNotebookPath: DEFAULT_NOTEBOOK_PATH, messageHandler: this.messageHandler }) }) }), _jsx(Grid, { item: true, container: true, xs: 12, md: 4, alignItems: "center", children: _jsxs(Typography, { variant: "subtitle1", children: ["Output Materials (", _jsx("code", { children: "materials_out" }), ")"] }) }), _jsx(Grid, { item: true, xs: 12, md: 8, children: _jsx(MaterialsSelector, { materials: newMaterials, selectedMaterials: newMaterials, setSelectedMaterials: (newMaterials) => this.setState({ newMaterials }) }) })] }) })); + }, children: super.render() }) }), _jsx(Grid, { item: true, container: true, xs: 12, md: 4, alignItems: "center", children: _jsxs(Typography, { variant: "subtitle1", children: ["Output Materials (", _jsx("code", { children: "materials_out" }), ")"] }) }), _jsx(Grid, { item: true, xs: 12, md: 8, children: _jsx(MaterialsSelector, { materials: newMaterials, selectedMaterials: newMaterials, setSelectedMaterials: (newMaterials) => this.setState({ newMaterials }) }) })] }) })); } } -export default JupyterLiteTransformation; +export default JupyterLiteTransformationDialog; diff --git a/dist/components/drawer_session/JupyterLiteSessionDrawer.d.ts b/dist/components/drawer_session/JupyterLiteSessionDrawer.d.ts new file mode 100644 index 00000000..a8cf7ba9 --- /dev/null +++ b/dist/components/drawer_session/JupyterLiteSessionDrawer.d.ts @@ -0,0 +1,5 @@ +import BaseJupyterLiteSessionComponent from "../include/jupyterlite/BaseJupyterLiteComponent"; +declare class JupyterLiteSessionDrawer extends BaseJupyterLiteSessionComponent { + render(): import("react/jsx-runtime").JSX.Element; +} +export default JupyterLiteSessionDrawer; diff --git a/dist/components/drawer_session/JupyterLiteSessionDrawer.js b/dist/components/drawer_session/JupyterLiteSessionDrawer.js new file mode 100644 index 00000000..8fbf63ac --- /dev/null +++ b/dist/components/drawer_session/JupyterLiteSessionDrawer.js @@ -0,0 +1,12 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import ResizableDrawer from "@exabyte-io/cove.js/dist/mui/components/custom/resizable-drawer/ResizableDrawer"; +import BaseJupyterLiteSessionComponent from "../include/jupyterlite/BaseJupyterLiteComponent"; +class JupyterLiteSessionDrawer extends BaseJupyterLiteSessionComponent { + render() { + // TODO: fix drawer sticking to the MD container and pass the ref to the resizable drawer then + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { show, onHide, containerRef } = this.props; + return (_jsx("div", { style: { display: show ? "block" : "none" }, children: _jsx(ResizableDrawer, { open: show, onClose: onHide, children: super.render() }) })); + } +} +export default JupyterLiteSessionDrawer; diff --git a/dist/components/header_menu/HeaderMenuToolbar.js b/dist/components/header_menu/HeaderMenuToolbar.js index e5634cf8..7cc8c6f2 100644 --- a/dist/components/header_menu/HeaderMenuToolbar.js +++ b/dist/components/header_menu/HeaderMenuToolbar.js @@ -105,10 +105,12 @@ class HeaderMenuToolbar extends React.Component { } renderViewMenu() { const { onSectionVisibilityToggle, isVisibleItemsList, isVisibleSourceEditor, isVisibleThreeDEditorFullscreen, } = this.props; - return (_jsxs(ButtonActivatedMenuMaterialUI, { title: "View", children: [_jsxs(MenuItem, { onClick: () => this.setState({ showThreejsEditorModal: true }), children: [_jsx(ListItemIcon, { children: _jsx(ThreeDEditorIcon, {}) }), "Multi-Material 3D Editor"] }), _jsx(Divider, {}), _jsxs(MenuItem, { onClick: () => onSectionVisibilityToggle("ItemsList"), children: [_jsx(ListItemIcon, { children: isVisibleItemsList ? _jsx(VisibilityOffIcon, {}) : _jsx(VisibilityIcon, {}) }), "Sidebar"] }), _jsxs(MenuItem, { onClick: () => onSectionVisibilityToggle("SourceEditor"), children: [_jsx(ListItemIcon, { children: isVisibleSourceEditor ? _jsx(VisibilityOffIcon, {}) : _jsx(VisibilityIcon, {}) }), "Source Editor"] }), _jsxs(MenuItem, { onClick: () => onSectionVisibilityToggle("ThreeDEditorFullscreen"), children: [_jsx(ListItemIcon, { children: isVisibleThreeDEditorFullscreen ? (_jsx(VisibilityOffIcon, {})) : (_jsx(VisibilityIcon, {})) }), "3D Viewer/Editor"] })] })); + return (_jsxs(ButtonActivatedMenuMaterialUI, { title: "View", children: [_jsxs(MenuItem, { onClick: () => this.setState({ showThreejsEditorModal: true }), children: [_jsx(ListItemIcon, { children: _jsx(ThreeDEditorIcon, {}) }), "Multi-Material 3D Editor"] }), _jsx(Divider, {}), _jsxs(MenuItem, { onClick: () => onSectionVisibilityToggle("ItemsList"), children: [_jsx(ListItemIcon, { children: isVisibleItemsList ? _jsx(VisibilityOffIcon, {}) : _jsx(VisibilityIcon, {}) }), "Sidebar"] }), _jsxs(MenuItem, { onClick: () => onSectionVisibilityToggle("SourceEditor"), children: [_jsx(ListItemIcon, { children: isVisibleSourceEditor ? _jsx(VisibilityOffIcon, {}) : _jsx(VisibilityIcon, {}) }), "Source Editor"] }), _jsxs(MenuItem, { onClick: () => onSectionVisibilityToggle("ThreeDEditorFullscreen"), children: [_jsx(ListItemIcon, { children: isVisibleThreeDEditorFullscreen ? (_jsx(VisibilityOffIcon, {})) : (_jsx(VisibilityIcon, {})) }), "3D Viewer/Editor"] }), _jsxs(MenuItem, { onClick: () => onSectionVisibilityToggle("JupyterLiteSessionDrawer"), children: [_jsx(ListItemIcon, { children: _jsx(Terminal, {}) }), "JupyterLite Session"] })] })); } renderAdvancedMenu() { - return (_jsxs(ButtonActivatedMenuMaterialUI, { title: "Advanced", children: [_jsxs(MenuItem, { onClick: () => this.setState({ showSupercellDialog: true }), children: [_jsx(ListItemIcon, { children: _jsx(SupercellIcon, {}) }), "Supercell"] }), _jsxs(MenuItem, { onClick: () => this.setState({ showCombinatorialDialog: true }), children: [_jsx(ListItemIcon, { children: _jsx(CombinatorialSetIcon, {}) }), "Combinatorial set"] }), _jsxs(MenuItem, { onClick: () => this.setState({ showInterpolateDialog: true }), children: [_jsx(ListItemIcon, { children: _jsx(InterpolatedSetIcon, {}) }), "Interpolated set"] }), _jsxs(MenuItem, { onClick: () => this.setState({ showSurfaceDialog: true }), children: [_jsx(ListItemIcon, { children: _jsx(SlabIcon, {}) }), "Surface / slab"] }), _jsxs(MenuItem, { onClick: () => this.setState({ showBoundaryConditionsDialog: true }), children: [_jsx(ListItemIcon, { children: _jsx(BoundaryConditionsIcon, {}) }), "Boundary Conditions"] }), false && (_jsxs(MenuItem, { children: [_jsx(ListItemIcon, { children: _jsx(PolymerIcon, {}) }), "Polymer"] })), false && (_jsxs(MenuItem, { children: [_jsx(ListItemIcon, { children: _jsx(NanotubeIcon, {}) }), "Nanotube"] })), _jsxs(MenuItem, { onClick: () => this.setState({ showPythonTransformation: true }), children: [_jsx(ListItemIcon, { children: _jsx(Terminal, {}) }), "Python Transformation"] }), _jsxs(MenuItem, { onClick: () => this.setState({ showJupyterLiteTransformation: true }), children: [_jsx(ListItemIcon, { children: _jsx(Terminal, {}) }), "JupyterLite Session"] })] })); + return (_jsxs(ButtonActivatedMenuMaterialUI, { title: "Advanced", children: [_jsxs(MenuItem, { onClick: () => this.setState({ showSupercellDialog: true }), children: [_jsx(ListItemIcon, { children: _jsx(SupercellIcon, {}) }), "Supercell"] }), _jsxs(MenuItem, { onClick: () => this.setState({ showCombinatorialDialog: true }), children: [_jsx(ListItemIcon, { children: _jsx(CombinatorialSetIcon, {}) }), "Combinatorial set"] }), _jsxs(MenuItem, { onClick: () => this.setState({ showInterpolateDialog: true }), children: [_jsx(ListItemIcon, { children: _jsx(InterpolatedSetIcon, {}) }), "Interpolated set"] }), _jsxs(MenuItem, { onClick: () => this.setState({ showSurfaceDialog: true }), children: [_jsx(ListItemIcon, { children: _jsx(SlabIcon, {}) }), "Surface / slab"] }), _jsxs(MenuItem, { onClick: () => this.setState({ showBoundaryConditionsDialog: true }), children: [_jsx(ListItemIcon, { children: _jsx(BoundaryConditionsIcon, {}) }), "Boundary Conditions"] }), false && (_jsxs(MenuItem, { children: [_jsx(ListItemIcon, { children: _jsx(PolymerIcon, {}) }), "Polymer"] })), false && (_jsxs(MenuItem, { children: [_jsx(ListItemIcon, { children: _jsx(NanotubeIcon, {}) }), "Nanotube"] })), _jsxs(MenuItem, { onClick: () => this.setState({ showPythonTransformation: true }), children: [_jsx(ListItemIcon, { children: _jsx(Terminal, {}) }), "Python Transformation"] }), _jsxs(MenuItem, { onClick: () => this.setState((state) => ({ + showJupyterLiteTransformation: !state.showJupyterLiteTransformation, + })), children: [_jsx(ListItemIcon, { children: _jsx(Terminal, {}) }), "JupyterLite Transformation"] })] })); } renderHelpMenu() { return (_jsxs(ButtonActivatedMenuMaterialUI, { title: "Help", children: [_jsxs(MenuItem, { onClick: () => this.openPageByURL("https://docs.exabyte.io/materials-designer/overview/"), children: [_jsx(ListItemIcon, { children: _jsx(HelpIcon, {}) }), "Documentation"] }), _jsxs(MenuItem, { onClick: () => this.openPageByURL("https://docs.exabyte.io/tutorials/materials/overview/"), children: [_jsx(ListItemIcon, { children: _jsx(AssignmentIcon, {}) }), "Tutorials"] })] })); @@ -150,7 +152,7 @@ class HeaderMenuToolbar extends React.Component { } }), _jsx(PythonTransformation, { show: showPythonTransformation, materials: materials, onHide: () => this.setState({ showPythonTransformation: false }), onSubmit: (...args) => { onAdd(...args); this.setState({ showPythonTransformation: false }); - } }), _jsx(JupyterLiteTransformation, { title: "JupyterLite Session", show: showJupyterLiteTransformation, materials: materials, onHide: () => this.setState({ showJupyterLiteTransformation: false }), onSubmit: (...args) => { + } }), _jsx(JupyterLiteTransformation, { title: "JupyterLite Transformation", show: showJupyterLiteTransformation, materials: materials, onHide: () => this.setState({ showJupyterLiteTransformation: false }), onMaterialsUpdate: (...args) => { onAdd(...args); this.setState({ showJupyterLiteTransformation: false }); } })] })); diff --git a/dist/components/include/jupyterlite/BaseJupyterLiteComponent.d.ts b/dist/components/include/jupyterlite/BaseJupyterLiteComponent.d.ts new file mode 100644 index 00000000..8466b2ae --- /dev/null +++ b/dist/components/include/jupyterlite/BaseJupyterLiteComponent.d.ts @@ -0,0 +1,219 @@ +import MessageHandler from "@exabyte-io/cove.js/dist/other/iframe-messaging"; +import { MaterialSchema } from "@mat3ra/esse/dist/js/types"; +import { Made } from "@mat3ra/made"; +import React from "react"; +export interface BaseJupyterLiteProps { + materials: Made.Material[]; + show: boolean; + onMaterialsUpdate: (newMaterials: Made.Material[]) => void; + onHide: () => void; + title?: string; + containerRef?: React.RefObject; +} +declare class BaseJupyterLiteSessionComponent

extends React.Component

{ + messageHandler: MessageHandler; + DEFAULT_NOTEBOOK_PATH: string; + componentDidMount(): void; + componentDidUpdate(prevProps: P & BaseJupyterLiteProps, prevState: S): void; + componentWillUnmount(): void; + sendMaterials: () => void; + getMaterialsForMessage: () => import("@mat3ra/made/dist/js/types").MaterialJSON[]; + getMaterialsToUse: () => (P & BaseJupyterLiteProps)["materials"]; + validateMaterialConfigs: (configs: MaterialSchema[]) => { + validatedMaterials: ({ + _json: import("@mat3ra/made/dist/js/material").MaterialSchemaJSON; + toJSON(): import("@mat3ra/made/dist/js/types").MaterialJSON; + src: import("@mat3ra/esse/dist/js/types").FileSourceSchema; + updateFormula(): void; + isNonPeriodic: boolean; + getDerivedPropertyByName(name: string): { + name?: "volume" | undefined; + units?: "angstrom^3" | undefined; + value: number; + } | { + name?: "density" | undefined; + units?: "g/cm^3" | undefined; + value: number; + } | { + pointGroupSymbol?: string | undefined; + spaceGroupSymbol?: string | undefined; + tolerance?: { + units?: "angstrom" | undefined; + value: number; + } | undefined; + name?: "symmetry" | undefined; + } | { + name?: "elemental_ratio" | undefined; + value: number; + element?: string | undefined; + } | { + name?: "p-norm" | undefined; + degree?: number | undefined; + value: number; + } | { + name?: "inchi" | undefined; + value: string; + } | { + name?: "inchi_key" | undefined; + value: string; + } | undefined; + getDerivedProperties(): import("@mat3ra/esse/dist/js/types").DerivedPropertiesSchema; + readonly formula: string; + readonly unitCellFormula: string; + setBasis(textOrObject: string | import("@mat3ra/made/dist/js/parsers/xyz").BasisConfig, format?: string | undefined, unitz?: string | undefined): void; + setBasisConstraints(constraints: import("@mat3ra/made/dist/js/constraints/constraints").Constraint[]): void; + readonly basis: import("@mat3ra/made/dist/js/parsers/xyz").BasisConfig; + readonly Basis: import("@mat3ra/made/dist/js/basis/constrained_basis").ConstrainedBasis; + readonly uniqueElements: string[]; + lattice: import("@mat3ra/made/dist/js/lattice/lattice_vectors").BravaisConfigProps | undefined; + readonly Lattice: Made.Lattice; + getInchiStringForHash(): string; + calculateHash(salt?: string | undefined, isScaled?: boolean | undefined, bypassNonPeriodicCheck?: boolean | undefined): string; + hash: string; + readonly scaledHash: string; + toCrystal(): void; + toCartesian(): void; + getBasisAsXyz(fractional?: boolean | undefined): string; + getAsQEFormat(): string; + getAsPOSCAR(ignoreOriginal?: boolean | undefined, omitConstraints?: boolean | undefined): string; + getACopyWithConventionalCell(): any; + getConsistencyChecks(): import("@mat3ra/esse/dist/js/types").ConsistencyCheck[]; + getBasisConsistencyChecks(): import("@mat3ra/esse/dist/js/types").ConsistencyCheck[]; + consistencyChecks: object[]; + addConsistencyChecks(array: object[]): void; + prop: { + (name: string, defaultValue: T): T; + (name: string): T_1 | undefined; + } & { + (name: string, defaultValue: T_2): T_2; + (name: string): T_1_1 | undefined; + } & { + (name: string, defaultValue: T_3): T_3; + (name: string): T_1_2 | undefined; + } & { + (name: string, defaultValue: T_4): T_4; + (name: string): T_1_3 | undefined; + } & { + (name: string, defaultValue: T_5): T_5; + (name: string): T_6 | undefined; + }; + setProp: ((name: string, value: unknown) => void) & ((name: string, value: unknown) => void) & ((name: string, value: unknown) => void) & ((name: string, value: unknown) => void) & ((name: string, value: unknown) => void); + unsetProp: ((name: string) => void) & ((name: string) => void) & ((name: string) => void) & ((name: string) => void) & ((name: string) => void); + setProps: ((json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined) => any) & ((json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined) => any) & ((json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined) => any) & ((json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined) => any) & ((json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined) => any); + toJSONSafe: ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject); + toJSONQuick: ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((exclude?: string[] | undefined) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject); + clone: ((extraContext?: object | undefined) => any) & ((extraContext?: object | undefined) => any) & ((extraContext?: object | undefined) => any) & ((extraContext?: object | undefined) => any) & ((extraContext?: object | undefined) => any); + validate: (() => void) & (() => void) & (() => void) & (() => void) & (() => void); + clean: ((config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) & ((config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject) => import("@mat3ra/code/dist/js/entity/in_memory").AnyObject); + isValid: (() => boolean) & (() => boolean) & (() => boolean) & (() => boolean) & (() => boolean); + id: string; + readonly cls: string; + getClsName: (() => string) & (() => string) & (() => string) & (() => string) & (() => string); + readonly slug: string; + readonly isSystemEntity: boolean; + getAsEntityReference: ((byIdOnly?: boolean | undefined) => import("@mat3ra/esse/dist/js/types").EntityReferenceSchema) & ((byIdOnly?: boolean | undefined) => import("@mat3ra/esse/dist/js/types").EntityReferenceSchema) & ((byIdOnly?: boolean | undefined) => import("@mat3ra/esse/dist/js/types").EntityReferenceSchema) & ((byIdOnly?: boolean | undefined) => import("@mat3ra/esse/dist/js/types").EntityReferenceSchema) & ((byIdOnly?: boolean | undefined) => import("@mat3ra/esse/dist/js/types").EntityReferenceSchema); + getEntityByName: ((entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string) => import("@mat3ra/code/dist/js/entity").InMemoryEntity) & ((entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string) => import("@mat3ra/code/dist/js/entity").InMemoryEntity) & ((entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string) => import("@mat3ra/code/dist/js/entity").InMemoryEntity) & ((entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string) => import("@mat3ra/code/dist/js/entity").InMemoryEntity) & ((entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string) => import("@mat3ra/code/dist/js/entity").InMemoryEntity); + metadata: object; + updateMetadata(object: object): void; + name: string; + setName(name: string): void; + readonly isDefault: boolean; + } & { + consistencyChecks: object[]; + addConsistencyChecks(array: object[]): void; + _json: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + prop(name: string, defaultValue: T_7): T_7; + prop(name: string): T_1_4 | undefined; + setProp(name: string, value: unknown): void; + unsetProp(name: string): void; + setProps(json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined): any; + toJSON(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONSafe(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONQuick(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + clone(extraContext?: object | undefined): any; + validate(): void; + clean(config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + isValid(): boolean; + id: string; + readonly cls: string; + getClsName(): string; + readonly slug: string; + readonly isSystemEntity: boolean; + getAsEntityReference(byIdOnly?: boolean | undefined): import("@mat3ra/esse/dist/js/types").EntityReferenceSchema; + getEntityByName(entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string): import("@mat3ra/code/dist/js/entity").InMemoryEntity; + } & { + metadata: object; + updateMetadata(object: object): void; + _json: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + prop(name: string, defaultValue: T_2_1): T_2_1; + prop(name: string): T_1_1_1 | undefined; + setProp(name: string, value: unknown): void; + unsetProp(name: string): void; + setProps(json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined): any; + toJSON(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONSafe(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONQuick(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + clone(extraContext?: object | undefined): any; + validate(): void; + clean(config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + isValid(): boolean; + id: string; + readonly cls: string; + getClsName(): string; + readonly slug: string; + readonly isSystemEntity: boolean; + getAsEntityReference(byIdOnly?: boolean | undefined): import("@mat3ra/esse/dist/js/types").EntityReferenceSchema; + getEntityByName(entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string): import("@mat3ra/code/dist/js/entity").InMemoryEntity; + } & { + name: string; + setName(name: string): void; + _json: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + prop(name: string, defaultValue: T_3_1): T_3_1; + prop(name: string): T_1_2_1 | undefined; + setProp(name: string, value: unknown): void; + unsetProp(name: string): void; + setProps(json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined): any; + toJSON(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONSafe(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONQuick(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + clone(extraContext?: object | undefined): any; + validate(): void; + clean(config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + isValid(): boolean; + id: string; + readonly cls: string; + getClsName(): string; + readonly slug: string; + readonly isSystemEntity: boolean; + getAsEntityReference(byIdOnly?: boolean | undefined): import("@mat3ra/esse/dist/js/types").EntityReferenceSchema; + getEntityByName(entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string): import("@mat3ra/code/dist/js/entity").InMemoryEntity; + } & { + readonly isDefault: boolean; + _json: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + prop(name: string, defaultValue: T_4_1): T_4_1; + prop(name: string): T_1_3_1 | undefined; + setProp(name: string, value: unknown): void; + unsetProp(name: string): void; + setProps(json?: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject | undefined): any; + toJSON(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONSafe(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + toJSONQuick(exclude?: string[] | undefined): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + clone(extraContext?: object | undefined): any; + validate(): void; + clean(config: import("@mat3ra/code/dist/js/entity/in_memory").AnyObject): import("@mat3ra/code/dist/js/entity/in_memory").AnyObject; + isValid(): boolean; + id: string; + readonly cls: string; + getClsName(): string; + readonly slug: string; + readonly isSystemEntity: boolean; + getAsEntityReference(byIdOnly?: boolean | undefined): import("@mat3ra/esse/dist/js/types").EntityReferenceSchema; + getEntityByName(entities: import("@mat3ra/code/dist/js/entity").InMemoryEntity[], entity: string, name: string): import("@mat3ra/code/dist/js/entity").InMemoryEntity; + } & import("@mat3ra/code/dist/js/entity").InMemoryEntity)[]; + validationErrors: string[]; + }; + handleSetMaterials: (data: any) => void; + setMaterials: (materials: Made.Material[]) => void; + render(): import("react/jsx-runtime").JSX.Element; +} +export default BaseJupyterLiteSessionComponent; diff --git a/dist/components/include/jupyterlite/BaseJupyterLiteComponent.js b/dist/components/include/jupyterlite/BaseJupyterLiteComponent.js new file mode 100644 index 00000000..f37cb93a --- /dev/null +++ b/dist/components/include/jupyterlite/BaseJupyterLiteComponent.js @@ -0,0 +1,74 @@ +import { jsx as _jsx } from "react/jsx-runtime"; +import MessageHandler from "@exabyte-io/cove.js/dist/other/iframe-messaging"; +import JupyterLiteSession from "@exabyte-io/cove.js/dist/other/jupyterlite/JupyterLiteSession"; +import { Made } from "@mat3ra/made"; +import { enqueueSnackbar } from "notistack"; +import React from "react"; +class BaseJupyterLiteSessionComponent extends React.Component { + constructor() { + super(...arguments); + this.messageHandler = new MessageHandler(); + this.DEFAULT_NOTEBOOK_PATH = "api-examples/other/materials_designer/Introduction.ipynb"; + this.sendMaterials = () => { + const materialsData = this.getMaterialsForMessage(); + this.messageHandler.sendData(materialsData); + }; + this.getMaterialsForMessage = () => { + const materials = this.getMaterialsToUse(); + return materials.map((material) => material.toJSON()); + }; + this.getMaterialsToUse = () => { + const { materials } = this.props; + return materials; + }; + this.validateMaterialConfigs = (configs) => { + const validationErrors = []; + const validatedMaterials = configs.reduce((validMaterials, config) => { + try { + const material = new Made.Material(config); + material.validate(); + validMaterials.push(material); + } + catch (e) { + validationErrors.push(`Failed to create material ${config.name}: ${e.message}`); + } + return validMaterials; + }, []); + return { validatedMaterials, validationErrors }; + }; + this.handleSetMaterials = (data) => { + const configs = data.materials; + if (Array.isArray(configs)) { + const { validatedMaterials, validationErrors } = this.validateMaterialConfigs(configs); + this.setMaterials(validatedMaterials); + validationErrors.forEach((errorMessage) => { + enqueueSnackbar(errorMessage, { variant: "error" }); + }); + } + else { + enqueueSnackbar("Invalid material data received", { variant: "error" }); + } + }; + this.setMaterials = (materials) => { + const { onMaterialsUpdate } = this.props; + onMaterialsUpdate(materials); + }; + } + componentDidMount() { + this.messageHandler.addHandlers("set-data", [this.handleSetMaterials]); + this.messageHandler.addHandlers("get-data", [this.getMaterialsForMessage]); + } + componentDidUpdate(prevProps, prevState) { + const { materials } = this.props; + if (prevProps.materials !== materials) { + this.sendMaterials(); + } + } + componentWillUnmount() { + this.messageHandler.destroy(); + } + render() { + return (_jsx(JupyterLiteSession, { defaultNotebookPath: this.DEFAULT_NOTEBOOK_PATH, messageHandler: this.messageHandler })); + } +} +export default BaseJupyterLiteSessionComponent; diff --git a/package-lock.json b/package-lock.json index d15eb486..b6f71553 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1374,9 +1374,9 @@ } }, "@codemirror/autocomplete": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.12.0.tgz", - "integrity": "sha512-r4IjdYFthwbCQyvqnSlx0WBHRHi8nBvU+WjJxFUij81qsBfhNudf/XKKmmC2j3m0LaOYUQTf3qiEK1J8lO1sdg==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.15.0.tgz", + "integrity": "sha512-G2Zm0mXznxz97JhaaOdoEG2cVupn4JjPaS4AcNvZzhOsnnG9YVN68VzfoUw6dYTsIxT6a/cmoFEN47KAWhXaOg==", "requires": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", @@ -1491,9 +1491,9 @@ } }, "@codemirror/view": { - "version": "6.24.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.24.0.tgz", - "integrity": "sha512-zK6m5pNkdhdJl8idPP1gA4N8JKTiSsOz8U/Iw+C1ChMwyLG7+MLiNXnH/wFuAk6KeGEe33/adOiAh5jMqee03w==", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.0.tgz", + "integrity": "sha512-nSSmzONpqsNzshPOxiKhK203R6BvABepugAe34QfQDbNDslyjkqBuKgrK5ZBvqNXpfxz5iLrlGTmEfhbQyH46A==", "requires": { "@codemirror/state": "^6.4.0", "style-mod": "^4.1.0", @@ -1760,9 +1760,9 @@ } }, "@exabyte-io/cove.js": { - "version": "2024.3.20-0", - "resolved": "https://registry.npmjs.org/@exabyte-io/cove.js/-/cove.js-2024.3.20-0.tgz", - "integrity": "sha512-qASIdx4Vc88CT2BT5CWeFcY5jjGhDRQAxEdfjYF6+S/k3tDBf+VbiL4Blyg16UsgEnskHs0zQfCWfVfGhscpbw==", + "version": "2024.3.27-0", + "resolved": "https://registry.npmjs.org/@exabyte-io/cove.js/-/cove.js-2024.3.27-0.tgz", + "integrity": "sha512-N0z9OP94mrb66WDedwFnm5Ybwcz2/dIhk6TdznfjfqP8xarHuW32CuHLBtUIs2eKgaGGbdX/XdKxTZoWhT+6zg==", "dev": true, "requires": { "@babel/eslint-parser": "^7.16.3", @@ -3728,15 +3728,15 @@ "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" }, "@rjsf/mui": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/@rjsf/mui/-/mui-5.17.1.tgz", - "integrity": "sha512-SToKW8i8dVbYEFo6BDG1oTolfw7ywbrYcvKoFPPIOvoOUv+VJi1cVaWGQ3q0gJQjyXdYYmt5YsLiC4L388LRiA==", + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/@rjsf/mui/-/mui-5.18.1.tgz", + "integrity": "sha512-QVu62jWmFLJD/16F11frSAIp6JpR5TGLsNbpgYp8r7d+SxnIfUPzzhlIplNBcVXqzBujWYkSd+cGQH8bevw/MA==", "dev": true }, "@rjsf/utils": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.17.1.tgz", - "integrity": "sha512-q1Igz/cuM2hi+jiXFkoaXqdRTUFB+a0jfVKNmZlHmvPmfYeeJfcfyOTzO8dQ41fHNHUFb15ryxa/TblDQimwkA==", + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.18.1.tgz", + "integrity": "sha512-BxXd5C8gxOSDCSgfDT+XZHpBZtu4F0jJZsnMQstWJ+9QKpmTiuvbkjk3c1J4zZ3CRNgGghVH5otU5gvzVWIxpQ==", "dev": true, "requires": { "json-schema-merge-allof": "^0.8.1", @@ -3755,9 +3755,9 @@ } }, "@rjsf/validator-ajv8": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/@rjsf/validator-ajv8/-/validator-ajv8-5.17.1.tgz", - "integrity": "sha512-KdvHsjDQ60b04fqnoqhfkiCv7E4n4NIHli8QU8dtpuUAVS/TOqDuOtDJVz6bv/rd/QNROGpxlO/OCccE0rmxLQ==", + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/@rjsf/validator-ajv8/-/validator-ajv8-5.18.1.tgz", + "integrity": "sha512-Cb4++kru+XL8q5FJDWMpongtY7zLUoNqZaHDbYdkPWLl0Q7duGMfYOIRAhPpWhaI9KAjj19kCpAjQicA8gEgaw==", "dev": true, "requires": { "ajv": "^8.12.0", @@ -4818,9 +4818,9 @@ } }, "@uiw/codemirror-extensions-basic-setup": { - "version": "4.21.24", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.21.24.tgz", - "integrity": "sha512-TJYKlPxNAVJNclW1EGumhC7I02jpdMgBon4jZvb5Aju9+tUzS44IwORxUx8BD8ZtH2UHmYS+04rE3kLk/BtnCQ==", + "version": "4.21.25", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.21.25.tgz", + "integrity": "sha512-eeUKlmEE8aSoSgelS8OR2elcPGntpRo669XinAqPCLa0eKorT2B0d3ts+AE+njAeGk744tiyAEbHb2n+6OQmJw==", "dev": true, "requires": { "@codemirror/autocomplete": "^6.0.0", @@ -4833,16 +4833,16 @@ } }, "@uiw/react-codemirror": { - "version": "4.21.24", - "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.21.24.tgz", - "integrity": "sha512-8zs5OuxbhikHocHBsVBMuW1vqlv4ccZAkt4rFwr7ebLP2Q6RwHsjpsR9GeGyAigAqonKRoeHugqF78UMrkaTgg==", + "version": "4.21.25", + "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.21.25.tgz", + "integrity": "sha512-mBrCoiffQ+hbTqV1JoixFEcH7BHXkS3PjTyNH7dE8Gzf3GSBRazhtSM5HrAFIiQ5FIRGFs8Gznc4UAdhtevMmw==", "dev": true, "requires": { "@babel/runtime": "^7.18.6", "@codemirror/commands": "^6.1.0", "@codemirror/state": "^6.1.1", "@codemirror/theme-one-dark": "^6.0.0", - "@uiw/codemirror-extensions-basic-setup": "4.21.24", + "@uiw/codemirror-extensions-basic-setup": "4.21.25", "codemirror": "^6.0.0" }, "dependencies": { @@ -13644,9 +13644,9 @@ "dev": true }, "katex": { - "version": "0.16.9", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.9.tgz", - "integrity": "sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ==", + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.10.tgz", + "integrity": "sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==", "dev": true, "requires": { "commander": "^8.3.0" @@ -16584,9 +16584,9 @@ } }, "prosemirror-history": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.3.2.tgz", - "integrity": "sha512-/zm0XoU/N/+u7i5zepjmZAEnpvjDtzoPWW6VmKptcAnPadN/SStsBjMImdCEbb3seiNTpveziPTIrXQbHLtU1g==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.0.tgz", + "integrity": "sha512-UUiGzDVcqo1lovOPdi9YxxUps3oBFWAIYkXLu3Ot+JPv1qzVogRbcizxK3LhHmtaUxclohgiOVesRw5QSlMnbQ==", "dev": true, "requires": { "prosemirror-state": "^1.2.2", @@ -16645,9 +16645,9 @@ } }, "prosemirror-view": { - "version": "1.33.2", - "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.33.2.tgz", - "integrity": "sha512-HYMowWXC4pPaTbOxdb8ewMlA/QyttZ9QWJmfzLOzoU5y3sNFqllbhGZ3xsYdnQWi9+iLY55TUDNP+dlqF+VWTw==", + "version": "1.33.3", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.33.3.tgz", + "integrity": "sha512-P4Ao/bc4OrU/2yLIf8dL4lJaEtjLR3QjIvQHgJYp2jUS7kYM4bSR6okbBjkqzOs/FwUon6UGjTLdKMnPL1MZqw==", "dev": true, "requires": { "prosemirror-model": "^1.16.0", @@ -16842,7 +16842,7 @@ }, "react": { "version": "17.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", "dev": true, "requires": { @@ -19442,9 +19442,9 @@ } }, "style-mod": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.0.tgz", - "integrity": "sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==" + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", + "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==" }, "stylehacks": { "version": "4.0.3", diff --git a/package.json b/package.json index b9789ac9..eb90a775 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "react-dom": "^17.0.0" }, "devDependencies": { - "@exabyte-io/cove.js": "2024.3.20-0", + "@exabyte-io/cove.js": "2024.3.27-0", "@exabyte-io/eslint-config": "^2023.8.29-1", "@mat3ra/esse": "2024.3.25-6", "@mat3ra/code": "2024.3.25-3", diff --git a/src/MaterialsDesigner.jsx b/src/MaterialsDesigner.jsx index e2f7fb3e..75f22a57 100644 --- a/src/MaterialsDesigner.jsx +++ b/src/MaterialsDesigner.jsx @@ -20,6 +20,7 @@ import { ThreeDEditorFullscreen } from "./components/3d_editor/ThreeDEditorFulls import EditorSelectionInfo, { FOOTER_HEIGHT, } from "./components/3d_editor_selection_info/EditorSelectionInfo"; +import JupyterLiteSessionDrawer from "./components/drawer_session/JupyterLiteSessionDrawer"; import HeaderMenuToolbar from "./components/header_menu/HeaderMenuToolbar"; import ItemsList from "./components/items_list/ItemsList"; import BasisEditor from "./components/source_editor/Basis"; @@ -69,6 +70,7 @@ const GRID_CONFIG_BY_VISIBILITY = { 3: { xs: 12, md: 0 }, }, }; + class MaterialsDesigner extends mix(React.Component).with(FullscreenComponentMixin) { constructor(props) { super(props); @@ -76,8 +78,10 @@ class MaterialsDesigner extends mix(React.Component).with(FullscreenComponentMix isVisibleItemsList: true, isVisibleSourceEditor: true, isVisibleThreeDEditorFullscreen: true, + isVisibleJupyterLiteSessionDrawer: false, importMaterialsDialogProps: null, }; + this.containerRef = React.createRef(); } shouldComponentUpdate(nextProps, nextState) { @@ -165,6 +169,9 @@ class MaterialsDesigner extends mix(React.Component).with(FullscreenComponentMix isVisibleItemsList={isVisibleItemsList} isVisibleSourceEditor={isVisibleSourceEditor} isVisibleThreeDEditorFullscreen={isVisibleThreeDEditorFullscreen} + isVisibleJupyterLiteSessionDrawer={ + this.state.isVisibleJupyterLiteSessionDrawer + } > {isVisibleItemsList && ( )} + {this.state.isVisibleJupyterLiteSessionDrawer && ( + { + this.props.onAdd(...args); + }} + onHide={() => { + this.setState({ + isVisibleJupyterLiteSessionDrawer: false, + }); + }} + containerRef={this.containerRef} + /> + )} diff --git a/src/components/3d_editor/advanced_geometry/python_transformation/JupyterLiteTransformation.tsx b/src/components/3d_editor/advanced_geometry/python_transformation/JupyterLiteTransformation.tsx index 77b9ba18..87fd468e 100644 --- a/src/components/3d_editor/advanced_geometry/python_transformation/JupyterLiteTransformation.tsx +++ b/src/components/3d_editor/advanced_geometry/python_transformation/JupyterLiteTransformation.tsx @@ -1,115 +1,63 @@ import Dialog from "@exabyte-io/cove.js/dist/mui/components/dialog/Dialog"; -import MessageHandler from "@exabyte-io/cove.js/dist/other/iframe-messaging"; -import JupyterLiteSession from "@exabyte-io/cove.js/dist/other/jupyterlite/JupyterLiteSession"; -import { MaterialSchema } from "@mat3ra/esse/dist/js/types"; import { Made } from "@mat3ra/made"; import { darkScrollbar } from "@mui/material"; import Grid from "@mui/material/Grid"; import Paper from "@mui/material/Paper"; import Typography from "@mui/material/Typography"; -import { enqueueSnackbar } from "notistack"; import React from "react"; import { theme } from "../../../../settings"; +import BaseJupyterLiteSessionComponent, { + BaseJupyterLiteProps, +} from "../../../include/jupyterlite/BaseJupyterLiteComponent"; import MaterialsSelector from "./MaterialsSelector"; -interface JupyterLiteTransformationProps { - title: string; - materials: Made.Material[]; - show: boolean; - onSubmit: (newMaterials: Made.Material[]) => void; - onHide: () => void; -} - -interface JupyterLiteTransformationState { - materials: Made.Material[]; +interface JupyterLiteTransformationDialogState { selectedMaterials: Made.Material[]; newMaterials: Made.Material[]; } -const DEFAULT_NOTEBOOK_PATH = "api-examples/other/materials_designer/Introduction.ipynb"; - -class JupyterLiteTransformation extends React.Component< - JupyterLiteTransformationProps, - JupyterLiteTransformationState +class JupyterLiteTransformationDialog extends BaseJupyterLiteSessionComponent< + BaseJupyterLiteProps, + JupyterLiteTransformationDialogState > { - messageHandler = new MessageHandler(); - - constructor(props: JupyterLiteTransformationProps) { + constructor(props: BaseJupyterLiteProps) { super(props); this.state = { - materials: props.materials, - selectedMaterials: [props.materials[0]], + selectedMaterials: [this.props.materials[0]], newMaterials: [], }; } - componentDidMount() { - this.messageHandler.addHandlers("set-data", [this.handleSetMaterials]); - this.messageHandler.addHandlers("get-data", [this.returnSelectedMaterials]); - } + componentDidUpdate( + prevProps: BaseJupyterLiteProps, + prevState: JupyterLiteTransformationDialogState, + ) { + if (prevProps.materials !== this.props.materials) { + this.setState({ selectedMaterials: [this.props.materials[0]] }); + } - componentDidUpdate(prevProps: JupyterLiteTransformationProps) { - const { materials } = this.props; - if (prevProps.materials !== materials) { - // eslint-disable-next-line react/no-did-update-set-state - this.setState({ materials }); + if (prevState.selectedMaterials !== this.state.selectedMaterials) { + this.sendMaterials(); } - this.messageHandler.sendData(this.returnSelectedMaterials()); } - returnSelectedMaterials = () => { - const { selectedMaterials } = this.state; - return selectedMaterials.map((material) => material.toJSON()); - }; - - validateMaterialConfigs = (configs: MaterialSchema[]) => { - const validationErrors: string[] = []; - const validatedMaterials = configs.reduce((validMaterials, config) => { - try { - const material = new Made.Material(config); - material.validate(); - validMaterials.push(material); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } catch (e: any) { - validationErrors.push( - `Failed to create material ${config.name}: ${JSON.stringify( - e.details.error[0], - )}`, - ); - } - return validMaterials; - }, [] as Made.Material[]); - return { validatedMaterials, validationErrors }; + handleSubmit = () => { + const { newMaterials } = this.state; + this.props.onMaterialsUpdate(newMaterials); }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - handleSetMaterials = (data: any) => { - const configs = data.materials as MaterialSchema[]; - if (Array.isArray(configs)) { - const { validatedMaterials, validationErrors } = this.validateMaterialConfigs(configs); - - this.setState({ newMaterials: validatedMaterials }); - - validationErrors.forEach((errorMessage) => { - enqueueSnackbar(errorMessage, { variant: "error" }); - }); - } else { - enqueueSnackbar("Invalid material data received", { variant: "error" }); - } + setMaterials = (newMaterials: Made.Material[]) => { + this.setState({ newMaterials }); }; - handleSubmit = async () => { - const { onSubmit, materials } = this.props; - const { newMaterials } = this.state; - - onSubmit(newMaterials); - this.setState({ selectedMaterials: [materials[0]], newMaterials: [] }); + getMaterialsToUse = () => { + return this.state.selectedMaterials; }; render() { - const { materials, selectedMaterials, newMaterials } = this.state; - const { title, show, onHide } = this.props; + const { title, show, onHide, materials } = this.props; + const { selectedMaterials, newMaterials } = this.state; return (

- + {super.render()} @@ -185,4 +130,4 @@ class JupyterLiteTransformation extends React.Component< } } -export default JupyterLiteTransformation; +export default JupyterLiteTransformationDialog; diff --git a/src/components/drawer_session/JupyterLiteSessionDrawer.tsx b/src/components/drawer_session/JupyterLiteSessionDrawer.tsx new file mode 100644 index 00000000..7549bb74 --- /dev/null +++ b/src/components/drawer_session/JupyterLiteSessionDrawer.tsx @@ -0,0 +1,22 @@ +import ResizableDrawer from "@exabyte-io/cove.js/dist/mui/components/custom/resizable-drawer/ResizableDrawer"; +import React from "react"; + +import BaseJupyterLiteSessionComponent from "../include/jupyterlite/BaseJupyterLiteComponent"; + +class JupyterLiteSessionDrawer extends BaseJupyterLiteSessionComponent { + render() { + // TODO: fix drawer sticking to the MD container and pass the ref to the resizable drawer then + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { show, onHide, containerRef } = this.props; + + return ( +
+ + {super.render()} + +
+ ); + } +} + +export default JupyterLiteSessionDrawer; diff --git a/src/components/header_menu/HeaderMenuToolbar.jsx b/src/components/header_menu/HeaderMenuToolbar.jsx index 1d858b9d..4aaf0e04 100644 --- a/src/components/header_menu/HeaderMenuToolbar.jsx +++ b/src/components/header_menu/HeaderMenuToolbar.jsx @@ -202,6 +202,12 @@ class HeaderMenuToolbar extends React.Component { 3D Viewer/Editor + onSectionVisibilityToggle("JupyterLiteSessionDrawer")}> + + + + JupyterLite Session + ); } @@ -262,11 +268,17 @@ class HeaderMenuToolbar extends React.Component { Python Transformation - this.setState({ showJupyterLiteTransformation: true })}> + + this.setState((state) => ({ + showJupyterLiteTransformation: !state.showJupyterLiteTransformation, + })) + } + > - JupyterLite Session + JupyterLite Transformation ); @@ -493,11 +505,11 @@ class HeaderMenuToolbar extends React.Component { /> this.setState({ showJupyterLiteTransformation: false })} - onSubmit={(...args) => { + onMaterialsUpdate={(...args) => { onAdd(...args); this.setState({ showJupyterLiteTransformation: false }); }} diff --git a/src/components/include/jupyterlite/BaseJupyterLiteComponent.tsx b/src/components/include/jupyterlite/BaseJupyterLiteComponent.tsx new file mode 100644 index 00000000..f2c33479 --- /dev/null +++ b/src/components/include/jupyterlite/BaseJupyterLiteComponent.tsx @@ -0,0 +1,104 @@ +import MessageHandler from "@exabyte-io/cove.js/dist/other/iframe-messaging"; +import JupyterLiteSession from "@exabyte-io/cove.js/dist/other/jupyterlite/JupyterLiteSession"; +import { MaterialSchema } from "@mat3ra/esse/dist/js/types"; +import { Made } from "@mat3ra/made"; +import { enqueueSnackbar } from "notistack"; +import React from "react"; + +export interface BaseJupyterLiteProps { + // eslint-disable-next-line react/no-unused-prop-types + materials: Made.Material[]; + // eslint-disable-next-line react/no-unused-prop-types + show: boolean; + onMaterialsUpdate: (newMaterials: Made.Material[]) => void; + // eslint-disable-next-line react/no-unused-prop-types + onHide: () => void; + // eslint-disable-next-line react/no-unused-prop-types + title?: string; + // eslint-disable-next-line react/no-unused-prop-types + containerRef?: React.RefObject; +} + +class BaseJupyterLiteSessionComponent

extends React.Component< + P & BaseJupyterLiteProps, + S +> { + messageHandler = new MessageHandler(); + + DEFAULT_NOTEBOOK_PATH = "api-examples/other/materials_designer/Introduction.ipynb"; + + componentDidMount() { + this.messageHandler.addHandlers("set-data", [this.handleSetMaterials]); + this.messageHandler.addHandlers("get-data", [this.getMaterialsForMessage]); + } + + componentDidUpdate(prevProps: P & BaseJupyterLiteProps, prevState: S) { + const { materials } = this.props; + if (prevProps.materials !== materials) { + this.sendMaterials(); + } + } + + componentWillUnmount() { + this.messageHandler.destroy(); + } + + sendMaterials = () => { + const materialsData = this.getMaterialsForMessage(); + this.messageHandler.sendData(materialsData); + }; + + getMaterialsForMessage = () => { + const materials = this.getMaterialsToUse(); + return materials.map((material) => material.toJSON()); + }; + + getMaterialsToUse = () => { + const { materials } = this.props; + return materials; + }; + + validateMaterialConfigs = (configs: MaterialSchema[]) => { + const validationErrors: string[] = []; + const validatedMaterials = configs.reduce((validMaterials, config) => { + try { + const material = new Made.Material(config); + material.validate(); + validMaterials.push(material); + } catch (e: any) { + validationErrors.push(`Failed to create material ${config.name}: ${e.message}`); + } + return validMaterials; + }, [] as Made.Material[]); + return { validatedMaterials, validationErrors }; + }; + + handleSetMaterials = (data: any) => { + const configs = data.materials as MaterialSchema[]; + if (Array.isArray(configs)) { + const { validatedMaterials, validationErrors } = this.validateMaterialConfigs(configs); + this.setMaterials(validatedMaterials); + validationErrors.forEach((errorMessage) => { + enqueueSnackbar(errorMessage, { variant: "error" }); + }); + } else { + enqueueSnackbar("Invalid material data received", { variant: "error" }); + } + }; + + setMaterials = (materials: Made.Material[]): void => { + const { onMaterialsUpdate } = this.props; + onMaterialsUpdate(materials); + }; + + render() { + return ( + + ); + } +} + +export default BaseJupyterLiteSessionComponent;