added view and edit of admin user and groups

This commit is contained in:
Maren Süwer
2018-08-16 10:55:39 +02:00
parent f2850370dd
commit 41589d785d
10 changed files with 390 additions and 12 deletions

View File

@@ -26,8 +26,17 @@
"force-base-url": "Force Base URL"
},
"admin-settings": {
"name": "Administration Settings",
"admin-groups": "Admin Groups",
"admin-user": "Admin Users"
"admin-users": "Admin Users",
"remove-group-button": "Remove Admin Group",
"remove-user-button": "Remove Admin User",
"add-group-error": "The group name you want to add is not valid",
"add-group-textfield": "Add group you want to add to admin groups here",
"add-group-button": "Add Admin Group",
"add-user-error": "The user name you want to add is not valid",
"add-user-textfield": "Add user you want to add to admin users here",
"add-user-button": "Add Admin User"
},
"general-settings": {
"realm-description": "Realm Description",

View File

@@ -0,0 +1,34 @@
//@flow
import React from "react";
import { DeleteButton } from "../../../components/buttons";
import { translate } from "react-i18next";
import classNames from "classnames";
type Props = {
t: string => string,
groupname: string,
removeGroup: string => void
};
type State = {};
class RemoveAdminGroupButton extends React.Component<Props, State> {
render() {
const { t , groupname, removeGroup} = this.props;
return (
<div className={classNames("is-pulled-right")}>
<DeleteButton
label={t("admin-settings.remove-group-button")}
action={(event: Event) => {
event.preventDefault();
removeGroup(groupname);
}}
/>
</div>
);
}
}
export default translate("config")(RemoveAdminGroupButton);

View File

@@ -0,0 +1,34 @@
//@flow
import React from "react";
import { DeleteButton } from "../../../components/buttons";
import { translate } from "react-i18next";
import classNames from "classnames";
type Props = {
t: string => string,
username: string,
removeUser: string => void
};
type State = {};
class RemoveAdminUserButton extends React.Component<Props, State> {
render() {
const { t , username, removeUser} = this.props;
return (
<div className={classNames("is-pulled-right")}>
<DeleteButton
label={t("admin-settings.remove-user-button")}
action={(event: Event) => {
event.preventDefault();
removeUser(username);
}}
/>
</div>
);
}
}
export default translate("config")(RemoveAdminUserButton);

View File

@@ -0,0 +1,71 @@
//@flow
import React from "react";
import { translate } from "react-i18next";
import { AddButton } from "../../../components/buttons";
import InputField from "../../../components/forms/InputField";
type Props = {
t: string => string,
addGroup: string => void
};
type State = {
groupToAdd: string,
//validationError: boolean
};
class AddAdminGroupField extends React.Component<Props, State> {
constructor(props) {
super(props);
this.state = {
groupToAdd: "",
//validationError: false
};
}
render() {
const { t } = this.props;
return (
<div className="field">
<InputField
label={t("admin-settings.add-group-textfield")}
errorMessage={t("admin-settings.add-group-error")}
onChange={this.handleAddGroupChange}
validationError={false}
value={this.state.groupToAdd}
onReturnPressed={this.appendGroup}
/>
<AddButton
label={t("admin-settings.add-group-button")}
action={this.addButtonClicked}
//disabled={!isMemberNameValid(this.state.memberToAdd)}
/>
</div>
);
}
addButtonClicked = (event: Event) => {
event.preventDefault();
this.appendGroup();
};
appendGroup = () => {
const { groupToAdd } = this.state;
//if (isMemberNameValid(memberToAdd)) {
this.props.addGroup(groupToAdd);
this.setState({ ...this.state, groupToAdd: "" });
// }
};
handleAddGroupChange = (groupname: string) => {
this.setState({
...this.state,
groupToAdd: groupname,
//validationError: membername.length > 0 && !isMemberNameValid(membername)
});
};
}
export default translate("config")(AddAdminGroupField);

View File

@@ -0,0 +1,71 @@
//@flow
import React from "react";
import { translate } from "react-i18next";
import { AddButton } from "../../../components/buttons";
import InputField from "../../../components/forms/InputField";
type Props = {
t: string => string,
addUser: string => void
};
type State = {
userToAdd: string,
//validationError: boolean
};
class AddAdminUserField extends React.Component<Props, State> {
constructor(props) {
super(props);
this.state = {
userToAdd: "",
//validationError: false
};
}
render() {
const { t } = this.props;
return (
<div className="field">
<InputField
label={t("admin-settings.add-user-textfield")}
errorMessage={t("admin-settings.add-user-error")}
onChange={this.handleAddUserChange}
validationError={false}
value={this.state.userToAdd}
onReturnPressed={this.appendUser}
/>
<AddButton
label={t("admin-settings.add-user-button")}
action={this.addButtonClicked}
//disabled={!isMemberNameValid(this.state.memberToAdd)}
/>
</div>
);
}
addButtonClicked = (event: Event) => {
event.preventDefault();
this.appendUser();
};
appendUser = () => {
const { userToAdd } = this.state;
//if (isMemberNameValid(memberToAdd)) {
this.props.addUser(userToAdd);
this.setState({ ...this.state, userToAdd: "" });
// }
};
handleAddUserChange = (username: string) => {
this.setState({
...this.state,
userToAdd: username,
//validationError: membername.length > 0 && !isMemberNameValid(membername)
});
};
}
export default translate("config")(AddAdminUserField);

View File

@@ -1,8 +1,12 @@
// @flow
import React from "react";
import { translate } from "react-i18next";
import { Checkbox, InputField } from "../../../components/forms/index";
import Subtitle from "../../../components/layout/Subtitle";
import AdminGroupTable from "../table/AdminGroupTable";
import ProxySettings from "./ProxySettings";
import AdminUserTable from "../table/AdminUserTable";
import AddAdminGroupField from "../fields/AddAdminGroupField";
import AddAdminUserField from "../fields/AddAdminUserField";
type Props = {
adminGroups: string[],
@@ -13,17 +17,58 @@ type Props = {
//TODO: Einbauen!
class AdminSettings extends React.Component<Props> {
render() {
const {
t,
adminGroups,
adminUsers
} = this.props;
const { t, adminGroups, adminUsers } = this.props;
return (
null
<div>
<Subtitle subtitle={t("admin-settings.name")} />
<AdminGroupTable
adminGroups={adminGroups}
onChange={(isValid, changedValue, name) =>
this.props.onChange(isValid, changedValue, name)
}
/>
<AddAdminGroupField addGroup={this.addGroup} />
<AdminUserTable
adminUsers={adminUsers}
onChange={(isValid, changedValue, name) =>
this.props.onChange(isValid, changedValue, name)
}
/>
<AddAdminUserField addUser={this.addUser} />
</div>
);
}
addGroup = (groupname: string) => {
if (this.isAdminGroupMember(groupname)) {
return;
}
this.props.onChange(
true,
[...this.props.adminGroups, groupname],
"adminGroups"
);
};
isAdminGroupMember = (groupname: string) => {
return this.props.adminGroups.includes(groupname);
};
addUser = (username: string) => {
if (this.isAdminUserMember(username)) {
return;
}
this.props.onChange(
true,
[...this.props.adminUsers, username],
"adminUsers"
);
};
isAdminUserMember = (username: string) => {
return this.props.adminUsers.includes(username);
};
}
export default translate("config")(AdminSettings);

View File

@@ -6,12 +6,14 @@ import type { Config } from "../../types/Config";
import ProxySettings from "./ProxySettings";
import GeneralSettings from "./GeneralSettings";
import BaseUrlSettings from "./BaseUrlSettings";
import AdminSettings from "./AdminSettings";
type Props = {
submitForm: Config => void,
config?: Config,
loading?: boolean,
t: string => string
t: string => string,
configUpdatePermission: boolean
};
type State = {
@@ -85,6 +87,7 @@ class ConfigForm extends React.Component<Props, State> {
this.onChange(isValid, changedValue, name)
}
/>
<hr />
<BaseUrlSettings
baseUrl={config.baseUrl}
forceBaseUrl={config.forceBaseUrl}
@@ -92,6 +95,15 @@ class ConfigForm extends React.Component<Props, State> {
this.onChange(isValid, changedValue, name)
}
/>
<hr />
<AdminSettings
adminGroups={config.adminGroups}
adminUsers={config.adminUsers}
onChange={(isValid, changedValue, name) =>
this.onChange(isValid, changedValue, name)
}
/>
<hr />
<ProxySettings
proxyPassword={config.proxyPassword ? config.proxyPassword : ""}
proxyPort={config.proxyPort}
@@ -102,6 +114,7 @@ class ConfigForm extends React.Component<Props, State> {
this.onChange(isValid, changedValue, name)
}
/>
<hr />
<SubmitButton
// disabled={!this.isValid()}
loading={loading}

View File

@@ -0,0 +1,47 @@
//@flow
import React from "react";
import { translate } from "react-i18next";
import RemoveAdminGroupButton from "../buttons/RemoveAdminGroupButton";
type Props = {
adminGroups: string[],
t: string => string,
onChange: (boolean, any, string) => void
};
type State = {};
class AdminGroupTable extends React.Component<Props, State> {
render() {
const { t } = this.props;
return (
<div>
<label className="label">{t("admin-settings.admin-groups")}</label>
<table className="table is-hoverable is-fullwidth">
<tbody>
{this.props.adminGroups.map(group => {
return (
<tr key={group}>
<td key={group}>{group}</td>
<td>
<RemoveAdminGroupButton
groupname={group}
removeGroup={this.removeGroup}
/>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
);
}
removeGroup = (groupname: string) => {
const newGroups = this.props.adminGroups.filter(name => name !== groupname);
this.props.onChange(true, newGroups, "adminGroups");
};
}
export default translate("config")(AdminGroupTable);

View File

@@ -0,0 +1,47 @@
//@flow
import React from "react";
import { translate } from "react-i18next";
import RemoveAdminUserButton from "../buttons/RemoveAdminUserButton";
type Props = {
adminUsers: string[],
t: string => string,
onChange: (boolean, any, string) => void
};
type State = {};
class AdminUserTable extends React.Component<Props, State> {
render() {
const { t } = this.props;
return (
<div>
<label className="label">{t("admin-settings.admin-users")}</label>
<table className="table is-hoverable is-fullwidth">
<tbody>
{this.props.adminUsers.map(user => {
return (
<tr key={user}>
<td key={user}>{user}</td>
<td>
<RemoveAdminUserButton
username={user}
removeUser={this.removeUser}
/>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
);
}
removeUser = (username: string) => {
const newUsers = this.props.adminUsers.filter(name => name !== username);
this.props.onChange(true, newUsers, "adminUsers");
};
}
export default translate("config")(AdminUserTable);

View File

@@ -7,7 +7,8 @@ import {
isFetchConfigPending,
getConfig,
modifyConfig,
isModifyConfigPending
isModifyConfigPending,
getConfigUpdatePermission
} from "../modules/config";
import connect from "react-redux/es/connect/connect";
import ErrorPage from "../../components/ErrorPage";
@@ -21,6 +22,7 @@ type Props = {
loading: boolean,
error: Error,
config: Config,
configUpdatePermission: boolean,
// dispatch functions
modifyConfig: (config: User, callback?: () => void) => void,
// context objects
@@ -31,6 +33,7 @@ type Props = {
class GlobalConfig extends React.Component<Props> {
configModified = (config: Config) => () => {
this.props.fetchConfig();
this.props.history.push(`/config`);
};
@@ -39,11 +42,12 @@ class GlobalConfig extends React.Component<Props> {
}
modifyConfig = (config: Config) => {
console.log(config);
this.props.modifyConfig(config, this.configModified(config));
};
render() {
const { t, error, loading, config } = this.props;
const { t, error, loading, config, configUpdatePermission } = this.props;
if (error) {
return (
@@ -51,6 +55,7 @@ class GlobalConfig extends React.Component<Props> {
title={t("global-config.error-title")}
subtitle={t("global-config.error-subtitle")}
error={error}
configUpdatePermission={configUpdatePermission}
/>
);
}
@@ -86,11 +91,13 @@ const mapStateToProps = state => {
const loading = isFetchConfigPending(state) || isModifyConfigPending(state); //TODO: Button lädt so nicht, sondern gesamte Seite
const error = getFetchConfigFailure(state);
const config = getConfig(state);
const configUpdatePermission = getConfigUpdatePermission(state);
return {
loading,
error,
config
config,
configUpdatePermission
};
};