mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-13 08:55:44 +01:00
refactor / new structure for repositoryRoles
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import type { User } from "@scm-manager/ui-types";
|
||||
import { NavLink } from "@scm-manager/ui-components";
|
||||
import { translate } from "react-i18next";
|
||||
|
||||
type Props = {
|
||||
user: User,
|
||||
editUrl: String,
|
||||
t: string => string
|
||||
};
|
||||
|
||||
class EditRepositoryRoleNavLink extends React.Component<Props> {
|
||||
isEditable = () => {
|
||||
return this.props.user._links.update;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { t, editUrl } = this.props;
|
||||
|
||||
if (!this.isEditable()) {
|
||||
return null;
|
||||
}
|
||||
return <NavLink to={editUrl} label={t("singleUser.menu.generalNavLink")} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default translate("users")(EditRepositoryRoleNavLink);
|
||||
@@ -0,0 +1,27 @@
|
||||
import React from "react";
|
||||
import { shallow } from "enzyme";
|
||||
import "../../../tests/enzyme";
|
||||
import "../../../tests/i18n";
|
||||
import EditUserNavLink from "./EditRepositoryRoleNavLink";
|
||||
|
||||
it("should render nothing, if the edit link is missing", () => {
|
||||
const user = {
|
||||
_links: {}
|
||||
};
|
||||
|
||||
const navLink = shallow(<EditUserNavLink user={user} editUrl='/user/edit'/>);
|
||||
expect(navLink.text()).toBe("");
|
||||
});
|
||||
|
||||
it("should render the navLink", () => {
|
||||
const user = {
|
||||
_links: {
|
||||
update: {
|
||||
href: "/users"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const navLink = shallow(<EditUserNavLink user={user} editUrl='/user/edit'/>);
|
||||
expect(navLink.text()).not.toBe("");
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import { translate } from "react-i18next";
|
||||
import type { User } from "@scm-manager/ui-types";
|
||||
import { NavLink } from "@scm-manager/ui-components";
|
||||
|
||||
type Props = {
|
||||
t: string => string,
|
||||
user: User,
|
||||
permissionsUrl: String
|
||||
};
|
||||
|
||||
class ChangePermissionNavLink extends React.Component<Props> {
|
||||
render() {
|
||||
const { t, permissionsUrl } = this.props;
|
||||
|
||||
// if (!this.hasPermissionToSetPermission()) {
|
||||
// return null;
|
||||
// }
|
||||
return <NavLink to={permissionsUrl} label={t("singleUser.menu.setPermissionsNavLink")} />;
|
||||
}
|
||||
|
||||
// hasPermissionToSetPermission = () => {
|
||||
// return this.props.user._links.permissions;
|
||||
// };
|
||||
}
|
||||
|
||||
export default translate("users")(ChangePermissionNavLink);
|
||||
@@ -0,0 +1,31 @@
|
||||
import React from "react";
|
||||
import { shallow } from "enzyme";
|
||||
import "../../../tests/enzyme";
|
||||
import "../../../tests/i18n";
|
||||
import SetPermissionsNavLink from "./RepositoryRoleDetailNavLink";
|
||||
|
||||
it("should render nothing, if the permissions link is missing", () => {
|
||||
const user = {
|
||||
_links: {}
|
||||
};
|
||||
|
||||
const navLink = shallow(
|
||||
<SetPermissionsNavLink user={user} permissionsUrl="/user/permissions" />
|
||||
);
|
||||
expect(navLink.text()).toBe("");
|
||||
});
|
||||
|
||||
it("should render the navLink", () => {
|
||||
const user = {
|
||||
_links: {
|
||||
permissions: {
|
||||
href: "/permissions"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const navLink = shallow(
|
||||
<SetPermissionsNavLink user={user} permissionsUrl="/user/permissions" />
|
||||
);
|
||||
expect(navLink.text()).not.toBe("");
|
||||
});
|
||||
2
scm-ui/src/config/components/navLinks/index.js
Normal file
2
scm-ui/src/config/components/navLinks/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default as EditRepositoryRoleNavLink } from "./EditRepositoryRoleNavLink";
|
||||
export { default as RepositoryRoleDetailNavLink } from "./RepositoryRoleDetailNavLink";
|
||||
@@ -15,7 +15,8 @@ class PermissionRoleRow extends React.Component<Props> {
|
||||
|
||||
render() {
|
||||
const { baseUrl, role } = this.props;
|
||||
const to = `${baseUrl}/${encodeURIComponent(role.name)}/edit`;
|
||||
const singleRoleUrl = baseUrl.substring(0, baseUrl.length - 1);
|
||||
const to = `${singleRoleUrl}/${encodeURIComponent(role.name)}`;
|
||||
return (
|
||||
<tr>
|
||||
<td>{this.renderLink(to, role.name)}</td>
|
||||
|
||||
@@ -10,8 +10,9 @@ 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 GlobalPermissionRoles from "./GlobalPermissionRoles";
|
||||
import GlobalPermissionRoleForm from "./GlobalPermissionRoleForm";
|
||||
import RepositoryRoles from "./RepositoryRoles";
|
||||
import RepositoryRoleForm from "./RepositoryRoleForm"
|
||||
import SingleRepositoryRole from "./SingleRepositoryRole";
|
||||
|
||||
type Props = {
|
||||
links: Links,
|
||||
@@ -57,13 +58,9 @@ class Config extends React.Component<Props> {
|
||||
<Route
|
||||
path={`${url}/roles`}
|
||||
exact
|
||||
render={() => (
|
||||
<GlobalPermissionRoles
|
||||
baseUrl={`${url}/role`}
|
||||
/>
|
||||
)}
|
||||
render={() => <RepositoryRoles baseUrl={`${url}/roles`} />}
|
||||
/>
|
||||
<Route path={`${url}/role`} component={GlobalPermissionRoleForm} />
|
||||
<Route path={`${url}/role`} component={SingleRepositoryRole} />
|
||||
<ExtensionPoint
|
||||
name="config.route"
|
||||
props={extensionProps}
|
||||
|
||||
@@ -6,12 +6,13 @@ 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 { getRepositoryVerbsLink } from "../../modules/indexResource";
|
||||
import {getRepositoryRolesLink, getRepositoryVerbsLink} from "../../modules/indexResource";
|
||||
|
||||
type Props = {
|
||||
role?: Role,
|
||||
@@ -24,14 +25,15 @@ type Props = {
|
||||
t: string => string,
|
||||
|
||||
// dispatch functions
|
||||
fetchAvailableVerbs: (link: string) => void
|
||||
fetchAvailableVerbs: (link: string) => void,
|
||||
addRole: (link: string, role: Role) => void
|
||||
};
|
||||
|
||||
type State = {
|
||||
role: Role
|
||||
};
|
||||
|
||||
class GlobalPermissionRoleForm extends React.Component<Props, State> {
|
||||
class RepositoryRoleForm extends React.Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
@@ -46,17 +48,8 @@ class GlobalPermissionRoleForm extends React.Component<Props, State> {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { fetchAvailableVerbs, verbsLink, role } = this.props;
|
||||
const { fetchAvailableVerbs, verbsLink} = this.props;
|
||||
fetchAvailableVerbs(verbsLink);
|
||||
|
||||
if (role) {
|
||||
this.setState({
|
||||
role: {
|
||||
...role,
|
||||
role: { verbs: role.verbs }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
isFalsy(value) {
|
||||
@@ -100,8 +93,7 @@ class GlobalPermissionRoleForm extends React.Component<Props, State> {
|
||||
submit = (event: Event) => {
|
||||
event.preventDefault();
|
||||
if (this.isValid()) {
|
||||
// this.props.submitForm(this.state.role);
|
||||
//TODO ADD createRole here
|
||||
this.props.addRole(this.props.repositoryRolesLink, this.state.role)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -155,12 +147,14 @@ const mapStateToProps = (state, ownProps) => {
|
||||
const error = getFetchVerbsFailure(state);
|
||||
const verbsLink = getRepositoryVerbsLink(state);
|
||||
const availableVerbs = getVerbsFromState(state);
|
||||
const repositoryRolesLink = getRepositoryRolesLink(state);
|
||||
|
||||
return {
|
||||
loading,
|
||||
error,
|
||||
verbsLink,
|
||||
availableVerbs
|
||||
availableVerbs,
|
||||
repositoryRolesLink
|
||||
};
|
||||
};
|
||||
|
||||
@@ -168,6 +162,9 @@ const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
fetchAvailableVerbs: (link: string) => {
|
||||
dispatch(fetchAvailableVerbs(link));
|
||||
},
|
||||
addRole: (link: string, role: Role) => {
|
||||
createRole(link, role)
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -175,4 +172,4 @@ const mapDispatchToProps = dispatch => {
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(translate("roles")(GlobalPermissionRoleForm));
|
||||
)(translate("roles")(RepositoryRoleForm));
|
||||
@@ -41,7 +41,7 @@ type Props = {
|
||||
fetchRolesByPage: (link: string, page: number) => void
|
||||
};
|
||||
|
||||
class GlobalPermissionRoles extends React.Component<Props> {
|
||||
class RepositoryRoles extends React.Component<Props> {
|
||||
componentDidMount() {
|
||||
const { fetchRolesByPage, rolesLink, page } = this.props;
|
||||
fetchRolesByPage(rolesLink, page);
|
||||
@@ -119,4 +119,4 @@ const mapDispatchToProps = dispatch => {
|
||||
export default withRouter(connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(translate("config")(GlobalPermissionRoles)));
|
||||
)(translate("config")(RepositoryRoles)));
|
||||
121
scm-ui/src/config/containers/SingleRepositoryRole.js
Normal file
121
scm-ui/src/config/containers/SingleRepositoryRole.js
Normal file
@@ -0,0 +1,121 @@
|
||||
//@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));
|
||||
Reference in New Issue
Block a user