From 8fd034d599a38fdde3defadd61ee181abd8015f9 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Wed, 15 May 2019 13:13:48 +0200 Subject: [PATCH 01/26] refactor / new structure for repositoryRoles --- .../navLinks/EditRepositoryRoleNavLink.js | 28 ++++ .../EditRepositoryRoleNavLink.test.js | 27 ++++ .../navLinks/RepositoryRoleDetailNavLink.js | 28 ++++ .../RepositoryRoleDetailNavLink.test.js | 31 +++++ .../src/config/components/navLinks/index.js | 2 + .../components/table/PermissionRoleRow.js | 3 +- scm-ui/src/config/containers/Config.js | 13 +- ...ssionRoleForm.js => RepositoryRoleForm.js} | 31 ++--- ...lPermissionRoles.js => RepositoryRoles.js} | 4 +- .../config/containers/SingleRepositoryRole.js | 121 ++++++++++++++++++ 10 files changed, 260 insertions(+), 28 deletions(-) create mode 100644 scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.js create mode 100644 scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.test.js create mode 100644 scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.js create mode 100644 scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.test.js create mode 100644 scm-ui/src/config/components/navLinks/index.js rename scm-ui/src/config/containers/{GlobalPermissionRoleForm.js => RepositoryRoleForm.js} (84%) rename scm-ui/src/config/containers/{GlobalPermissionRoles.js => RepositoryRoles.js} (96%) create mode 100644 scm-ui/src/config/containers/SingleRepositoryRole.js diff --git a/scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.js b/scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.js new file mode 100644 index 0000000000..419ca330cc --- /dev/null +++ b/scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.js @@ -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 { + isEditable = () => { + return this.props.user._links.update; + }; + + render() { + const { t, editUrl } = this.props; + + if (!this.isEditable()) { + return null; + } + return ; + } +} + +export default translate("users")(EditRepositoryRoleNavLink); diff --git a/scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.test.js b/scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.test.js new file mode 100644 index 0000000000..7e86e9bcda --- /dev/null +++ b/scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.test.js @@ -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(); + expect(navLink.text()).toBe(""); +}); + +it("should render the navLink", () => { + const user = { + _links: { + update: { + href: "/users" + } + } + }; + + const navLink = shallow(); + expect(navLink.text()).not.toBe(""); +}); diff --git a/scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.js b/scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.js new file mode 100644 index 0000000000..cc04aa6b50 --- /dev/null +++ b/scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.js @@ -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 { + render() { + const { t, permissionsUrl } = this.props; + + // if (!this.hasPermissionToSetPermission()) { + // return null; + // } + return ; + } + + // hasPermissionToSetPermission = () => { + // return this.props.user._links.permissions; + // }; +} + +export default translate("users")(ChangePermissionNavLink); diff --git a/scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.test.js b/scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.test.js new file mode 100644 index 0000000000..8cf5231387 --- /dev/null +++ b/scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.test.js @@ -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( + + ); + expect(navLink.text()).toBe(""); +}); + +it("should render the navLink", () => { + const user = { + _links: { + permissions: { + href: "/permissions" + } + } + }; + + const navLink = shallow( + + ); + expect(navLink.text()).not.toBe(""); +}); diff --git a/scm-ui/src/config/components/navLinks/index.js b/scm-ui/src/config/components/navLinks/index.js new file mode 100644 index 0000000000..7fafde676d --- /dev/null +++ b/scm-ui/src/config/components/navLinks/index.js @@ -0,0 +1,2 @@ +export { default as EditRepositoryRoleNavLink } from "./EditRepositoryRoleNavLink"; +export { default as RepositoryRoleDetailNavLink } from "./RepositoryRoleDetailNavLink"; diff --git a/scm-ui/src/config/components/table/PermissionRoleRow.js b/scm-ui/src/config/components/table/PermissionRoleRow.js index f42627540c..73a2cbc05c 100644 --- a/scm-ui/src/config/components/table/PermissionRoleRow.js +++ b/scm-ui/src/config/components/table/PermissionRoleRow.js @@ -15,7 +15,8 @@ class PermissionRoleRow extends React.Component { 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 ( {this.renderLink(to, role.name)} diff --git a/scm-ui/src/config/containers/Config.js b/scm-ui/src/config/containers/Config.js index ee973cf64b..38b5401926 100644 --- a/scm-ui/src/config/containers/Config.js +++ b/scm-ui/src/config/containers/Config.js @@ -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 { ( - - )} + render={() => } /> - + 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 { +class RepositoryRoleForm extends React.Component { constructor(props: Props) { super(props); @@ -46,17 +48,8 @@ class GlobalPermissionRoleForm extends React.Component { } 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 { 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)); diff --git a/scm-ui/src/config/containers/GlobalPermissionRoles.js b/scm-ui/src/config/containers/RepositoryRoles.js similarity index 96% rename from scm-ui/src/config/containers/GlobalPermissionRoles.js rename to scm-ui/src/config/containers/RepositoryRoles.js index 2691bf3988..41cbd11bf5 100644 --- a/scm-ui/src/config/containers/GlobalPermissionRoles.js +++ b/scm-ui/src/config/containers/RepositoryRoles.js @@ -41,7 +41,7 @@ type Props = { fetchRolesByPage: (link: string, page: number) => void }; -class GlobalPermissionRoles extends React.Component { +class RepositoryRoles extends React.Component { 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))); diff --git a/scm-ui/src/config/containers/SingleRepositoryRole.js b/scm-ui/src/config/containers/SingleRepositoryRole.js new file mode 100644 index 0000000000..dcdba90b31 --- /dev/null +++ b/scm-ui/src/config/containers/SingleRepositoryRole.js @@ -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 { + 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 ( + + ); + } + + if (!role || loading) { + return ; + } + + const url = this.matchedUrl(); + + const extensionProps = { + role, + url + }; + + return ( + +
+
+ } /> + } + /> + +
+
+
+ ); + } +} + +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)); From dabba5a091df12dd0e8ac6a2160453fef14d0b00 Mon Sep 17 00:00:00 2001 From: Florian Scholdei Date: Wed, 15 May 2019 14:35:05 +0200 Subject: [PATCH 02/26] remove redundancy, run prettier --- scm-ui/src/repos/branches/modules/branches.js | 5 ++-- scm-ui/src/repos/modules/changesets.js | 19 ++++++++++---- scm-ui/src/repos/modules/repos.js | 4 +-- scm-ui/src/repos/modules/repositoryTypes.js | 5 +--- .../repos/permissions/modules/permissions.js | 26 +++++++++++++------ 5 files changed, 36 insertions(+), 23 deletions(-) diff --git a/scm-ui/src/repos/branches/modules/branches.js b/scm-ui/src/repos/branches/modules/branches.js index 40228eac91..7886a0fcbf 100644 --- a/scm-ui/src/repos/branches/modules/branches.js +++ b/scm-ui/src/repos/branches/modules/branches.js @@ -307,10 +307,9 @@ const reduceByBranchesSuccess = (state, payload) => { const byName = repoState.byName || {}; repoState.byName = byName; - if(response._embedded) { + if (response._embedded) { const branches = response._embedded.branches; - const names = branches.map(b => b.name); - response._embedded.branches = names; + response._embedded.branches = branches.map(b => b.name); for (let branch of branches) { byName[branch.name] = branch; } diff --git a/scm-ui/src/repos/modules/changesets.js b/scm-ui/src/repos/modules/changesets.js index 80c405f5de..3cd617ac56 100644 --- a/scm-ui/src/repos/modules/changesets.js +++ b/scm-ui/src/repos/modules/changesets.js @@ -1,10 +1,19 @@ // @flow -import {FAILURE_SUFFIX, PENDING_SUFFIX, SUCCESS_SUFFIX} from "../../modules/types"; -import {apiClient, urls} from "@scm-manager/ui-components"; -import {isPending} from "../../modules/pending"; -import {getFailure} from "../../modules/failure"; -import type {Action, Branch, PagedCollection, Repository} from "@scm-manager/ui-types"; +import { + FAILURE_SUFFIX, + PENDING_SUFFIX, + SUCCESS_SUFFIX +} from "../../modules/types"; +import { apiClient, urls } from "@scm-manager/ui-components"; +import { isPending } from "../../modules/pending"; +import { getFailure } from "../../modules/failure"; +import type { + Action, + Branch, + PagedCollection, + Repository +} from "@scm-manager/ui-types"; export const FETCH_CHANGESETS = "scm/repos/FETCH_CHANGESETS"; export const FETCH_CHANGESETS_PENDING = `${FETCH_CHANGESETS}_${PENDING_SUFFIX}`; diff --git a/scm-ui/src/repos/modules/repos.js b/scm-ui/src/repos/modules/repos.js index cd48f89fea..ae942e668b 100644 --- a/scm-ui/src/repos/modules/repos.js +++ b/scm-ui/src/repos/modules/repos.js @@ -353,15 +353,13 @@ function normalizeByNamespaceAndName( const reducerByNames = (state: Object, repository: Repository) => { const identifier = createIdentifier(repository); - const newState = { + return { ...state, byNames: { ...state.byNames, [identifier]: repository } }; - - return newState; }; export default function reducer( diff --git a/scm-ui/src/repos/modules/repositoryTypes.js b/scm-ui/src/repos/modules/repositoryTypes.js index d96d24b612..043ab04d68 100644 --- a/scm-ui/src/repos/modules/repositoryTypes.js +++ b/scm-ui/src/repos/modules/repositoryTypes.js @@ -49,10 +49,7 @@ export function shouldFetchRepositoryTypes(state: Object) { ) { return false; } - if (state.repositoryTypes && state.repositoryTypes.length > 0) { - return false; - } - return true; + return !(state.repositoryTypes && state.repositoryTypes.length > 0); } export function fetchRepositoryTypesPending(): Action { diff --git a/scm-ui/src/repos/permissions/modules/permissions.js b/scm-ui/src/repos/permissions/modules/permissions.js index 2b0263bf35..2aa9d139c5 100644 --- a/scm-ui/src/repos/permissions/modules/permissions.js +++ b/scm-ui/src/repos/permissions/modules/permissions.js @@ -77,10 +77,18 @@ const CONTENT_TYPE = "application/vnd.scmm-repositoryPermission+json"; // fetch available permissions -export function fetchAvailablePermissionsIfNeeded(repositoryRolesLink: string, repositoryVerbsLink: string) { +export function fetchAvailablePermissionsIfNeeded( + repositoryRolesLink: string, + repositoryVerbsLink: string +) { return function(dispatch: any, getState: () => Object) { if (shouldFetchAvailablePermissions(getState())) { - return fetchAvailablePermissions(dispatch, getState, repositoryRolesLink, repositoryVerbsLink); + return fetchAvailablePermissions( + dispatch, + getState, + repositoryRolesLink, + repositoryVerbsLink + ); } }; } @@ -97,7 +105,8 @@ export function fetchAvailablePermissions( .then(repositoryRoles => repositoryRoles.json()) .then(repositoryRoles => repositoryRoles._embedded.repositoryRoles) .then(repositoryRoles => { - return apiClient.get(repositoryVerbsLink) + return apiClient + .get(repositoryVerbsLink) .then(repositoryVerbs => repositoryVerbs.json()) .then(repositoryVerbs => repositoryVerbs.verbs) .then(repositoryVerbs => { @@ -577,8 +586,7 @@ export function getPermissionsOfRepo( repoName: string ) { if (state.permissions && state.permissions[namespace + "/" + repoName]) { - const permissions = state.permissions[namespace + "/" + repoName].entries; - return permissions; + return state.permissions[namespace + "/" + repoName].entries; } } @@ -739,9 +747,11 @@ export function findMatchingRoleName( if (!verbs) { return ""; } - const matchingRole = !! availableRoles && availableRoles.find(role => { - return equalVerbs(role.verbs, verbs); - }); + const matchingRole = + !!availableRoles && + availableRoles.find(role => { + return equalVerbs(role.verbs, verbs); + }); if (matchingRole) { return matchingRole.name; From 77d8a3ad21bb91224fbd025cf117fb92a8acee3e Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Wed, 15 May 2019 14:48:12 +0200 Subject: [PATCH 03/26] create Custom Repo Role --- scm-ui/src/config/containers/Config.js | 3 +- .../roles/containers/CreateRepositoryRole.js | 75 +++++++++++++++++++ .../roles/containers/RepositoryRoleForm.js | 15 ++-- .../roles/containers/SingleRepositoryRole.js | 1 + 4 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 scm-ui/src/config/roles/containers/CreateRepositoryRole.js diff --git a/scm-ui/src/config/containers/Config.js b/scm-ui/src/config/containers/Config.js index 75f26003d7..8c5a3b1fcc 100644 --- a/scm-ui/src/config/containers/Config.js +++ b/scm-ui/src/config/containers/Config.js @@ -12,6 +12,7 @@ import { getLinks } from "../../modules/indexResource"; import GlobalConfig from "./GlobalConfig"; import RepositoryRoles from "../roles/containers/RepositoryRoles"; import SingleRepositoryRole from "../roles/containers/SingleRepositoryRole"; +import CreateRepositoryRole from "../roles/containers/CreateRepositoryRole"; type Props = { links: Links, @@ -65,7 +66,7 @@ class Config extends React.Component { /> } + render={() => } /> void +}; + +class CreateRepositoryRole extends React.Component { + //Callback after dispatch + repositoryRoleCreated = (role: Role) => { + const { history } = this.props; + history.push("/role/" + role.name); + }; + + createRepositoryRole = (role: Role) => { + this.props.addRole(this.props.repositoryRolesLink, role, () => + this.repositoryRoleCreated(role) + ); + }; + + render() { + return ( + <> + this.createRepositoryRole(role)} + /> + + ); + } +} + +const mapStateToProps = (state, ownProps) => { + const loading = isFetchVerbsPending(state); + const error = getFetchVerbsFailure(state); + const verbsLink = getRepositoryVerbsLink(state); + const repositoryRolesLink = getRepositoryRolesLink(state); + + return { + loading, + error, + verbsLink, + repositoryRolesLink + }; +}; + +const mapDispatchToProps = dispatch => { + return { + addRole: (link: string, role: Role) => { + dispatch(createRole(link, role)); + } + }; +}; + +export default connect( + mapStateToProps, + mapDispatchToProps +)(translate("roles")(CreateRepositoryRole)); diff --git a/scm-ui/src/config/roles/containers/RepositoryRoleForm.js b/scm-ui/src/config/roles/containers/RepositoryRoleForm.js index 20f3faa713..0e0065ce16 100644 --- a/scm-ui/src/config/roles/containers/RepositoryRoleForm.js +++ b/scm-ui/src/config/roles/containers/RepositoryRoleForm.js @@ -20,13 +20,14 @@ type Props = { disabled: boolean, availableVerbs: string[], verbsLink: string, + submitForm: Role => void, // context objects t: string => string, // dispatch functions - fetchAvailableVerbs: (link: string) => void, - addRole: (link: string, role: Role) => void + fetchAvailableVerbs: (link: string) => void + // addRole: (link: string, role: Role) => void }; type State = { @@ -93,7 +94,7 @@ class RepositoryRoleForm extends React.Component { submit = (event: Event) => { event.preventDefault(); if (this.isValid()) { - this.props.addRole(this.props.repositoryRolesLink, this.state.role) + this.props.submitForm(this.state.role) } }; @@ -122,7 +123,7 @@ class RepositoryRoleForm extends React.Component { label={t("roles.create.name")} onChange={this.handleNameChange} value={role.name ? role.name : ""} - disabled={!!role.name || disabled} + disabled={disabled} /> @@ -163,9 +164,9 @@ const mapDispatchToProps = dispatch => { fetchAvailableVerbs: (link: string) => { dispatch(fetchAvailableVerbs(link)); }, - addRole: (link: string, role: Role) => { - createRole(link, role) - } + // addRole: (link: string, role: Role) => { + // createRole(link, role) + // } }; }; diff --git a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js index e1aa171152..f39d55ab77 100644 --- a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js @@ -21,6 +21,7 @@ type Props = { loading: boolean, error: Error, repositoryRolesLink: string, + disabled: boolean, // dispatcher function fetchRoleByName: (string, string) => void, From 8ebd720f8ef0afbd99462e75089321609ccaf96f Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Wed, 15 May 2019 15:21:43 +0200 Subject: [PATCH 04/26] prepare RepoRoleDetailsView --- .../roles/components/PermissionRoleRow.js | 3 ++- .../roles/containers/SingleRepositoryRole.js | 24 +++++++++++-------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/scm-ui/src/config/roles/components/PermissionRoleRow.js b/scm-ui/src/config/roles/components/PermissionRoleRow.js index ba38fc5c4e..9f06eb56de 100644 --- a/scm-ui/src/config/roles/components/PermissionRoleRow.js +++ b/scm-ui/src/config/roles/components/PermissionRoleRow.js @@ -20,7 +20,8 @@ class PermissionRoleRow extends React.Component { render() { const { baseUrl, role } = this.props; - const to = `${baseUrl}/${encodeURIComponent(role.name)}/info`; + const singleRepoRoleUrl = baseUrl.substring(0, baseUrl.length - 1); + const to = `${singleRepoRoleUrl}/${encodeURIComponent(role.name)}/info`; return ( {this.renderLink(to, role.name, !role._links.update)} diff --git a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js index f39d55ab77..cc4e94cdd0 100644 --- a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js @@ -14,9 +14,12 @@ 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"; +import RepositoryRoleForm from "./RepositoryRoleForm"; +import {withRouter} from "react-router-dom"; +import PermissionRoleDetail from "../components/PermissionRoleDetail"; type Props = { - name: string, + roleName: string, role: Role, loading: boolean, error: Error, @@ -34,7 +37,8 @@ type Props = { class SingleRepositoryRole extends React.Component { componentDidMount() { - this.props.fetchRoleByName(this.props.repositoryRolesLink, this.props.name); + this.props.fetchRoleByName(this.props.repositoryRolesLink, this.props.roleName); + console.log(this.props.match) } stripEndingSlash = (url: string) => { @@ -76,7 +80,7 @@ class SingleRepositoryRole extends React.Component {
- } /> + } /> } @@ -94,14 +98,14 @@ class SingleRepositoryRole extends React.Component { } 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 roleName = ownProps.match.params.role; + const role = getRoleByName(state, roleName); + const loading = isFetchRolePending(state, roleName); + const error = getFetchRoleFailure(state, roleName); const repositoryRolesLink = getRepositoryRolesLink(state); return { repositoryRolesLink, - name, + roleName, role, loading, error @@ -116,7 +120,7 @@ const mapDispatchToProps = dispatch => { }; }; -export default connect( +export default withRouter(connect( mapStateToProps, mapDispatchToProps -)(translate("users")(SingleRepositoryRole)); +)(translate("users")(SingleRepositoryRole))); From 42bc84a6a5117ee563ec0dcb75e3fa8cf55df266 Mon Sep 17 00:00:00 2001 From: Florian Scholdei Date: Wed, 15 May 2019 15:48:02 +0200 Subject: [PATCH 05/26] add role to RepositoryPermissions ui-type and local state in CreatePermissionForm --- .../packages/ui-components/src/buttons/Button.js | 2 ++ .../packages/ui-types/src/RepositoryPermissions.js | 13 +++++++------ .../permissions/containers/CreatePermissionForm.js | 14 ++++++++------ 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/scm-ui-components/packages/ui-components/src/buttons/Button.js b/scm-ui-components/packages/ui-components/src/buttons/Button.js index 2102bb540a..5e80db1e45 100644 --- a/scm-ui-components/packages/ui-components/src/buttons/Button.js +++ b/scm-ui-components/packages/ui-components/src/buttons/Button.js @@ -12,6 +12,8 @@ export type ButtonProps = { fullWidth?: boolean, className?: string, children?: React.Node, + + // context props classes: any }; diff --git a/scm-ui-components/packages/ui-types/src/RepositoryPermissions.js b/scm-ui-components/packages/ui-types/src/RepositoryPermissions.js index ed3c925283..fe8cb3fd44 100644 --- a/scm-ui-components/packages/ui-types/src/RepositoryPermissions.js +++ b/scm-ui-components/packages/ui-types/src/RepositoryPermissions.js @@ -1,14 +1,15 @@ //@flow import type {Links} from "./hal"; +export type PermissionCreateEntry = { + name: string, + role?: string, + verbs: string[], + groupPermission: boolean +} + export type Permission = PermissionCreateEntry & { _links: Links }; -export type PermissionCreateEntry = { - name: string, - verbs: string[], - groupPermission: boolean -} - export type PermissionCollection = Permission[]; diff --git a/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js b/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js index 94fc707dc1..6f66867d99 100644 --- a/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js +++ b/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js @@ -32,6 +32,7 @@ type Props = { type State = { name: string, + role?: string, verbs: string[], groupPermission: boolean, valid: boolean, @@ -45,6 +46,7 @@ class CreatePermissionForm extends React.Component { this.state = { name: "", + role: props.availableRoles[0].name, verbs: props.availableRoles[0].verbs, groupPermission: false, valid: true, @@ -137,9 +139,7 @@ class CreatePermissionForm extends React.Component { const { verbs, showAdvancedDialog } = this.state; - const availableRoleNames = availableRoles.map( - r => r.name - ); + const availableRoleNames = availableRoles.map(r => r.name); const matchingRole = findMatchingRoleName(availableRoles, verbs); const advancedDialog = showAdvancedDialog ? ( @@ -230,6 +230,7 @@ class CreatePermissionForm extends React.Component { submitAdvancedPermissionsDialog = (newVerbs: string[]) => { this.setState({ showAdvancedDialog: false, + role: undefined, verbs: newVerbs }); }; @@ -237,6 +238,7 @@ class CreatePermissionForm extends React.Component { submit = e => { this.props.createPermission({ name: this.state.name, + role: this.state.role, verbs: this.state.verbs, groupPermission: this.state.groupPermission }); @@ -247,6 +249,7 @@ class CreatePermissionForm extends React.Component { removeState = () => { this.setState({ name: "", + role: undefined, verbs: this.props.availableRoles[0].verbs, valid: true, value: undefined @@ -259,14 +262,13 @@ class CreatePermissionForm extends React.Component { return; } this.setState({ + role: selectedRole.name, verbs: selectedRole.verbs }); }; findAvailableRole = (roleName: string) => { - return this.props.availableRoles.find( - role => role.name === roleName - ); + return this.props.availableRoles.find(role => role.name === roleName); }; } From a028e874b4f49cf7c65024281c0f2369c592b1c7 Mon Sep 17 00:00:00 2001 From: Florian Scholdei Date: Wed, 15 May 2019 15:48:38 +0200 Subject: [PATCH 06/26] add missing de translation --- scm-ui/public/locales/de/config.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scm-ui/public/locales/de/config.json b/scm-ui/public/locales/de/config.json index cfa610042f..cc1847b184 100644 --- a/scm-ui/public/locales/de/config.json +++ b/scm-ui/public/locales/de/config.json @@ -10,7 +10,6 @@ "navLink": "Berechtigungsrollen", "title": "Berechtigungsrollen", "noPermissionRoles": "Keine Berechtigungsrollen gefunden.", - "system": "System", "createButton": "Berechtigungsrolle erstellen", "form": { "subtitle": "Berechtigungsrolle bearbeiten", @@ -19,6 +18,10 @@ "submit": "Speichern" } }, + "role": { + "name": "Name", + "system": "System" + }, "config-form": { "submit": "Speichern", "submit-success-notification": "Einstellungen wurden erfolgreich geƤndert!", From 52b01e9a9d266f9d5759ce132789a630143d9e85 Mon Sep 17 00:00:00 2001 From: Florian Scholdei Date: Wed, 15 May 2019 15:52:16 +0200 Subject: [PATCH 07/26] add missing props and definitions --- .../permissions/containers/Permissions.js | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/scm-ui/src/repos/permissions/containers/Permissions.js b/scm-ui/src/repos/permissions/containers/Permissions.js index 02c43d254c..eff984ad5d 100644 --- a/scm-ui/src/repos/permissions/containers/Permissions.js +++ b/scm-ui/src/repos/permissions/containers/Permissions.js @@ -19,7 +19,9 @@ import { getDeletePermissionsFailure, getModifyPermissionsFailure, modifyPermissionReset, - deletePermissionReset, getAvailableRepositoryRoles, getAvailableRepositoryVerbs + deletePermissionReset, + getAvailableRepositoryRoles, + getAvailableRepositoryVerbs } from "../modules/permissions"; import { Loading, @@ -38,11 +40,14 @@ import CreatePermissionForm from "./CreatePermissionForm"; import type { History } from "history"; import { getPermissionsLink } from "../../modules/repos"; import { - getGroupAutoCompleteLink, getRepositoryRolesLink, getRepositoryVerbsLink, + getGroupAutoCompleteLink, + getRepositoryRolesLink, + getRepositoryVerbsLink, getUserAutoCompleteLink } from "../../../modules/indexResource"; type Props = { + availablePermissions: boolean, availableRepositoryRoles: RepositoryRole[], availableVerbs: string[], namespace: string, @@ -59,7 +64,10 @@ type Props = { userAutoCompleteLink: string, //dispatch functions - fetchAvailablePermissionsIfNeeded: () => void, + fetchAvailablePermissionsIfNeeded: ( + repositoryRolesLink: string, + repositoryVerbsLink: string + ) => void, fetchPermissions: (link: string, namespace: string, repoName: string) => void, createPermission: ( link: string, @@ -77,7 +85,6 @@ type Props = { history: History }; - class Permissions extends React.Component { componentDidMount() { const { @@ -251,8 +258,16 @@ const mapDispatchToProps = dispatch => { fetchPermissions: (link: string, namespace: string, repoName: string) => { dispatch(fetchPermissions(link, namespace, repoName)); }, - fetchAvailablePermissionsIfNeeded: (repositoryRolesLink: string, repositoryVerbsLink: string) => { - dispatch(fetchAvailablePermissionsIfNeeded(repositoryRolesLink, repositoryVerbsLink)); + fetchAvailablePermissionsIfNeeded: ( + repositoryRolesLink: string, + repositoryVerbsLink: string + ) => { + dispatch( + fetchAvailablePermissionsIfNeeded( + repositoryRolesLink, + repositoryVerbsLink + ) + ); }, createPermission: ( link: string, From 6c627bfe005fce88226e11499be1316ec6ebd141 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Wed, 15 May 2019 16:41:14 +0200 Subject: [PATCH 08/26] update RepositoryRoleDetailsView --- .../roles/components/PermissionRoleDetail.js | 29 --------- .../roles/components/PermissionRoleDetails.js | 37 +++++++++++ .../components/PermissionRoleDetailsTable.js | 65 +++++++++++++++++++ .../roles/containers/SingleRepositoryRole.js | 55 +++++++++------- 4 files changed, 135 insertions(+), 51 deletions(-) delete mode 100644 scm-ui/src/config/roles/components/PermissionRoleDetail.js create mode 100644 scm-ui/src/config/roles/components/PermissionRoleDetails.js create mode 100644 scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js diff --git a/scm-ui/src/config/roles/components/PermissionRoleDetail.js b/scm-ui/src/config/roles/components/PermissionRoleDetail.js deleted file mode 100644 index 496443eef2..0000000000 --- a/scm-ui/src/config/roles/components/PermissionRoleDetail.js +++ /dev/null @@ -1,29 +0,0 @@ -//@flow -import React from "react"; -import { translate } from "react-i18next"; -import type { Role } from "@scm-manager/ui-types"; -import SystemRoleTag from "./SystemRoleTag"; - -type Props = { - role: Role, - - // context props - t: string => string, -}; - -class PermissionRoleDetail extends React.Component { - render() { - const { role, t } = this.props; - - return ( -
-
- {t("role.name")}: {role.name}{" "} - -
-
- ); - } -} - -export default translate("config")(PermissionRoleDetail); diff --git a/scm-ui/src/config/roles/components/PermissionRoleDetails.js b/scm-ui/src/config/roles/components/PermissionRoleDetails.js new file mode 100644 index 0000000000..f4793cf067 --- /dev/null +++ b/scm-ui/src/config/roles/components/PermissionRoleDetails.js @@ -0,0 +1,37 @@ +//@flow +import React from "react"; +import { translate } from "react-i18next"; +import type { Role } from "@scm-manager/ui-types"; +import ExtensionPoint from "@scm-manager/ui-extensions/lib/ExtensionPoint"; +import PermissionRoleDetailsTable from "./PermissionRoleDetailsTable"; + +type Props = { + role: Role, + + // context props + t: string => string, +}; + +class PermissionRoleDetails extends React.Component { + render() { + const { role } = this.props; + + return ( + +
+ +
+
+ +
+
+ + ); + } +} + +export default translate("roles")(PermissionRoleDetails); diff --git a/scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js b/scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js new file mode 100644 index 0000000000..a66b080adf --- /dev/null +++ b/scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js @@ -0,0 +1,65 @@ +//@flow +import React from "react"; +import type { Role } from "@scm-manager/ui-types"; +import { translate } from "react-i18next"; +import { compose } from "redux"; +import injectSheet from "react-jss"; + +type Props = { + role: Role, + // context props + t: string => string +}; + +const styles = { + spacing: { + padding: "0 !important" + } +}; + +class PermissionRoleDetailsTable extends React.Component { + render() { + const { role, t } = this.props; + return ( + + + + + + + + + + + {this.renderVerbs()} + +
{t("repositoryRole.name")}{role.name}
{t("repositoryRole.type")}{role.type}
+ ); + } + + renderVerbs() { + const { role, t, classes } = this.props; + + let verbs = null; + if (role.verbs.length > 0) { + verbs = ( + + {t("repositoryRole.verbs")} + +
    + {role.verbs.map(verb => { + return
  • {verb}
  • ; + })} +
+ + + ); + } + return verbs; + } +} + +export default compose( + injectSheet(styles), + translate("roles") +)(PermissionRoleDetailsTable); diff --git a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js index cc4e94cdd0..6c77bfd46b 100644 --- a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js @@ -1,22 +1,24 @@ //@flow import React from "react"; import { connect } from "react-redux"; -import { - Page, - Loading, - ErrorPage -} from "@scm-manager/ui-components"; +import {Loading, ErrorPage, Title} from "@scm-manager/ui-components"; import { Route } from "react-router"; import type { History } from "history"; -import { EditRepositoryRoleNavLink, RepositoryRoleDetailNavLink } from "../../components/navLinks"; +import { + EditRepositoryRoleNavLink, +} 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"; -import RepositoryRoleForm from "./RepositoryRoleForm"; -import {withRouter} from "react-router-dom"; -import PermissionRoleDetail from "../components/PermissionRoleDetail"; +import { getRepositoryRolesLink } from "../../../modules/indexResource"; +import { ExtensionPoint } from "@scm-manager/ui-extensions"; +import { + fetchRoleByName, + getFetchRoleFailure, + getRoleByName, + isFetchRolePending +} from "../modules/roles"; +import { withRouter } from "react-router-dom"; +import PermissionRoleDetail from "../components/PermissionRoleDetails"; type Props = { roleName: string, @@ -37,8 +39,11 @@ type Props = { class SingleRepositoryRole extends React.Component { componentDidMount() { - this.props.fetchRoleByName(this.props.repositoryRolesLink, this.props.roleName); - console.log(this.props.match) + this.props.fetchRoleByName( + this.props.repositoryRolesLink, + this.props.roleName + ); + console.log(this.props.match); } stripEndingSlash = (url: string) => { @@ -77,22 +82,26 @@ class SingleRepositoryRole extends React.Component { }; return ( - + <> + <div className="columns"> <div className="column is-three-quarters"> - <Route path={url} component={() => <PermissionRoleDetail role={role} />} /> + <Route + path={url} + component={() => <PermissionRoleDetail role={role} />} + /> <Route path={`${url}/settings/general`} component={() => <EditRepositoryRoleNavLink role={role} />} /> <ExtensionPoint - name="user.route" + name="roles.route" props={extensionProps} renderAll={true} /> </div> </div> - </Page> + </> ); } } @@ -120,7 +129,9 @@ const mapDispatchToProps = dispatch => { }; }; -export default withRouter(connect( - mapStateToProps, - mapDispatchToProps -)(translate("users")(SingleRepositoryRole))); +export default withRouter( + connect( + mapStateToProps, + mapDispatchToProps + )(translate("config")(SingleRepositoryRole)) +); From 60cf070c448b7ff8052ca263597128dc8b010a4b Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch <eduard.heimbuch@cloudogu.com> Date: Wed, 15 May 2019 16:57:28 +0200 Subject: [PATCH 09/26] refactor / enable routing after createRepoRole --- scm-ui/src/config/containers/Config.js | 2 +- .../config/roles/components/PermissionRoleDetails.js | 2 +- .../roles/components/PermissionRoleDetailsTable.js | 2 +- .../config/roles/containers/CreateRepositoryRole.js | 12 ++++++------ .../config/roles/containers/RepositoryRoleForm.js | 8 +------- 5 files changed, 10 insertions(+), 16 deletions(-) diff --git a/scm-ui/src/config/containers/Config.js b/scm-ui/src/config/containers/Config.js index 8c5a3b1fcc..63173c0b9b 100644 --- a/scm-ui/src/config/containers/Config.js +++ b/scm-ui/src/config/containers/Config.js @@ -66,7 +66,7 @@ class Config extends React.Component<Props> { /> <Route path={`${url}/roles/create`} - render={() => <CreateRepositoryRole disabled={false} />} + render={() => <CreateRepositoryRole disabled={false} history={this.props.history} />} /> <ExtensionPoint name="config.route" diff --git a/scm-ui/src/config/roles/components/PermissionRoleDetails.js b/scm-ui/src/config/roles/components/PermissionRoleDetails.js index f4793cf067..92dab08b86 100644 --- a/scm-ui/src/config/roles/components/PermissionRoleDetails.js +++ b/scm-ui/src/config/roles/components/PermissionRoleDetails.js @@ -34,4 +34,4 @@ class PermissionRoleDetails extends React.Component<Props> { } } -export default translate("roles")(PermissionRoleDetails); +export default translate("config")(PermissionRoleDetails); diff --git a/scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js b/scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js index a66b080adf..67d752fb8c 100644 --- a/scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js +++ b/scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js @@ -61,5 +61,5 @@ class PermissionRoleDetailsTable extends React.Component<Props> { export default compose( injectSheet(styles), - translate("roles") + translate("config") )(PermissionRoleDetailsTable); diff --git a/scm-ui/src/config/roles/containers/CreateRepositoryRole.js b/scm-ui/src/config/roles/containers/CreateRepositoryRole.js index 55c9eac10d..6592ff566a 100644 --- a/scm-ui/src/config/roles/containers/CreateRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/CreateRepositoryRole.js @@ -19,14 +19,14 @@ type Props = { repositoryRolesLink: string, //dispatch function - addRole: (link: string, role: Role) => void + addRole: (link: string, role: Role, callback?: () => void) => void }; class CreateRepositoryRole extends React.Component<Props> { - //Callback after dispatch + repositoryRoleCreated = (role: Role) => { const { history } = this.props; - history.push("/role/" + role.name); + history.push("/config/role/" + role.name); }; createRepositoryRole = (role: Role) => { @@ -63,8 +63,8 @@ const mapStateToProps = (state, ownProps) => { const mapDispatchToProps = dispatch => { return { - addRole: (link: string, role: Role) => { - dispatch(createRole(link, role)); + addRole: (link: string, role: Role, callback?: () => void) => { + dispatch(createRole(link, role, callback)); } }; }; @@ -72,4 +72,4 @@ const mapDispatchToProps = dispatch => { export default connect( mapStateToProps, mapDispatchToProps -)(translate("roles")(CreateRepositoryRole)); +)(translate("config")(CreateRepositoryRole)); diff --git a/scm-ui/src/config/roles/containers/RepositoryRoleForm.js b/scm-ui/src/config/roles/containers/RepositoryRoleForm.js index 0e0065ce16..e35c2f2c2f 100644 --- a/scm-ui/src/config/roles/containers/RepositoryRoleForm.js +++ b/scm-ui/src/config/roles/containers/RepositoryRoleForm.js @@ -6,7 +6,6 @@ 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, @@ -27,7 +26,6 @@ type Props = { // dispatch functions fetchAvailableVerbs: (link: string) => void - // addRole: (link: string, role: Role) => void }; type State = { @@ -107,7 +105,6 @@ class RepositoryRoleForm extends React.Component<Props, State> { : availableVerbs.map(verb => ( <PermissionCheckbox key={verb} - // disabled={readOnly} name={verb} checked={role.verbs.includes(verb)} onChange={this.handleVerbChange} @@ -164,13 +161,10 @@ const mapDispatchToProps = dispatch => { fetchAvailableVerbs: (link: string) => { dispatch(fetchAvailableVerbs(link)); }, - // addRole: (link: string, role: Role) => { - // createRole(link, role) - // } }; }; export default connect( mapStateToProps, mapDispatchToProps -)(translate("roles")(RepositoryRoleForm)); +)(translate("config")(RepositoryRoleForm)); From 3c44f9910f30440b39fb0f3db21a0d1c6c1c5cbc Mon Sep 17 00:00:00 2001 From: Florian Scholdei <florian.scholdei@cloudogu.com> Date: Wed, 15 May 2019 17:15:00 +0200 Subject: [PATCH 10/26] add translation for custom role selection --- scm-ui/public/locales/de/repos.json | 1 + scm-ui/public/locales/en/repos.json | 1 + 2 files changed, 2 insertions(+) diff --git a/scm-ui/public/locales/de/repos.json b/scm-ui/public/locales/de/repos.json index f4ee071613..4ba7a725e6 100644 --- a/scm-ui/public/locales/de/repos.json +++ b/scm-ui/public/locales/de/repos.json @@ -119,6 +119,7 @@ "error-subtitle": "Unbekannter Fehler bei Berechtigung", "name": "Benutzer oder Gruppe", "role": "Rolle", + "custom": "CUSTOM", "permissions": "Berechtigung", "group-permission": "Gruppenberechtigung", "user-permission": "Benutzerberechtigung", diff --git a/scm-ui/public/locales/en/repos.json b/scm-ui/public/locales/en/repos.json index 7344547d49..9a2e83f983 100644 --- a/scm-ui/public/locales/en/repos.json +++ b/scm-ui/public/locales/en/repos.json @@ -122,6 +122,7 @@ "error-subtitle": "Unknown permissions error", "name": "User or group", "role": "Role", + "custom": "CUSTOM", "permissions": "Permissions", "group-permission": "Group Permission", "user-permission": "User Permission", From 394c1f53d47ba0bdf2d5b91f18e5d70d9a8b777e Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch <eduard.heimbuch@cloudogu.com> Date: Wed, 15 May 2019 17:30:42 +0200 Subject: [PATCH 11/26] create EditRepoRoles --- .../roles/components/PermissionRoleDetails.js | 6 +- .../roles/containers/EditRepositoryRole.js | 71 +++++++++++++++++++ .../roles/containers/RepositoryRoleForm.js | 3 + .../roles/containers/SingleRepositoryRole.js | 37 +++++----- 4 files changed, 98 insertions(+), 19 deletions(-) create mode 100644 scm-ui/src/config/roles/containers/EditRepositoryRole.js diff --git a/scm-ui/src/config/roles/components/PermissionRoleDetails.js b/scm-ui/src/config/roles/components/PermissionRoleDetails.js index 92dab08b86..8ca21b1ac3 100644 --- a/scm-ui/src/config/roles/components/PermissionRoleDetails.js +++ b/scm-ui/src/config/roles/components/PermissionRoleDetails.js @@ -4,9 +4,11 @@ import { translate } from "react-i18next"; import type { Role } from "@scm-manager/ui-types"; import ExtensionPoint from "@scm-manager/ui-extensions/lib/ExtensionPoint"; import PermissionRoleDetailsTable from "./PermissionRoleDetailsTable"; +import {Button, Subtitle} from "@scm-manager/ui-components"; type Props = { role: Role, + url: string, // context props t: string => string, @@ -14,13 +16,15 @@ type Props = { class PermissionRoleDetails extends React.Component<Props> { render() { - const { role } = this.props; + const { role, url } = this.props; return ( <div> <PermissionRoleDetailsTable role={role}/> <hr/> + <Subtitle subtitle={"repositoryRoles.edit"}/> + <Button label={"test"} link={`${url}/edit`} color="primary" /> <div className="content"> <ExtensionPoint name="roles.repositoryRole-details.information" diff --git a/scm-ui/src/config/roles/containers/EditRepositoryRole.js b/scm-ui/src/config/roles/containers/EditRepositoryRole.js new file mode 100644 index 0000000000..f16db79dda --- /dev/null +++ b/scm-ui/src/config/roles/containers/EditRepositoryRole.js @@ -0,0 +1,71 @@ +// @flow +import React from "react"; +import RepositoryRoleForm from "./RepositoryRoleForm"; +import { connect } from "react-redux"; +import { translate } from "react-i18next"; +import { + getModifyRoleFailure, + isModifyRolePending, + modifyRole, +} from "../modules/roles"; +import type { Role } from "@scm-manager/ui-types"; + +type Props = { + disabled: boolean, + role: Role, + repositoryRolesLink: string, + + //dispatch function + updateRole: (link: string, role: Role, callback?: () => void) => void +}; + + + +class EditRepositoryRole extends React.Component<Props> { + + repositoryRoleUpdated = (role: Role) => { + const { history } = this.props; + history.push("/config/role/" + role.name); + }; + + updateRepositoryRole = (role: Role) => { + this.props.updateRole(role, () => + this.repositoryRoleUpdated(role) + ); + }; + + render() { + return ( + <> + <RepositoryRoleForm + disabled={false} + role={this.props.role} + submitForm={role => this.updateRepositoryRole(role)} + /> + </> + ); + } +} + +const mapStateToProps = (state, ownProps) => { + const loading = isModifyRolePending(state); + const error = getModifyRoleFailure(state); + + return { + loading, + error, + }; +}; + +const mapDispatchToProps = dispatch => { + return { + updateRole: (role: Role, callback?: () => void) => { + dispatch(modifyRole(role, callback)); + } + }; +}; + +export default connect( + mapStateToProps, + mapDispatchToProps +)(translate("config")(EditRepositoryRole)); diff --git a/scm-ui/src/config/roles/containers/RepositoryRoleForm.js b/scm-ui/src/config/roles/containers/RepositoryRoleForm.js index e35c2f2c2f..852e097e4a 100644 --- a/scm-ui/src/config/roles/containers/RepositoryRoleForm.js +++ b/scm-ui/src/config/roles/containers/RepositoryRoleForm.js @@ -49,6 +49,9 @@ class RepositoryRoleForm extends React.Component<Props, State> { componentDidMount() { const { fetchAvailableVerbs, verbsLink} = this.props; fetchAvailableVerbs(verbsLink); + if (this.props.role) { + this.setState({role: this.props.role}) + } } isFalsy(value) { diff --git a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js index 6c77bfd46b..6b4f48819a 100644 --- a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js @@ -1,12 +1,10 @@ //@flow import React from "react"; import { connect } from "react-redux"; -import {Loading, ErrorPage, Title} from "@scm-manager/ui-components"; +import { Loading, ErrorPage, Title } from "@scm-manager/ui-components"; import { Route } from "react-router"; import type { History } from "history"; -import { - EditRepositoryRoleNavLink, -} from "../../components/navLinks"; +import { EditRepositoryRoleNavLink } from "../../components/navLinks"; import { translate } from "react-i18next"; import type { Role } from "@scm-manager/ui-types"; import { getRepositoryRolesLink } from "../../../modules/indexResource"; @@ -19,6 +17,8 @@ import { } from "../modules/roles"; import { withRouter } from "react-router-dom"; import PermissionRoleDetail from "../components/PermissionRoleDetails"; +import EditRepositoryRole from "./EditRepositoryRole"; +import Switch from "react-router-dom/es/Switch"; type Props = { roleName: string, @@ -83,22 +83,23 @@ class SingleRepositoryRole extends React.Component<Props> { return ( <> - <Title title={t("repositoryRoles.title")}/> + <Title title={t("repositoryRoles.title")} /> <div className="columns"> <div className="column is-three-quarters"> - <Route - path={url} - component={() => <PermissionRoleDetail role={role} />} - /> - <Route - path={`${url}/settings/general`} - component={() => <EditRepositoryRoleNavLink role={role} />} - /> - <ExtensionPoint - name="roles.route" - props={extensionProps} - renderAll={true} - /> + <Route + path={url} + component={() => <PermissionRoleDetail role={role} url={url} />} + /> + <Route + path={`${url}`} + exact + component={() => <EditRepositoryRole role={role} />} + /> + <ExtensionPoint + name="roles.route" + props={extensionProps} + renderAll={true} + /> </div> </div> </> From 32d7eb87017417ccd6347077cec7c57f247e51e7 Mon Sep 17 00:00:00 2001 From: Florian Scholdei <florian.scholdei@cloudogu.com> Date: Wed, 15 May 2019 17:30:48 +0200 Subject: [PATCH 12/26] role-ready repositoryPermissionView --- .../ui-types/src/RepositoryPermissions.js | 2 +- .../containers/AdvancedPermissionsDialog.js | 6 +- .../containers/CreatePermissionForm.js | 39 +++++---- .../containers/SinglePermission.js | 80 +++++++++---------- .../repos/permissions/modules/permissions.js | 32 -------- 5 files changed, 61 insertions(+), 98 deletions(-) diff --git a/scm-ui-components/packages/ui-types/src/RepositoryPermissions.js b/scm-ui-components/packages/ui-types/src/RepositoryPermissions.js index fe8cb3fd44..14a2298fbe 100644 --- a/scm-ui-components/packages/ui-types/src/RepositoryPermissions.js +++ b/scm-ui-components/packages/ui-types/src/RepositoryPermissions.js @@ -4,7 +4,7 @@ import type {Links} from "./hal"; export type PermissionCreateEntry = { name: string, role?: string, - verbs: string[], + verbs?: string[], groupPermission: boolean } diff --git a/scm-ui/src/repos/permissions/containers/AdvancedPermissionsDialog.js b/scm-ui/src/repos/permissions/containers/AdvancedPermissionsDialog.js index cc662e5f06..d15b9112b9 100644 --- a/scm-ui/src/repos/permissions/containers/AdvancedPermissionsDialog.js +++ b/scm-ui/src/repos/permissions/containers/AdvancedPermissionsDialog.js @@ -26,9 +26,11 @@ class AdvancedPermissionsDialog extends React.Component<Props, State> { const verbs = {}; props.availableVerbs.forEach( - verb => (verbs[verb] = props.selectedVerbs.includes(verb)) + verb => + (verbs[verb] = props.selectedVerbs + ? props.selectedVerbs.includes(verb) + : false) ); - this.state = { verbs }; } diff --git a/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js b/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js index 6f66867d99..8ee1e7edbb 100644 --- a/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js +++ b/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js @@ -1,6 +1,12 @@ // @flow import React from "react"; import { translate } from "react-i18next"; +import type { + RepositoryRole, + PermissionCollection, + PermissionCreateEntry, + SelectValue +} from "@scm-manager/ui-types"; import { Autocomplete, SubmitButton, @@ -8,32 +14,27 @@ import { LabelWithHelpIcon, Radio } from "@scm-manager/ui-components"; -import RoleSelector from "../components/RoleSelector"; -import type { - RepositoryRole, - PermissionCollection, - PermissionCreateEntry, - SelectValue -} from "@scm-manager/ui-types"; import * as validator from "../components/permissionValidation"; -import { findMatchingRoleName } from "../modules/permissions"; +import RoleSelector from "../components/RoleSelector"; import AdvancedPermissionsDialog from "./AdvancedPermissionsDialog"; type Props = { - t: string => string, availableRoles: RepositoryRole[], availableVerbs: string[], createPermission: (permission: PermissionCreateEntry) => void, loading: boolean, currentPermissions: PermissionCollection, groupAutoCompleteLink: string, - userAutoCompleteLink: string + userAutoCompleteLink: string, + + // Context props + t: string => string }; type State = { name: string, role?: string, - verbs: string[], + verbs?: string[], groupPermission: boolean, valid: boolean, value?: SelectValue, @@ -47,7 +48,7 @@ class CreatePermissionForm extends React.Component<Props, State> { this.state = { name: "", role: props.availableRoles[0].name, - verbs: props.availableRoles[0].verbs, + verbs: undefined, groupPermission: false, valid: true, value: undefined, @@ -92,6 +93,7 @@ class CreatePermissionForm extends React.Component<Props, State> { }); }); } + renderAutocompletionField = () => { const { t } = this.props; if (this.state.groupPermission) { @@ -136,11 +138,9 @@ class CreatePermissionForm extends React.Component<Props, State> { render() { const { t, availableRoles, availableVerbs, loading } = this.props; - - const { verbs, showAdvancedDialog } = this.state; + const { role, verbs, showAdvancedDialog } = this.state; const availableRoleNames = availableRoles.map(r => r.name); - const matchingRole = findMatchingRoleName(availableRoles, verbs); const advancedDialog = showAdvancedDialog ? ( <AdvancedPermissionsDialog @@ -189,7 +189,7 @@ class CreatePermissionForm extends React.Component<Props, State> { label={t("permission.role")} helpText={t("permission.help.roleHelpText")} handleRoleChange={this.handleRoleChange} - role={matchingRole} + role={role} /> </div> <div className="column"> @@ -249,8 +249,8 @@ class CreatePermissionForm extends React.Component<Props, State> { removeState = () => { this.setState({ name: "", - role: undefined, - verbs: this.props.availableRoles[0].verbs, + role: this.props.availableRoles[0].name, + verbs: undefined, valid: true, value: undefined }); @@ -262,8 +262,7 @@ class CreatePermissionForm extends React.Component<Props, State> { return; } this.setState({ - role: selectedRole.name, - verbs: selectedRole.verbs + role: selectedRole.name }); }; diff --git a/scm-ui/src/repos/permissions/containers/SinglePermission.js b/scm-ui/src/repos/permissions/containers/SinglePermission.js index c90d6ab968..5fed0084a7 100644 --- a/scm-ui/src/repos/permissions/containers/SinglePermission.js +++ b/scm-ui/src/repos/permissions/containers/SinglePermission.js @@ -1,16 +1,12 @@ // @flow import React from "react"; -import type { - RepositoryRole, - Permission -} from "@scm-manager/ui-types"; +import type { RepositoryRole, Permission } from "@scm-manager/ui-types"; import { translate } from "react-i18next"; import { modifyPermission, isModifyPermissionPending, deletePermission, - isDeletePermissionPending, - findMatchingRoleName + isDeletePermissionPending } from "../modules/permissions"; import { connect } from "react-redux"; import type { History } from "history"; @@ -47,7 +43,6 @@ type Props = { }; type State = { - role: string, permission: Permission, showAdvancedDialog: boolean }; @@ -69,39 +64,34 @@ class SinglePermission extends React.Component<Props, State> { constructor(props: Props) { super(props); - const defaultPermission = props.availableRoles - ? props.availableRoles[0] + const defaultPermission = props.availableRepositoryRoles + ? props.availableRepositoryRoles[0] : {}; this.state = { permission: { name: "", + role: undefined, verbs: defaultPermission.verbs, groupPermission: false, _links: {} }, - role: defaultPermission.name, showAdvancedDialog: false }; } componentDidMount() { - const { availableRepositoryRoles, permission } = this.props; - - const matchingRole = findMatchingRoleName( - availableRepositoryRoles, - permission.verbs - ); + const { permission } = this.props; if (permission) { this.setState({ permission: { name: permission.name, + role: permission.role, verbs: permission.verbs, groupPermission: permission.groupPermission, _links: permission._links - }, - role: matchingRole + } }); } } @@ -115,7 +105,7 @@ class SinglePermission extends React.Component<Props, State> { }; render() { - const { role, permission, showAdvancedDialog } = this.state; + const { permission, showAdvancedDialog } = this.state; const { t, availableRepositoryRoles, @@ -125,18 +115,17 @@ class SinglePermission extends React.Component<Props, State> { repoName, classes } = this.props; - const availableRoleNames = !!availableRepositoryRoles && availableRepositoryRoles.map( - r => r.name - ); + const availableRoleNames = + !!availableRepositoryRoles && availableRepositoryRoles.map(r => r.name); const readOnly = !this.mayChangePermissions(); const roleSelector = readOnly ? ( - <td>{role}</td> + <td>{permission.role ? permission.role : t("permission.custom")}</td> ) : ( <td> <RoleSelector handleRoleChange={this.handleRoleChange} availableRoles={availableRoleNames} - role={role} + role={permission.role} loading={loading} /> </td> @@ -154,9 +143,15 @@ class SinglePermission extends React.Component<Props, State> { const iconType = permission && permission.groupPermission ? ( - <i title={t("permission.group")} className={classNames("fas fa-user-friends", classes.iconColor)} /> + <i + title={t("permission.group")} + className={classNames("fas fa-user-friends", classes.iconColor)} + /> ) : ( - <i title={t("permission.user")} className={classNames("fas fa-user", classes.iconColor)} /> + <i + title={t("permission.user")} + className={classNames("fas fa-user", classes.iconColor)} + /> ); return ( @@ -199,42 +194,41 @@ class SinglePermission extends React.Component<Props, State> { submitAdvancedPermissionsDialog = (newVerbs: string[]) => { const { permission } = this.state; - const newRole = findMatchingRoleName( - this.props.availableRoles, - newVerbs - ); this.setState( { showAdvancedDialog: false, - permission: { ...permission, verbs: newVerbs }, - role: newRole + permission: { ...permission, role: undefined, verbs: newVerbs } }, - () => this.modifyPermission(newVerbs) + () => this.modifyPermissionVerbs(newVerbs) ); }; handleRoleChange = (role: string) => { - const selectedRole = this.findAvailableRole(role); + const { permission } = this.state; this.setState( { - permission: { - ...this.state.permission, - verbs: selectedRole.verbs - }, - role: role + permission: { ...permission, role: role, verbs: undefined } }, - () => this.modifyPermission(selectedRole.verbs) + () => this.modifyPermissionRole(role) ); }; findAvailableRole = (roleName: string) => { const { availableRepositoryRoles } = this.props; - return availableRepositoryRoles.find( - role => role.name === roleName + return availableRepositoryRoles.find(role => role.name === roleName); + }; + + modifyPermissionRole = (role: string) => { + let permission = this.state.permission; + permission.role = role; + this.props.modifyPermission( + permission, + this.props.namespace, + this.props.repoName ); }; - modifyPermission = (verbs: string[]) => { + modifyPermissionVerbs = (verbs: string[]) => { let permission = this.state.permission; permission.verbs = verbs; this.props.modifyPermission( diff --git a/scm-ui/src/repos/permissions/modules/permissions.js b/scm-ui/src/repos/permissions/modules/permissions.js index 2aa9d139c5..abd25eb459 100644 --- a/scm-ui/src/repos/permissions/modules/permissions.js +++ b/scm-ui/src/repos/permissions/modules/permissions.js @@ -739,35 +739,3 @@ export function getModifyPermissionsFailure( } return null; } - -export function findMatchingRoleName( - availableRoles: RepositoryRole[], - verbs: string[] -) { - if (!verbs) { - return ""; - } - const matchingRole = - !!availableRoles && - availableRoles.find(role => { - return equalVerbs(role.verbs, verbs); - }); - - if (matchingRole) { - return matchingRole.name; - } else { - return ""; - } -} - -function equalVerbs(verbs1: string[], verbs2: string[]) { - if (!verbs1 || !verbs2) { - return false; - } - - if (verbs1.length !== verbs2.length) { - return false; - } - - return verbs1.every(verb => verbs2.includes(verb)); -} From a726005730c42f0f1905a0a5929fad12e1d1b744 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch <eduard.heimbuch@cloudogu.com> Date: Thu, 16 May 2019 08:38:26 +0200 Subject: [PATCH 13/26] update Translations --- scm-ui/public/locales/de/config.json | 12 +++++++++++- scm-ui/public/locales/en/config.json | 13 ++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/scm-ui/public/locales/de/config.json b/scm-ui/public/locales/de/config.json index cfa610042f..eff3efa718 100644 --- a/scm-ui/public/locales/de/config.json +++ b/scm-ui/public/locales/de/config.json @@ -6,12 +6,22 @@ "errorTitle": "Fehler", "errorSubtitle": "Unbekannter Einstellungen Fehler" }, - "roles": { + "repositoryRole": { "navLink": "Berechtigungsrollen", "title": "Berechtigungsrollen", "noPermissionRoles": "Keine Berechtigungsrollen gefunden.", "system": "System", "createButton": "Berechtigungsrolle erstellen", + "name": "Name", + "type": "Typ", + "verbs": "Verben", + "button": { + "edit": "Bearbeiten" + }, + "create": { + "name": "Name" + }, + "edit": "Berechtigungsrolle bearbeiten", "form": { "subtitle": "Berechtigungsrolle bearbeiten", "name": "Name", diff --git a/scm-ui/public/locales/en/config.json b/scm-ui/public/locales/en/config.json index e4ecc39874..bdb245544a 100644 --- a/scm-ui/public/locales/en/config.json +++ b/scm-ui/public/locales/en/config.json @@ -6,11 +6,22 @@ "errorTitle": "Error", "errorSubtitle": "Unknown Config Error" }, - "roles": { + "repositoryRole": { "navLink": "Permission Roles", "title": "Permission Roles", "noPermissionRoles": "No permission roles found.", + "system": "System", "createButton": "Create Permission Role", + "name": "Name", + "type": "Type", + "verbs": "Verbs", + "edit": "Edit Permission Role", + "button": { + "edit": "Edit" + }, + "create": { + "name": "Name" + }, "form": { "subtitle": "Edit Permission Role", "name": "Name", From 8fbe20afd6890a78446c433c53fece36d44f97fc Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch <eduard.heimbuch@cloudogu.com> Date: Thu, 16 May 2019 08:55:31 +0200 Subject: [PATCH 14/26] update EditRepositoryRole / fix Translationkeys --- scm-ui/src/config/containers/Config.js | 4 +- .../roles/components/PermissionRoleDetails.js | 31 +++++++++++----- .../roles/components/PermissionRoleTable.js | 2 +- .../roles/containers/CreateRepositoryRole.js | 2 +- .../roles/containers/EditRepositoryRole.js | 6 +-- .../roles/containers/RepositoryRoleForm.js | 14 +++---- .../roles/containers/RepositoryRoles.js | 8 ++-- .../roles/containers/SingleRepositoryRole.js | 37 +++++++++---------- 8 files changed, 57 insertions(+), 47 deletions(-) diff --git a/scm-ui/src/config/containers/Config.js b/scm-ui/src/config/containers/Config.js index 63173c0b9b..61e5931e24 100644 --- a/scm-ui/src/config/containers/Config.js +++ b/scm-ui/src/config/containers/Config.js @@ -57,7 +57,7 @@ class Config extends React.Component<Props> { <Route path={url} exact component={GlobalConfig} /> <Route path={`${url}/role/:role`} - render={() => <SingleRepositoryRole baseUrl={`${url}/roles`} />} + render={() => <SingleRepositoryRole baseUrl={`${url}/roles`} history={this.props.history} />} /> <Route path={`${url}/roles`} @@ -83,7 +83,7 @@ class Config extends React.Component<Props> { /> <NavLink to={`${url}/roles`} - label={t("roles.navLink")} + label={t("repositoryRole.navLink")} activeWhenMatch={this.matchesRoles} /> <ExtensionPoint diff --git a/scm-ui/src/config/roles/components/PermissionRoleDetails.js b/scm-ui/src/config/roles/components/PermissionRoleDetails.js index 8ca21b1ac3..fa68a66d25 100644 --- a/scm-ui/src/config/roles/components/PermissionRoleDetails.js +++ b/scm-ui/src/config/roles/components/PermissionRoleDetails.js @@ -4,36 +4,47 @@ import { translate } from "react-i18next"; import type { Role } from "@scm-manager/ui-types"; import ExtensionPoint from "@scm-manager/ui-extensions/lib/ExtensionPoint"; import PermissionRoleDetailsTable from "./PermissionRoleDetailsTable"; -import {Button, Subtitle} from "@scm-manager/ui-components"; +import { Button, Subtitle } from "@scm-manager/ui-components"; type Props = { role: Role, url: string, // context props - t: string => string, + t: string => string }; class PermissionRoleDetails extends React.Component<Props> { + renderEditButton() { + const { t, url } = this.props; + if (!!this.props.role._links.update) { + return ( + <Button + label={t("repositoryRole.button.edit")} + link={`${url}/edit`} + color="primary" + /> + ); + } + return null; + } + render() { - const { role, url } = this.props; + const { role } = this.props; return ( - <div> - <PermissionRoleDetailsTable role={role}/> - <hr/> - <Subtitle subtitle={"repositoryRoles.edit"}/> - <Button label={"test"} link={`${url}/edit`} color="primary" /> + <PermissionRoleDetailsTable role={role} /> + <hr /> + {this.renderEditButton()} <div className="content"> <ExtensionPoint - name="roles.repositoryRole-details.information" + name="repositoryRole.role-details.information" renderAll={true} props={{ role }} /> </div> </div> - ); } } diff --git a/scm-ui/src/config/roles/components/PermissionRoleTable.js b/scm-ui/src/config/roles/components/PermissionRoleTable.js index 895883d8c4..a585a84bca 100644 --- a/scm-ui/src/config/roles/components/PermissionRoleTable.js +++ b/scm-ui/src/config/roles/components/PermissionRoleTable.js @@ -18,7 +18,7 @@ class PermissionRoleTable extends React.Component<Props> { <table className="card-table table is-hoverable is-fullwidth"> <thead> <tr> - <th>{t("roles.form.name")}</th> + <th>{t("repositoryRole.form.name")}</th> </tr> </thead> <tbody> diff --git a/scm-ui/src/config/roles/containers/CreateRepositoryRole.js b/scm-ui/src/config/roles/containers/CreateRepositoryRole.js index 6592ff566a..e77df73deb 100644 --- a/scm-ui/src/config/roles/containers/CreateRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/CreateRepositoryRole.js @@ -26,7 +26,7 @@ class CreateRepositoryRole extends React.Component<Props> { repositoryRoleCreated = (role: Role) => { const { history } = this.props; - history.push("/config/role/" + role.name); + history.push("/config/role/" + role.name + "/info"); }; createRepositoryRole = (role: Role) => { diff --git a/scm-ui/src/config/roles/containers/EditRepositoryRole.js b/scm-ui/src/config/roles/containers/EditRepositoryRole.js index f16db79dda..98599863fc 100644 --- a/scm-ui/src/config/roles/containers/EditRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/EditRepositoryRole.js @@ -25,7 +25,7 @@ class EditRepositoryRole extends React.Component<Props> { repositoryRoleUpdated = (role: Role) => { const { history } = this.props; - history.push("/config/role/" + role.name); + history.push("/config/roles"); }; updateRepositoryRole = (role: Role) => { @@ -38,13 +38,13 @@ class EditRepositoryRole extends React.Component<Props> { return ( <> <RepositoryRoleForm - disabled={false} + nameDisabled={true} role={this.props.role} submitForm={role => this.updateRepositoryRole(role)} /> </> ); - } + }w } const mapStateToProps = (state, ownProps) => { diff --git a/scm-ui/src/config/roles/containers/RepositoryRoleForm.js b/scm-ui/src/config/roles/containers/RepositoryRoleForm.js index 852e097e4a..3515cddcfb 100644 --- a/scm-ui/src/config/roles/containers/RepositoryRoleForm.js +++ b/scm-ui/src/config/roles/containers/RepositoryRoleForm.js @@ -16,7 +16,7 @@ import {getRepositoryRolesLink, getRepositoryVerbsLink} from "../../../modules/i type Props = { role?: Role, loading?: boolean, - disabled: boolean, + nameDisabled: boolean, availableVerbs: string[], verbsLink: string, submitForm: Role => void, @@ -63,7 +63,7 @@ class RepositoryRoleForm extends React.Component<Props, State> { return !( this.isFalsy(role) || this.isFalsy(role.name) || - this.isFalsy(role.verbs) + this.isFalsy(role.verbs.length > 0) ); }; @@ -100,7 +100,7 @@ class RepositoryRoleForm extends React.Component<Props, State> { }; render() { - const { loading, availableVerbs, disabled, t } = this.props; + const { loading, availableVerbs, nameDisabled, t } = this.props; const { role } = this.state; const verbSelectBoxes = !availableVerbs @@ -120,10 +120,10 @@ class RepositoryRoleForm extends React.Component<Props, State> { <div className="column"> <InputField name="name" - label={t("roles.create.name")} + label={t("repositoryRole.create.name")} onChange={this.handleNameChange} value={role.name ? role.name : ""} - disabled={disabled} + disabled={nameDisabled} /> </div> </div> @@ -133,8 +133,8 @@ class RepositoryRoleForm extends React.Component<Props, State> { <div className="column"> <SubmitButton loading={loading} - label={t("roles.create.submit")} - disabled={disabled || !this.isValid()} + label={t("repositoryRole.form.submit")} + disabled={!this.isValid()} /> </div> </div> diff --git a/scm-ui/src/config/roles/containers/RepositoryRoles.js b/scm-ui/src/config/roles/containers/RepositoryRoles.js index 5a613e1fcd..35f2888e89 100644 --- a/scm-ui/src/config/roles/containers/RepositoryRoles.js +++ b/scm-ui/src/config/roles/containers/RepositoryRoles.js @@ -56,7 +56,7 @@ class RepositoryRoles extends React.Component<Props> { return ( <div> - <Title title={t("roles.title")} /> + <Title title={t("repositoryRole.title")} /> {this.renderPermissionsTable()} {this.renderCreateButton()} </div> @@ -69,19 +69,19 @@ class RepositoryRoles extends React.Component<Props> { return ( <> <PermissionRoleTable baseUrl={baseUrl} roles={roles} /> - <LinkPaginator collection={list} page={page} /> + <LinkPaginator collection={list} page={page} /> </> ); } return ( - <Notification type="info">{t("roles.noPermissionRoles")}</Notification> + <Notification type="info">{t("repositoryRole.noPermissionRoles")}</Notification> ); } renderCreateButton() { const { canAddRoles, baseUrl, t } = this.props; if (canAddRoles) { - return <CreateButton label={t("roles.createButton")} link={`${baseUrl}/create`} />; + return <CreateButton label={t("repositoryRole.createButton")} link={`${baseUrl}/create`} />; } return null; } diff --git a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js index 6b4f48819a..247021c855 100644 --- a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js @@ -4,7 +4,6 @@ import { connect } from "react-redux"; import { Loading, ErrorPage, Title } from "@scm-manager/ui-components"; import { Route } from "react-router"; import type { History } from "history"; -import { EditRepositoryRoleNavLink } from "../../components/navLinks"; import { translate } from "react-i18next"; import type { Role } from "@scm-manager/ui-types"; import { getRepositoryRolesLink } from "../../../modules/indexResource"; @@ -18,7 +17,6 @@ import { import { withRouter } from "react-router-dom"; import PermissionRoleDetail from "../components/PermissionRoleDetails"; import EditRepositoryRole from "./EditRepositoryRole"; -import Switch from "react-router-dom/es/Switch"; type Props = { roleName: string, @@ -43,7 +41,6 @@ class SingleRepositoryRole extends React.Component<Props> { this.props.repositoryRolesLink, this.props.roleName ); - console.log(this.props.match); } stripEndingSlash = (url: string) => { @@ -67,7 +64,7 @@ class SingleRepositoryRole extends React.Component<Props> { subtitle={t("singleUser.errorSubtitle")} error={error} /> - ); + );0 } if (!role || loading) { @@ -83,23 +80,25 @@ class SingleRepositoryRole extends React.Component<Props> { return ( <> - <Title title={t("repositoryRoles.title")} /> + <Title title={t("repositoryRole.title")} /> <div className="columns"> <div className="column is-three-quarters"> - <Route - path={url} - component={() => <PermissionRoleDetail role={role} url={url} />} - /> - <Route - path={`${url}`} - exact - component={() => <EditRepositoryRole role={role} />} - /> - <ExtensionPoint - name="roles.route" - props={extensionProps} - renderAll={true} - /> + <Route + path={`${url}/info`} + component={() => ( + <PermissionRoleDetail role={role} url={url} /> + )} + /> + <Route + path={`${url}/edit`} + exact + component={() => <EditRepositoryRole role={role} history={this.props.history} />} + /> + <ExtensionPoint + name="roles.route" + props={extensionProps} + renderAll={true} + /> </div> </div> </> From 45733db6fa294623257c828db4b72f06d2318b65 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch <eduard.heimbuch@cloudogu.com> Date: Thu, 16 May 2019 08:56:17 +0200 Subject: [PATCH 15/26] fix Translationkeys --- scm-ui/src/config/roles/containers/SingleRepositoryRole.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js index 247021c855..d42d36e173 100644 --- a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js @@ -60,8 +60,8 @@ class SingleRepositoryRole extends React.Component<Props> { if (error) { return ( <ErrorPage - title={t("singleUser.errorTitle")} - subtitle={t("singleUser.errorSubtitle")} + title={t("repositoryRole.errorTitle")} + subtitle={t("repositoryRole.errorSubtitle")} error={error} /> );0 From 7ed60eb5e1ca5944e8df2ed759daba86d9b07db3 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch <eduard.heimbuch@cloudogu.com> Date: Thu, 16 May 2019 09:28:39 +0200 Subject: [PATCH 16/26] remove unused classes and tests --- .../navLinks/EditRepositoryRoleNavLink.js | 28 ----------------- .../EditRepositoryRoleNavLink.test.js | 27 ---------------- .../navLinks/RepositoryRoleDetailNavLink.js | 28 ----------------- .../RepositoryRoleDetailNavLink.test.js | 31 ------------------- .../src/config/components/navLinks/index.js | 2 -- 5 files changed, 116 deletions(-) delete mode 100644 scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.js delete mode 100644 scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.test.js delete mode 100644 scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.js delete mode 100644 scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.test.js delete mode 100644 scm-ui/src/config/components/navLinks/index.js diff --git a/scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.js b/scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.js deleted file mode 100644 index 419ca330cc..0000000000 --- a/scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.js +++ /dev/null @@ -1,28 +0,0 @@ -//@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); diff --git a/scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.test.js b/scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.test.js deleted file mode 100644 index 7e86e9bcda..0000000000 --- a/scm-ui/src/config/components/navLinks/EditRepositoryRoleNavLink.test.js +++ /dev/null @@ -1,27 +0,0 @@ -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(""); -}); diff --git a/scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.js b/scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.js deleted file mode 100644 index cc04aa6b50..0000000000 --- a/scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.js +++ /dev/null @@ -1,28 +0,0 @@ -//@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); diff --git a/scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.test.js b/scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.test.js deleted file mode 100644 index 8cf5231387..0000000000 --- a/scm-ui/src/config/components/navLinks/RepositoryRoleDetailNavLink.test.js +++ /dev/null @@ -1,31 +0,0 @@ -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(""); -}); diff --git a/scm-ui/src/config/components/navLinks/index.js b/scm-ui/src/config/components/navLinks/index.js deleted file mode 100644 index 7fafde676d..0000000000 --- a/scm-ui/src/config/components/navLinks/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { default as EditRepositoryRoleNavLink } from "./EditRepositoryRoleNavLink"; -export { default as RepositoryRoleDetailNavLink } from "./RepositoryRoleDetailNavLink"; From e62c2084c64f70e719a43166b0457bc1ca06e3f8 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch <eduard.heimbuch@cloudogu.com> Date: Thu, 16 May 2019 10:01:33 +0200 Subject: [PATCH 17/26] update RepoRoles Pagination --- scm-ui/src/config/containers/Config.js | 11 ++++++++-- .../roles/containers/EditRepositoryRole.js | 2 +- .../roles/containers/RepositoryRoles.js | 21 +++++++++++++++++++ .../roles/containers/SingleRepositoryRole.js | 2 +- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/scm-ui/src/config/containers/Config.js b/scm-ui/src/config/containers/Config.js index 61e5931e24..08ad13b833 100644 --- a/scm-ui/src/config/containers/Config.js +++ b/scm-ui/src/config/containers/Config.js @@ -1,7 +1,7 @@ // @flow import React from "react"; import { translate } from "react-i18next"; -import { Route } from "react-router"; +import { Route, Switch } from "react-router-dom"; import { ExtensionPoint } from "@scm-manager/ui-extensions"; import type { History } from "history"; import { connect } from "react-redux"; @@ -54,6 +54,7 @@ class Config extends React.Component<Props> { <Page> <div className="columns"> <div className="column is-three-quarters"> + <Switch> <Route path={url} exact component={GlobalConfig} /> <Route path={`${url}/role/:role`} @@ -68,11 +69,17 @@ class Config extends React.Component<Props> { path={`${url}/roles/create`} render={() => <CreateRepositoryRole disabled={false} history={this.props.history} />} /> + <Route + path={`${url}/roles/:page`} + exact + render={() => <RepositoryRoles baseUrl={`${url}/roles/:page`} />} + /> <ExtensionPoint name="config.route" props={extensionProps} renderAll={true} /> + </Switch> </div> <div className="column is-one-quarter"> <Navigation> @@ -82,7 +89,7 @@ class Config extends React.Component<Props> { label={t("config.globalConfigurationNavLink")} /> <NavLink - to={`${url}/roles`} + to={`${url}/roles/`} label={t("repositoryRole.navLink")} activeWhenMatch={this.matchesRoles} /> diff --git a/scm-ui/src/config/roles/containers/EditRepositoryRole.js b/scm-ui/src/config/roles/containers/EditRepositoryRole.js index 98599863fc..0bc7e71e8d 100644 --- a/scm-ui/src/config/roles/containers/EditRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/EditRepositoryRole.js @@ -25,7 +25,7 @@ class EditRepositoryRole extends React.Component<Props> { repositoryRoleUpdated = (role: Role) => { const { history } = this.props; - history.push("/config/roles"); + history.push("/config/roles/"); }; updateRepositoryRole = (role: Role) => { diff --git a/scm-ui/src/config/roles/containers/RepositoryRoles.js b/scm-ui/src/config/roles/containers/RepositoryRoles.js index 35f2888e89..c9c0a5dd49 100644 --- a/scm-ui/src/config/roles/containers/RepositoryRoles.js +++ b/scm-ui/src/config/roles/containers/RepositoryRoles.js @@ -47,6 +47,27 @@ class RepositoryRoles extends React.Component<Props> { fetchRolesByPage(rolesLink, page); } + componentDidUpdate = (prevProps: Props) => { + const { + loading, + list, + page, + rolesLink, + location, + fetchRolesByPage + } = this.props; + if (list && page && !loading) { + const statePage: number = list.page + 1; + if (page !== statePage || prevProps.location.search !== location.search) { + fetchRolesByPage( + rolesLink, + page, + urls.getQueryStringFromLocation(location) + ); + } + } + }; + render() { const { t, loading } = this.props; diff --git a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js index d42d36e173..e234c7c38b 100644 --- a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js @@ -64,7 +64,7 @@ class SingleRepositoryRole extends React.Component<Props> { subtitle={t("repositoryRole.errorSubtitle")} error={error} /> - );0 + ); } if (!role || loading) { From d402b0fe19c16d7287296e2571fbebffe5feda40 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch <eduard.heimbuch@cloudogu.com> Date: Thu, 16 May 2019 10:04:57 +0200 Subject: [PATCH 18/26] fix CreateLink after Pagination --- scm-ui/src/config/containers/Config.js | 60 +++++++++++++++----------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/scm-ui/src/config/containers/Config.js b/scm-ui/src/config/containers/Config.js index 08ad13b833..496dce4611 100644 --- a/scm-ui/src/config/containers/Config.js +++ b/scm-ui/src/config/containers/Config.js @@ -55,30 +55,42 @@ class Config extends React.Component<Props> { <div className="columns"> <div className="column is-three-quarters"> <Switch> - <Route path={url} exact component={GlobalConfig} /> - <Route - path={`${url}/role/:role`} - render={() => <SingleRepositoryRole baseUrl={`${url}/roles`} history={this.props.history} />} - /> - <Route - path={`${url}/roles`} - exact - render={() => <RepositoryRoles baseUrl={`${url}/roles`} />} - /> - <Route - path={`${url}/roles/create`} - render={() => <CreateRepositoryRole disabled={false} history={this.props.history} />} - /> - <Route - path={`${url}/roles/:page`} - exact - render={() => <RepositoryRoles baseUrl={`${url}/roles/:page`} />} - /> - <ExtensionPoint - name="config.route" - props={extensionProps} - renderAll={true} - /> + <Route path={url} exact component={GlobalConfig} /> + <Route + path={`${url}/role/:role`} + render={() => ( + <SingleRepositoryRole + baseUrl={`${url}/roles`} + history={this.props.history} + /> + )} + /> + <Route + path={`${url}/roles`} + exact + render={() => <RepositoryRoles baseUrl={`${url}/roles`} />} + /> + <Route + path={`${url}/roles/create`} + render={() => ( + <CreateRepositoryRole + disabled={false} + history={this.props.history} + /> + )} + /> + <Route + path={`${url}/roles/:page`} + exact + render={() => ( + <RepositoryRoles baseUrl={`${url}/roles`} /> + )} + /> + <ExtensionPoint + name="config.route" + props={extensionProps} + renderAll={true} + /> </Switch> </div> <div className="column is-one-quarter"> From 916de8da8a6b6c5d5c575d43d5eb27efea38cd78 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch <eduard.heimbuch@cloudogu.com> Date: Thu, 16 May 2019 10:10:10 +0200 Subject: [PATCH 19/26] add Title to CreateRepositoryRole --- .../src/config/roles/containers/CreateRepositoryRole.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scm-ui/src/config/roles/containers/CreateRepositoryRole.js b/scm-ui/src/config/roles/containers/CreateRepositoryRole.js index e77df73deb..1ea0d3f1cf 100644 --- a/scm-ui/src/config/roles/containers/CreateRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/CreateRepositoryRole.js @@ -3,6 +3,7 @@ import React from "react"; import RepositoryRoleForm from "./RepositoryRoleForm"; import { connect } from "react-redux"; import { translate } from "react-i18next"; +import { Title } from "@scm-manager/ui-components"; import { createRole, getFetchVerbsFailure, @@ -19,7 +20,10 @@ type Props = { repositoryRolesLink: string, //dispatch function - addRole: (link: string, role: Role, callback?: () => void) => void + addRole: (link: string, role: Role, callback?: () => void) => void, + + // context objects + t: string => string }; class CreateRepositoryRole extends React.Component<Props> { @@ -36,8 +40,10 @@ class CreateRepositoryRole extends React.Component<Props> { }; render() { + const { t } = this.props; return ( <> + <Title title={t("repositoryRole.title")} /> <RepositoryRoleForm disabled={this.props.disabled} submitForm={role => this.createRepositoryRole(role)} From 3461f6680b6280dc21dec4eb6655c7fe2a13320d Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch <eduard.heimbuch@cloudogu.com> Date: Thu, 16 May 2019 10:50:12 +0200 Subject: [PATCH 20/26] show verb translations --- .../config/roles/components/AvailableVerbs.js | 46 +++++++++++++++++++ .../components/PermissionRoleDetailsTable.js | 40 +++------------- 2 files changed, 52 insertions(+), 34 deletions(-) create mode 100644 scm-ui/src/config/roles/components/AvailableVerbs.js diff --git a/scm-ui/src/config/roles/components/AvailableVerbs.js b/scm-ui/src/config/roles/components/AvailableVerbs.js new file mode 100644 index 0000000000..1b27f95b83 --- /dev/null +++ b/scm-ui/src/config/roles/components/AvailableVerbs.js @@ -0,0 +1,46 @@ +//@flow +import React from "react"; +import type { Role } from "@scm-manager/ui-types"; +import { translate } from "react-i18next"; +import { compose } from "redux"; +import injectSheet from "react-jss"; + +type Props = { + role: Role, + // context props + t: string => string +}; + +const styles = { + spacing: { + padding: "0 !important" + } +}; + +class AvailableVerbs extends React.Component<Props> { + + render() { + const { role, t, classes } = this.props; + + let verbs = null; + if (role.verbs.length > 0) { + verbs = ( + <tr> + <td className={classes.spacing}> + <ul> + {role.verbs.map(verb => { + return <li>{t("verbs.repository." + verb + ".displayName")}</li>; + })} + </ul> + </td> + </tr> + ); + } + return (verbs); + } +} + +export default compose( + injectSheet(styles), + translate("plugins") +)(AvailableVerbs); diff --git a/scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js b/scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js index 67d752fb8c..f320547237 100644 --- a/scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js +++ b/scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js @@ -2,8 +2,7 @@ import React from "react"; import type { Role } from "@scm-manager/ui-types"; import { translate } from "react-i18next"; -import { compose } from "redux"; -import injectSheet from "react-jss"; +import AvailableVerbs from "./AvailableVerbs"; type Props = { role: Role, @@ -11,12 +10,6 @@ type Props = { t: string => string }; -const styles = { - spacing: { - padding: "0 !important" - } -}; - class PermissionRoleDetailsTable extends React.Component<Props> { render() { const { role, t } = this.props; @@ -31,35 +24,14 @@ class PermissionRoleDetailsTable extends React.Component<Props> { <th>{t("repositoryRole.type")}</th> <td>{role.type}</td> </tr> - {this.renderVerbs()} + <tr> + <th>{t("repositoryRole.verbs")}</th> + <AvailableVerbs role={role} /> + </tr> </tbody> </table> ); } - - renderVerbs() { - const { role, t, classes } = this.props; - - let verbs = null; - if (role.verbs.length > 0) { - verbs = ( - <tr> - <th>{t("repositoryRole.verbs")}</th> - <td className={classes.spacing}> - <ul> - {role.verbs.map(verb => { - return <li>{verb}</li>; - })} - </ul> - </td> - </tr> - ); - } - return verbs; - } } -export default compose( - injectSheet(styles), - translate("config") -)(PermissionRoleDetailsTable); +export default translate("config")(PermissionRoleDetailsTable); From e34781789dc259c68ac6f18dfaff5f5aca663488 Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer <rene.pfeuffer@cloudogu.com> Date: Thu, 16 May 2019 12:12:46 +0200 Subject: [PATCH 21/26] Set role instead of collection of verbs for repository owner --- .../scm/api/v2/resources/RepositoryCollectionResource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java index b4d148b4bf..8b351aa46a 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java @@ -106,7 +106,7 @@ public class RepositoryCollectionResource { private Repository createModelObjectFromDto(@Valid RepositoryDto repositoryDto) { Repository repository = dtoToRepositoryMapper.map(repositoryDto, null); - repository.setPermissions(singletonList(new RepositoryPermission(currentUser(), singletonList("*"), false))); + repository.setPermissions(singletonList(new RepositoryPermission(currentUser(), "OWNER", false))); return repository; } From 46456d0390e776fe83142fd3dc46ad8797df5da4 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch <eduard.heimbuch@cloudogu.com> Date: Thu, 16 May 2019 12:17:18 +0200 Subject: [PATCH 22/26] add Errorhandling to CreateRepoRole & EditRepoRole --- .../roles/containers/CreateRepositoryRole.js | 14 +++++++---- .../roles/containers/EditRepositoryRole.js | 23 +++++++++++-------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/scm-ui/src/config/roles/containers/CreateRepositoryRole.js b/scm-ui/src/config/roles/containers/CreateRepositoryRole.js index 1ea0d3f1cf..4a572a3206 100644 --- a/scm-ui/src/config/roles/containers/CreateRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/CreateRepositoryRole.js @@ -3,9 +3,10 @@ import React from "react"; import RepositoryRoleForm from "./RepositoryRoleForm"; import { connect } from "react-redux"; import { translate } from "react-i18next"; -import { Title } from "@scm-manager/ui-components"; +import { ErrorNotification, Title } from "@scm-manager/ui-components"; import { createRole, + getCreateRoleFailure, getFetchVerbsFailure, isFetchVerbsPending } from "../modules/roles"; @@ -18,6 +19,7 @@ import { type Props = { disabled: boolean, repositoryRolesLink: string, + error?: Error, //dispatch function addRole: (link: string, role: Role, callback?: () => void) => void, @@ -27,7 +29,6 @@ type Props = { }; class CreateRepositoryRole extends React.Component<Props> { - repositoryRoleCreated = (role: Role) => { const { history } = this.props; history.push("/config/role/" + role.name + "/info"); @@ -40,7 +41,12 @@ class CreateRepositoryRole extends React.Component<Props> { }; render() { - const { t } = this.props; + const { t, error } = this.props; + + if (error) { + return <ErrorNotification error={error} />; + } + return ( <> <Title title={t("repositoryRole.title")} /> @@ -55,7 +61,7 @@ class CreateRepositoryRole extends React.Component<Props> { const mapStateToProps = (state, ownProps) => { const loading = isFetchVerbsPending(state); - const error = getFetchVerbsFailure(state); + const error = getFetchVerbsFailure(state) || getCreateRoleFailure(state); const verbsLink = getRepositoryVerbsLink(state); const repositoryRolesLink = getRepositoryRolesLink(state); diff --git a/scm-ui/src/config/roles/containers/EditRepositoryRole.js b/scm-ui/src/config/roles/containers/EditRepositoryRole.js index 0bc7e71e8d..1555c63ce8 100644 --- a/scm-ui/src/config/roles/containers/EditRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/EditRepositoryRole.js @@ -6,35 +6,38 @@ import { translate } from "react-i18next"; import { getModifyRoleFailure, isModifyRolePending, - modifyRole, + modifyRole } from "../modules/roles"; +import { ErrorNotification } from "@scm-manager/ui-components"; import type { Role } from "@scm-manager/ui-types"; type Props = { disabled: boolean, role: Role, repositoryRolesLink: string, + error?: Error, //dispatch function updateRole: (link: string, role: Role, callback?: () => void) => void }; - - class EditRepositoryRole extends React.Component<Props> { - repositoryRoleUpdated = (role: Role) => { const { history } = this.props; history.push("/config/roles/"); }; updateRepositoryRole = (role: Role) => { - this.props.updateRole(role, () => - this.repositoryRoleUpdated(role) - ); + this.props.updateRole(role, () => this.repositoryRoleUpdated(role)); }; render() { + const { error } = this.props; + + if (error) { + return <ErrorNotification error={error} />; + } + return ( <> <RepositoryRoleForm @@ -44,16 +47,16 @@ class EditRepositoryRole extends React.Component<Props> { /> </> ); - }w + } } const mapStateToProps = (state, ownProps) => { const loading = isModifyRolePending(state); - const error = getModifyRoleFailure(state); + const error = getModifyRoleFailure(state, ownProps.role.name); return { loading, - error, + error }; }; From bb2dc3738d2148afb87d98cd3d784c194341b30c Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer <rene.pfeuffer@cloudogu.com> Date: Thu, 16 May 2019 12:19:52 +0200 Subject: [PATCH 23/26] Take verbs of role for initial advanced permission settings --- .../permissions/containers/CreatePermissionForm.js | 5 ++++- .../permissions/containers/SinglePermission.js | 13 +++++++++---- .../src/repos/permissions/modules/permissions.js | 14 ++++++++++++++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js b/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js index 8ee1e7edbb..c09baf50fa 100644 --- a/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js +++ b/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js @@ -17,6 +17,7 @@ import { import * as validator from "../components/permissionValidation"; import RoleSelector from "../components/RoleSelector"; import AdvancedPermissionsDialog from "./AdvancedPermissionsDialog"; +import { findVerbsForRole } from "../modules/permissions"; type Props = { availableRoles: RepositoryRole[], @@ -142,10 +143,12 @@ class CreatePermissionForm extends React.Component<Props, State> { const availableRoleNames = availableRoles.map(r => r.name); + const selectedVerbs = role ? findVerbsForRole(availableRoles, role) : verbs; + const advancedDialog = showAdvancedDialog ? ( <AdvancedPermissionsDialog availableVerbs={availableVerbs} - selectedVerbs={verbs} + selectedVerbs={selectedVerbs} onClose={this.closeAdvancedPermissionsDialog} onSubmit={this.submitAdvancedPermissionsDialog} /> diff --git a/scm-ui/src/repos/permissions/containers/SinglePermission.js b/scm-ui/src/repos/permissions/containers/SinglePermission.js index 5fed0084a7..bdb96de0bd 100644 --- a/scm-ui/src/repos/permissions/containers/SinglePermission.js +++ b/scm-ui/src/repos/permissions/containers/SinglePermission.js @@ -6,7 +6,8 @@ import { modifyPermission, isModifyPermissionPending, deletePermission, - isDeletePermissionPending + isDeletePermissionPending, + findVerbsForRole } from "../modules/permissions"; import { connect } from "react-redux"; import type { History } from "history"; @@ -131,11 +132,15 @@ class SinglePermission extends React.Component<Props, State> { </td> ); - const advancedDialg = showAdvancedDialog ? ( + const selectedVerbs = permission.role + ? findVerbsForRole(availableRepositoryRoles, permission.role) + : permission.verbs; + + const advancedDialog = showAdvancedDialog ? ( <AdvancedPermissionsDialog readOnly={readOnly} availableVerbs={availableRepositoryVerbs} - selectedVerbs={permission.verbs} + selectedVerbs={selectedVerbs} onClose={this.closeAdvancedPermissionsDialog} onSubmit={this.submitAdvancedPermissionsDialog} /> @@ -174,7 +179,7 @@ class SinglePermission extends React.Component<Props, State> { deletePermission={this.deletePermission} loading={this.props.deleteLoading} /> - {advancedDialg} + {advancedDialog} </td> </tr> ); diff --git a/scm-ui/src/repos/permissions/modules/permissions.js b/scm-ui/src/repos/permissions/modules/permissions.js index abd25eb459..276f28f672 100644 --- a/scm-ui/src/repos/permissions/modules/permissions.js +++ b/scm-ui/src/repos/permissions/modules/permissions.js @@ -739,3 +739,17 @@ export function getModifyPermissionsFailure( } return null; } + +export function findVerbsForRole( + availableRepositoryRoles: RepositoryRole[], + roleName: string +) { + const matchingRole = availableRepositoryRoles.find( + role => roleName === role.name + ); + if (matchingRole) { + return matchingRole.verbs; + } else { + return []; + } +} From 510ea51e769eda1fa907ab5053e51dd7998c64e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= <rene.pfeuffer@cloudogu.com> Date: Thu, 16 May 2019 13:06:08 +0200 Subject: [PATCH 24/26] Fix unit test --- .../sonia/scm/api/v2/resources/RepositoryRootResourceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java index 55754469ec..c47250470d 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java @@ -332,7 +332,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase { .hasSize(1) .allSatisfy(p -> { assertThat(p.getName()).isEqualTo("trillian"); - assertThat(p.getVerbs()).containsExactly("*"); + assertThat(p.getRole()).isEqualTo("OWNER"); }); } From 3ea48103463766aadeaec84ba5dd66073c9e483b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= <rene.pfeuffer@cloudogu.com> Date: Thu, 16 May 2019 13:36:11 +0200 Subject: [PATCH 25/26] Finish rename Role to RepositoryRole --- .../packages/ui-types/src/RepositoryRole.js | 3 ++ .../packages/ui-types/src/Role.js | 12 ----- .../packages/ui-types/src/index.js | 1 - .../config/roles/components/AvailableVerbs.js | 11 ++--- .../roles/components/PermissionRoleDetails.js | 4 +- .../components/PermissionRoleDetailsTable.js | 4 +- .../roles/components/PermissionRoleRow.js | 4 +- .../roles/components/PermissionRoleTable.js | 4 +- .../roles/containers/CreateRepositoryRole.js | 10 ++--- .../roles/containers/EditRepositoryRole.js | 16 ++++--- .../roles/containers/RepositoryRoleForm.js | 21 +++++---- .../roles/containers/RepositoryRoles.js | 29 +++++++----- .../roles/containers/SingleRepositoryRole.js | 36 +++++++-------- scm-ui/src/config/roles/modules/roles.js | 45 ++++++++++--------- 14 files changed, 105 insertions(+), 95 deletions(-) delete mode 100644 scm-ui-components/packages/ui-types/src/Role.js diff --git a/scm-ui-components/packages/ui-types/src/RepositoryRole.js b/scm-ui-components/packages/ui-types/src/RepositoryRole.js index 8b8ffc933f..195bdfe05c 100644 --- a/scm-ui-components/packages/ui-types/src/RepositoryRole.js +++ b/scm-ui-components/packages/ui-types/src/RepositoryRole.js @@ -1,10 +1,13 @@ // @flow +import type {Links} from "./hal"; + export type RepositoryRole = { name: string, verbs: string[], type?: string, creationDate?: string, lastModified?: string, + _links: Links }; diff --git a/scm-ui-components/packages/ui-types/src/Role.js b/scm-ui-components/packages/ui-types/src/Role.js deleted file mode 100644 index 00e794b886..0000000000 --- a/scm-ui-components/packages/ui-types/src/Role.js +++ /dev/null @@ -1,12 +0,0 @@ -//@flow - -import type { Links } from "./hal"; - -export type Role = { - name: string, - verbs: string[], - creationDate?: number, - lastModified?: number, - system: boolean, - _links: Links -}; diff --git a/scm-ui-components/packages/ui-types/src/index.js b/scm-ui-components/packages/ui-types/src/index.js index 0272b1e2cb..4024710300 100644 --- a/scm-ui-components/packages/ui-types/src/index.js +++ b/scm-ui-components/packages/ui-types/src/index.js @@ -16,7 +16,6 @@ export type { Changeset } from "./Changesets"; export type { Tag } from "./Tags"; export type { Config } from "./Config"; -export type { Role } from "./Role"; export type { IndexResources } from "./IndexResources"; diff --git a/scm-ui/src/config/roles/components/AvailableVerbs.js b/scm-ui/src/config/roles/components/AvailableVerbs.js index 1b27f95b83..dbe0b50a77 100644 --- a/scm-ui/src/config/roles/components/AvailableVerbs.js +++ b/scm-ui/src/config/roles/components/AvailableVerbs.js @@ -1,12 +1,12 @@ //@flow import React from "react"; -import type { Role } from "@scm-manager/ui-types"; +import type { RepositoryRole } from "@scm-manager/ui-types"; import { translate } from "react-i18next"; import { compose } from "redux"; import injectSheet from "react-jss"; type Props = { - role: Role, + role: RepositoryRole, // context props t: string => string }; @@ -18,7 +18,6 @@ const styles = { }; class AvailableVerbs extends React.Component<Props> { - render() { const { role, t, classes } = this.props; @@ -29,14 +28,16 @@ class AvailableVerbs extends React.Component<Props> { <td className={classes.spacing}> <ul> {role.verbs.map(verb => { - return <li>{t("verbs.repository." + verb + ".displayName")}</li>; + return ( + <li>{t("verbs.repository." + verb + ".displayName")}</li> + ); })} </ul> </td> </tr> ); } - return (verbs); + return verbs; } } diff --git a/scm-ui/src/config/roles/components/PermissionRoleDetails.js b/scm-ui/src/config/roles/components/PermissionRoleDetails.js index fa68a66d25..1977ddde2a 100644 --- a/scm-ui/src/config/roles/components/PermissionRoleDetails.js +++ b/scm-ui/src/config/roles/components/PermissionRoleDetails.js @@ -1,13 +1,13 @@ //@flow import React from "react"; import { translate } from "react-i18next"; -import type { Role } from "@scm-manager/ui-types"; +import type { RepositoryRole } from "@scm-manager/ui-types"; import ExtensionPoint from "@scm-manager/ui-extensions/lib/ExtensionPoint"; import PermissionRoleDetailsTable from "./PermissionRoleDetailsTable"; import { Button, Subtitle } from "@scm-manager/ui-components"; type Props = { - role: Role, + role: RepositoryRole, url: string, // context props diff --git a/scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js b/scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js index f320547237..dd0502cb02 100644 --- a/scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js +++ b/scm-ui/src/config/roles/components/PermissionRoleDetailsTable.js @@ -1,11 +1,11 @@ //@flow import React from "react"; -import type { Role } from "@scm-manager/ui-types"; +import type { RepositoryRole } from "@scm-manager/ui-types"; import { translate } from "react-i18next"; import AvailableVerbs from "./AvailableVerbs"; type Props = { - role: Role, + role: RepositoryRole, // context props t: string => string }; diff --git a/scm-ui/src/config/roles/components/PermissionRoleRow.js b/scm-ui/src/config/roles/components/PermissionRoleRow.js index 9f06eb56de..8a10bf93d0 100644 --- a/scm-ui/src/config/roles/components/PermissionRoleRow.js +++ b/scm-ui/src/config/roles/components/PermissionRoleRow.js @@ -1,12 +1,12 @@ // @flow import React from "react"; import { Link } from "react-router-dom"; -import type { Role } from "@scm-manager/ui-types"; +import type { RepositoryRole } from "@scm-manager/ui-types"; import SystemRoleTag from "./SystemRoleTag"; type Props = { baseUrl: string, - role: Role + role: RepositoryRole }; class PermissionRoleRow extends React.Component<Props> { diff --git a/scm-ui/src/config/roles/components/PermissionRoleTable.js b/scm-ui/src/config/roles/components/PermissionRoleTable.js index a585a84bca..bb98f7c3e9 100644 --- a/scm-ui/src/config/roles/components/PermissionRoleTable.js +++ b/scm-ui/src/config/roles/components/PermissionRoleTable.js @@ -1,12 +1,12 @@ // @flow import React from "react"; import { translate } from "react-i18next"; -import type { Role } from "@scm-manager/ui-types"; +import type { RepositoryRole } from "@scm-manager/ui-types"; import PermissionRoleRow from "./PermissionRoleRow"; type Props = { baseUrl: string, - roles: Role[], + roles: RepositoryRole[], t: string => string }; diff --git a/scm-ui/src/config/roles/containers/CreateRepositoryRole.js b/scm-ui/src/config/roles/containers/CreateRepositoryRole.js index 4a572a3206..88f42f8353 100644 --- a/scm-ui/src/config/roles/containers/CreateRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/CreateRepositoryRole.js @@ -10,7 +10,7 @@ import { getFetchVerbsFailure, isFetchVerbsPending } from "../modules/roles"; -import type { Role } from "@scm-manager/ui-types"; +import type { RepositoryRole } from "@scm-manager/ui-types"; import { getRepositoryRolesLink, getRepositoryVerbsLink @@ -22,19 +22,19 @@ type Props = { error?: Error, //dispatch function - addRole: (link: string, role: Role, callback?: () => void) => void, + addRole: (link: string, role: RepositoryRole, callback?: () => void) => void, // context objects t: string => string }; class CreateRepositoryRole extends React.Component<Props> { - repositoryRoleCreated = (role: Role) => { + repositoryRoleCreated = (role: RepositoryRole) => { const { history } = this.props; history.push("/config/role/" + role.name + "/info"); }; - createRepositoryRole = (role: Role) => { + createRepositoryRole = (role: RepositoryRole) => { this.props.addRole(this.props.repositoryRolesLink, role, () => this.repositoryRoleCreated(role) ); @@ -75,7 +75,7 @@ const mapStateToProps = (state, ownProps) => { const mapDispatchToProps = dispatch => { return { - addRole: (link: string, role: Role, callback?: () => void) => { + addRole: (link: string, role: RepositoryRole, callback?: () => void) => { dispatch(createRole(link, role, callback)); } }; diff --git a/scm-ui/src/config/roles/containers/EditRepositoryRole.js b/scm-ui/src/config/roles/containers/EditRepositoryRole.js index 1555c63ce8..deb0a77583 100644 --- a/scm-ui/src/config/roles/containers/EditRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/EditRepositoryRole.js @@ -9,25 +9,29 @@ import { modifyRole } from "../modules/roles"; import { ErrorNotification } from "@scm-manager/ui-components"; -import type { Role } from "@scm-manager/ui-types"; +import type { RepositoryRole } from "@scm-manager/ui-types"; type Props = { disabled: boolean, - role: Role, + role: RepositoryRole, repositoryRolesLink: string, error?: Error, //dispatch function - updateRole: (link: string, role: Role, callback?: () => void) => void + updateRole: ( + link: string, + role: RepositoryRole, + callback?: () => void + ) => void }; class EditRepositoryRole extends React.Component<Props> { - repositoryRoleUpdated = (role: Role) => { + repositoryRoleUpdated = (role: RepositoryRole) => { const { history } = this.props; history.push("/config/roles/"); }; - updateRepositoryRole = (role: Role) => { + updateRepositoryRole = (role: RepositoryRole) => { this.props.updateRole(role, () => this.repositoryRoleUpdated(role)); }; @@ -62,7 +66,7 @@ const mapStateToProps = (state, ownProps) => { const mapDispatchToProps = dispatch => { return { - updateRole: (role: Role, callback?: () => void) => { + updateRole: (role: RepositoryRole, callback?: () => void) => { dispatch(modifyRole(role, callback)); } }; diff --git a/scm-ui/src/config/roles/containers/RepositoryRoleForm.js b/scm-ui/src/config/roles/containers/RepositoryRoleForm.js index 3515cddcfb..43d901a285 100644 --- a/scm-ui/src/config/roles/containers/RepositoryRoleForm.js +++ b/scm-ui/src/config/roles/containers/RepositoryRoleForm.js @@ -2,7 +2,7 @@ import React from "react"; import { connect } from "react-redux"; import { translate } from "react-i18next"; -import type { Role } from "@scm-manager/ui-types"; +import type { RepositoryRole } from "@scm-manager/ui-types"; import { InputField, SubmitButton } from "@scm-manager/ui-components"; import PermissionCheckbox from "../../../repos/permissions/components/PermissionCheckbox"; import { @@ -11,15 +11,18 @@ import { getVerbsFromState, isFetchVerbsPending } from "../modules/roles"; -import {getRepositoryRolesLink, getRepositoryVerbsLink} from "../../../modules/indexResource"; +import { + getRepositoryRolesLink, + getRepositoryVerbsLink +} from "../../../modules/indexResource"; type Props = { - role?: Role, + role?: RepositoryRole, loading?: boolean, nameDisabled: boolean, availableVerbs: string[], verbsLink: string, - submitForm: Role => void, + submitForm: RepositoryRole => void, // context objects t: string => string, @@ -29,7 +32,7 @@ type Props = { }; type State = { - role: Role + role: RepositoryRole }; class RepositoryRoleForm extends React.Component<Props, State> { @@ -47,10 +50,10 @@ class RepositoryRoleForm extends React.Component<Props, State> { } componentDidMount() { - const { fetchAvailableVerbs, verbsLink} = this.props; + const { fetchAvailableVerbs, verbsLink } = this.props; fetchAvailableVerbs(verbsLink); if (this.props.role) { - this.setState({role: this.props.role}) + this.setState({ role: this.props.role }); } } @@ -95,7 +98,7 @@ class RepositoryRoleForm extends React.Component<Props, State> { submit = (event: Event) => { event.preventDefault(); if (this.isValid()) { - this.props.submitForm(this.state.role) + this.props.submitForm(this.state.role); } }; @@ -163,7 +166,7 @@ const mapDispatchToProps = dispatch => { return { fetchAvailableVerbs: (link: string) => { dispatch(fetchAvailableVerbs(link)); - }, + } }; }; diff --git a/scm-ui/src/config/roles/containers/RepositoryRoles.js b/scm-ui/src/config/roles/containers/RepositoryRoles.js index c9c0a5dd49..f148b120e0 100644 --- a/scm-ui/src/config/roles/containers/RepositoryRoles.js +++ b/scm-ui/src/config/roles/containers/RepositoryRoles.js @@ -1,10 +1,10 @@ // @flow import React from "react"; import { connect } from "react-redux"; -import {withRouter} from "react-router-dom"; +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 type { RepositoryRole, PagedCollection } from "@scm-manager/ui-types"; import { Title, Loading, @@ -25,7 +25,7 @@ import PermissionRoleTable from "../components/PermissionRoleTable"; import { getRolesLink } from "../../../modules/indexResource"; type Props = { baseUrl: string, - roles: Role[], + roles: RepositoryRole[], loading: boolean, error: Error, canAddRoles: boolean, @@ -90,19 +90,26 @@ class RepositoryRoles extends React.Component<Props> { return ( <> <PermissionRoleTable baseUrl={baseUrl} roles={roles} /> - <LinkPaginator collection={list} page={page} /> + <LinkPaginator collection={list} page={page} /> </> ); } return ( - <Notification type="info">{t("repositoryRole.noPermissionRoles")}</Notification> + <Notification type="info"> + {t("repositoryRole.noPermissionRoles")} + </Notification> ); } renderCreateButton() { const { canAddRoles, baseUrl, t } = this.props; if (canAddRoles) { - return <CreateButton label={t("repositoryRole.createButton")} link={`${baseUrl}/create`} />; + return ( + <CreateButton + label={t("repositoryRole.createButton")} + link={`${baseUrl}/create`} + /> + ); } return null; } @@ -137,7 +144,9 @@ const mapDispatchToProps = dispatch => { }; }; -export default withRouter(connect( - mapStateToProps, - mapDispatchToProps -)(translate("config")(RepositoryRoles))); +export default withRouter( + connect( + mapStateToProps, + mapDispatchToProps + )(translate("config")(RepositoryRoles)) +); diff --git a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js index e234c7c38b..3bb951ac1a 100644 --- a/scm-ui/src/config/roles/containers/SingleRepositoryRole.js +++ b/scm-ui/src/config/roles/containers/SingleRepositoryRole.js @@ -5,7 +5,7 @@ import { Loading, ErrorPage, Title } from "@scm-manager/ui-components"; import { Route } from "react-router"; import type { History } from "history"; import { translate } from "react-i18next"; -import type { Role } from "@scm-manager/ui-types"; +import type { RepositoryRole } from "@scm-manager/ui-types"; import { getRepositoryRolesLink } from "../../../modules/indexResource"; import { ExtensionPoint } from "@scm-manager/ui-extensions"; import { @@ -20,7 +20,7 @@ import EditRepositoryRole from "./EditRepositoryRole"; type Props = { roleName: string, - role: Role, + role: RepositoryRole, loading: boolean, error: Error, repositoryRolesLink: string, @@ -83,22 +83,22 @@ class SingleRepositoryRole extends React.Component<Props> { <Title title={t("repositoryRole.title")} /> <div className="columns"> <div className="column is-three-quarters"> - <Route - path={`${url}/info`} - component={() => ( - <PermissionRoleDetail role={role} url={url} /> - )} - /> - <Route - path={`${url}/edit`} - exact - component={() => <EditRepositoryRole role={role} history={this.props.history} />} - /> - <ExtensionPoint - name="roles.route" - props={extensionProps} - renderAll={true} - /> + <Route + path={`${url}/info`} + component={() => <PermissionRoleDetail role={role} url={url} />} + /> + <Route + path={`${url}/edit`} + exact + component={() => ( + <EditRepositoryRole role={role} history={this.props.history} /> + )} + /> + <ExtensionPoint + name="roles.route" + props={extensionProps} + renderAll={true} + /> </div> </div> </> diff --git a/scm-ui/src/config/roles/modules/roles.js b/scm-ui/src/config/roles/modules/roles.js index a7a3ce3d93..fffc395e9e 100644 --- a/scm-ui/src/config/roles/modules/roles.js +++ b/scm-ui/src/config/roles/modules/roles.js @@ -4,7 +4,11 @@ import { isPending } from "../../../modules/pending"; import { getFailure } from "../../../modules/failure"; import * as types from "../../../modules/types"; import { combineReducers, Dispatch } from "redux"; -import type {Action, PagedCollection, Repository, Role} from "@scm-manager/ui-types"; +import type { + Action, + PagedCollection, + RepositoryRole +} from "@scm-manager/ui-types"; export const FETCH_ROLES = "scm/roles/FETCH_ROLES"; export const FETCH_ROLES_PENDING = `${FETCH_ROLES}_${types.PENDING_SUFFIX}`; @@ -138,12 +142,12 @@ export function fetchRoleByName(link: string, name: string) { return fetchRole(roleUrl, name); } -export function fetchRoleByLink(role: Role) { +export function fetchRoleByLink(role: RepositoryRole) { return fetchRole(role._links.self.href, role.name); } // create role -export function createRolePending(role: Role): Action { +export function createRolePending(role: RepositoryRole): Action { return { type: CREATE_ROLE_PENDING, role @@ -169,7 +173,11 @@ export function createRoleReset() { }; } -export function createRole(link: string, role: Role, callback?: () => void) { +export function createRole( + link: string, + role: RepositoryRole, + callback?: () => void +) { return function(dispatch: Dispatch) { dispatch(createRolePending(role)); return apiClient @@ -233,7 +241,7 @@ function verbReducer(state: any = {}, action: any = {}) { } // modify role -export function modifyRolePending(role: Role): Action { +export function modifyRolePending(role: RepositoryRole): Action { return { type: MODIFY_ROLE_PENDING, payload: role, @@ -241,7 +249,7 @@ export function modifyRolePending(role: Role): Action { }; } -export function modifyRoleSuccess(role: Role): Action { +export function modifyRoleSuccess(role: RepositoryRole): Action { return { type: MODIFY_ROLE_SUCCESS, payload: role, @@ -249,7 +257,7 @@ export function modifyRoleSuccess(role: Role): Action { }; } -export function modifyRoleFailure(role: Role, error: Error): Action { +export function modifyRoleFailure(role: RepositoryRole, error: Error): Action { return { type: MODIFY_ROLE_FAILURE, payload: { @@ -260,14 +268,14 @@ export function modifyRoleFailure(role: Role, error: Error): Action { }; } -export function modifyRoleReset(role: Role): Action { +export function modifyRoleReset(role: RepositoryRole): Action { return { type: MODIFY_ROLE_RESET, itemId: role.name }; } -export function modifyRole(role: Role, callback?: () => void) { +export function modifyRole(role: RepositoryRole, callback?: () => void) { return function(dispatch: Dispatch) { dispatch(modifyRolePending(role)); return apiClient @@ -288,7 +296,7 @@ export function modifyRole(role: Role, callback?: () => void) { } // delete role -export function deleteRolePending(role: Role): Action { +export function deleteRolePending(role: RepositoryRole): Action { return { type: DELETE_ROLE_PENDING, payload: role, @@ -296,7 +304,7 @@ export function deleteRolePending(role: Role): Action { }; } -export function deleteRoleSuccess(role: Role): Action { +export function deleteRoleSuccess(role: RepositoryRole): Action { return { type: DELETE_ROLE_SUCCESS, payload: role, @@ -304,7 +312,7 @@ export function deleteRoleSuccess(role: Role): Action { }; } -export function deleteRoleFailure(role: Role, error: Error): Action { +export function deleteRoleFailure(role: RepositoryRole, error: Error): Action { return { type: DELETE_ROLE_FAILURE, payload: { @@ -315,7 +323,7 @@ export function deleteRoleFailure(role: Role, error: Error): Action { }; } -export function deleteRole(role: Role, callback?: () => void) { +export function deleteRole(role: RepositoryRole, callback?: () => void) { return function(dispatch: any) { dispatch(deleteRolePending(role)); return apiClient @@ -333,7 +341,7 @@ export function deleteRole(role: Role, callback?: () => void) { } function extractRolesByNames( - roles: Role[], + roles: RepositoryRole[], roleNames: string[], oldRolesByNames: Object ) { @@ -460,7 +468,7 @@ export function getRolesFromState(state: Object) { if (!roleNames) { return null; } - const roleEntries: Role[] = []; + const roleEntries: RepositoryRole[] = []; for (let roleName of roleNames) { roleEntries.push(state.roles.byNames[roleName]); @@ -470,12 +478,7 @@ export function getRolesFromState(state: Object) { } export function getRoleCreateLink(state: Object) { - if ( - state && - state.list && - state.list._links && - state.list._links.create - ) { + if (state && state.list && state.list._links && state.list._links.create) { return state.list._links.create.href; } } From 781198d9a7b65204ce18ec2bf391145265e0c35a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= <rene.pfeuffer@cloudogu.com> Date: Thu, 16 May 2019 13:42:41 +0200 Subject: [PATCH 26/26] Reset verbs when a role is selected --- .../src/repos/permissions/containers/CreatePermissionForm.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js b/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js index c09baf50fa..765d752d37 100644 --- a/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js +++ b/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js @@ -265,7 +265,8 @@ class CreatePermissionForm extends React.Component<Props, State> { return; } this.setState({ - role: selectedRole.name + role: selectedRole.name, + verbs: [] }); };