Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


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

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"@mui/styles": "^5.11.9",
"@rjsf/validator-ajv8": "^5.1.0",
"@types/lodash": "^4.14.202",
"@types/moment-duration-format": "^2.2.7",
"@types/node": "^20.11.30",
"@types/react": "^17.0.2",
"@types/react-dom": "^17.0.2",
Expand Down
87 changes: 52 additions & 35 deletions src/components/Compute.jsx → src/components/Compute.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,56 @@
/* eslint-disable react/require-default-props */
/* eslint-disable jsx-a11y/anchor-is-valid */
/* eslint-disable react/prop-types */
import Dropdown from "@mat3ra/cove/dist/mui/components/dropdown";
import IconByName from "@mat3ra/cove/dist/mui/components/icon/IconByName";
import { showWarningAlert } from "@mat3ra/cove/dist/other/alerts";
import Box from "@mui/material/Box";
import { styled } from "@mui/material/styles";
import setClass from "classnames";
import PropTypes from "prop-types";
import React from "react";

import { ComputeForm } from "./ComputeForm";
import { StatusTrackTable } from "./StatusTrackTable";
import type { AccountUser } from "./Notify";
import { StatusTrackTable, StatusTrackEntry } from "./StatusTrackTable";

import EntityHeader from "@mat3ra/cove/dist/mui-composed/components/entity-header/EntityHeader";
import type { Account, ClusterNode, CoreUser } from "./ComputeForm";

/** Minimal shape `Compute` needs off the host's job entity. */
export interface ComputeJob {
statusTrack?: unknown[];
statusTrackSorted: StatusTrackEntry[];
usedApplicationNames: string[];
}

interface ComputeProps {
className?: string;
showHeader?: boolean;
isLoading?: boolean;
adjustable?: boolean;
editable?: boolean;
showComputeForm?: boolean;
showStatusTrack?: boolean;
compute: any;
user: CoreUser;
account: Account;
clusters: ClusterNode[];
onUpdate: (s: string) => void;
job: ComputeJob;
showAdvancedOptions?: boolean;
accountUsers: AccountUser[];
isAccountUsersLoading: boolean;
}

interface ComputeState {
isAutoSet: boolean;
}

const DropdownButton = styled("div")(({ theme }) => ({
border: `1px solid ${theme.palette.border?.dark ?? theme.palette.divider}`,
// `theme.palette.border` is a real @mat3ra/cove theme augmentation (`src/theme/mui.d.ts`),
// but cove only ships its `dist/` build - the augmentation file itself isn't published, so
// ive's own compilation can't see it. Cast locally rather than treat it as dead code.
border: `1px solid ${
(theme.palette as { border?: { dark?: string } }).border?.dark ?? theme.palette.divider
}`,
borderRadius: "4px",
padding: theme.spacing(1),
width: "40px",
Expand All @@ -38,8 +72,16 @@ const EntityHeaderContainer = styled("div")(() => ({
width: "100%",
}));

class Compute extends React.Component {
constructor(props) {
class Compute extends React.Component<ComputeProps, ComputeState> {
static defaultProps = {
editable: true,
showHeader: true,
clusters: [],
showComputeForm: true,
showStatusTrack: true,
};

constructor(props: ComputeProps) {
super(props);
this.state = {
isAutoSet: false,
Expand Down Expand Up @@ -100,8 +142,6 @@ class Compute extends React.Component {
icon="pages.compute"
isLoading={isLoading}
editable={false}
adjustable
isDescriptionEditorHidden
/>
{adjustable || editable ? (
<AutoSetActionContainer>
Expand All @@ -116,14 +156,14 @@ class Compute extends React.Component {
) : null}
{showComputeForm && (
<ComputeForm
editable={editable}
editable={Boolean(editable)}
compute={compute}
user={user}
account={account}
clusters={clusters}
onUpdate={onUpdate}
appName={job.workflow.usedApplicationNames[0]}
showAdvancedOptions={showAdvancedOptions}
appName={job.usedApplicationNames[0]}
showAdvancedOptions={Boolean(showAdvancedOptions)}
accountUsers={accountUsers}
isAccountUsersLoading={isAccountUsersLoading}
/>
Expand All @@ -138,27 +178,4 @@ class Compute extends React.Component {
}
}

Compute.propTypes = {
editable: PropTypes.bool,
compute: PropTypes.object,
job: PropTypes.object,
user: PropTypes.object,
account: PropTypes.object,
clusters: PropTypes.array,
onUpdate: PropTypes.func,
showComputeForm: PropTypes.bool,
showStatusTrack: PropTypes.bool,
showAdvancedOptions: PropTypes.bool,
accountUsers: PropTypes.array,
};

Compute.defaultProps = {
editable: true,
// eslint-disable-next-line react/default-props-match-prop-types
showHeader: true,
clusters: [],
showComputeForm: true,
showStatusTrack: true,
};

export default Compute;
6 changes: 2 additions & 4 deletions src/components/ComputeForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import omitBy from "lodash/omitBy";
import React from "react";

import { getComputeSchema, getComputeValidator } from "../validators";
import Notify from "./Notify";
import Notify, { AccountUser } from "./Notify";
import QueuesTable from "./QueuesTable";

import { LoadingIndicator } from "@mat3ra/cove/dist/mui-composed/components/loading/LoadingIndicator";
Expand Down Expand Up @@ -299,7 +299,7 @@ function resolveComputeUISchema(appName: string): UISchema {
interface ComputeFormProps {
user: CoreUser;
account: Account;
accountUsers: CoreUser[];
accountUsers: AccountUser[];
clusters: ClusterNode[];
isAccountUsersLoading: boolean;
showAdvancedOptions: boolean;
Expand Down Expand Up @@ -453,7 +453,6 @@ export class ComputeForm extends React.Component<ComputeFormProps, ComputeFormSt
const {
editable,
showAdvancedOptions,
user,
accountUsers,
isAccountUsersLoading,
compute,
Expand Down Expand Up @@ -515,7 +514,6 @@ export class ComputeForm extends React.Component<ComputeFormProps, ComputeFormSt
<LoadingIndicator key="loading-indicator" size="small" included />
) : (
<Notify
user={user}
accountUsers={accountUsers}
editable={editable}
onUpdate={this.onNotifyUpdate}
Expand Down
24 changes: 0 additions & 24 deletions src/components/ComputeHandler.js

This file was deleted.

65 changes: 39 additions & 26 deletions src/components/Notify.jsx → src/components/Notify.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/* eslint-disable react/require-default-props */
/* eslint-disable jsx-a11y/label-has-associated-control */
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
/* eslint-disable jsx-a11y/anchor-is-valid */
/* eslint-disable react/prop-types */
import { EMAIL_NOTIFICATIONS } from "@mat3ra/ide";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
Expand All @@ -14,14 +12,35 @@ import InputLabel from "@mui/material/InputLabel";
import MenuItem from "@mui/material/MenuItem";
import OutlinedInput from "@mui/material/OutlinedInput";
import Paper from "@mui/material/Paper";
import Select from "@mui/material/Select";
import Select, { SelectChangeEvent } from "@mui/material/Select";
import Typography from "@mui/material/Typography";
import setClass from "classnames";
import PropTypes from "prop-types";
import React from "react";

import AccountCard from "@mat3ra/cove/dist/mui-composed/components/account/AccountCard";

/** Minimal shape of an account-user entry, as passed from the host application. */
export interface AccountUser {
entity: { id: string | number; email: string; [key: string]: unknown };
account: { entity: { name?: string; [key: string]: unknown } };
}

interface NotifyProps {
notify?: string;
email?: string;
accountUsers: AccountUser[];
editable?: boolean;
onUpdate: (payload: { notify: string; email: string }) => void;
}

interface NotifyState {
notify: string;
isBegin: boolean;
isAbort: boolean;
isEnd: boolean;
selectedUsers: AccountUser[];
}

const IS_BEGIN = "isBegin";
const IS_ABORT = "isAbort";
const IS_END = "isEnd";
Expand All @@ -36,8 +55,12 @@ const MenuProps = {
},
};

class Notify extends React.Component {
constructor(props) {
class Notify extends React.Component<NotifyProps, NotifyState> {
static defaultProps = {
editable: true,
};

constructor(props: NotifyProps) {
super(props);

const { notify = "", email, accountUsers } = this.props;
Expand All @@ -57,10 +80,8 @@ class Notify extends React.Component {
};
}

selectNotifyAccount = (event) => {
const {
target: { value: selectedUsers },
} = event;
selectNotifyAccount = (event: SelectChangeEvent<AccountUser[]>) => {
const selectedUsers = event.target.value as AccountUser[];
const { editable, onUpdate } = this.props;
const { isBegin, isAbort, isEnd } = this.state;

Expand Down Expand Up @@ -113,17 +134,17 @@ class Notify extends React.Component {
},
() => {
const { notify, selectedUsers: users } = this.state;
onUpdate({ notify, email: users.map((user) => user.email).join(",") });
onUpdate({ notify, email: users.map((user) => user.entity.email).join(",") });
},
);
}
};

toggleOption(optionName) {
toggleOption(optionName: string) {
const { onUpdate } = this.props;
const { selectedUsers } = this.state;
const isSelectedUsers = !!selectedUsers.length;
let updatedState;
let updatedState: Partial<NotifyState>;

if (!isSelectedUsers) {
return;
Expand All @@ -143,7 +164,7 @@ class Notify extends React.Component {
throw new Error(`Not supported optionName ${optionName}`);
}

this.setState(updatedState, () => {
this.setState((prevState) => ({ ...prevState, ...updatedState }), () => {
const { notify, selectedUsers: users } = this.state;
onUpdate({
notify: users.length ? notify : EMAIL_NOTIFICATIONS.never,
Expand Down Expand Up @@ -224,14 +245,16 @@ class Notify extends React.Component {
onChange={this.selectNotifyAccount}
input={<OutlinedInput label="Select users" />}
renderValue={(selected) => {
return selected.map((user) => user.account.entity.name).join(", ");
return (selected as AccountUser[])
.map((user) => user.account.entity.name)
.join(", ");
}}
MenuProps={MenuProps}
disabled={!editable}>
{accountUsers.map((item) => (
<MenuItem
key={item.entity.id}
value={item}
value={item as unknown as string}
className="users-multiselect-item">
<Checkbox
checked={
Expand Down Expand Up @@ -298,14 +321,4 @@ class Notify extends React.Component {
}
}

Notify.propTypes = {
onUpdate: PropTypes.func,
editable: PropTypes.bool,
email: PropTypes.string,
};

Notify.defaultProps = {
editable: true,
};

export default Notify;
6 changes: 4 additions & 2 deletions src/components/QueuesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import { ClustersLoadHandler } from "../utils/clusters_load";
/** Minimal interface for queue objects passed from the host application. */
export interface Queue {
name: string;
displayName: string;
// esse's `compute/queue` schema never lists `displayName`/`capacity` in `required` -
// real Queue instances can genuinely have either undefined.
displayName?: string;
maxAvailableNodect: number;
capacity: string;
capacity?: string;
load: number;
getETAClient: () => { display: string };
}
Expand Down
Loading