Skip to content

Commit

Permalink
Merge branch 'master' of github.com:scalableminds/webknossos into fi…
Browse files Browse the repository at this point in the history
…x_login_styles

* 'master' of github.com:scalableminds/webknossos:
  Added members to admin team page (#6915)
  • Loading branch information
hotzenklotz committed Mar 15, 2023
2 parents d5df517 + 516a6ac commit 62cf6f8
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 28 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
[Commits](https://github.com/scalableminds/webknossos/compare/23.03.1...HEAD)

### Added
- Added list of all respective team members to the administration page for teams. [#6915](https://github.com/scalableminds/webknossos/pull/6915)

### Changed
- Updated the styling of the "welcome" screen for new users to be in line with the new branding. [#6904](https://github.com/scalableminds/webknossos/pull/6904)
Expand Down
81 changes: 76 additions & 5 deletions frontend/javascripts/admin/team/team_list_view.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,72 @@
// @ts-expect-error ts-migrate(7016) FIXME: Could not find a declaration file for module '@sca... Remove this comment to see the full error message
import { PropTypes } from "@scalableminds/prop-types";
import { Table, Spin, Button, Input, Modal, Alert } from "antd";
import { Table, Spin, Button, Input, Modal, Alert, Tag } from "antd";
import { DeleteOutlined, PlusOutlined } from "@ant-design/icons";
import * as React from "react";
import _ from "lodash";
import type { APITeam } from "types/api_flow_types";
import { getEditableTeams, deleteTeam } from "admin/admin_rest_api";
import type { APITeam, APITeamMembership, APIUser } from "types/api_flow_types";
import { getEditableTeams, deleteTeam, getEditableUsers } from "admin/admin_rest_api";
import { handleGenericError } from "libs/error_handling";
import LinkButton from "components/link_button";
import CreateTeamModal from "admin/team/create_team_modal_view";
import Persistence from "libs/persistence";
import * as Utils from "libs/utils";
import messages from "messages";
import { stringToColor } from "libs/format_utils";
const { Column } = Table;
const { Search } = Input;
const typeHint: APITeam[] = [];

type Props = {};
type State = {
isLoading: boolean;
teams: Array<APITeam>;
teams: APITeam[];
users: APIUser[];
searchQuery: string;
isTeamCreationModalVisible: boolean;
};

export function renderTeamRolesAndPermissionsForUser(user: APIUser) {
//used by user list page
const tags = [
...(user.isOrganizationOwner ? [["Organization Owner", "cyan"]] : []),
...(user.isAdmin
? [["Admin - Access to all Teams", "red"]]
: [
...(user.isDatasetManager ? [["Dataset Manager - Edit all Datasets", "geekblue"]] : []),
...user.teams.map((team) => {
const roleName = team.isTeamManager ? "Team Manager" : "Member";
return [`${team.name}: ${roleName}`, stringToColor(roleName)];
}),
]),
];

return tags.map(([text, color]) => (
<Tag key={`${text}_${user.id}`} color={color} style={{ marginBottom: 4 }}>
{text}
</Tag>
));
}

function renderTeamRolesForUser(user: APIUser, highlightedTeam: APITeam) {
// used by teams list page
// does not include dataset managers and team names
const tags = user.isAdmin
? [["Admin - Access to all Teams", "red"]]
: user.teams
.filter((team) => team.id === highlightedTeam.id)
.map((team) => {
const roleName = team.isTeamManager ? "Team Manager" : "Member";
return [`${roleName}`, stringToColor(roleName)];
});

return tags.map(([text, color]) => (
<Tag key={`${text}_${user.id}`} color={color} style={{ marginBottom: 4 }}>
{text}
</Tag>
));
}

const persistence = new Persistence<Pick<State, "searchQuery">>(
{
searchQuery: PropTypes.string,
Expand All @@ -33,6 +78,7 @@ class TeamListView extends React.PureComponent<Props, State> {
state: State = {
isLoading: true,
teams: [],
users: [],
searchQuery: "",
isTeamCreationModalVisible: false,
};
Expand All @@ -48,10 +94,11 @@ class TeamListView extends React.PureComponent<Props, State> {
}

async fetchData(): Promise<void> {
const teams = await getEditableTeams();
const [teams, users] = await Promise.all([getEditableTeams(), getEditableUsers()]);
this.setState({
isLoading: false,
teams,
users,
});
}

Expand Down Expand Up @@ -112,6 +159,26 @@ class TeamListView extends React.PureComponent<Props, State> {
);
}

renderUsersForTeam(team: APITeam) {
const teamMembers = this.state.users.filter(
(user) =>
user.teams.some((userTeam: APITeamMembership) => userTeam.id === team.id) || user.isAdmin,
);

if (teamMembers.length === 0) return messages["team.no_members"];

return (
<ul>
{teamMembers.map((teamMember) => (
<li>
{teamMember.firstName} {teamMember.lastName} ({teamMember.email}){" "}
{renderTeamRolesForUser(teamMember, team)}
</li>
))}
</ul>
);
}

render() {
const marginRight = {
marginRight: 20,
Expand Down Expand Up @@ -165,6 +232,10 @@ class TeamListView extends React.PureComponent<Props, State> {
pagination={{
defaultPageSize: 50,
}}
expandable={{
expandedRowRender: (team) => this.renderUsersForTeam(team),
rowExpandable: (_team) => true,
}}
style={{
marginTop: 30,
marginBottom: 30,
Expand Down
27 changes: 4 additions & 23 deletions frontend/javascripts/admin/user/user_list_view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import type { OxalisState } from "oxalis/store";
import { enforceActiveUser } from "oxalis/model/accessors/user_accessor";
import LinkButton from "components/link_button";
import { getEditableUsers, updateUser } from "admin/admin_rest_api";
import { stringToColor } from "libs/format_utils";
import EditableTextLabel from "oxalis/view/components/editable_text_label";
import ExperienceModalView from "admin/user/experience_modal_view";
import Persistence from "libs/persistence";
Expand All @@ -43,6 +42,7 @@ import messages from "messages";
import { logoutUserAction } from "../../oxalis/model/actions/user_actions";
import Store from "../../oxalis/store";
import { enforceActiveOrganization } from "oxalis/model/accessors/organization_accessors";
import { renderTeamRolesAndPermissionsForUser } from "admin/team/team_list_view";

const { Column } = Table;
const { Search } = Input;
Expand Down Expand Up @@ -543,28 +543,9 @@ class UserListView extends React.PureComponent<Props, State> {
dataIndex="teams"
key="teams_"
width={250}
render={(_teams: APITeamMembership[], user: APIUser) => {
const tags = [
...(user.isOrganizationOwner ? [["Organization Owner", "cyan"]] : []),
...(user.isAdmin
? [["Admin - Access to all Teams", "red"]]
: [
...(user.isDatasetManager
? [["Dataset Manager - Edit all Datasets", "geekblue"]]
: []),
...user.teams.map((team) => {
const roleName = team.isTeamManager ? "Team Manager" : "Member";
return [`${team.name}: ${roleName}`, stringToColor(roleName)];
}),
]),
];

return tags.map(([text, color]) => (
<Tag key={`${text}_${user.id}`} color={color} style={{ marginBottom: 4 }}>
{text}
</Tag>
));
}}
render={(_teams: APITeamMembership[], user: APIUser) =>
renderTeamRolesAndPermissionsForUser(user)
}
/>
<Column
title="Status"
Expand Down
1 change: 1 addition & 0 deletions frontend/javascripts/messages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ instead. Only enable this option if you understand its effect. All layers will n
"This download does only include the volume data annotated in the tasks of this project. The fallback volume data is excluded.",
"script.delete": "Do you really want to delete this script?",
"team.delete": "Do you really want to delete this team?",
"team.no_members": "This team has no members assigned yet.",
"taskType.delete": "Do you really want to delete this task type and all its associated tasks?",
"auth.registration_email_input": "Please input your E-mail!",
"auth.registration_email_invalid": "The input is not valid E-mail!",
Expand Down

0 comments on commit 62cf6f8

Please sign in to comment.