@plone/volto
Version:
Volto
222 lines (207 loc) • 7.45 kB
JSX
import React, { useEffect, useState, useMemo } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { useIntl } from 'react-intl';
import { Checkbox, Form, Input } from 'semantic-ui-react';
import isEqual from 'lodash/isEqual';
import debounce from 'lodash/debounce';
import { messages } from '@plone/volto/helpers/MessageLabels/MessageLabels';
import { listGroups } from '@plone/volto/actions/groups/groups'; // getRegistry
import UserGroupMembershipListing from '@plone/volto/components/manage/Controlpanels/Users/UserGroupMembershipListing';
const UserGroupMembershipMatrix = ({ many_users, many_groups }) => {
const intl = useIntl();
const dispatch = useDispatch();
const [query_user, setQuery_user] = useState(''); // Show users matching the search string
const [query_group, setQuery_group] = useState(''); // Show groups matching the search string
const [query_group_filter, setQuery_group_filter] = useState(''); // Offer groups matching the search string to filter users
const [groups_filter, setGroups_filter] = useState([]); // Show users joining these groups.
const [add_joined_groups, setAdd_joined_groups] = useState(false);
let filter_options = useSelector((state) => state.groups.filter_groups);
if (filter_options) {
filter_options = filter_options.map((group) => ({
value: group.id,
label: group.title || group.id,
}));
filter_options.sort(function (a, b) {
var labelA = a.label.toUpperCase();
var labelB = b.label.toUpperCase();
if (labelA < labelB) {
return -1;
}
if (labelA > labelB) {
return 1;
}
return 0;
});
}
const debouncedListGroups = useMemo(
() =>
debounce((query_group_filter) => {
dispatch(listGroups('', query_group_filter));
}, 300),
[dispatch],
);
useEffect(() => {
// TODO fetch group for at least query_group_filter.length > 1?
if (!many_groups || (many_groups && query_group_filter.length > 1)) {
debouncedListGroups(query_group_filter);
}
}, [debouncedListGroups, many_groups, query_group_filter]);
const onReset = (event) => {
// event.preventDefault();
let element = event.target.querySelector('input');
element.value = '';
element.focus();
let searchtype = element.name;
switch (searchtype) {
case 'SearchUser':
setQuery_user('');
break;
case 'SearchGroup':
setQuery_group('');
break;
case 'SearchGroupFilter':
setQuery_group_filter('');
setGroups_filter([]);
break;
default:
break;
}
};
const onChangeSearchUsers = (event) => {
if (many_users || many_groups) {
// search only on hitting return key
if (event.keyCode === 13) {
setQuery_user(event.target.value);
event.preventDefault();
}
} else {
setQuery_user(event.target.value);
}
};
const onChangeSearchGroups = (event) => {
if (many_users || many_groups) {
// search only on hitting return key
if (event.keyCode === 13) {
setQuery_group(event.target.value);
event.preventDefault();
}
} else {
setQuery_group(event.target.value);
}
};
const onSelectOptionHandler = (filter_option, checked) => {
let groups_filter_set_new = [];
if (checked) {
groups_filter_set_new = new Set([...groups_filter, filter_option]);
} else {
groups_filter_set_new = groups_filter.filter(
(el) => el.value !== filter_option.value,
);
}
if (!isEqual(groups_filter_set_new, new Set(groups_filter))) {
setGroups_filter([...groups_filter_set_new]);
}
};
const onToggleJoinedGroups = (checked) => {
setAdd_joined_groups(checked);
};
const onChangeSearchGroupsFilter = (event) => {
if (many_users || many_groups) {
// search only on hitting return key
if (event.keyCode === 13) {
setQuery_group_filter(event.target.value);
event.preventDefault();
}
} else {
setQuery_group_filter(event.target.value);
}
};
return (
<div className="controlpanel_matrix">
<div className="controlpanel_search_wrapper">
<div className="controlpanel_search_y">
<Form className="search_users" onSubmit={onReset}>
<Form.Field>
<Input
name="SearchUser"
action={{ icon: 'delete' }}
placeholder={intl.formatMessage(messages.searchUsers)}
onChange={onChangeSearchUsers}
onKeyDown={onChangeSearchUsers}
id="user-search-input"
/>
</Form.Field>
</Form>
</div>
<div className="controlpanel_search_x">
<Form className="search_groups" onSubmit={onReset}>
<Form.Field>
<Input
name="SearchGroup"
action={{ icon: 'delete' }}
placeholder={intl.formatMessage(messages.searchGroups)}
onChange={onChangeSearchGroups}
onKeyDown={onChangeSearchGroups}
id="group-search-input"
/>
</Form.Field>
<Form.Field>
<Checkbox
name="addJoinedGroups"
label={intl.formatMessage(messages.addJoinedGroups)}
title={intl.formatMessage(messages.addJoinedGroups)}
defaultChecked={false}
onChange={(event, { checked }) => {
onToggleJoinedGroups(checked);
}}
/>
</Form.Field>
</Form>
</div>
</div>
<div className="controlpanel_listing_wrapper">
<div className="controlpanel_filter">
<h3>{intl.formatMessage(messages.filterByGroups)}</h3>
<Form className="search_filter_groups" onSubmit={onReset}>
<Form.Field>
<Input
name="SearchGroupFilter"
action={{ icon: 'delete' }}
placeholder={intl.formatMessage(messages.searchGroups)}
onChange={onChangeSearchGroupsFilter}
onKeyDown={onChangeSearchGroupsFilter}
id="groupfilter-search-input"
/>
</Form.Field>
</Form>
{(!many_groups || query_group_filter.length > 1) &&
filter_options?.map((filter_option) => (
<React.Fragment key={filter_option.value}>
<Form.Field>
<Checkbox
name={`filter_option_${filter_option.value}`}
key={filter_option.value}
title={filter_option.label}
label={filter_option.label}
defaultChecked={false}
onChange={(event, { checked }) => {
onSelectOptionHandler(filter_option, checked);
}}
/>
</Form.Field>
</React.Fragment>
))}
</div>
<UserGroupMembershipListing
query_user={query_user}
query_group={query_group}
groups_filter={groups_filter}
add_joined_groups={add_joined_groups}
many_users={many_users}
many_groups={many_groups}
/>
</div>
</div>
);
};
export default UserGroupMembershipMatrix;