import React, { PureComponent } from "react";
import PropTypes from "prop-types";
import clsx from "clsx";
import { makeStyles, withStyles } from "@material-ui/core/styles";
import { fetchDescriptiveAttributes } from "../utilFunctions/fetchFunctions";
import { AcceptButton, CancelButton, StyledButton } from "../Buttons";
import StyledDialogContent from "./StyledDialogContent"
import CustomTextField from "../Inputs/CustomTextField";
import CircleHelper from "../Feedback/CircleHelper";
import StyledPaper from "../Surfaces/StyledPaper";
import Dialog from "@material-ui/core/Dialog";
import DialogActions from "@material-ui/core/DialogActions";
import DialogTitle from "@material-ui/core/DialogTitle";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import EyeSettings from "mdi-material-ui/EyeSettings";
const SettingsIcons = withStyles({
root: {
color: "inherit",
marginRight: 16,
minWidth: 0,
}
}, {name: "MuiListItemIcon"})(props => <ListItemIcon {...props}>{props.children}</ListItemIcon>);
const useStyles = makeStyles(theme => ({
root: {
padding: 0,
textAlign: "center",
textTransform: "none"
},
warning: {
color: theme.palette.warning.main
},
}), {name: "UpdateHelperText"});
function UpdateAlert(props, ref) {
const { children, onClick } = props;
const classes = useStyles();
return (
<StyledButton
ButtonRef={ref}
className={clsx("MuiFormHelperText-root", classes.root, classes.warning)}
onClick={onClick}
>
{children}
</StyledButton>
);
}
const UpdateAlertForwardRef = React.forwardRef(UpdateAlert);
/**
* <h3>Overview</h3>
* Allows a user to choose global object's visible name in current project.
* If there are no description or identification attributes in current information table,
* only default option is available.
*
* @constructor
* @category Dialogs
* @param {Object} props
* @param {function} props.onClose - Callback fired when the component requests to be closed.
* @param {function} props.onObjectNamesChanges - Callback fired when global object names have been changed.
* @param {function} props.onSnackbarOpen - Callback fired when the component requests to display an error.
* @param {boolean} props.open - If <code>true</code> the dialog is open.
* @param {string} props.projectId - The identifier of a selected project.
* @param {string} props.serverBase - The host and port in the URL of an API call.
* @returns {React.PureComponent}
*/
class SettingsProjectDialog extends PureComponent {
constructor(props) {
super(props);
this.state = {
loading: {
attributes: false,
objectVisibleName: false
},
attributes: ["Default"],
objectVisibleName: "Default",
isEverywhere: true,
hasChanged: false
};
this._attributes = ["Default"];
};
processResult = (result, setStateCallback) => {
if (this._isMounted && result != null && result.hasOwnProperty("available")
&& result.hasOwnProperty("actual")) {
const objectVisibleName = result.actual === null ? "Default" : result.actual;
this.setState(({isEverywhere}) => ({
attributes: [ ...this._attributes, ...result.available ],
objectVisibleName: objectVisibleName,
isEverywhere: result.hasOwnProperty("isEverywhere") ? result.isEverywhere : isEverywhere
}), () => {
if (typeof setStateCallback === "function") setStateCallback(objectVisibleName);
});
}
};
getDescriptiveAttributes = (processResultCallback) => {
this.setState(({loading}) => ({
loading: { ...loading, objectVisibleName: true }
}), () => {
const { projectId, serverBase } = this.props;
const resource = "metadata";
const pathParams = { projectId };
const queryParams = { objectVisibleName: undefined };
const method = "GET";
fetchDescriptiveAttributes(
resource, pathParams, queryParams, method, serverBase
).then(result => {
this.processResult(result, processResultCallback);
}).catch(
this.props.onSnackbarOpen
).finally(() => {
if (this._isMounted) {
this.setState(({loading}) => ({
loading: { ...loading, objectVisibleName: false }
}));
}
});
});
};
postDescriptiveAttributes = (finallyCallback) => {
this.setState(({loading}) => ({
loading: { ...loading, attributes: true }
}), () => {
const { projectId, serverBase } = this.props;
const { objectVisibleName } = this.state;
const resource = "metadata"
const pathParams = { projectId };
const queryParams = { objectVisibleName: objectVisibleName === "Default"
? undefined : objectVisibleName };
const method = "POST";
fetchDescriptiveAttributes(
resource, pathParams, queryParams, method, serverBase
).then(result => {
this.processResult(result, this.props.onObjectNamesChange);
}).catch(
this.props.onSnackbarOpen
).finally(() => {
if (this._isMounted) {
this.setState(({loading}) => ({
loading: { ...loading, attributes: false }
}), () => {
if (typeof finallyCallback === "function") finallyCallback();
});
}
});
});
}
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
onIndexOptionChange = (event) => {
this.setState({
objectVisibleName: event.target.value,
hasChanged: true
});
};
onAcceptClick = (setStateCallback) => {
const { hasChanged } = this.state;
if (hasChanged) {
this.postDescriptiveAttributes(() => {
this.setState({
hasChanged: false
}, () => {
if (typeof setStateCallback === "function") setStateCallback();
});
});
} else {
this.props.onClose();
}
};
onEnterKeyPress = (event) => {
if (event.which === 13 ) {
event.preventDefault();
this.onAcceptClick();
}
};
getHelperText = (isEverywhere) => {
if (isEverywhere) {
return undefined;
}
return "Visible object name has changed in some tabs. Click to refresh."
}
render() {
const { attributes, objectVisibleName, isEverywhere } = this.state;
const { open } = this.props;
return (
<Dialog
aria-labelledby={"settings-project-dialog"}
onBackdropClick={this.props.onClose}
onEnter={() => this.getDescriptiveAttributes(() => {
const {isEverywhere} = this.state;
if (!isEverywhere) this.props.onObjectNamesChange(null);
})}
onEscapeKeyDown={this.props.onClose}
onKeyPress={this.onEnterKeyPress}
open={open}
PaperComponent={StyledPaper}
>
<DialogTitle>
Customize project settings
</DialogTitle>
<StyledDialogContent style={{overflow: "hidden"}}>
<List style={{width: "100%"}}>
<ListItem disableGutters={true}>
<SettingsIcons>
<EyeSettings />
</SettingsIcons>
<CustomTextField
helperText={this.getHelperText(isEverywhere)}
FormHelperTextProps={{
component: UpdateAlertForwardRef,
onClick: this.postDescriptiveAttributes
}}
onChange={this.onIndexOptionChange}
outsideLabel={"Choose visible object name"}
select={true}
value={objectVisibleName}
>
{attributes}
</CustomTextField>
<CircleHelper
title={"Changes visible object name globally."}
TooltipProps={{
placement: "top-end"
}}
WrapperProps={{
style: {marginLeft: 16}
}}
/>
</ListItem>
</List>
</StyledDialogContent>
<DialogActions>
<CancelButton onClick={this.props.onClose} />
<AcceptButton onClick={() => this.onAcceptClick(this.props.onClose)} />
</DialogActions>
</Dialog>
);
}
}
SettingsProjectDialog.propTypes = {
onClose: PropTypes.func,
onObjectNamesChange: PropTypes.func,
onSnackbarOpen: PropTypes.func,
open: PropTypes.bool.isRequired,
projectId: PropTypes.string,
serverBase: PropTypes.string
};
export default SettingsProjectDialog;
Source