unified langs + added deletegroup component + renamed editgroup to general

This commit is contained in:
Florian Scholdei
2019-01-23 13:20:57 +01:00
parent 7160aa98f9
commit 5f7432c758
11 changed files with 90 additions and 77 deletions

View File

@@ -11,11 +11,16 @@
"title": "Groups", "title": "Groups",
"subtitle": "Create, read, update and delete groups" "subtitle": "Create, read, update and delete groups"
}, },
"single-group": { "singleGroup": {
"navigationLabel": "Group Navigation",
"informationNavLink": "Information",
"errorTitle": "Error", "errorTitle": "Error",
"errorSubtitle": "Unknown group error" "errorSubtitle": "Unknown group error",
"menu": {
"navigationLabel": "Group Navigation",
"informationNavLink": "Information",
"settingsNavLink": "Settings",
"editNavLink": "General",
"permissionsNavLink": "Permissions"
}
}, },
"add-group": { "add-group": {
"title": "Create Group", "title": "Create Group",
@@ -53,9 +58,10 @@
"memberHelpText": "Usernames of the group members" "memberHelpText": "Usernames of the group members"
} }
}, },
"delete-group-button": { "deleteGroup": {
"label": "Delete", "subtitle": "Delete Group",
"confirm-alert": { "button": "Delete",
"confirmAlert": {
"title": "Delete Group", "title": "Delete Group",
"message": "Do you really want to delete the group?", "message": "Do you really want to delete the group?",
"submit": "Yes", "submit": "Yes",

View File

@@ -118,7 +118,7 @@
"loading": "Loading..." "loading": "Loading..."
} }
}, },
"delete": { "deleteRepo": {
"subtitle": "Delete Repository", "subtitle": "Delete Repository",
"button": "Delete", "button": "Delete",
"confirmAlert": { "confirmAlert": {

View File

@@ -42,10 +42,10 @@
"title": "Create User", "title": "Create User",
"subtitle": "Create a new user" "subtitle": "Create a new user"
}, },
"delete": { "deleteUser": {
"subtitle": "Delete User", "subtitle": "Delete User",
"button": "Delete", "button": "Delete",
"confirm-alert": { "confirmAlert": {
"title": "Delete user", "title": "Delete user",
"message": "Do you really want to delete the user?", "message": "Do you really want to delete the user?",
"submit": "Yes", "submit": "Yes",

View File

@@ -2,16 +2,16 @@
import React from "react"; import React from "react";
import { translate } from "react-i18next"; import { translate } from "react-i18next";
import type { Group } from "@scm-manager/ui-types"; import type { Group } from "@scm-manager/ui-types";
import { NavAction, confirmAlert } from "@scm-manager/ui-components"; import { Subtitle, DeleteButton, confirmAlert } from "@scm-manager/ui-components";
type Props = { type Props = {
group: Group, group: Group,
confirmDialog?: boolean, confirmDialog?: boolean,
t: string => string, deleteGroup: (group: Group) => void,
deleteGroup: (group: Group) => void t: string => string
}; };
export class DeleteGroupNavLink extends React.Component<Props> { export class DeleteGroup extends React.Component<Props> {
static defaultProps = { static defaultProps = {
confirmDialog: true confirmDialog: true
}; };
@@ -23,15 +23,15 @@ export class DeleteGroupNavLink extends React.Component<Props> {
confirmDelete = () => { confirmDelete = () => {
const { t } = this.props; const { t } = this.props;
confirmAlert({ confirmAlert({
title: t("delete-group-button.confirm-alert.title"), title: t("deleteGroup.confirmAlert.title"),
message: t("delete-group-button.confirm-alert.message"), message: t("deleteGroup.confirmAlert.message"),
buttons: [ buttons: [
{ {
label: t("delete-group-button.confirm-alert.submit"), label: t("deleteGroup.confirmAlert.submit"),
onClick: () => this.deleteGroup() onClick: () => this.deleteGroup()
}, },
{ {
label: t("delete-group-button.confirm-alert.cancel"), label: t("deleteGroup.confirmAlert.cancel"),
onClick: () => null onClick: () => null
} }
] ]
@@ -49,8 +49,21 @@ export class DeleteGroupNavLink extends React.Component<Props> {
if (!this.isDeletable()) { if (!this.isDeletable()) {
return null; return null;
} }
return <NavAction label={t("delete-group-button.label")} action={action} />;
return (
<>
<Subtitle subtitle={t("deleteGroup.subtitle")} />
<div className="columns">
<div className="column">
<DeleteButton
label={t("deleteGroup.button")}
action={action}
/>
</div>
</div>
</>
);
} }
} }
export default translate("groups")(DeleteGroupNavLink); export default translate("groups")(DeleteGroup);

View File

@@ -1,8 +1,8 @@
import React from "react"; import React from "react";
import { mount, shallow } from "enzyme"; import { mount, shallow } from "enzyme";
import "../../../tests/enzyme"; import "../../tests/enzyme";
import "../../../tests/i18n"; import "../../../tests/i18n";
import DeleteGroupNavLink from "./DeleteGroupNavLink"; import DeleteGroup from "./DeleteGroup";
import { confirmAlert } from "@scm-manager/ui-components"; import { confirmAlert } from "@scm-manager/ui-components";
jest.mock("@scm-manager/ui-components", () => ({ jest.mock("@scm-manager/ui-components", () => ({
@@ -17,7 +17,7 @@ describe("DeleteGroupNavLink", () => {
}; };
const navLink = shallow( const navLink = shallow(
<DeleteGroupNavLink group={group} deleteGroup={() => {}} /> <DeleteGroup group={group} deleteGroup={() => {}} />
); );
expect(navLink.text()).toBe(""); expect(navLink.text()).toBe("");
}); });
@@ -32,7 +32,7 @@ describe("DeleteGroupNavLink", () => {
}; };
const navLink = mount( const navLink = mount(
<DeleteGroupNavLink group={group} deleteGroup={() => {}} /> <DeleteGroup group={group} deleteGroup={() => {}} />
); );
expect(navLink.text()).not.toBe(""); expect(navLink.text()).not.toBe("");
}); });
@@ -47,7 +47,7 @@ describe("DeleteGroupNavLink", () => {
}; };
const navLink = mount( const navLink = mount(
<DeleteGroupNavLink group={group} deleteGroup={() => {}} /> <DeleteGroup group={group} deleteGroup={() => {}} />
); );
navLink.find("a").simulate("click"); navLink.find("a").simulate("click");
@@ -69,7 +69,7 @@ describe("DeleteGroupNavLink", () => {
} }
const navLink = mount( const navLink = mount(
<DeleteGroupNavLink <DeleteGroup
group={group} group={group}
confirmDialog={false} confirmDialog={false}
deleteGroup={capture} deleteGroup={capture}

View File

@@ -12,13 +12,13 @@ type Props = {
type State = {}; type State = {};
class EditGroupNavLink extends React.Component<Props, State> { class GeneralGroupNavLink extends React.Component<Props, State> {
render() { render() {
const { t, editUrl } = this.props; const { t, editUrl } = this.props;
if (!this.isEditable()) { if (!this.isEditable()) {
return null; return null;
} }
return <NavLink label={t("edit-group-button.label")} to={editUrl} />; return <NavLink label={t("singleGroup.menu.editNavLink")} to={editUrl} />;
} }
isEditable = () => { isEditable = () => {
@@ -26,4 +26,4 @@ class EditGroupNavLink extends React.Component<Props, State> {
}; };
} }
export default translate("groups")(EditGroupNavLink); export default translate("groups")(GeneralGroupNavLink);

View File

@@ -4,14 +4,14 @@ import React from "react";
import { shallow } from "enzyme"; import { shallow } from "enzyme";
import "../../../tests/enzyme"; import "../../../tests/enzyme";
import "../../../tests/i18n"; import "../../../tests/i18n";
import EditGroupNavLink from "./EditGroupNavLink"; import GeneralGroupNavLink from "./GeneralGroupNavLink";
it("should render nothing, if the edit link is missing", () => { it("should render nothing, if the edit link is missing", () => {
const group = { const group = {
_links: {} _links: {}
}; };
const navLink = shallow(<EditGroupNavLink group={group} editUrl='/group/edit'/>); const navLink = shallow(<GeneralGroupNavLink group={group} editUrl='/group/edit'/>);
expect(navLink.text()).toBe(""); expect(navLink.text()).toBe("");
}); });
@@ -24,6 +24,6 @@ it("should render the navLink", () => {
} }
}; };
const navLink = shallow(<EditGroupNavLink group={group} editUrl='/group/edit'/>); const navLink = shallow(<GeneralGroupNavLink group={group} editUrl='/group/edit'/>);
expect(navLink.text()).not.toBe(""); expect(navLink.text()).not.toBe("");
}); });

View File

@@ -1,2 +1 @@
export { default as DeleteGroupNavLink } from "./DeleteGroupNavLink"; export { default as GeneralGroupNavLink } from "./GeneralGroupNavLink";
export { default as EditGroupNavLink } from "./EditGroupNavLink";

View File

@@ -6,22 +6,22 @@ import {
ErrorPage, ErrorPage,
Loading, Loading,
Navigation, Navigation,
SubNavigation,
Section, Section,
NavLink NavLink
} from "@scm-manager/ui-components"; } from "@scm-manager/ui-components";
import { Route } from "react-router"; import { Route } from "react-router";
import { Details } from "./../components/table"; import { Details } from "./../components/table";
import { DeleteGroupNavLink, EditGroupNavLink } from "./../components/navLinks"; import {
GeneralGroupNavLink
} from "./../components/navLinks";
import type { Group } from "@scm-manager/ui-types"; import type { Group } from "@scm-manager/ui-types";
import type { History } from "history"; import type { History } from "history";
import { import {
deleteGroup,
fetchGroupByName, fetchGroupByName,
getGroupByName, getGroupByName,
isFetchGroupPending, isFetchGroupPending,
getFetchGroupFailure, getFetchGroupFailure
getDeleteGroupFailure,
isDeleteGroupPending
} from "../modules/groups"; } from "../modules/groups";
import { translate } from "react-i18next"; import { translate } from "react-i18next";
@@ -36,7 +36,6 @@ type Props = {
groupLink: string, groupLink: string,
// dispatcher functions // dispatcher functions
deleteGroup: (group: Group, callback?: () => void) => void,
fetchGroupByName: (string, string) => void, fetchGroupByName: (string, string) => void,
// context objects // context objects
@@ -57,14 +56,6 @@ class SingleGroup extends React.Component<Props> {
return url; return url;
}; };
deleteGroup = (group: Group) => {
this.props.deleteGroup(group, this.groupDeleted);
};
groupDeleted = () => {
this.props.history.push("/groups");
};
matchedUrl = () => { matchedUrl = () => {
return this.stripEndingSlash(this.props.match.url); return this.stripEndingSlash(this.props.match.url);
}; };
@@ -75,8 +66,8 @@ class SingleGroup extends React.Component<Props> {
if (error) { if (error) {
return ( return (
<ErrorPage <ErrorPage
title={t("single-group.errorTitle")} title={t("singleGroup.errorTitle")}
subtitle={t("single-group.errorSubtitle")} subtitle={t("singleGroup.errorSubtitle")}
error={error} error={error}
/> />
); );
@@ -98,18 +89,27 @@ class SingleGroup extends React.Component<Props> {
component={() => <Details group={group} />} component={() => <Details group={group} />}
/> />
<Route <Route
path={`${url}/edit`} path={`${url}/settings/general`}
exact exact
component={() => <EditGroup group={group} />} component={() => <EditGroup group={group} />}
/> />
</div> </div>
<div className="column"> <div className="column">
<Navigation> <Navigation>
<Section label={t("single-group.navigationLabel")}> <Section label={t("singleGroup.menu.navigationLabel")}>
<NavLink <NavLink
to={`${url}`} to={`${url}`}
label={t("single-group.informationNavLink")} label={t("singleGroup.menu.informationNavLink")}
/> />
<SubNavigation
to={`${url}/settings/general`}
label={t("singleGroup.menu.settingsNavLink")}
>
<GeneralGroupNavLink
group={group}
editUrl={`${url}/settings/general`}
/>
</SubNavigation>
</Section> </Section>
</Navigation> </Navigation>
</div> </div>
@@ -122,10 +122,8 @@ class SingleGroup extends React.Component<Props> {
const mapStateToProps = (state, ownProps) => { const mapStateToProps = (state, ownProps) => {
const name = ownProps.match.params.name; const name = ownProps.match.params.name;
const group = getGroupByName(state, name); const group = getGroupByName(state, name);
const loading = const loading = isFetchGroupPending(state, name);
isFetchGroupPending(state, name) || isDeleteGroupPending(state, name); const error = getFetchGroupFailure(state, name);
const error =
getFetchGroupFailure(state, name) || getDeleteGroupFailure(state, name);
const groupLink = getGroupsLink(state); const groupLink = getGroupsLink(state);
return { return {
@@ -141,9 +139,6 @@ const mapDispatchToProps = dispatch => {
return { return {
fetchGroupByName: (link: string, name: string) => { fetchGroupByName: (link: string, name: string) => {
dispatch(fetchGroupByName(link, name)); dispatch(fetchGroupByName(link, name));
},
deleteGroup: (group: Group, callback?: () => void) => {
dispatch(deleteGroup(group, callback));
} }
}; };
}; };

View File

@@ -1,8 +1,8 @@
//@flow //@flow
import React from "react"; import React from "react";
import { translate } from "react-i18next"; import { translate } from "react-i18next";
import { Subtitle, DeleteButton, confirmAlert } from "@scm-manager/ui-components";
import type { Repository } from "@scm-manager/ui-types"; import type { Repository } from "@scm-manager/ui-types";
import { Subtitle, DeleteButton, confirmAlert } from "@scm-manager/ui-components";
type Props = { type Props = {
repository: Repository, repository: Repository,
@@ -20,22 +20,22 @@ class DeleteRepo extends React.Component<Props> {
confirmDialog: true confirmDialog: true
}; };
delete = () => { deleteRepo = () => {
this.props.delete(this.props.repository); this.props.delete(this.props.repository);
}; };
confirmDelete = () => { confirmDelete = () => {
const { t } = this.props; const { t } = this.props;
confirmAlert({ confirmAlert({
title: t("delete.confirmAlert.title"), title: t("deleteRepo.confirmAlert.title"),
message: t("delete.confirmAlert.message"), message: t("deleteRepo.confirmAlert.message"),
buttons: [ buttons: [
{ {
label: t("delete.confirmAlert.submit"), label: t("deleteRepo.confirmAlert.submit"),
onClick: () => this.delete() onClick: () => this.deleteRepo()
}, },
{ {
label: t("delete.confirmAlert.cancel"), label: t("deleteRepo.confirmAlert.cancel"),
onClick: () => null onClick: () => null
} }
] ]
@@ -48,7 +48,7 @@ class DeleteRepo extends React.Component<Props> {
render() { render() {
const { confirmDialog, t } = this.props; const { confirmDialog, t } = this.props;
const action = confirmDialog ? this.confirmDelete : this.delete(); const action = confirmDialog ? this.confirmDelete : this.deleteRepo;
if (!this.isDeletable()) { if (!this.isDeletable()) {
return null; return null;
@@ -56,11 +56,11 @@ class DeleteRepo extends React.Component<Props> {
return ( return (
<> <>
<Subtitle subtitle={t("delete.subtitle")} /> <Subtitle subtitle={t("deleteRepo.subtitle")} />
<div className="columns"> <div className="columns">
<div className="column"> <div className="column">
<DeleteButton <DeleteButton
label={t("delete.button")} label={t("deleteRepo.button")}
action={action} action={action}
/> />
</div> </div>

View File

@@ -1,8 +1,8 @@
// @flow // @flow
import React from "react"; import React from "react";
import { translate } from "react-i18next"; import { translate } from "react-i18next";
import { Subtitle, DeleteButton, confirmAlert } from "@scm-manager/ui-components";
import type { User } from "@scm-manager/ui-types"; import type { User } from "@scm-manager/ui-types";
import { Subtitle, DeleteButton, confirmAlert } from "@scm-manager/ui-components";
type Props = { type Props = {
user: User, user: User,
@@ -27,15 +27,15 @@ class DeleteUser extends React.Component<Props> {
confirmDelete = () => { confirmDelete = () => {
const { t } = this.props; const { t } = this.props;
confirmAlert({ confirmAlert({
title: t("delete.confirm-alert.title"), title: t("deleteUser.confirmAlert.title"),
message: t("delete.confirm-alert.message"), message: t("deleteUser.confirmAlert.message"),
buttons: [ buttons: [
{ {
label: t("delete.confirm-alert.submit"), label: t("deleteUser.confirmAlert.submit"),
onClick: () => this.deleteUser() onClick: () => this.deleteUser()
}, },
{ {
label: t("delete.confirm-alert.cancel"), label: t("deleteUser.confirmAlert.cancel"),
onClick: () => null onClick: () => null
} }
] ]
@@ -56,11 +56,11 @@ class DeleteUser extends React.Component<Props> {
return ( return (
<> <>
<Subtitle subtitle={t("delete.subtitle")} /> <Subtitle subtitle={t("deleteUser.subtitle")} />
<div className="columns"> <div className="columns">
<div className="column"> <div className="column">
<DeleteButton <DeleteButton
label={t("delete.button")} label={t("deleteUser.button")}
action={action} action={action}
/> />
</div> </div>