This commit is contained in:
Eduard Heimbuch
2019-05-15 14:06:40 +02:00
13 changed files with 114 additions and 26 deletions

View File

@@ -10,9 +10,8 @@ import type { Links } from "@scm-manager/ui-types";
import { Page, Navigation, NavLink, Section } from "@scm-manager/ui-components";
import { getLinks } from "../../modules/indexResource";
import GlobalConfig from "./GlobalConfig";
import RepositoryRoles from "./RepositoryRoles";
import RepositoryRoleForm from "./RepositoryRoleForm"
import SingleRepositoryRole from "./SingleRepositoryRole";
import RepositoryRoles from "../roles/containers/RepositoryRoles";
import SingleRepositoryRole from "../roles/containers/SingleRepositoryRole";
type Props = {
links: Links,
@@ -37,7 +36,7 @@ class Config extends React.Component<Props> {
matchesRoles = (route: any) => {
const url = this.matchedUrl();
const regex = new RegExp(`${url}/role/.+/edit`);
const regex = new RegExp(`${url}/role/`);
return route.location.pathname.match(regex);
};
@@ -55,12 +54,19 @@ class Config extends React.Component<Props> {
<div className="columns">
<div className="column is-three-quarters">
<Route path={url} exact component={GlobalConfig} />
<Route
path={`${url}/role/:role`}
render={() => <SingleRepositoryRole baseUrl={`${url}/roles`} />}
/>
<Route
path={`${url}/roles`}
exact
render={() => <RepositoryRoles baseUrl={`${url}/roles`} />}
/>
<Route path={`${url}/role`} component={SingleRepositoryRole} />
<Route
path={`${url}/roles/create`}
render={() => <CreatePermissionRole />}
/>
<ExtensionPoint
name="config.route"
props={extensionProps}

View File

@@ -1,175 +0,0 @@
// @flow
import React from "react";
import { connect } from "react-redux";
import { translate } from "react-i18next";
import type { Role } from "@scm-manager/ui-types";
import { InputField, SubmitButton } from "@scm-manager/ui-components";
import PermissionCheckbox from "../../repos/permissions/components/PermissionCheckbox";
import {
createRole,
fetchAvailableVerbs,
getFetchVerbsFailure,
getVerbsFromState,
isFetchVerbsPending
} from "../modules/roles";
import {getRepositoryRolesLink, getRepositoryVerbsLink} from "../../modules/indexResource";
type Props = {
role?: Role,
loading?: boolean,
disabled: boolean,
availableVerbs: string[],
verbsLink: string,
// context objects
t: string => string,
// dispatch functions
fetchAvailableVerbs: (link: string) => void,
addRole: (link: string, role: Role) => void
};
type State = {
role: Role
};
class RepositoryRoleForm extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
role: {
name: "",
verbs: [],
system: false,
_links: {}
}
};
}
componentDidMount() {
const { fetchAvailableVerbs, verbsLink} = this.props;
fetchAvailableVerbs(verbsLink);
}
isFalsy(value) {
return !value;
}
isValid = () => {
const { role } = this.state;
return !(
this.isFalsy(role) ||
this.isFalsy(role.name) ||
this.isFalsy(role.verbs)
);
};
handleNameChange = (name: string) => {
this.setState({
role: {
...this.state.role,
name
}
});
};
handleVerbChange = (value: boolean, name: string) => {
const { role } = this.state;
const newVerbs = value
? [...role.verbs, name]
: role.verbs.filter(v => v !== name);
this.setState({
...this.state,
role: {
...role,
verbs: newVerbs
}
});
};
submit = (event: Event) => {
event.preventDefault();
if (this.isValid()) {
this.props.addRole(this.props.repositoryRolesLink, this.state.role)
}
};
render() {
const { loading, availableVerbs, disabled, t } = this.props;
const { role } = this.state;
const verbSelectBoxes = !availableVerbs
? null
: availableVerbs.map(verb => (
<PermissionCheckbox
key={verb}
// disabled={readOnly}
name={verb}
checked={role.verbs.includes(verb)}
onChange={this.handleVerbChange}
/>
));
return (
<form onSubmit={this.submit}>
<div className="columns">
<div className="column">
<InputField
name="name"
label={t("roles.create.name")}
onChange={this.handleNameChange}
value={role.name ? role.name : ""}
disabled={!!role.name || disabled}
/>
</div>
</div>
<>{verbSelectBoxes}</>
<hr />
<div className="columns">
<div className="column">
<SubmitButton
loading={loading}
label={t("roles.create.submit")}
disabled={disabled || !this.isValid()}
/>
</div>
</div>
</form>
);
}
}
const mapStateToProps = (state, ownProps) => {
const loading = isFetchVerbsPending(state);
const error = getFetchVerbsFailure(state);
const verbsLink = getRepositoryVerbsLink(state);
const availableVerbs = getVerbsFromState(state);
const repositoryRolesLink = getRepositoryRolesLink(state);
return {
loading,
error,
verbsLink,
availableVerbs,
repositoryRolesLink
};
};
const mapDispatchToProps = dispatch => {
return {
fetchAvailableVerbs: (link: string) => {
dispatch(fetchAvailableVerbs(link));
},
addRole: (link: string, role: Role) => {
createRole(link, role)
}
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(translate("roles")(RepositoryRoleForm));

View File

@@ -1,122 +0,0 @@
// @flow
import React from "react";
import { connect } from "react-redux";
import {withRouter} from "react-router-dom";
import { translate } from "react-i18next";
import type { History } from "history";
import type { Role, PagedCollection } from "@scm-manager/ui-types";
import {
Title,
Loading,
Notification,
LinkPaginator,
urls,
CreateButton
} from "@scm-manager/ui-components";
import {
fetchRolesByPage,
getRolesFromState,
selectListAsCollection,
isPermittedToCreateRoles,
isFetchRolesPending,
getFetchRolesFailure
} from "../modules/roles";
import PermissionRoleTable from "../components/table/PermissionRoleTable";
import { getRolesLink } from "../../modules/indexResource";
type Props = {
baseUrl: string,
roles: Role[],
loading: boolean,
error: Error,
canAddRoles: boolean,
list: PagedCollection,
page: number,
rolesLink: string,
// context objects
t: string => string,
history: History,
// dispatch functions
fetchRolesByPage: (link: string, page: number) => void
};
class RepositoryRoles extends React.Component<Props> {
componentDidMount() {
const { fetchRolesByPage, rolesLink, page } = this.props;
fetchRolesByPage(rolesLink, page);
}
render() {
const { t, loading } = this.props;
if (loading) {
return <Loading />;
}
return (
<div>
<Title title={t("roles.title")} />
{this.renderPermissionsTable()}
{this.renderCreateButton()}
</div>
);
}
renderPermissionsTable() {
const { baseUrl, roles, list, page, t } = this.props;
if (roles && roles.length > 0) {
return (
<>
<PermissionRoleTable baseUrl={baseUrl} roles={roles} />
<LinkPaginator collection={list} page={page} />
</>
);
}
return (
<Notification type="info">{t("roles.noPermissionRoles")}</Notification>
);
}
renderCreateButton() {
const { canAddRoles, baseUrl, t } = this.props;
if (canAddRoles) {
return <CreateButton label={t("roles.createButton")} link={`${baseUrl}/create`} />;
}
return null;
}
}
const mapStateToProps = (state, ownProps) => {
const { match } = ownProps;
const roles = getRolesFromState(state);
const loading = isFetchRolesPending(state);
const error = getFetchRolesFailure(state);
const page = urls.getPageFromMatch(match);
const canAddRoles = isPermittedToCreateRoles(state);
const list = selectListAsCollection(state);
const rolesLink = getRolesLink(state);
return {
roles,
loading,
error,
canAddRoles,
list,
page,
rolesLink
};
};
const mapDispatchToProps = dispatch => {
return {
fetchRolesByPage: (link: string, page: number) => {
dispatch(fetchRolesByPage(link, page));
}
};
};
export default withRouter(connect(
mapStateToProps,
mapDispatchToProps
)(translate("config")(RepositoryRoles)));

View File

@@ -1,121 +0,0 @@
//@flow
import React from "react";
import { connect } from "react-redux";
import {
Page,
Loading,
ErrorPage
} from "@scm-manager/ui-components";
import { Route } from "react-router";
import type { History } from "history";
import { EditRepositoryRoleNavLink, RepositoryRoleDetailNavLink } from "./../components/navLinks";
import { translate } from "react-i18next";
import type { Role } from "@scm-manager/ui-types";
import {getRepositoryRolesLink} from "../../modules/indexResource";
import {ExtensionPoint} from "@scm-manager/ui-extensions";
import {fetchRoleByName, getFetchRoleFailure, getRoleByName, isFetchRolePending} from "../modules/roles";
type Props = {
name: string,
role: Role,
loading: boolean,
error: Error,
repositoryRolesLink: string,
// dispatcher function
fetchRoleByName: (string, string) => void,
// context objects
t: string => string,
match: any,
history: History
};
class SingleRepositoryRole extends React.Component<Props> {
componentDidMount() {
this.props.fetchRoleByName(this.props.repositoryRolesLink, this.props.name);
}
stripEndingSlash = (url: string) => {
if (url.endsWith("/")) {
return url.substring(0, url.length - 2);
}
return url;
};
matchedUrl = () => {
return this.stripEndingSlash(this.props.match.url);
};
render() {
const { t, loading, error, role } = this.props;
if (error) {
return (
<ErrorPage
title={t("singleUser.errorTitle")}
subtitle={t("singleUser.errorSubtitle")}
error={error}
/>
);
}
if (!role || loading) {
return <Loading />;
}
const url = this.matchedUrl();
const extensionProps = {
role,
url
};
return (
<Page title={role.displayName}>
<div className="columns">
<div className="column is-three-quarters">
<Route path={url} exact component={() => <RepositoryRoleDetailNavLink role={role} />} />
<Route
path={`${url}/settings/general`}
component={() => <EditRepositoryRoleNavLink role={role} />}
/>
<ExtensionPoint
name="user.route"
props={extensionProps}
renderAll={true}
/>
</div>
</div>
</Page>
);
}
}
const mapStateToProps = (state, ownProps) => {
const name = ownProps.match.params.name;
const role = getRoleByName(state, name);
const loading = isFetchRolePending(state, name);
const error = getFetchRoleFailure(state, name);
const repositoryRolesLink = getRepositoryRolesLink(state);
return {
repositoryRolesLink,
name,
role,
loading,
error
};
};
const mapDispatchToProps = dispatch => {
return {
fetchRoleByName: (link: string, name: string) => {
dispatch(fetchRoleByName(link, name));
}
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(translate("users")(SingleRepositoryRole));