import React, { useCallback, useMemo } from 'react' import { useUpdate, useNotify, useRefresh, useRecordContext, useTranslate, useResourceContext, } from 'react-admin' import Switch from '@material-ui/core/Switch' import { makeStyles } from '@material-ui/core/styles' import { Tooltip, FormControlLabel } from '@material-ui/core' import PropTypes from 'prop-types' const useStyles = makeStyles((theme) => ({ enabledSwitch: { '& .MuiSwitch-colorSecondary.Mui-checked': { color: theme.palette.success?.main || theme.palette.primary.main, }, '& .MuiSwitch-colorSecondary.Mui-checked + .MuiSwitch-track': { backgroundColor: theme.palette.success?.main || theme.palette.primary.main, }, }, errorSwitch: { '& .MuiSwitch-thumb': { backgroundColor: theme.palette.warning.main, }, '& .MuiSwitch-track': { backgroundColor: theme.palette.warning.light, opacity: 0.7, }, }, })) /** * Shared toggle switch for enabling/disabling plugins. * Used in both PluginList (compact) and PluginShow (with label). * * @param {Object} props * @param {boolean} [props.showLabel=false] - Whether to show the enable/disable label * @param {string} [props.size='small'] - Switch size ('small' or 'medium') * @param {Object} [props.manifest=null] - Parsed manifest object for permission checking */ const ToggleEnabledSwitch = ({ showLabel = false, size = 'small', manifest = null, }) => { const resource = useResourceContext() const record = useRecordContext() const notify = useNotify() const refresh = useRefresh() const translate = useTranslate() const classes = useStyles() const [toggleEnabled, { loading }] = useUpdate( resource, record?.id, { enabled: !record?.enabled }, record, { undoable: false, onSuccess: () => { refresh() notify( record?.enabled ? 'resources.plugin.notifications.disabled' : 'resources.plugin.notifications.enabled', 'info', ) }, onFailure: (error) => { refresh() notify( error?.message || 'resources.plugin.notifications.error', 'warning', ) }, }, ) const handleClick = useCallback( (e) => { e.stopPropagation() toggleEnabled() }, [toggleEnabled], ) const hasError = !!record?.lastError // Check if users permission is required but not configured const usersPermissionRequired = useMemo(() => { if (!manifest?.permissions?.users) return false if (record?.allUsers) return false // Check if users array is empty or not set if (!record?.users) return true try { const users = JSON.parse(record.users) return users.length === 0 } catch { return true } }, [manifest, record?.allUsers, record?.users]) // Check if library permission is required but not configured const libraryPermissionRequired = useMemo(() => { if (!manifest?.permissions?.library) return false if (record?.allLibraries) return false // Check if libraries array is empty or not set if (!record?.libraries) return true try { const libraries = JSON.parse(record.libraries) return libraries.length === 0 } catch { return true } }, [manifest, record?.allLibraries, record?.libraries]) const permissionRequired = usersPermissionRequired || libraryPermissionRequired const isDisabled = loading || hasError || (permissionRequired && !record?.enabled) const tooltipTitle = useMemo(() => { if (hasError) { return translate('resources.plugin.actions.disabledDueToError') } if (usersPermissionRequired && !record?.enabled) { return translate('resources.plugin.actions.disabledUsersRequired') } if (libraryPermissionRequired && !record?.enabled) { return translate('resources.plugin.actions.disabledLibrariesRequired') } if (!showLabel) { return translate( record?.enabled ? 'resources.plugin.actions.disable' : 'resources.plugin.actions.enable', ) } return '' }, [ hasError, usersPermissionRequired, libraryPermissionRequired, showLabel, record?.enabled, translate, ]) const switchElement = ( ) if (showLabel) { const showTooltip = hasError || (permissionRequired && !record?.enabled) return ( ) } return ( {switchElement} ) } ToggleEnabledSwitch.propTypes = { showLabel: PropTypes.bool, size: PropTypes.oneOf(['small', 'medium']), manifest: PropTypes.object, } export default ToggleEnabledSwitch