mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-02 11:35:57 +01:00
finish delete implementation and restructure components
This commit is contained in:
@@ -28,5 +28,14 @@
|
||||
},
|
||||
"repository-form": {
|
||||
"submit": "Speichern"
|
||||
},
|
||||
"delete-nav-action": {
|
||||
"label": "Delete",
|
||||
"confirm-alert": {
|
||||
"title": "Delete repository",
|
||||
"message": "Do you really want to delete the repository?",
|
||||
"submit": "Yes",
|
||||
"cancel": "No"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
59
scm-ui/src/repos/components/DeleteNavAction.js
Normal file
59
scm-ui/src/repos/components/DeleteNavAction.js
Normal file
@@ -0,0 +1,59 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import { translate } from "react-i18next";
|
||||
import { confirmAlert } from "../../components/modals/ConfirmAlert";
|
||||
import { NavAction } from "../../components/navigation";
|
||||
import type { Repository } from "../types/Repositories";
|
||||
|
||||
type Props = {
|
||||
repository: Repository,
|
||||
confirmDialog?: boolean,
|
||||
delete: Repository => void,
|
||||
|
||||
// context props
|
||||
t: string => string
|
||||
};
|
||||
|
||||
class DeleteNavAction extends React.Component<Props> {
|
||||
static defaultProps = {
|
||||
confirmDialog: true
|
||||
};
|
||||
|
||||
delete = () => {
|
||||
this.props.delete(this.props.repository);
|
||||
};
|
||||
|
||||
confirmDelete = () => {
|
||||
const { t } = this.props;
|
||||
confirmAlert({
|
||||
title: t("delete-nav-action.confirm-alert.title"),
|
||||
message: t("delete-nav-action.confirm-alert.message"),
|
||||
buttons: [
|
||||
{
|
||||
label: t("delete-nav-action.confirm-alert.submit"),
|
||||
onClick: () => this.delete()
|
||||
},
|
||||
{
|
||||
label: t("delete-nav-action.confirm-alert.cancel"),
|
||||
onClick: () => null
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
isDeletable = () => {
|
||||
return this.props.repository._links.delete;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { confirmDialog, t } = this.props;
|
||||
const action = confirmDialog ? this.confirmDelete : this.delete();
|
||||
|
||||
if (!this.isDeletable()) {
|
||||
return null;
|
||||
}
|
||||
return <NavAction label={t("delete-nav-action.label")} action={action} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default translate("repos")(DeleteNavAction);
|
||||
79
scm-ui/src/repos/components/DeleteNavAction.test.js
Normal file
79
scm-ui/src/repos/components/DeleteNavAction.test.js
Normal file
@@ -0,0 +1,79 @@
|
||||
import React from "react";
|
||||
import { mount, shallow } from "enzyme";
|
||||
import "../../tests/enzyme";
|
||||
import "../../tests/i18n";
|
||||
import DeleteNavAction from "./DeleteNavAction";
|
||||
|
||||
import { confirmAlert } from "../../components/modals/ConfirmAlert";
|
||||
jest.mock("../../components/modals/ConfirmAlert");
|
||||
|
||||
describe("DeleteNavAction", () => {
|
||||
it("should render nothing, if the delete link is missing", () => {
|
||||
const repository = {
|
||||
_links: {}
|
||||
};
|
||||
|
||||
const navLink = shallow(
|
||||
<DeleteNavAction repository={repository} delete={() => {}} />
|
||||
);
|
||||
expect(navLink.text()).toBe("");
|
||||
});
|
||||
|
||||
it("should render the navLink", () => {
|
||||
const repository = {
|
||||
_links: {
|
||||
delete: {
|
||||
href: "/repositories"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const navLink = mount(
|
||||
<DeleteNavAction repository={repository} delete={() => {}} />
|
||||
);
|
||||
expect(navLink.text()).not.toBe("");
|
||||
});
|
||||
|
||||
it("should open the confirm dialog on navLink click", () => {
|
||||
const repository = {
|
||||
_links: {
|
||||
delete: {
|
||||
href: "/repositorys"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const navLink = mount(
|
||||
<DeleteNavAction repository={repository} delete={() => {}} />
|
||||
);
|
||||
navLink.find("a").simulate("click");
|
||||
|
||||
expect(confirmAlert.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
it("should call the delete repository function with delete url", () => {
|
||||
const repository = {
|
||||
_links: {
|
||||
delete: {
|
||||
href: "/repos"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let calledUrl = null;
|
||||
function capture(repository) {
|
||||
calledUrl = repository._links.delete.href;
|
||||
}
|
||||
|
||||
const navLink = mount(
|
||||
<DeleteNavAction
|
||||
repository={repository}
|
||||
confirmDialog={false}
|
||||
delete={capture}
|
||||
/>
|
||||
);
|
||||
navLink.find("a").simulate("click");
|
||||
|
||||
expect(calledUrl).toBe("/repos");
|
||||
});
|
||||
});
|
||||
@@ -1,12 +1,12 @@
|
||||
// @flow
|
||||
import React from "react";
|
||||
import { translate } from "react-i18next";
|
||||
import { InputField, Select } from "../../components/forms";
|
||||
import { SubmitButton } from "../../components/buttons";
|
||||
import type { Repository } from "../types/Repositories";
|
||||
import { InputField, Select } from "../../../components/forms/index";
|
||||
import { SubmitButton } from "../../../components/buttons/index";
|
||||
import type { Repository } from "../../types/Repositories";
|
||||
import * as validator from "./repositoryValidation";
|
||||
import type { RepositoryType } from "../types/RepositoryTypes";
|
||||
import Textarea from "../../components/forms/Textarea";
|
||||
import type { RepositoryType } from "../../types/RepositoryTypes";
|
||||
import Textarea from "../../../components/forms/Textarea";
|
||||
|
||||
type Props = {
|
||||
submitForm: Repository => void,
|
||||
2
scm-ui/src/repos/components/form/index.js
Normal file
2
scm-ui/src/repos/components/form/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
import RepositoryForm from "./RepositoryForm";
|
||||
export default RepositoryForm;
|
||||
@@ -1,5 +1,5 @@
|
||||
// @flow
|
||||
import * as generalValidator from "../../components/validation";
|
||||
import * as generalValidator from "../../../components/validation";
|
||||
|
||||
export const isNameValid = (name: string) => {
|
||||
return generalValidator.isNameValid(name);
|
||||
@@ -2,12 +2,12 @@
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import injectSheet from "react-jss";
|
||||
import type { Repository } from "../types/Repositories";
|
||||
import DateFromNow from "../../components/DateFromNow";
|
||||
import type { Repository } from "../../types/Repositories";
|
||||
import DateFromNow from "../../../components/DateFromNow";
|
||||
import RepositoryEntryLink from "./RepositoryEntryLink";
|
||||
import classNames from "classnames";
|
||||
|
||||
import icon from "../../images/blib.jpg";
|
||||
import icon from "../../../images/blib.jpg";
|
||||
|
||||
// TODO we need a variable or something central for the hover
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import type { RepositoryGroup } from "../types/Repositories";
|
||||
import type { RepositoryGroup } from "../../types/Repositories";
|
||||
import injectSheet from "react-jss";
|
||||
import classNames from "classnames";
|
||||
import RepositoryEntry from "./RepositoryEntry";
|
||||
@@ -1,7 +1,7 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
|
||||
import type { Repository } from "../types/Repositories";
|
||||
import type { Repository } from "../../types/Repositories";
|
||||
|
||||
import groupByNamespace from "./groupByNamespace";
|
||||
import RepositoryGroupEntry from "./RepositoryGroupEntry";
|
||||
@@ -1,5 +1,5 @@
|
||||
// @flow
|
||||
import type { Repository, RepositoryGroup } from "../types/Repositories";
|
||||
import type { Repository, RepositoryGroup } from "../../types/Repositories";
|
||||
|
||||
export default function groupByNamespace(
|
||||
repositories: Repository[]
|
||||
2
scm-ui/src/repos/components/list/index.js
Normal file
2
scm-ui/src/repos/components/list/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
import RepositoryList from "./RepositoryList";
|
||||
export default RepositoryList;
|
||||
@@ -3,7 +3,7 @@ import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { translate } from "react-i18next";
|
||||
import { Page } from "../../components/layout";
|
||||
import RepositoryForm from "../components/RepositoryForm";
|
||||
import RepositoryForm from "../components/form";
|
||||
import type { RepositoryType } from "../types/RepositoryTypes";
|
||||
import {
|
||||
fetchRepositoryTypesIfNeeded,
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
} from "../modules/repos";
|
||||
import { translate } from "react-i18next";
|
||||
import { Page } from "../../components/layout";
|
||||
import RepositoryList from "../components/RepositoryList";
|
||||
import RepositoryList from "../components/list";
|
||||
import Paginator from "../../components/Paginator";
|
||||
import { withRouter } from "react-router-dom";
|
||||
import type { History } from "history";
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import {
|
||||
deleteRepo,
|
||||
fetchRepo,
|
||||
getFetchRepoFailure,
|
||||
getRepository,
|
||||
@@ -15,6 +16,9 @@ import ErrorPage from "../../components/ErrorPage";
|
||||
import { translate } from "react-i18next";
|
||||
import { Navigation, NavLink, Section } from "../../components/navigation";
|
||||
import RepositoryDetails from "../components/RepositoryDetails";
|
||||
import DeleteNavAction from "../components/DeleteNavAction";
|
||||
|
||||
import type { History } from "history";
|
||||
|
||||
type Props = {
|
||||
namespace: string,
|
||||
@@ -25,9 +29,11 @@ type Props = {
|
||||
|
||||
// dispatch functions
|
||||
fetchRepo: (namespace: string, name: string) => void,
|
||||
deleteRepo: (repository: Repository, () => void) => void,
|
||||
|
||||
// context props
|
||||
t: string => string,
|
||||
history: History,
|
||||
match: any
|
||||
};
|
||||
|
||||
@@ -49,6 +55,14 @@ class RepositoryRoot extends React.Component<Props> {
|
||||
return this.stripEndingSlash(this.props.match.url);
|
||||
};
|
||||
|
||||
deleted = () => {
|
||||
this.props.history.push("/repos");
|
||||
};
|
||||
|
||||
delete = (repository: Repository) => {
|
||||
this.props.deleteRepo(repository, this.deleted);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { loading, error, repository, t } = this.props;
|
||||
|
||||
@@ -81,6 +95,7 @@ class RepositoryRoot extends React.Component<Props> {
|
||||
<div className="column">
|
||||
<Navigation>
|
||||
<Section label={t("repository-root.actions-label")}>
|
||||
<DeleteNavAction repository={repository} delete={this.delete} />
|
||||
<NavLink to="/repos" label={t("repository-root.back-label")} />
|
||||
</Section>
|
||||
</Navigation>
|
||||
@@ -109,6 +124,9 @@ const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
fetchRepo: (namespace: string, name: string) => {
|
||||
dispatch(fetchRepo(namespace, name));
|
||||
},
|
||||
deleteRepo: (repository: Repository, callback: () => void) => {
|
||||
dispatch(deleteRepo(repository, callback));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user