split AddRepository component into two separate components to simplify the state handling

This commit is contained in:
Eduard Heimbuch
2020-12-02 13:26:31 +01:00
parent 7db33d2e65
commit dffe466405
6 changed files with 81 additions and 76 deletions

View File

@@ -31,13 +31,13 @@ import Users from "../users/containers/Users";
import Login from "../containers/Login";
import Logout from "../containers/Logout";
import { ProtectedRoute, ErrorBoundary } from "@scm-manager/ui-components";
import { ErrorBoundary, ProtectedRoute } from "@scm-manager/ui-components";
import { binder, ExtensionPoint } from "@scm-manager/ui-extensions";
import CreateUser from "../users/containers/CreateUser";
import SingleUser from "../users/containers/SingleUser";
import RepositoryRoot from "../repos/containers/RepositoryRoot";
import AddRepository from "../repos/containers/AddRepository";
import CreateRepository from "../repos/containers/CreateRepository";
import Groups from "../groups/containers/Groups";
import SingleGroup from "../groups/containers/SingleGroup";
@@ -47,6 +47,7 @@ import Admin from "../admin/containers/Admin";
import Profile from "./Profile";
import NamespaceRoot from "../repos/namespaces/containers/NamespaceRoot";
import ImportRepository from "../repos/containers/ImportRepository";
type Props = {
me: Me;
@@ -77,8 +78,8 @@ class Main extends React.Component<Props> {
<Route path="/logout" component={Logout} />
<Redirect exact strict from="/repos" to="/repos/" />
<ProtectedRoute exact path="/repos/" component={Overview} authenticated={authenticated} />
<ProtectedRoute exact path="/repos/create" component={AddRepository} authenticated={authenticated} />
<ProtectedRoute exact path="/repos/import" component={AddRepository} authenticated={authenticated} />
<ProtectedRoute exact path="/repos/create" component={CreateRepository} authenticated={authenticated} />
<ProtectedRoute exact path="/repos/import" component={ImportRepository} authenticated={authenticated} />
<ProtectedRoute exact path="/repos/:namespace" component={Overview} authenticated={authenticated} />
<ProtectedRoute exact path="/repos/:namespace/:page" component={Overview} authenticated={authenticated} />
<ProtectedRoute path="/repo/:namespace/:name" component={RepositoryRoot} authenticated={authenticated} />

View File

@@ -49,21 +49,21 @@ const ImportRepositoryFromUrl: FC<Props> = ({ url, setImportPending }) => {
});
const [valid, setValid] = useState({ namespaceAndName: false, contact: true, importUrl: false });
const isValid = () => {
return Object.values(valid).every(v => v);
};
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | undefined>();
const history = useHistory();
const [t] = useTranslation("repos");
const isValid = () => Object.values(valid).every(v => v);
const handleImportLoading = (loading: boolean) => {
setLoading(loading);
setImportPending(loading);
setLoading(loading);
};
const submit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
setError(undefined);
const currentPath = history.location.pathname;
handleImportLoading(true);
apiClient

View File

@@ -45,7 +45,6 @@ import {
} from "../../admin/modules/namespaceStrategies";
import { RouteComponentProps, withRouter } from "react-router-dom";
import { compose } from "redux";
import ImportRepository from "./ImportRepository";
type Props = WithTranslation &
RouteComponentProps & {
@@ -72,19 +71,7 @@ type Props = WithTranslation &
history: History;
};
type State = {
importPending: boolean;
};
class AddRepository extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
importPending: false
};
}
class CreateRepository extends React.Component<Props> {
componentDidMount() {
this.props.resetForm();
this.props.fetchRepositoryTypesIfNeeded();
@@ -95,30 +82,6 @@ class AddRepository extends React.Component<Props, State> {
this.props.history.push("/repo/" + repo.namespace + "/" + repo.name);
};
resolveLocation = () => {
const currentUrl = this.props.location.pathname;
if (currentUrl.includes("/repos/create")) {
return "create";
}
if (currentUrl.includes("/repos/import")) {
return "import";
}
return "";
};
isImportPage = () => this.resolveLocation() === "import";
isCreatePage = () => this.resolveLocation() === "create";
getSubtitle = () => {
if (this.isCreatePage()) {
return "create.subtitle";
} else if (this.isImportPage() && this.state.importPending) {
return "import.pending.subtitle";
} else {
return "import.subtitle";
}
};
render() {
const {
pageLoading,
@@ -135,19 +98,12 @@ class AddRepository extends React.Component<Props, State> {
return (
<Page
title={t("create.title")}
subtitle={t(this.getSubtitle())}
afterTitle={<RepositoryFormSwitcher creationMode={this.isImportPage() ? "IMPORT" : "CREATE"} />}
subtitle={t("create.subtitle")}
afterTitle={<RepositoryFormSwitcher creationMode={"CREATE"} />}
loading={pageLoading}
error={error}
showContentOnError={true}
>
{this.isImportPage() && (
<ImportRepository
repositoryTypes={repositoryTypes}
setPending={(importPending: boolean) => this.setState({ importPending })}
/>
)}
{this.isCreatePage() && (
<RepositoryForm
repositoryTypes={repositoryTypes}
loading={createLoading}
@@ -157,7 +113,6 @@ class AddRepository extends React.Component<Props, State> {
}}
indexResources={indexResources}
/>
)}
</Page>
);
}
@@ -205,4 +160,4 @@ export default compose(
withRouter,
withTranslation("repos"),
connect(mapStateToProps, mapDispatchToProps)
)(AddRepository);
)(CreateRepository);

View File

@@ -29,22 +29,41 @@ import { useTranslation } from "react-i18next";
import ImportRepositoryTypeSelect from "../components/ImportRepositoryTypeSelect";
import ImportTypeSelect from "../components/ImportTypeSelect";
import ImportRepositoryFromUrl from "../components/ImportRepositoryFromUrl";
import { Loading, Notification } from "@scm-manager/ui-components";
import { Loading, Notification, Page } from "@scm-manager/ui-components";
import RepositoryFormSwitcher from "../components/form/RepositoryFormSwitcher";
import {
fetchRepositoryTypesIfNeeded,
getFetchRepositoryTypesFailure,
getRepositoryTypes,
isFetchRepositoryTypesPending
} from "../modules/repositoryTypes";
import { connect } from "react-redux";
import { fetchNamespaceStrategiesIfNeeded } from "../../admin/modules/namespaceStrategies";
type Props = {
repositoryTypes: RepositoryType[];
setPending: (pending: boolean) => void;
pageLoading: boolean;
error?: Error;
fetchRepositoryTypesIfNeeded: () => void;
fetchNamespaceStrategiesIfNeeded: () => void;
};
const ImportRepository: FC<Props> = ({ repositoryTypes, setPending }) => {
const ImportRepository: FC<Props> = ({
repositoryTypes,
pageLoading,
error,
fetchRepositoryTypesIfNeeded,
fetchNamespaceStrategiesIfNeeded
}) => {
const [importPending, setImportPending] = useState(false);
const [repositoryType, setRepositoryType] = useState<RepositoryType | undefined>();
const [importType, setImportType] = useState("");
const [t] = useTranslation("repos");
useEffect(() => {
setPending(importPending);
}, [importPending]);
fetchRepositoryTypesIfNeeded();
fetchNamespaceStrategiesIfNeeded();
}, [repositoryTypes]);
const changeRepositoryType = (repositoryType: RepositoryType) => {
setRepositoryType(repositoryType);
@@ -65,7 +84,14 @@ const ImportRepository: FC<Props> = ({ repositoryTypes, setPending }) => {
};
return (
<div>
<Page
title={t("create.title")}
subtitle={t("import.subtitle")}
afterTitle={<RepositoryFormSwitcher creationMode={"IMPORT"} />}
loading={pageLoading}
error={error}
showContentOnError={true}
>
{importPending && (
<>
<Notification type="info">{t("import.pending.infoText")}</Notification>
@@ -92,8 +118,31 @@ const ImportRepository: FC<Props> = ({ repositoryTypes, setPending }) => {
</>
)}
{importType && renderImportComponent()}
</div>
</Page>
);
};
export default ImportRepository;
const mapStateToProps = (state: any) => {
const repositoryTypes = getRepositoryTypes(state);
const pageLoading = isFetchRepositoryTypesPending(state);
const error = getFetchRepositoryTypesFailure(state);
return {
repositoryTypes,
pageLoading,
error
};
};
const mapDispatchToProps = (dispatch: any) => {
return {
fetchRepositoryTypesIfNeeded: () => {
dispatch(fetchRepositoryTypesIfNeeded());
},
fetchNamespaceStrategiesIfNeeded: () => {
dispatch(fetchNamespaceStrategiesIfNeeded());
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(ImportRepository);

View File

@@ -289,7 +289,7 @@
},
"D6SHRfqQw1": {
"displayName": "Repository Import fehlgeschlagen",
"description": "Das Repository konnte nicht importiert werden. Entweder wurden die Zugangsdaten (Benutzername/Passwort) nicht gesetzt oder sind fehlerhaft. Bitte prüfen Sie Ihre Eingaben."
"description": "Das Repository konnte nicht importiert werden. Möglicherweise wurden die Zugangsdaten (Benutzername/Passwort) nicht gesetzt oder sind fehlerhaft. Bitte prüfen Sie Ihre Eingaben."
}
},
"namespaceStrategies": {

View File

@@ -289,7 +289,7 @@
},
"D6SHRfqQw1": {
"displayName": "Repository import failed",
"description": "The repository could not be imported. Either the credentials (username/password) are wrong or missing. Please check your inputs."
"description": "The repository could not be imported. It's likely that either the credentials (username/password) are wrong or missing. Please check your inputs."
}
},
"namespaceStrategies": {