{runtimes => (
@@ -278,7 +277,6 @@ class Exercise extends Component {
Exercise.propTypes = {
userId: PropTypes.string.isRequired,
- instance: ImmutablePropTypes.map,
match: PropTypes.shape({
params: PropTypes.shape({
exerciseId: PropTypes.string.isRequired,
@@ -315,10 +313,8 @@ export default withLinks(
}
) => {
const userId = loggedInUserIdSelector(state);
- const instanceId = selectedInstanceId(state);
return {
userId,
- instance: instanceSelector(state, instanceId),
exercise: exerciseSelector(exerciseId)(state),
forkedFrom: exerciseForkedFromSelector(exerciseId)(state),
runtimeEnvironments: runtimeEnvironmentsSelector(state),
diff --git a/src/pages/GroupInfo/GroupInfo.js b/src/pages/GroupInfo/GroupInfo.js
index 6d31b94a6..968e50120 100644
--- a/src/pages/GroupInfo/GroupInfo.js
+++ b/src/pages/GroupInfo/GroupInfo.js
@@ -39,7 +39,7 @@ import { getLocalizedName, transformLocalizedTextsFormData } from '../../helpers
import { isReady } from '../../redux/helpers/resourceManager/index';
import Box from '../../components/widgets/Box';
import Callout from '../../components/widgets/Callout';
-import GroupTree from '../../components/Groups/GroupTree/GroupTree';
+import GroupsTreeContainer from '../../containers/GroupsTreeContainer';
import EditGroupForm, { EDIT_GROUP_FORM_EMPTY_INITIAL_VALUES } from '../../components/forms/EditGroupForm';
import AddSupervisor from '../../components/Groups/AddSupervisor';
import { BanIcon, GroupIcon } from '../../components/icons';
@@ -227,16 +227,11 @@ class GroupInfo extends Component {
title={}
unlimitedHeight
extraPadding>
-
)}
diff --git a/src/pages/Instance/Instance.js b/src/pages/Instance/Instance.js
index 6c59fd616..10aa4ed1e 100644
--- a/src/pages/Instance/Instance.js
+++ b/src/pages/Instance/Instance.js
@@ -6,10 +6,9 @@ import { formValueSelector } from 'redux-form';
import { FormattedMessage, injectIntl } from 'react-intl';
import { Row, Col } from 'react-bootstrap';
import { Link } from 'react-router-dom';
-import { defaultMemoize } from 'reselect';
import Box from '../../components/widgets/Box';
-import GroupTree from '../../components/Groups/GroupTree';
+import GroupsTreeContainer from '../../containers/GroupsTreeContainer';
import Button from '../../components/widgets/TheButton';
import Page from '../../components/layout/Page';
import LicencesTableContainer from '../../containers/LicencesTableContainer';
@@ -20,37 +19,34 @@ import FetchManyResourceRenderer from '../../components/helpers/FetchManyResourc
import ResourceRenderer from '../../components/helpers/ResourceRenderer';
import NotVerifiedEmailCallout from '../../components/Users/NotVerifiedEmailCallout';
-import { fetchUser } from '../../redux/modules/users';
+import { fetchUser, fetchByIds } from '../../redux/modules/users';
import { fetchInstanceIfNeeded } from '../../redux/modules/instances';
import { instanceSelector, isAdminOfInstance } from '../../redux/selectors/instances';
import { createGroup, fetchAllGroups } from '../../redux/modules/groups';
-import { notArchivedGroupsSelector, fetchManyGroupsStatus } from '../../redux/selectors/groups';
+import { fetchManyGroupsStatus, getGroupsAdmins } from '../../redux/selectors/groups';
import { loggedInUserIdSelector } from '../../redux/selectors/auth';
import { isLoggedAsSuperAdmin, getUser } from '../../redux/selectors/users';
import { transformLocalizedTextsFormData, getLocalizedName } from '../../helpers/localizedData';
-import { resourceStatus } from '../../redux/helpers/resourceManager';
import withLinks from '../../helpers/withLinks';
import InstanceInfoTable from '../../components/Instances/InstanceDetail/InstanceInfoTable';
-const anyGroupVisible = defaultMemoize(groups =>
- Boolean(groups.size > 0 && groups.find(group => group.getIn(['data', 'permissionHints', 'viewDetail'])))
-);
-
class Instance extends Component {
- static loadAsync = ({ instanceId, fetchGroupsStatus = null }, dispatch) => {
- const promises = [dispatch(fetchInstanceIfNeeded(instanceId))];
- if (fetchGroupsStatus === resourceStatus.FAILED) {
- promises.push(dispatch(fetchAllGroups()));
- }
- return Promise.all(promises);
- };
+ static customLoadGroups = true; // Marker for the App async load, that we will load groups ourselves.
+
+ static loadAsync = ({ instanceId }, dispatch) =>
+ Promise.all([
+ dispatch(fetchInstanceIfNeeded(instanceId)),
+ dispatch(fetchAllGroups({ archived: true })).then(({ value: groups }) =>
+ dispatch(fetchByIds(getGroupsAdmins(groups)))
+ ),
+ ]);
- componentDidMount = () => this.props.loadAsync(this.props.fetchGroupsStatus);
+ componentDidMount = () => this.props.loadAsync();
componentDidUpdate(prevProps) {
if (this.props.match.params.instanceId !== prevProps.match.params.instanceId) {
- this.props.loadAsync(this.props.fetchGroupsStatus);
+ this.props.loadAsync();
}
}
@@ -63,7 +59,6 @@ class Instance extends Component {
user,
refreshUser,
instance,
- groups,
fetchGroupsStatus,
createGroup,
isAdmin,
@@ -128,16 +123,7 @@ class Instance extends Component {
{data.rootGroupId !== null && (
- {() =>
- anyGroupVisible(groups) ? (
-
- ) : (
-
- )
- }
+ {() => }
)}
@@ -183,7 +169,6 @@ Instance.propTypes = {
userId: PropTypes.string.isRequired,
user: ImmutablePropTypes.map,
instance: ImmutablePropTypes.map,
- groups: ImmutablePropTypes.map,
fetchGroupsStatus: PropTypes.string,
createGroup: PropTypes.func.isRequired,
isAdmin: PropTypes.bool.isRequired,
@@ -210,7 +195,6 @@ export default withLinks(
userId,
user: getUser(userId)(state),
instance: instanceSelector(state, instanceId),
- groups: notArchivedGroupsSelector(state),
fetchGroupsStatus: fetchManyGroupsStatus(state),
isAdmin: isAdminOfInstance(userId, instanceId)(state),
isSuperAdmin: isLoggedAsSuperAdmin(state),
@@ -238,7 +222,7 @@ export default withLinks(
instanceId,
})
).then(() => Promise.all([dispatch(fetchAllGroups()), dispatch(fetchUser(userId))])),
- loadAsync: fetchGroupsStatus => Instance.loadAsync({ instanceId, fetchGroupsStatus }, dispatch),
+ loadAsync: () => Instance.loadAsync({ instanceId }, dispatch),
refreshUser: userId => dispatch(fetchUser(userId)),
})
)(injectIntl(Instance))
diff --git a/src/redux/selectors/groups.js b/src/redux/selectors/groups.js
index 333e11d90..cfc37fd00 100644
--- a/src/redux/selectors/groups.js
+++ b/src/redux/selectors/groups.js
@@ -147,3 +147,14 @@ export const groupsUserIsMemberSelector = createSelector(
[notArchivedGroupsSelector, getParam, getLang],
groupsUserIsMember
);
+
+/**
+ * Helper selector-related function that extracts unique admin IDs form given groups
+ * @param {Array} groups as JS objects
+ * @returns {String[]} unique user IDs
+ */
+export const getGroupsAdmins = groups => {
+ const ids = new Set(); // set ensures each id is represented once
+ groups.forEach(group => group && group.primaryAdminsIds && group.primaryAdminsIds.forEach(id => ids.add(id)));
+ return Array.from(ids);
+};