migrate ui-components from flow to typescript

This commit is contained in:
Sebastian Sdorra
2019-10-20 16:59:02 +02:00
parent c41efbdc4f
commit f49e17a3a7
151 changed files with 2039 additions and 25265 deletions

View File

@@ -1,7 +1,8 @@
import React from 'react';
import { translate } from 'react-i18next';
import { Links } from '@scm-manager/ui-types';
import { apiClient, SubmitButton, Loading, ErrorNotification } from '../';
import React from "react";
import { translate } from "react-i18next";
import { Links, Link } from "@scm-manager/ui-types";
import { apiClient, SubmitButton, Loading, ErrorNotification } from "../";
import { FormEvent } from "react";
type RenderProps = {
readOnly: boolean;
@@ -25,7 +26,7 @@ type State = {
error?: Error;
fetching: boolean;
modifying: boolean;
contentType?: string;
contentType?: string | null;
configChanged: boolean;
configuration?: ConfigurationType;
@@ -44,7 +45,7 @@ class Configuration extends React.Component<Props, State> {
fetching: true,
modifying: false,
configChanged: false,
valid: false,
valid: false
};
}
@@ -60,23 +61,23 @@ class Configuration extends React.Component<Props, State> {
}
captureContentType = (response: Response) => {
const contentType = response.headers.get('Content-Type');
const contentType = response.headers.get("Content-Type");
this.setState({
contentType,
contentType
});
return response;
};
getContentType = (): string => {
const { contentType } = this.state;
return contentType ? contentType : 'application/json';
return contentType ? contentType : "application/json";
};
handleError = (error: Error) => {
this.setState({
error,
fetching: false,
modifying: false,
modifying: false
});
};
@@ -84,16 +85,17 @@ class Configuration extends React.Component<Props, State> {
this.setState({
configuration,
fetching: false,
error: undefined,
error: undefined
});
};
getModificationUrl = (): string | null | undefined => {
getModificationUrl = (): string | undefined => {
const { configuration } = this.state;
if (configuration) {
const links = configuration._links;
if (links && links.update) {
return links.update.href;
const link = links.update as Link;
return link.href;
}
}
};
@@ -106,33 +108,40 @@ class Configuration extends React.Component<Props, State> {
configurationChanged = (configuration: ConfigurationType, valid: boolean) => {
this.setState({
modifiedConfiguration: configuration,
valid,
valid
});
};
modifyConfiguration = (event: Event) => {
modifyConfiguration = (event: FormEvent) => {
event.preventDefault();
this.setState({
modifying: true,
modifying: true
});
const { modifiedConfiguration } = this.state;
const modificationUrl = this.getModificationUrl();
if (modificationUrl) {
apiClient
.put(
this.getModificationUrl(),
modificationUrl,
modifiedConfiguration,
this.getContentType(),
this.getContentType()
)
.then(() =>
this.setState({
modifying: false,
configChanged: true,
valid: false,
}),
valid: false
})
)
.catch(this.handleError);
} else {
this.setState({
error: new Error("no modification link available")
});
}
};
renderConfigChangedNotification = () => {
@@ -143,11 +152,11 @@ class Configuration extends React.Component<Props, State> {
className="delete"
onClick={() =>
this.setState({
configChanged: false,
configChanged: false
})
}
/>
{this.props.t('config.form.submit-success-notification')}
{this.props.t("config.form.submit-success-notification")}
</div>
);
}
@@ -168,7 +177,7 @@ class Configuration extends React.Component<Props, State> {
const renderProps: RenderProps = {
readOnly,
initialConfiguration: configuration,
onConfigurationChange: this.configurationChanged,
onConfigurationChange: this.configurationChanged
};
return (
@@ -178,7 +187,7 @@ class Configuration extends React.Component<Props, State> {
{this.props.render(renderProps)}
<hr />
<SubmitButton
label={t('config.form.submit')}
label={t("config.form.submit")}
disabled={!valid || readOnly}
loading={modifying}
/>
@@ -189,4 +198,4 @@ class Configuration extends React.Component<Props, State> {
}
}
export default translate('config')(Configuration);
export default translate("config")(Configuration);

View File

@@ -1,11 +1,22 @@
import React from 'react';
import { binder } from '@scm-manager/ui-extensions';
import { NavLink } from '../navigation';
import { Route } from 'react-router-dom';
import { translate } from 'react-i18next';
import React from "react";
import { binder } from "@scm-manager/ui-extensions";
import { NavLink } from "../navigation";
import { Route } from "react-router-dom";
import { translate } from "react-i18next";
import { Repository, Links, Link } from "@scm-manager/ui-types";
type GlobalRouteProps = {
url: string;
links: Links;
};
type RepositoryRouteProps = {
url: string;
repository: Repository;
};
class ConfigurationBinder {
i18nNamespace: string = 'plugins';
i18nNamespace: string = "plugins";
navLink(to: string, labelI18nKey: string, t: any) {
return <NavLink to={to} label={t(labelI18nKey)} />;
@@ -19,44 +30,53 @@ class ConfigurationBinder {
to: string,
labelI18nKey: string,
linkName: string,
ConfigurationComponent: any,
ConfigurationComponent: any
) {
// create predicate based on the link name of the index resource
// if the linkname is not available, the navigation link and the route are not bound to the extension points
const configPredicate = (props: object) => {
const configPredicate = (props: any) => {
return props.links && props.links[linkName];
};
// create NavigationLink with translated label
const ConfigNavLink = translate(this.i18nNamespace)(({ t }) => {
return this.navLink('/admin/settings' + to, labelI18nKey, t);
return this.navLink("/admin/settings" + to, labelI18nKey, t);
});
// bind navigation link to extension point
binder.bind('admin.setting', ConfigNavLink, configPredicate);
binder.bind("admin.setting", ConfigNavLink, configPredicate);
// route for global configuration, passes the link from the index resource to component
const ConfigRoute = ({ url, links, ...additionalProps }) => {
const link = links[linkName].href;
return this.route(
url + '/settings' + to,
<ConfigurationComponent link={link} {...additionalProps} />,
);
const ConfigRoute = ({
url,
links,
...additionalProps
}: GlobalRouteProps) => {
const link = links[linkName];
if (link) {
return this.route(
url + "/settings" + to,
<ConfigurationComponent
link={(link as Link).href}
{...additionalProps}
/>
);
}
};
// bind config route to extension point
binder.bind('admin.route', ConfigRoute, configPredicate);
binder.bind("admin.route", ConfigRoute, configPredicate);
}
bindRepository(
to: string,
labelI18nKey: string,
linkName: string,
RepositoryComponent: any,
RepositoryComponent: any
) {
// create predicate based on the link name of the current repository route
// if the linkname is not available, the navigation link and the route are not bound to the extension points
const repoPredicate = (props: object) => {
const repoPredicate = (props: any) => {
return (
props.repository &&
props.repository._links &&
@@ -70,34 +90,40 @@ class ConfigurationBinder {
});
// bind navigation link to extension point
binder.bind('repository.navigation', RepoNavLink, repoPredicate);
binder.bind("repository.navigation", RepoNavLink, repoPredicate);
// route for global configuration, passes the current repository to component
const RepoRoute = ({ url, repository, ...additionalProps }) => {
const link = repository._links[linkName].href;
return this.route(
url + to,
<RepositoryComponent
repository={repository}
link={link}
{...additionalProps}
/>,
);
const RepoRoute = ({
url,
repository,
...additionalProps
}: RepositoryRouteProps) => {
const link = repository._links[linkName];
if (link) {
return this.route(
url + to,
<RepositoryComponent
repository={repository}
link={(link as Link).href}
{...additionalProps}
/>
);
}
};
// bind config route to extension point
binder.bind('repository.route', RepoRoute, repoPredicate);
binder.bind("repository.route", RepoRoute, repoPredicate);
}
bindRepositorySetting(
to: string,
labelI18nKey: string,
linkName: string,
RepositoryComponent: any,
RepositoryComponent: any
) {
// create predicate based on the link name of the current repository route
// if the linkname is not available, the navigation link and the route are not bound to the extension points
const repoPredicate = (props: object) => {
const repoPredicate = (props: any) => {
return (
props.repository &&
props.repository._links &&
@@ -107,27 +133,33 @@ class ConfigurationBinder {
// create NavigationLink with translated label
const RepoNavLink = translate(this.i18nNamespace)(({ t, url }) => {
return this.navLink(url + '/settings' + to, labelI18nKey, t);
return this.navLink(url + "/settings" + to, labelI18nKey, t);
});
// bind navigation link to extension point
binder.bind('repository.setting', RepoNavLink, repoPredicate);
binder.bind("repository.setting", RepoNavLink, repoPredicate);
// route for global configuration, passes the current repository to component
const RepoRoute = ({ url, repository, ...additionalProps }) => {
const link = repository._links[linkName].href;
return this.route(
url + '/settings' + to,
<RepositoryComponent
repository={repository}
link={link}
{...additionalProps}
/>,
);
const RepoRoute = ({
url,
repository,
...additionalProps
}: RepositoryRouteProps) => {
const link = repository._links[linkName];
if (link) {
return this.route(
url + "/settings" + to,
<RepositoryComponent
repository={repository}
link={(link as Link).href}
{...additionalProps}
/>
);
}
};
// bind config route to extension point
binder.bind('repository.route', RepoRoute, repoPredicate);
binder.bind("repository.route", RepoRoute, repoPredicate);
}
}

View File

@@ -1,2 +1,2 @@
export { default as ConfigurationBinder } from './ConfigurationBinder';
export { default as Configuration } from './Configuration';
export { default as ConfigurationBinder } from "./ConfigurationBinder";
export { default as Configuration } from "./Configuration";