import { css, cx } from '@emotion/css'; import React, { FC, PureComponent, useRef, useState } from 'react'; import { GrafanaTheme } from '@grafana/data'; import { Button, ConfirmButton, ConfirmModal, Input, LegacyInputStatus, stylesFactory } from '@grafana/ui'; import { config } from 'app/core/config'; import { contextSrv } from 'app/core/core'; import { AccessControlAction, UserDTO } from 'app/types'; interface Props { user: UserDTO; onUserUpdate: (user: UserDTO) => void; onUserDelete: (userId: number) => void; onUserDisable: (userId: number) => void; onUserEnable: (userId: number) => void; onPasswordChange(password: string): void; } export function UserProfile({ user, onUserUpdate, onUserDelete, onUserDisable, onUserEnable, onPasswordChange, }: Props) { const [showDeleteModal, setShowDeleteModal] = useState(false); const [showDisableModal, setShowDisableModal] = useState(false); const deleteUserRef = useRef(null); const showDeleteUserModal = (show: boolean) => () => { setShowDeleteModal(show); if (!show && deleteUserRef.current) { deleteUserRef.current.focus(); } }; const disableUserRef = useRef(null); const showDisableUserModal = (show: boolean) => () => { setShowDisableModal(show); if (!show && disableUserRef.current) { disableUserRef.current.focus(); } }; const handleUserDelete = () => onUserDelete(user.id); const handleUserDisable = () => onUserDisable(user.id); const handleUserEnable = () => onUserEnable(user.id); const onUserNameChange = (newValue: string) => { onUserUpdate({ ...user, name: newValue, }); }; const onUserEmailChange = (newValue: string) => { onUserUpdate({ ...user, email: newValue, }); }; const onUserLoginChange = (newValue: string) => { onUserUpdate({ ...user, login: newValue, }); }; const authSource = user.authLabels?.length && user.authLabels[0]; const lockMessage = authSource ? `Synced via ${authSource}` : ''; const styles = getStyles(config.theme); const editLocked = user.isExternal || !contextSrv.hasPermissionInMetadata(AccessControlAction.UsersWrite, user); const passwordChangeLocked = user.isExternal || !contextSrv.hasPermissionInMetadata(AccessControlAction.UsersPasswordUpdate, user); const canDelete = contextSrv.hasPermissionInMetadata(AccessControlAction.UsersDelete, user); const canDisable = contextSrv.hasPermissionInMetadata(AccessControlAction.UsersDisable, user); const canEnable = contextSrv.hasPermissionInMetadata(AccessControlAction.UsersEnable, user); return ( <>

User information

{canDelete && ( <> )} {user.isDisabled && canEnable && ( )} {!user.isDisabled && canDisable && ( <> )}
); } const getStyles = stylesFactory((theme: GrafanaTheme) => { return { buttonRow: css` margin-top: 0.8rem; > * { margin-right: 16px; } `, }; }); interface UserProfileRowProps { label: string; value?: string; locked?: boolean; lockMessage?: string; inputType?: string; onChange?: (value: string) => void; } interface UserProfileRowState { value: string; editing: boolean; } export class UserProfileRow extends PureComponent { inputElem?: HTMLInputElement; static defaultProps: Partial = { value: '', locked: false, lockMessage: '', inputType: 'text', }; state = { editing: false, value: this.props.value || '', }; setInputElem = (elem: any) => { this.inputElem = elem; }; onEditClick = () => { if (this.props.inputType === 'password') { // Reset value for password field this.setState({ editing: true, value: '' }, this.focusInput); } else { this.setState({ editing: true }, this.focusInput); } }; onCancelClick = () => { this.setState({ editing: false, value: this.props.value || '' }); }; onInputChange = (event: React.ChangeEvent, status?: LegacyInputStatus) => { if (status === LegacyInputStatus.Invalid) { return; } this.setState({ value: event.target.value }); }; onInputBlur = (event: React.FocusEvent, status?: LegacyInputStatus) => { if (status === LegacyInputStatus.Invalid) { return; } this.setState({ value: event.target.value }); }; focusInput = () => { if (this.inputElem && this.inputElem.focus) { this.inputElem.focus(); } }; onSave = () => { if (this.props.onChange) { this.props.onChange(this.state.value); } }; render() { const { label, locked, lockMessage, inputType } = this.props; const { value } = this.state; const labelClass = cx( 'width-16', css` font-weight: 500; ` ); if (locked) { return ; } const inputId = `${label}-input`; return ( {this.state.editing ? ( ) : ( {this.props.value} )} Edit ); } } interface LockedRowProps { label: string; value?: any; lockMessage?: string; } export const LockedRow: FC = ({ label, value, lockMessage }) => { const lockMessageClass = css` font-style: italic; margin-right: 0.6rem; `; const labelClass = cx( 'width-16', css` font-weight: 500; ` ); return ( {label} {value} {lockMessage} ); };