import React, { useCallback, useEffect, useState } from 'react';
import {
defaultSupportedCommandsNameForBroadcastUse,
defaultSupportedCommandsNameForSingleUse,
defaultSupportedSlackEventActions,
} from '@growi/slack';
import { useTranslation } from 'next-i18next';
import PropTypes from 'prop-types';
import { apiv3Put } from '~/client/util/apiv3-client';
import { toastError, toastSuccess } from '~/client/util/toastr';
import loggerFactory from '~/utils/logger';
const logger = loggerFactory('growi:SlackIntegration:ManageCommandsProcess');
const PermissionTypes = {
ALLOW_ALL: 'allowAll',
DENY_ALL: 'denyAll',
ALLOW_SPECIFIED: 'allowSpecified',
};
const defaultCommandsName = [
...defaultSupportedCommandsNameForBroadcastUse,
...defaultSupportedCommandsNameForSingleUse,
];
// A utility function that returns the new state but identical to the previous state
const getUpdatedChannelsList = (commandPermissionObj, commandName, value) => {
// string to array
const allowedChannelsArray = value.split(',');
// trim whitespace from all elements
const trimedAllowedChannelsArray = allowedChannelsArray.map((channelName) =>
channelName.trim(),
);
commandPermissionObj[commandName] = trimedAllowedChannelsArray;
return commandPermissionObj;
};
// A utility function that returns the new state
const getUpdatedPermissionSettings = (
commandPermissionObj,
commandName,
value,
) => {
const editedCommandPermissionObj = { ...commandPermissionObj };
switch (value) {
case PermissionTypes.ALLOW_ALL:
editedCommandPermissionObj[commandName] = true;
break;
case PermissionTypes.DENY_ALL:
editedCommandPermissionObj[commandName] = false;
break;
case PermissionTypes.ALLOW_SPECIFIED:
editedCommandPermissionObj[commandName] = [];
break;
default:
logger.error('Not implemented');
break;
}
return editedCommandPermissionObj;
};
const SinglePermissionSettingComponent = ({
commandName,
editingCommandPermission,
onPermissionTypeClicked,
onPermissionListChanged,
}) => {
const { t } = useTranslation();
if (editingCommandPermission == null) {
return null;
}
function permissionTypeClickHandler(e) {
if (onPermissionTypeClicked == null) {
return;
}
onPermissionTypeClicked(e);
}
function onPermissionListChangeHandler(e) {
if (onPermissionListChanged == null) {
return;
}
onPermissionListChanged(e);
}
const permission = editingCommandPermission[commandName];
const hiddenClass = Array.isArray(permission) ? '' : 'd-none';
const textareaDefaultValue = Array.isArray(permission)
? permission.join(',')
: '';
return (
{commandName}
);
};
SinglePermissionSettingComponent.propTypes = {
commandName: PropTypes.string,
editingCommandPermission: PropTypes.object,
onPermissionTypeClicked: PropTypes.func,
onPermissionListChanged: PropTypes.func,
};
// biome-ignore lint:*:noExplicitModuleBoundaryTypes: Temporary Alternative to @typescript-eslint/explicit-module-boundary-types
const ManageCommandsProcessWithoutProxy = ({
commandPermission,
eventActionsPermission,
}) => {
const { t } = useTranslation();
const [editingCommandPermission, setEditingCommandPermission] = useState({});
const [editingEventActionsPermission, setEditingEventActionsPermission] =
useState({});
useEffect(() => {
if (commandPermission == null) {
return;
}
const updatedState = { ...commandPermission };
setEditingCommandPermission(updatedState);
}, [commandPermission]);
useEffect(() => {
if (eventActionsPermission == null) {
return;
}
const updatedState = { ...eventActionsPermission };
setEditingEventActionsPermission(updatedState);
}, [eventActionsPermission]);
const updatePermissionsCommandsState = useCallback((e) => {
const { target } = e;
const { name: commandName, value } = target;
setEditingCommandPermission((commandPermissionObj) =>
getUpdatedPermissionSettings(commandPermissionObj, commandName, value),
);
}, []);
const updatePermissionsEventsState = useCallback((e) => {
const { target } = e;
const { name: actionName, value } = target;
setEditingEventActionsPermission((eventActionPermissionObj) =>
getUpdatedPermissionSettings(eventActionPermissionObj, actionName, value),
);
}, []);
const updateCommandsChannelsListState = useCallback((e) => {
const { target } = e;
const { name: commandName, value } = target;
setEditingCommandPermission((commandPermissionObj) => ({
...getUpdatedChannelsList(commandPermissionObj, commandName, value),
}));
}, []);
const updateEventsChannelsListState = useCallback((e) => {
const { target } = e;
const { name: actionName, value } = target;
setEditingEventActionsPermission((eventActionPermissionObj) => ({
...getUpdatedChannelsList(eventActionPermissionObj, actionName, value),
}));
}, []);
const updateCommandsHandler = async (e) => {
try {
await apiv3Put(
'/slack-integration-settings/without-proxy/update-permissions',
{
commandPermission: editingCommandPermission,
eventActionsPermission: editingEventActionsPermission,
},
);
toastSuccess(
t('toaster.update_successed', {
target: 'the permission for commands',
ns: 'commons',
}),
);
} catch (err) {
toastError(err);
logger.error(err);
}
};
return (
{t('admin:slack_integration.accordion.growi_commands')}
{defaultCommandsName.map((commandName) => {
return (
);
})}
Events
{defaultSupportedSlackEventActions.map((actionName) => (
))}
);
};
ManageCommandsProcessWithoutProxy.propTypes = {
commandPermission: PropTypes.object,
eventActionsPermission: PropTypes.object,
};
export default ManageCommandsProcessWithoutProxy;