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() {
|
render() {
|
||||||
const { baseUrl, role } = this.props;
|
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 (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
<td>{this.renderLink(to, role.name)}</td>
|
<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 { Page, Navigation, NavLink, Section } from "@scm-manager/ui-components";
|
||||||
import { getLinks } from "../../modules/indexResource";
|
import { getLinks } from "../../modules/indexResource";
|
||||||
import GlobalConfig from "./GlobalConfig";
|
import GlobalConfig from "./GlobalConfig";
|
||||||
import GlobalPermissionRoles from "./GlobalPermissionRoles";
|
import RepositoryRoles from "./RepositoryRoles";
|
||||||
import GlobalPermissionRoleForm from "./GlobalPermissionRoleForm";
|
import RepositoryRoleForm from "./RepositoryRoleForm"
|
||||||
|
import SingleRepositoryRole from "./SingleRepositoryRole";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
links: Links,
|
links: Links,
|
||||||
@@ -57,13 +58,9 @@ class Config extends React.Component<Props> {
|
|||||||
<Route
|
<Route
|
||||||
path={`${url}/roles`}
|
path={`${url}/roles`}
|
||||||
exact
|
exact
|
||||||
render={() => (
|
render={() => <RepositoryRoles baseUrl={`${url}/roles`} />}
|
||||||
<GlobalPermissionRoles
|
|
||||||
baseUrl={`${url}/role`}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
<Route path={`${url}/role`} component={GlobalPermissionRoleForm} />
|
<Route path={`${url}/role`} component={SingleRepositoryRole} />
|
||||||
<ExtensionPoint
|
<ExtensionPoint
|
||||||
name="config.route"
|
name="config.route"
|
||||||
props={extensionProps}
|
props={extensionProps}
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ import type { Role } from "@scm-manager/ui-types";
|
|||||||
import { InputField, SubmitButton } from "@scm-manager/ui-components";
|
import { InputField, SubmitButton } from "@scm-manager/ui-components";
|
||||||
import PermissionCheckbox from "../../repos/permissions/components/PermissionCheckbox";
|
import PermissionCheckbox from "../../repos/permissions/components/PermissionCheckbox";
|
||||||
import {
|
import {
|
||||||
|
createRole,
|
||||||
fetchAvailableVerbs,
|
fetchAvailableVerbs,
|
||||||
getFetchVerbsFailure,
|
getFetchVerbsFailure,
|
||||||
getVerbsFromState,
|
getVerbsFromState,
|
||||||
isFetchVerbsPending
|
isFetchVerbsPending
|
||||||
} from "../modules/roles";
|
} from "../modules/roles";
|
||||||
import { getRepositoryVerbsLink } from "../../modules/indexResource";
|
import {getRepositoryRolesLink, getRepositoryVerbsLink} from "../../modules/indexResource";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
role?: Role,
|
role?: Role,
|
||||||
@@ -24,14 +25,15 @@ type Props = {
|
|||||||
t: string => string,
|
t: string => string,
|
||||||
|
|
||||||
// dispatch functions
|
// dispatch functions
|
||||||
fetchAvailableVerbs: (link: string) => void
|
fetchAvailableVerbs: (link: string) => void,
|
||||||
|
addRole: (link: string, role: Role) => void
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
role: Role
|
role: Role
|
||||||
};
|
};
|
||||||
|
|
||||||
class GlobalPermissionRoleForm extends React.Component<Props, State> {
|
class RepositoryRoleForm extends React.Component<Props, State> {
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@@ -46,17 +48,8 @@ class GlobalPermissionRoleForm extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { fetchAvailableVerbs, verbsLink, role } = this.props;
|
const { fetchAvailableVerbs, verbsLink} = this.props;
|
||||||
fetchAvailableVerbs(verbsLink);
|
fetchAvailableVerbs(verbsLink);
|
||||||
|
|
||||||
if (role) {
|
|
||||||
this.setState({
|
|
||||||
role: {
|
|
||||||
...role,
|
|
||||||
role: { verbs: role.verbs }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isFalsy(value) {
|
isFalsy(value) {
|
||||||
@@ -100,8 +93,7 @@ class GlobalPermissionRoleForm extends React.Component<Props, State> {
|
|||||||
submit = (event: Event) => {
|
submit = (event: Event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (this.isValid()) {
|
if (this.isValid()) {
|
||||||
// this.props.submitForm(this.state.role);
|
this.props.addRole(this.props.repositoryRolesLink, this.state.role)
|
||||||
//TODO ADD createRole here
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -155,12 +147,14 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
const error = getFetchVerbsFailure(state);
|
const error = getFetchVerbsFailure(state);
|
||||||
const verbsLink = getRepositoryVerbsLink(state);
|
const verbsLink = getRepositoryVerbsLink(state);
|
||||||
const availableVerbs = getVerbsFromState(state);
|
const availableVerbs = getVerbsFromState(state);
|
||||||
|
const repositoryRolesLink = getRepositoryRolesLink(state);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
loading,
|
loading,
|
||||||
error,
|
error,
|
||||||
verbsLink,
|
verbsLink,
|
||||||
availableVerbs
|
availableVerbs,
|
||||||
|
repositoryRolesLink
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -168,6 +162,9 @@ const mapDispatchToProps = dispatch => {
|
|||||||
return {
|
return {
|
||||||
fetchAvailableVerbs: (link: string) => {
|
fetchAvailableVerbs: (link: string) => {
|
||||||
dispatch(fetchAvailableVerbs(link));
|
dispatch(fetchAvailableVerbs(link));
|
||||||
|
},
|
||||||
|
addRole: (link: string, role: Role) => {
|
||||||
|
createRole(link, role)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -175,4 +172,4 @@ const mapDispatchToProps = dispatch => {
|
|||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
mapDispatchToProps
|
||||||
)(translate("roles")(GlobalPermissionRoleForm));
|
)(translate("roles")(RepositoryRoleForm));
|
||||||
@@ -41,7 +41,7 @@ type Props = {
|
|||||||
fetchRolesByPage: (link: string, page: number) => void
|
fetchRolesByPage: (link: string, page: number) => void
|
||||||
};
|
};
|
||||||
|
|
||||||
class GlobalPermissionRoles extends React.Component<Props> {
|
class RepositoryRoles extends React.Component<Props> {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { fetchRolesByPage, rolesLink, page } = this.props;
|
const { fetchRolesByPage, rolesLink, page } = this.props;
|
||||||
fetchRolesByPage(rolesLink, page);
|
fetchRolesByPage(rolesLink, page);
|
||||||
@@ -119,4 +119,4 @@ const mapDispatchToProps = dispatch => {
|
|||||||
export default withRouter(connect(
|
export default withRouter(connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
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