94 lines
3.4 KiB
JavaScript
94 lines
3.4 KiB
JavaScript
/*
|
|
* This file is part of Cockpit.
|
|
*
|
|
* Copyright (C) 2019 Red Hat, Inc.
|
|
*
|
|
* Cockpit is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2.1 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Cockpit is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
import React from 'react';
|
|
import PropTypes from 'prop-types';
|
|
|
|
import { Button } from '@patternfly/react-core';
|
|
import { OverlayTrigger, Tooltip } from 'patternfly-react';
|
|
|
|
import cockpit from "cockpit";
|
|
|
|
/**
|
|
* UI element wrapper for something that requires privilege. When access is not
|
|
* allowed, then wrap the element into a Tooltip.
|
|
*
|
|
* Note that the wrapped element itself needs to be disabled explicitly, this
|
|
* wrapper cannot do this (unfortunately wrapping it into a disabled span does
|
|
* not inherit).
|
|
*/
|
|
export function Privileged({ excuse, allowed, placement, tooltipId, children }) {
|
|
// wrap into extra <span> so that a disabled child keeps the tooltip working
|
|
let contents = <span id={allowed ? null : tooltipId}>{ children }</span>;
|
|
if (!allowed) {
|
|
contents = (
|
|
<OverlayTrigger placement={ placement || "top" }
|
|
overlay={ <Tooltip id={ tooltipId + "_tooltip" }>{ excuse }</Tooltip> }>
|
|
{ contents }
|
|
</OverlayTrigger>);
|
|
}
|
|
return contents;
|
|
}
|
|
|
|
/**
|
|
* Convenience element for a Privilege wrapped Button
|
|
*/
|
|
export class PrivilegedButton extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = { allowed: true };
|
|
this.onPermissionChanged = this.onPermissionChanged.bind(this);
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.props.permission.addEventListener("changed", this.onPermissionChanged);
|
|
this.onPermissionChanged();
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
this.props.permission.removeEventListener("changed", this.onPermissionChanged);
|
|
}
|
|
|
|
onPermissionChanged() {
|
|
// default to allowed while not yet initialized
|
|
this.setState({ allowed: this.props.permission.allowed !== false });
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<Privileged allowed={ this.state.allowed } tooltipId={ this.props.tooltipId } placement={ this.props.placement }
|
|
excuse={ cockpit.format(this.props.excuse, this.props.permission.user ? this.props.permission.user.name : '') }>
|
|
<Button id={ this.props.buttonId } variant={ this.props.variant } onClick={ this.props.onClick }
|
|
isInline isDisabled={ !this.state.allowed } aria-label={ this.props.ariaLabel }>
|
|
{ this.props.children }
|
|
</Button>
|
|
</Privileged>);
|
|
}
|
|
}
|
|
|
|
PrivilegedButton.propTypes = {
|
|
permission: PropTypes.object.isRequired,
|
|
excuse: PropTypes.string.isRequired, // must contain a $0, replaced with user name
|
|
onClick: PropTypes.func,
|
|
variant: PropTypes.string,
|
|
placement: PropTypes.string, // default: top
|
|
buttonId: PropTypes.string,
|
|
tooltipId: PropTypes.string,
|
|
ariaLabel: PropTypes.string,
|
|
};
|