mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-02 11:35:57 +01:00
split AddRepository component into two separate components to simplify the state handling
This commit is contained in:
@@ -31,13 +31,13 @@ import Users from "../users/containers/Users";
|
|||||||
import Login from "../containers/Login";
|
import Login from "../containers/Login";
|
||||||
import Logout from "../containers/Logout";
|
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 { binder, ExtensionPoint } from "@scm-manager/ui-extensions";
|
||||||
|
|
||||||
import CreateUser from "../users/containers/CreateUser";
|
import CreateUser from "../users/containers/CreateUser";
|
||||||
import SingleUser from "../users/containers/SingleUser";
|
import SingleUser from "../users/containers/SingleUser";
|
||||||
import RepositoryRoot from "../repos/containers/RepositoryRoot";
|
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 Groups from "../groups/containers/Groups";
|
||||||
import SingleGroup from "../groups/containers/SingleGroup";
|
import SingleGroup from "../groups/containers/SingleGroup";
|
||||||
@@ -47,6 +47,7 @@ import Admin from "../admin/containers/Admin";
|
|||||||
|
|
||||||
import Profile from "./Profile";
|
import Profile from "./Profile";
|
||||||
import NamespaceRoot from "../repos/namespaces/containers/NamespaceRoot";
|
import NamespaceRoot from "../repos/namespaces/containers/NamespaceRoot";
|
||||||
|
import ImportRepository from "../repos/containers/ImportRepository";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
me: Me;
|
me: Me;
|
||||||
@@ -77,8 +78,8 @@ class Main extends React.Component<Props> {
|
|||||||
<Route path="/logout" component={Logout} />
|
<Route path="/logout" component={Logout} />
|
||||||
<Redirect exact strict from="/repos" to="/repos/" />
|
<Redirect exact strict from="/repos" to="/repos/" />
|
||||||
<ProtectedRoute exact path="/repos/" component={Overview} authenticated={authenticated} />
|
<ProtectedRoute exact path="/repos/" component={Overview} authenticated={authenticated} />
|
||||||
<ProtectedRoute exact path="/repos/create" component={AddRepository} authenticated={authenticated} />
|
<ProtectedRoute exact path="/repos/create" component={CreateRepository} authenticated={authenticated} />
|
||||||
<ProtectedRoute exact path="/repos/import" component={AddRepository} 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" component={Overview} authenticated={authenticated} />
|
||||||
<ProtectedRoute exact path="/repos/:namespace/:page" component={Overview} authenticated={authenticated} />
|
<ProtectedRoute exact path="/repos/:namespace/:page" component={Overview} authenticated={authenticated} />
|
||||||
<ProtectedRoute path="/repo/:namespace/:name" component={RepositoryRoot} authenticated={authenticated} />
|
<ProtectedRoute path="/repo/:namespace/:name" component={RepositoryRoot} authenticated={authenticated} />
|
||||||
|
|||||||
@@ -49,21 +49,21 @@ const ImportRepositoryFromUrl: FC<Props> = ({ url, setImportPending }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [valid, setValid] = useState({ namespaceAndName: false, contact: true, importUrl: false });
|
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 [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState<Error | undefined>();
|
const [error, setError] = useState<Error | undefined>();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const [t] = useTranslation("repos");
|
const [t] = useTranslation("repos");
|
||||||
|
|
||||||
|
const isValid = () => Object.values(valid).every(v => v);
|
||||||
|
|
||||||
const handleImportLoading = (loading: boolean) => {
|
const handleImportLoading = (loading: boolean) => {
|
||||||
setLoading(loading);
|
|
||||||
setImportPending(loading);
|
setImportPending(loading);
|
||||||
|
setLoading(loading);
|
||||||
};
|
};
|
||||||
|
|
||||||
const submit = (event: FormEvent<HTMLFormElement>) => {
|
const submit = (event: FormEvent<HTMLFormElement>) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
setError(undefined);
|
||||||
const currentPath = history.location.pathname;
|
const currentPath = history.location.pathname;
|
||||||
handleImportLoading(true);
|
handleImportLoading(true);
|
||||||
apiClient
|
apiClient
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ import {
|
|||||||
} from "../../admin/modules/namespaceStrategies";
|
} from "../../admin/modules/namespaceStrategies";
|
||||||
import { RouteComponentProps, withRouter } from "react-router-dom";
|
import { RouteComponentProps, withRouter } from "react-router-dom";
|
||||||
import { compose } from "redux";
|
import { compose } from "redux";
|
||||||
import ImportRepository from "./ImportRepository";
|
|
||||||
|
|
||||||
type Props = WithTranslation &
|
type Props = WithTranslation &
|
||||||
RouteComponentProps & {
|
RouteComponentProps & {
|
||||||
@@ -72,19 +71,7 @@ type Props = WithTranslation &
|
|||||||
history: History;
|
history: History;
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = {
|
class CreateRepository extends React.Component<Props> {
|
||||||
importPending: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AddRepository extends React.Component<Props, State> {
|
|
||||||
constructor(props: Props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
importPending: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.resetForm();
|
this.props.resetForm();
|
||||||
this.props.fetchRepositoryTypesIfNeeded();
|
this.props.fetchRepositoryTypesIfNeeded();
|
||||||
@@ -95,30 +82,6 @@ class AddRepository extends React.Component<Props, State> {
|
|||||||
this.props.history.push("/repo/" + repo.namespace + "/" + repo.name);
|
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() {
|
render() {
|
||||||
const {
|
const {
|
||||||
pageLoading,
|
pageLoading,
|
||||||
@@ -135,29 +98,21 @@ class AddRepository extends React.Component<Props, State> {
|
|||||||
return (
|
return (
|
||||||
<Page
|
<Page
|
||||||
title={t("create.title")}
|
title={t("create.title")}
|
||||||
subtitle={t(this.getSubtitle())}
|
subtitle={t("create.subtitle")}
|
||||||
afterTitle={<RepositoryFormSwitcher creationMode={this.isImportPage() ? "IMPORT" : "CREATE"} />}
|
afterTitle={<RepositoryFormSwitcher creationMode={"CREATE"} />}
|
||||||
loading={pageLoading}
|
loading={pageLoading}
|
||||||
error={error}
|
error={error}
|
||||||
showContentOnError={true}
|
showContentOnError={true}
|
||||||
>
|
>
|
||||||
{this.isImportPage() && (
|
<RepositoryForm
|
||||||
<ImportRepository
|
repositoryTypes={repositoryTypes}
|
||||||
repositoryTypes={repositoryTypes}
|
loading={createLoading}
|
||||||
setPending={(importPending: boolean) => this.setState({ importPending })}
|
namespaceStrategy={namespaceStrategies.current}
|
||||||
/>
|
createRepository={(repo, initRepository) => {
|
||||||
)}
|
createRepo(repoLink, repo, initRepository, (repo: Repository) => this.repoCreated(repo));
|
||||||
{this.isCreatePage() && (
|
}}
|
||||||
<RepositoryForm
|
indexResources={indexResources}
|
||||||
repositoryTypes={repositoryTypes}
|
/>
|
||||||
loading={createLoading}
|
|
||||||
namespaceStrategy={namespaceStrategies.current}
|
|
||||||
createRepository={(repo, initRepository) => {
|
|
||||||
createRepo(repoLink, repo, initRepository, (repo: Repository) => this.repoCreated(repo));
|
|
||||||
}}
|
|
||||||
indexResources={indexResources}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -205,4 +160,4 @@ export default compose(
|
|||||||
withRouter,
|
withRouter,
|
||||||
withTranslation("repos"),
|
withTranslation("repos"),
|
||||||
connect(mapStateToProps, mapDispatchToProps)
|
connect(mapStateToProps, mapDispatchToProps)
|
||||||
)(AddRepository);
|
)(CreateRepository);
|
||||||
@@ -29,22 +29,41 @@ import { useTranslation } from "react-i18next";
|
|||||||
import ImportRepositoryTypeSelect from "../components/ImportRepositoryTypeSelect";
|
import ImportRepositoryTypeSelect from "../components/ImportRepositoryTypeSelect";
|
||||||
import ImportTypeSelect from "../components/ImportTypeSelect";
|
import ImportTypeSelect from "../components/ImportTypeSelect";
|
||||||
import ImportRepositoryFromUrl from "../components/ImportRepositoryFromUrl";
|
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 = {
|
type Props = {
|
||||||
repositoryTypes: RepositoryType[];
|
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 [importPending, setImportPending] = useState(false);
|
||||||
const [repositoryType, setRepositoryType] = useState<RepositoryType | undefined>();
|
const [repositoryType, setRepositoryType] = useState<RepositoryType | undefined>();
|
||||||
const [importType, setImportType] = useState("");
|
const [importType, setImportType] = useState("");
|
||||||
const [t] = useTranslation("repos");
|
const [t] = useTranslation("repos");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setPending(importPending);
|
fetchRepositoryTypesIfNeeded();
|
||||||
}, [importPending]);
|
fetchNamespaceStrategiesIfNeeded();
|
||||||
|
}, [repositoryTypes]);
|
||||||
|
|
||||||
const changeRepositoryType = (repositoryType: RepositoryType) => {
|
const changeRepositoryType = (repositoryType: RepositoryType) => {
|
||||||
setRepositoryType(repositoryType);
|
setRepositoryType(repositoryType);
|
||||||
@@ -65,7 +84,14 @@ const ImportRepository: FC<Props> = ({ repositoryTypes, setPending }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<Page
|
||||||
|
title={t("create.title")}
|
||||||
|
subtitle={t("import.subtitle")}
|
||||||
|
afterTitle={<RepositoryFormSwitcher creationMode={"IMPORT"} />}
|
||||||
|
loading={pageLoading}
|
||||||
|
error={error}
|
||||||
|
showContentOnError={true}
|
||||||
|
>
|
||||||
{importPending && (
|
{importPending && (
|
||||||
<>
|
<>
|
||||||
<Notification type="info">{t("import.pending.infoText")}</Notification>
|
<Notification type="info">{t("import.pending.infoText")}</Notification>
|
||||||
@@ -92,8 +118,31 @@ const ImportRepository: FC<Props> = ({ repositoryTypes, setPending }) => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{importType && renderImportComponent()}
|
{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);
|
||||||
|
|||||||
@@ -289,7 +289,7 @@
|
|||||||
},
|
},
|
||||||
"D6SHRfqQw1": {
|
"D6SHRfqQw1": {
|
||||||
"displayName": "Repository Import fehlgeschlagen",
|
"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": {
|
"namespaceStrategies": {
|
||||||
|
|||||||
@@ -289,7 +289,7 @@
|
|||||||
},
|
},
|
||||||
"D6SHRfqQw1": {
|
"D6SHRfqQw1": {
|
||||||
"displayName": "Repository import failed",
|
"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": {
|
"namespaceStrategies": {
|
||||||
|
|||||||
Reference in New Issue
Block a user