Skip to content

Commit

Permalink
Merge pull request #206 from Exabyte-io/feature/SOF-7291
Browse files Browse the repository at this point in the history
Feature/SOF-7291
  • Loading branch information
VsevolodX committed Apr 14, 2024
2 parents 25c3229 + 22cd099 commit 13c087d
Show file tree
Hide file tree
Showing 18 changed files with 599 additions and 96 deletions.
@@ -0,0 +1,17 @@
export default PythonTransformation;
declare class PythonTransformation extends React.Component<any, any, any> {
constructor(props: any);
state: {
pyodide: null;
};
onLoad: (pyodideInstance: any) => void;
render(): React.JSX.Element;
}
declare namespace PythonTransformation {
namespace propTypes {
const show: PropTypes.Validator<boolean>;
const onHide: PropTypes.Validator<(...args: any[]) => any>;
}
}
import React from "react";
import PropTypes from "prop-types";
@@ -0,0 +1,27 @@
import PyodideLoader from "@exabyte-io/cove.js/dist/other/pyodide";
import Dialog from "@mui/material/Dialog";
import PropTypes from "prop-types";
import React from "react";
class PythonTransformation extends React.Component {
constructor(props) {
super(props);
this.onLoad = (pyodideInstance) => {
this.setState({ pyodide: pyodideInstance });
};
this.state = {
pyodide: null,
};
}
render() {
const { show, onHide } = this.props;
return (React.createElement(React.Fragment, null,
React.createElement(PyodideLoader, { onLoad: this.onLoad, triggerLoad: show }),
React.createElement(Dialog, { open: show, onClose: onHide, fullWidth: true, maxWidth: "lg", PaperProps: { sx: { width: "60vw", height: "60vh", padding: "20px" } } },
React.createElement("div", null, this.state.pyodide ? "Pyodide is loaded" : "Pyodide is not loaded"))));
}
}
PythonTransformation.propTypes = {
show: PropTypes.bool.isRequired,
onHide: PropTypes.func.isRequired,
};
export default PythonTransformation;
20 changes: 20 additions & 0 deletions dist/components/include/SAlertContentTmpl.d.ts
@@ -0,0 +1,20 @@
export default SAlertContentTmpl;
declare function SAlertContentTmpl({ id, classNames, condition, styles, message, handleClose, }: {
id: any;
classNames: any;
condition: any;
styles: any;
message: any;
handleClose: any;
}): import("react/jsx-runtime").JSX.Element;
declare namespace SAlertContentTmpl {
namespace propTypes {
const id: PropTypes.Validator<string>;
const classNames: PropTypes.Validator<string>;
const condition: PropTypes.Validator<string>;
const styles: PropTypes.Validator<object>;
const message: PropTypes.Validator<NonNullable<NonNullable<string | object | null | undefined>>>;
const handleClose: PropTypes.Validator<(...args: any[]) => any>;
}
}
import PropTypes from "prop-types";
18 changes: 18 additions & 0 deletions dist/components/include/SAlertContentTmpl.js
@@ -0,0 +1,18 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/* eslint-disable jsx-a11y/label-has-associated-control, jsx-a11y/control-has-associated-label */
import PropTypes from "prop-types";
import React from "react";
const SAlertContentTmpl = function SAlertContentTmpl({ id, classNames, condition, styles, message, handleClose, }) {
return (_jsxs("div", { id: id, style: styles, className: `alert alert-${condition} ${classNames} growl-animated animated`, children: [_jsx("button", { type: "button", "data-growl": "dismiss", className: "close s-alert-close", onClick: handleClose }), _jsx("span", { children: message })] }));
};
SAlertContentTmpl.propTypes = {
id: PropTypes.string.isRequired,
classNames: PropTypes.string.isRequired,
condition: PropTypes.string.isRequired,
// eslint-disable-next-line react/forbid-prop-types
styles: PropTypes.object.isRequired,
// eslint-disable-next-line react/forbid-prop-types
message: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
handleClose: PropTypes.func.isRequired,
};
export default SAlertContentTmpl;
20 changes: 20 additions & 0 deletions dist/components/include/StandataImportModal.d.ts
@@ -0,0 +1,20 @@
import { MaterialSchema } from "@exabyte-io/code.js/dist/types";
import { Made } from "@exabyte-io/made.js";
import React from "react";
interface StandataImportModalProps {
show: boolean;
onClose: () => void;
onSubmit: (materials: Made.Material[]) => void;
defaultMaterialConfigs: MaterialSchema[];
}
interface StandataImportModalState {
selectedMaterialConfigs: MaterialSchema[];
}
declare class StandataImportModal extends React.Component<StandataImportModalProps, StandataImportModalState> {
constructor(props: StandataImportModalProps);
handleMaterialSelect: (materialConfigs: MaterialSchema[] | []) => void;
handleRemoveMaterial: (index: number) => void;
addMaterials: () => void;
render(): import("react/jsx-runtime").JSX.Element;
}
export default StandataImportModal;
84 changes: 84 additions & 0 deletions dist/components/include/StandataImportModal.js
@@ -0,0 +1,84 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import Dialog from "@exabyte-io/cove.js/dist/mui/components/dialog/Dialog";
import IconByName from "@exabyte-io/cove.js/dist/mui/components/icon/IconByName";
import { Made } from "@exabyte-io/made.js";
import CheckBoxOutlineBlank from "@mui/icons-material/CheckBoxOutlineBlank";
import Autocomplete from "@mui/material/Autocomplete";
import Checkbox from "@mui/material/Checkbox";
import Grid from "@mui/material/Grid";
import IconButton from "@mui/material/IconButton";
import TextField from "@mui/material/TextField";
import { DataGrid } from "@mui/x-data-grid";
import React from "react";
class StandataImportModal extends React.Component {
constructor(props) {
super(props);
this.handleMaterialSelect = (materialConfigs) => {
this.setState({
selectedMaterialConfigs: [...materialConfigs],
});
};
this.handleRemoveMaterial = (index) => {
this.setState((prevState) => ({
selectedMaterialConfigs: prevState.selectedMaterialConfigs.filter((_, i) => i !== index),
}));
};
this.addMaterials = () => {
const { selectedMaterialConfigs } = this.state;
const materials = selectedMaterialConfigs.map((config) => new Made.Material(config));
const { onSubmit } = this.props;
onSubmit(materials);
this.setState({ selectedMaterialConfigs: [] });
};
this.state = {
selectedMaterialConfigs: [],
};
}
render() {
const { show, onClose, defaultMaterialConfigs } = this.props;
const { selectedMaterialConfigs } = this.state;
const selectedMaterials = selectedMaterialConfigs.map((config) => new Made.Material(config));
const columns = [
{ field: "name", headerName: "Name", flex: 1, headerAlign: "center", align: "center" },
{
field: "lattice",
headerName: "Lattice",
flex: 1,
headerAlign: "center",
align: "center",
},
{
field: "formula",
headerName: "Formula",
flex: 1,
headerAlign: "center",
align: "center",
},
{
field: "actions",
headerName: "Actions",
headerAlign: "center",
align: "center",
flex: 1,
sortable: false,
filterable: false,
disableColumnMenu: true,
renderCell: (params) => (_jsx(IconButton, { id: `${params.row.name.replace(/\s+/g, "-")}-remove-button`, color: "inherit", onClick: () => this.handleRemoveMaterial(params.row.id), children: _jsx(IconByName, { name: "actions.remove", fontSize: "small" }) })),
},
];
return (_jsx(Dialog, { open: show, id: "standataImportModalDialog", title: "Import from Standata", onClose: onClose, onSubmit: this.addMaterials, children: _jsxs(Grid, { container: true, spacing: 2, children: [_jsx(Grid, { item: true, xs: 12, children: _jsx(Autocomplete, { multiple: true, id: "materials-autocomplete", "data-tid": "materials-selector", disableCloseOnSelect: true, options: defaultMaterialConfigs || [], value: selectedMaterialConfigs || null, getOptionLabel: (material) => material.name || "Not available", onChange: (event, newValues) => this.handleMaterialSelect(newValues), renderOption: (props, option, { selected }) => (
// eslint-disable-next-line react/jsx-props-no-spreading
_jsxs("li", { ...props, "data-tid": "select-material", children: [_jsx(Checkbox, { icon: _jsx(CheckBoxOutlineBlank, { fontSize: "small" }), checkedIcon: _jsx(IconByName, { name: "shapes.check", fontSize: "small" }), checked: selected }), option.name] })), renderInput: (params) => (_jsx(TextField
// eslint-disable-next-line react/jsx-props-no-spreading
, { ...params, label: "Selected Materials", placeholder: "Select materials" })) }) }), _jsx(Grid, { item: true, xs: 12, style: { minHeight: 300 }, children: _jsx(DataGrid, { "data-name": "data-grid", hideFooter: true, rows: selectedMaterials.map((material, index) => {
var _a;
return ({
name: material.name,
lattice: ((_a = material.lattice) === null || _a === void 0 ? void 0 : _a.type) || "TRI",
formula: material.formula || "Not available",
id: index,
});
}), columns: columns }) })] }) }));
}
}
export default StandataImportModal;
@@ -1,4 +1,4 @@
import MessageHandler from "@exabyte-io/cove.js/dist/other/iframe-messaging";
import JupyterLiteSession, { IMessageHandlerConfigItem } from "@exabyte-io/cove.js/dist/other/jupyterlite/JupyterLiteSession";
import { MaterialSchema } from "@mat3ra/esse/dist/js/types";
import { Made } from "@mat3ra/made";
import React from "react";
Expand All @@ -11,11 +11,9 @@ export interface BaseJupyterLiteProps {
containerRef?: React.RefObject<HTMLDivElement>;
}
declare class BaseJupyterLiteSessionComponent<P = never, S = never> extends React.Component<P & BaseJupyterLiteProps, S> {
messageHandler: MessageHandler;
DEFAULT_NOTEBOOK_PATH: string;
componentDidMount(): void;
jupyterLiteSessionRef: React.RefObject<JupyterLiteSession>;
componentDidUpdate(prevProps: P & BaseJupyterLiteProps, prevState: S): void;
componentWillUnmount(): void;
sendMaterials: () => void;
getMaterialsForMessage: () => import("@mat3ra/made/dist/js/types").MaterialJSON[];
getMaterialsToUse: () => (P & BaseJupyterLiteProps)["materials"];
Expand Down Expand Up @@ -213,6 +211,7 @@ declare class BaseJupyterLiteSessionComponent<P = never, S = never> extends Reac
validationErrors: string[];
};
handleSetMaterials: (data: any) => void;
messageHandlerConfigs: IMessageHandlerConfigItem[];
setMaterials: (materials: Made.Material[]) => void;
render(): import("react/jsx-runtime").JSX.Element;
}
Expand Down
27 changes: 16 additions & 11 deletions dist/components/include/jupyterlite/BaseJupyterLiteComponent.js
@@ -1,17 +1,18 @@
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 { Action } from "@mat3ra/esse/dist/js/types";
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.jupyterLiteSessionRef = React.createRef();
this.sendMaterials = () => {
var _a;
const materialsData = this.getMaterialsForMessage();
this.messageHandler.sendData(materialsData);
(_a = this.jupyterLiteSessionRef.current) === null || _a === void 0 ? void 0 : _a.sendData(materialsData);
};
this.getMaterialsForMessage = () => {
const materials = this.getMaterialsToUse();
Expand Down Expand Up @@ -49,26 +50,30 @@ class BaseJupyterLiteSessionComponent extends React.Component {
enqueueSnackbar("Invalid material data received", { variant: "error" });
}
};
// eslint-disable-next-line react/sort-comp
this.messageHandlerConfigs = [
{
action: Action.setData,
handlers: [this.handleSetMaterials],
},
{
action: Action.getData,
handlers: [this.getMaterialsForMessage],
},
];
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 }));
return (_jsx(JupyterLiteSession, { defaultNotebookPath: this.DEFAULT_NOTEBOOK_PATH, messageHandlerConfigs: this.messageHandlerConfigs, ref: this.jupyterLiteSessionRef }));
}
}
export default BaseJupyterLiteSessionComponent;
2 changes: 2 additions & 0 deletions dist/components/include/material-ui/theme.d.ts
@@ -0,0 +1,2 @@
export const DarkMaterialUITheme: import("@mui/material").Theme;
export const LightMaterialUITheme: import("@mui/material").Theme;
34 changes: 34 additions & 0 deletions dist/components/include/material-ui/theme.js
@@ -0,0 +1,34 @@
import { createTheme } from "@mui/material";
// adopted from: https://material-ui.com/customization/themes/#theme-configuration-variables
const DarkThemeConfig = {
palette: {
// Switching the dark mode on is a single property value change.
mode: "dark",
},
typography: {
// Tell Material-UI what's the font-size on the html element is.
htmlFontSize: 12,
},
overrides: {
MuiFormControl: {
root: {
margin: 10,
minWidth: 120,
},
},
MuiOutlinedInput: {
root: {
"& .MuiOutlinedInput-notchedOutline": {
border: "none",
},
},
},
},
};
export const DarkMaterialUITheme = createTheme(DarkThemeConfig);
export const LightMaterialUITheme = createTheme({
typography: DarkThemeConfig.typography,
palette: {
mode: "light",
},
});
8 changes: 4 additions & 4 deletions dist/material.d.ts
Expand Up @@ -256,21 +256,21 @@ export class Material extends Material_base {
}, {
id?: number | undefined;
}] | undefined;
bondType?: "double" | "single" | "triple" | "quadruple" | "aromatic" | "tautomeric" | "dative" | "other" | undefined;
bondType?: "double" | "other" | "single" | "triple" | "quadruple" | "aromatic" | "tautomeric" | "dative" | undefined;
}[] | undefined;
};
lattice: {
name?: "lattice" | undefined;
vectors?: {
alat?: number | undefined;
units?: "m" | "alat" | "bohr" | "angstrom" | "crystal" | "km" | "pm" | "nm" | "a.u." | "fractional" | "cartesian" | undefined;
units?: "m" | "angstrom" | "crystal" | "km" | "pm" | "nm" | "a.u." | "bohr" | "fractional" | "cartesian" | "alat" | undefined;
a: [number, number, number];
b: [number, number, number];
c: [number, number, number];
} | undefined;
type: "CUB" | "BCC" | "FCC" | "TET" | "MCL" | "ORC" | "ORCC" | "ORCF" | "ORCI" | "HEX" | "BCT" | "TRI" | "MCLC" | "RHL";
units?: {
length?: "bohr" | "angstrom" | undefined;
length?: "angstrom" | "bohr" | undefined;
angle?: "degree" | "radian" | undefined;
} | undefined;
a: number;
Expand Down Expand Up @@ -333,7 +333,7 @@ export class Material extends Material_base {
consistencyChecks?: {
key: string;
name: "default" | "atomsTooClose" | "atomsOverlap";
severity: "info" | "warning" | "error";
severity: "error" | "warning" | "info";
message: string;
}[] | undefined;
schemaVersion?: string | undefined;
Expand Down
@@ -0,0 +1,12 @@
"use strict";

Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _default;
var _material_designer_page = require("../widgets/material_designer_page");
function _default() {
this.Then(/^I see UploadDialog$/, () => {
_material_designer_page.materialDesignerPage.designerWidget.defaultImportModalDialog.isVisible();
});
}
@@ -0,0 +1,12 @@
"use strict";

Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _default;
var _material_designer_page = require("../widgets/material_designer_page");
function _default() {
this.Then(/^the UploadDialog should be closed$/, () => {
_material_designer_page.materialDesignerPage.designerWidget.defaultImportModalDialog.waitForDisappear();
});
}
@@ -0,0 +1,12 @@
"use strict";

Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _default;
var _material_designer_page = require("../widgets/material_designer_page");
function _default() {
this.When(/^I open UploadDialog/, () => {
_material_designer_page.materialDesignerPage.designerWidget.headerMenu.selectMenuItemByNameAndItemNumber("Input/Output", 1);
});
}

0 comments on commit 13c087d

Please sign in to comment.