Added first UI changes

This commit is contained in:
Janika Kefel
2018-12-13 14:49:59 +01:00
parent 16eb433618
commit 3a62f81ba0
18 changed files with 1339 additions and 11242 deletions

View File

@@ -1,86 +1,93 @@
// @flow
import React from "react";
import { translate } from "react-i18next";
import { Subtitle, AddEntryToTableField } from "@scm-manager/ui-components";
import AdminGroupTable from "../table/AdminGroupTable";
import AdminUserTable from "../table/AdminUserTable";
type Props = {
adminGroups: string[],
adminUsers: string[],
t: string => string,
onChange: (boolean, any, string) => void,
hasUpdatePermission: boolean
};
class AdminSettings extends React.Component<Props> {
render() {
const { t, adminGroups, adminUsers, hasUpdatePermission } = this.props;
return (
<div>
<Subtitle subtitle={t("admin-settings.name")} />
<AdminGroupTable
adminGroups={adminGroups}
onChange={(isValid, changedValue, name) =>
this.props.onChange(isValid, changedValue, name)
}
disabled={!hasUpdatePermission}
/>
<AddEntryToTableField
addEntry={this.addGroup}
disabled={!hasUpdatePermission}
buttonLabel={t("admin-settings.add-group-button")}
fieldLabel={t("admin-settings.add-group-textfield")}
errorMessage={t("admin-settings.add-group-error")}
/>
<AdminUserTable
adminUsers={adminUsers}
onChange={(isValid, changedValue, name) =>
this.props.onChange(isValid, changedValue, name)
}
disabled={!hasUpdatePermission}
/>
<AddEntryToTableField
addEntry={this.addUser}
disabled={!hasUpdatePermission}
buttonLabel={t("admin-settings.add-user-button")}
fieldLabel={t("admin-settings.add-user-textfield")}
errorMessage={t("admin-settings.add-user-error")}
/>
</div>
);
}
addGroup = (groupname: string) => {
if (this.isAdminGroupMember(groupname)) {
return;
}
this.props.onChange(
true,
[...this.props.adminGroups, groupname],
"adminGroups"
);
};
isAdminGroupMember = (groupname: string) => {
return this.props.adminGroups.includes(groupname);
};
addUser = (username: string) => {
if (this.isAdminUserMember(username)) {
return;
}
this.props.onChange(
true,
[...this.props.adminUsers, username],
"adminUsers"
);
};
isAdminUserMember = (username: string) => {
return this.props.adminUsers.includes(username);
};
}
export default translate("config")(AdminSettings);
// @flow
import React from "react";
import { translate } from "react-i18next";
import { Subtitle, AddEntryToTableField } from "@scm-manager/ui-components";
import AdminGroupTable from "../table/AdminGroupTable";
import AdminUserTable from "../table/AdminUserTable";
type Props = {
adminGroups: string[],
adminUsers: string[],
t: string => string,
onChange: (boolean, any, string) => void,
hasUpdatePermission: boolean
};
class AdminSettings extends React.Component<Props> {
render() {
const { t, adminGroups, adminUsers, hasUpdatePermission } = this.props;
return (
<div>
<Subtitle subtitle={t("admin-settings.name")} />
<div class="columns">
<div class="column is-half">
<AdminGroupTable
adminGroups={adminGroups}
onChange={(isValid, changedValue, name) =>
this.props.onChange(isValid, changedValue, name)
}
disabled={!hasUpdatePermission}
/>
<AddEntryToTableField
addEntry={this.addGroup}
disabled={!hasUpdatePermission}
buttonLabel={t("admin-settings.add-group-button")}
fieldLabel={t("admin-settings.add-group-textfield")}
errorMessage={t("admin-settings.add-group-error")}
/>
</div>
<div class="column is-half">
<AdminUserTable
adminUsers={adminUsers}
onChange={(isValid, changedValue, name) =>
this.props.onChange(isValid, changedValue, name)
}
disabled={!hasUpdatePermission}
/>
<AddEntryToTableField
addEntry={this.addUser}
disabled={!hasUpdatePermission}
buttonLabel={t("admin-settings.add-user-button")}
fieldLabel={t("admin-settings.add-user-textfield")}
errorMessage={t("admin-settings.add-user-error")}
/>
</div>
</div>
</div>
);
}
addGroup = (groupname: string) => {
if (this.isAdminGroupMember(groupname)) {
return;
}
this.props.onChange(
true,
[...this.props.adminGroups, groupname],
"adminGroups"
);
};
isAdminGroupMember = (groupname: string) => {
return this.props.adminGroups.includes(groupname);
};
addUser = (username: string) => {
if (this.isAdminUserMember(username)) {
return;
}
this.props.onChange(
true,
[...this.props.adminUsers, username],
"adminUsers"
);
};
isAdminUserMember = (username: string) => {
return this.props.adminUsers.includes(username);
};
}
export default translate("config")(AdminSettings);

View File

@@ -1,47 +1,54 @@
// @flow
import React from "react";
import { translate } from "react-i18next";
import { Checkbox, InputField, Subtitle } from "@scm-manager/ui-components";
type Props = {
baseUrl: string,
forceBaseUrl: boolean,
t: string => string,
onChange: (boolean, any, string) => void,
hasUpdatePermission: boolean
};
class BaseUrlSettings extends React.Component<Props> {
render() {
const { t, baseUrl, forceBaseUrl, hasUpdatePermission } = this.props;
return (
<div>
<Subtitle subtitle={t("base-url-settings.name")} />
<Checkbox
checked={forceBaseUrl}
label={t("base-url-settings.force-base-url")}
onChange={this.handleForceBaseUrlChange}
disabled={!hasUpdatePermission}
helpText={t("help.forceBaseUrlHelpText")}
/>
<InputField
label={t("base-url-settings.base-url")}
onChange={this.handleBaseUrlChange}
value={baseUrl}
disabled={!hasUpdatePermission}
helpText={t("help.baseUrlHelpText")}
/>
</div>
);
}
handleBaseUrlChange = (value: string) => {
this.props.onChange(true, value, "baseUrl");
};
handleForceBaseUrlChange = (value: boolean) => {
this.props.onChange(true, value, "forceBaseUrl");
};
}
export default translate("config")(BaseUrlSettings);
// @flow
import React from "react";
import { translate } from "react-i18next";
import { Checkbox, InputField, Subtitle } from "@scm-manager/ui-components";
type Props = {
baseUrl: string,
forceBaseUrl: boolean,
t: string => string,
onChange: (boolean, any, string) => void,
hasUpdatePermission: boolean
};
class BaseUrlSettings extends React.Component<Props> {
render() {
const { t, baseUrl, forceBaseUrl, hasUpdatePermission } = this.props;
return (
<div>
<Subtitle subtitle={t("base-url-settings.name")} />
<div class="columns">
<div class="column is-half">
<Checkbox
checked={forceBaseUrl}
label={t("base-url-settings.force-base-url")}
onChange={this.handleForceBaseUrlChange}
disabled={!hasUpdatePermission}
helpText={t("help.forceBaseUrlHelpText")}
/>
</div>
<div class="column is-half">
<InputField
label={t("base-url-settings.base-url")}
onChange={this.handleBaseUrlChange}
value={baseUrl}
disabled={!hasUpdatePermission}
helpText={t("help.baseUrlHelpText")}
/>
</div>
</div>
</div>
);
}
handleBaseUrlChange = (value: string) => {
this.props.onChange(true, value, "baseUrl");
};
handleForceBaseUrlChange = (value: boolean) => {
this.props.onChange(true, value, "forceBaseUrl");
};
}
export default translate("config")(BaseUrlSettings);

View File

@@ -1,137 +1,165 @@
// @flow
import React from "react";
import { translate } from "react-i18next";
import { Checkbox, InputField } from "@scm-manager/ui-components";
type Props = {
realmDescription: string,
enableRepositoryArchive: boolean,
disableGroupingGrid: boolean,
dateFormat: string,
anonymousAccessEnabled: boolean,
skipFailedAuthenticators: boolean,
pluginUrl: string,
enabledXsrfProtection: boolean,
defaultNamespaceStrategy: string,
t: string => string,
onChange: (boolean, any, string) => void,
hasUpdatePermission: boolean
};
class GeneralSettings extends React.Component<Props> {
render() {
const {
t,
realmDescription,
enableRepositoryArchive,
disableGroupingGrid,
dateFormat,
anonymousAccessEnabled,
skipFailedAuthenticators,
pluginUrl,
enabledXsrfProtection,
defaultNamespaceStrategy,
hasUpdatePermission
} = this.props;
return (
<div>
<InputField
label={t("general-settings.realm-description")}
onChange={this.handleRealmDescriptionChange}
value={realmDescription}
disabled={!hasUpdatePermission}
helpText={t("help.realmDescriptionHelpText")}
/>
<InputField
label={t("general-settings.date-format")}
onChange={this.handleDateFormatChange}
value={dateFormat}
disabled={!hasUpdatePermission}
helpText={t("help.dateFormatHelpText")}
/>
<InputField
label={t("general-settings.plugin-url")}
onChange={this.handlePluginUrlChange}
value={pluginUrl}
disabled={!hasUpdatePermission}
helpText={t("help.pluginRepositoryHelpText")}
/>
<InputField
label={t("general-settings.default-namespace-strategy")}
onChange={this.handleDefaultNamespaceStrategyChange}
value={defaultNamespaceStrategy}
disabled={!hasUpdatePermission}
helpText={t("help.defaultNameSpaceStrategyHelpText")}
/>
<Checkbox
checked={enabledXsrfProtection}
label={t("general-settings.enabled-xsrf-protection")}
onChange={this.handleEnabledXsrfProtectionChange}
disabled={!hasUpdatePermission}
helpText={t("help.enableXsrfProtectionHelpText")}
/>
<Checkbox
checked={enableRepositoryArchive}
label={t("general-settings.enable-repository-archive")}
onChange={this.handleEnableRepositoryArchiveChange}
disabled={!hasUpdatePermission}
helpText={t("help.enableRepositoryArchiveHelpText")}
/>
<Checkbox
checked={disableGroupingGrid}
label={t("general-settings.disable-grouping-grid")}
onChange={this.handleDisableGroupingGridChange}
disabled={!hasUpdatePermission}
helpText={t("help.disableGroupingGridHelpText")}
/>
<Checkbox
checked={anonymousAccessEnabled}
label={t("general-settings.anonymous-access-enabled")}
onChange={this.handleAnonymousAccessEnabledChange}
disabled={!hasUpdatePermission}
helpText={t("help.allowAnonymousAccessHelpText")}
/>
<Checkbox
checked={skipFailedAuthenticators}
label={t("general-settings.skip-failed-authenticators")}
onChange={this.handleSkipFailedAuthenticatorsChange}
disabled={!hasUpdatePermission}
helpText={t("help.skipFailedAuthenticatorsHelpText")}
/>
</div>
);
}
handleRealmDescriptionChange = (value: string) => {
this.props.onChange(true, value, "realmDescription");
};
handleEnableRepositoryArchiveChange = (value: boolean) => {
this.props.onChange(true, value, "enableRepositoryArchive");
};
handleDisableGroupingGridChange = (value: boolean) => {
this.props.onChange(true, value, "disableGroupingGrid");
};
handleDateFormatChange = (value: string) => {
this.props.onChange(true, value, "dateFormat");
};
handleAnonymousAccessEnabledChange = (value: string) => {
this.props.onChange(true, value, "anonymousAccessEnabled");
};
handleSkipFailedAuthenticatorsChange = (value: string) => {
this.props.onChange(true, value, "skipFailedAuthenticators");
};
handlePluginUrlChange = (value: string) => {
this.props.onChange(true, value, "pluginUrl");
};
handleEnabledXsrfProtectionChange = (value: boolean) => {
this.props.onChange(true, value, "enabledXsrfProtection");
};
handleDefaultNamespaceStrategyChange = (value: string) => {
this.props.onChange(true, value, "defaultNamespaceStrategy");
};
}
export default translate("config")(GeneralSettings);
// @flow
import React from "react";
import { translate } from "react-i18next";
import { Checkbox, InputField } from "@scm-manager/ui-components";
type Props = {
realmDescription: string,
enableRepositoryArchive: boolean,
disableGroupingGrid: boolean,
dateFormat: string,
anonymousAccessEnabled: boolean,
skipFailedAuthenticators: boolean,
pluginUrl: string,
enabledXsrfProtection: boolean,
defaultNamespaceStrategy: string,
t: string => string,
onChange: (boolean, any, string) => void,
hasUpdatePermission: boolean
};
class GeneralSettings extends React.Component<Props> {
render() {
const {
t,
realmDescription,
enableRepositoryArchive,
disableGroupingGrid,
dateFormat,
anonymousAccessEnabled,
skipFailedAuthenticators,
pluginUrl,
enabledXsrfProtection,
defaultNamespaceStrategy,
hasUpdatePermission
} = this.props;
return (
<div>
<div class="columns">
<div class="column is-half">
<InputField
label={t("general-settings.realm-description")}
onChange={this.handleRealmDescriptionChange}
value={realmDescription}
disabled={!hasUpdatePermission}
helpText={t("help.realmDescriptionHelpText")}
/>
</div>
<div class="column is-half">
<InputField
label={t("general-settings.date-format")}
onChange={this.handleDateFormatChange}
value={dateFormat}
disabled={!hasUpdatePermission}
helpText={t("help.dateFormatHelpText")}
/>
</div>
</div>
<div class="columns">
<div class="column is-half">
<InputField
label={t("general-settings.plugin-url")}
onChange={this.handlePluginUrlChange}
value={pluginUrl}
disabled={!hasUpdatePermission}
helpText={t("help.pluginRepositoryHelpText")}
/>
</div>
<div class="column is-half">
<InputField
label={t("general-settings.default-namespace-strategy")}
onChange={this.handleDefaultNamespaceStrategyChange}
value={defaultNamespaceStrategy}
disabled={!hasUpdatePermission}
helpText={t("help.defaultNameSpaceStrategyHelpText")}
/>
</div>
</div>
<div class="columns">
<div class="column is-half">
<Checkbox
checked={enabledXsrfProtection}
label={t("general-settings.enabled-xsrf-protection")}
onChange={this.handleEnabledXsrfProtectionChange}
disabled={!hasUpdatePermission}
helpText={t("help.enableXsrfProtectionHelpText")}
/>
</div>
<div class="column is-half">
<Checkbox
checked={enableRepositoryArchive}
label={t("general-settings.enable-repository-archive")}
onChange={this.handleEnableRepositoryArchiveChange}
disabled={!hasUpdatePermission}
helpText={t("help.enableRepositoryArchiveHelpText")}
/>
</div>
</div>
<div class="columns">
<div class="column is-half">
<Checkbox
checked={disableGroupingGrid}
label={t("general-settings.disable-grouping-grid")}
onChange={this.handleDisableGroupingGridChange}
disabled={!hasUpdatePermission}
helpText={t("help.disableGroupingGridHelpText")}
/>
</div>
<div class="column is-half">
<Checkbox
checked={anonymousAccessEnabled}
label={t("general-settings.anonymous-access-enabled")}
onChange={this.handleAnonymousAccessEnabledChange}
disabled={!hasUpdatePermission}
helpText={t("help.allowAnonymousAccessHelpText")}
/>
</div>
</div>
<div class="columns">
<div class="column is-half">
<Checkbox
checked={skipFailedAuthenticators}
label={t("general-settings.skip-failed-authenticators")}
onChange={this.handleSkipFailedAuthenticatorsChange}
disabled={!hasUpdatePermission}
helpText={t("help.skipFailedAuthenticatorsHelpText")}
/>
</div>
</div>
</div>
);
}
handleRealmDescriptionChange = (value: string) => {
this.props.onChange(true, value, "realmDescription");
};
handleEnableRepositoryArchiveChange = (value: boolean) => {
this.props.onChange(true, value, "enableRepositoryArchive");
};
handleDisableGroupingGridChange = (value: boolean) => {
this.props.onChange(true, value, "disableGroupingGrid");
};
handleDateFormatChange = (value: string) => {
this.props.onChange(true, value, "dateFormat");
};
handleAnonymousAccessEnabledChange = (value: string) => {
this.props.onChange(true, value, "anonymousAccessEnabled");
};
handleSkipFailedAuthenticatorsChange = (value: string) => {
this.props.onChange(true, value, "skipFailedAuthenticators");
};
handlePluginUrlChange = (value: string) => {
this.props.onChange(true, value, "pluginUrl");
};
handleEnabledXsrfProtectionChange = (value: boolean) => {
this.props.onChange(true, value, "enabledXsrfProtection");
};
handleDefaultNamespaceStrategyChange = (value: string) => {
this.props.onChange(true, value, "defaultNamespaceStrategy");
};
}
export default translate("config")(GeneralSettings);

View File

@@ -1,91 +1,97 @@
// @flow
import React from "react";
import { translate } from "react-i18next";
import {
InputField,
Subtitle,
validation as validator
} from "@scm-manager/ui-components";
type Props = {
loginAttemptLimit: number,
loginAttemptLimitTimeout: number,
t: string => string,
onChange: (boolean, any, string) => void,
hasUpdatePermission: boolean
};
type State = {
loginAttemptLimitError: boolean,
loginAttemptLimitTimeoutError: boolean
};
class LoginAttempt extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
loginAttemptLimitError: false,
loginAttemptLimitTimeoutError: false
};
}
render() {
const {
t,
loginAttemptLimit,
loginAttemptLimitTimeout,
hasUpdatePermission
} = this.props;
return (
<div>
<Subtitle subtitle={t("login-attempt.name")} />
<InputField
label={t("login-attempt.login-attempt-limit")}
onChange={this.handleLoginAttemptLimitChange}
value={loginAttemptLimit}
disabled={!hasUpdatePermission}
validationError={this.state.loginAttemptLimitError}
errorMessage={t("validation.login-attempt-limit-invalid")}
helpText={t("help.loginAttemptLimitHelpText")}
/>
<InputField
label={t("login-attempt.login-attempt-limit-timeout")}
onChange={this.handleLoginAttemptLimitTimeoutChange}
value={loginAttemptLimitTimeout}
disabled={!hasUpdatePermission}
validationError={this.state.loginAttemptLimitTimeoutError}
errorMessage={t("validation.login-attempt-limit-timeout-invalid")}
helpText={t("help.loginAttemptLimitTimeoutHelpText")}
/>
</div>
);
}
//TODO: set Error in ConfigForm to disable Submit Button!
handleLoginAttemptLimitChange = (value: string) => {
this.setState({
...this.state,
loginAttemptLimitError: !validator.isNumberValid(value)
});
this.props.onChange(
validator.isNumberValid(value),
value,
"loginAttemptLimit"
);
};
handleLoginAttemptLimitTimeoutChange = (value: string) => {
this.setState({
...this.state,
loginAttemptLimitTimeoutError: !validator.isNumberValid(value)
});
this.props.onChange(
validator.isNumberValid(value),
value,
"loginAttemptLimitTimeout"
);
};
}
export default translate("config")(LoginAttempt);
// @flow
import React from "react";
import { translate } from "react-i18next";
import {
InputField,
Subtitle,
validation as validator
} from "@scm-manager/ui-components";
type Props = {
loginAttemptLimit: number,
loginAttemptLimitTimeout: number,
t: string => string,
onChange: (boolean, any, string) => void,
hasUpdatePermission: boolean
};
type State = {
loginAttemptLimitError: boolean,
loginAttemptLimitTimeoutError: boolean
};
class LoginAttempt extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
loginAttemptLimitError: false,
loginAttemptLimitTimeoutError: false
};
}
render() {
const {
t,
loginAttemptLimit,
loginAttemptLimitTimeout,
hasUpdatePermission
} = this.props;
return (
<div>
<Subtitle subtitle={t("login-attempt.name")} />
<div class="columns">
<div class="column is-half">
<InputField
label={t("login-attempt.login-attempt-limit")}
onChange={this.handleLoginAttemptLimitChange}
value={loginAttemptLimit}
disabled={!hasUpdatePermission}
validationError={this.state.loginAttemptLimitError}
errorMessage={t("validation.login-attempt-limit-invalid")}
helpText={t("help.loginAttemptLimitHelpText")}
/>
</div>
<div class="column is-half">
<InputField
label={t("login-attempt.login-attempt-limit-timeout")}
onChange={this.handleLoginAttemptLimitTimeoutChange}
value={loginAttemptLimitTimeout}
disabled={!hasUpdatePermission}
validationError={this.state.loginAttemptLimitTimeoutError}
errorMessage={t("validation.login-attempt-limit-timeout-invalid")}
helpText={t("help.loginAttemptLimitTimeoutHelpText")}
/>
</div>
</div>
</div>
);
}
//TODO: set Error in ConfigForm to disable Submit Button!
handleLoginAttemptLimitChange = (value: string) => {
this.setState({
...this.state,
loginAttemptLimitError: !validator.isNumberValid(value)
});
this.props.onChange(
validator.isNumberValid(value),
value,
"loginAttemptLimit"
);
};
handleLoginAttemptLimitTimeoutChange = (value: string) => {
this.setState({
...this.state,
loginAttemptLimitTimeoutError: !validator.isNumberValid(value)
});
this.props.onChange(
validator.isNumberValid(value),
value,
"loginAttemptLimitTimeout"
);
};
}
export default translate("config")(LoginAttempt);

View File

@@ -1,126 +1,146 @@
// @flow
import React from "react";
import { translate } from "react-i18next";
import {
Checkbox,
InputField,
Subtitle,
AddEntryToTableField
} from "@scm-manager/ui-components";
import ProxyExcludesTable from "../table/ProxyExcludesTable";
type Props = {
proxyPassword: string,
proxyPort: number,
proxyServer: string,
proxyUser: string,
enableProxy: boolean,
proxyExcludes: string[],
t: string => string,
onChange: (boolean, any, string) => void,
hasUpdatePermission: boolean
};
class ProxySettings extends React.Component<Props> {
render() {
const {
t,
proxyPassword,
proxyPort,
proxyServer,
proxyUser,
enableProxy,
proxyExcludes,
hasUpdatePermission
} = this.props;
return (
<div>
<Subtitle subtitle={t("proxy-settings.name")} />
<Checkbox
checked={enableProxy}
label={t("proxy-settings.enable-proxy")}
onChange={this.handleEnableProxyChange}
disabled={!hasUpdatePermission}
helpText={t("help.enableProxyHelpText")}
/>
<InputField
label={t("proxy-settings.proxy-password")}
onChange={this.handleProxyPasswordChange}
value={proxyPassword}
type="password"
disabled={!enableProxy || !hasUpdatePermission}
helpText={t("help.proxyPasswordHelpText")}
/>
<InputField
label={t("proxy-settings.proxy-port")}
value={proxyPort}
onChange={this.handleProxyPortChange}
disabled={!enableProxy || !hasUpdatePermission}
helpText={t("help.proxyPortHelpText")}
/>
<InputField
label={t("proxy-settings.proxy-server")}
value={proxyServer}
onChange={this.handleProxyServerChange}
disabled={!enableProxy || !hasUpdatePermission}
helpText={t("help.proxyServerHelpText")}
/>
<InputField
label={t("proxy-settings.proxy-user")}
value={proxyUser}
onChange={this.handleProxyUserChange}
disabled={!enableProxy || !hasUpdatePermission}
helpText={t("help.proxyUserHelpText")}
/>
<ProxyExcludesTable
proxyExcludes={proxyExcludes}
onChange={(isValid, changedValue, name) =>
this.props.onChange(isValid, changedValue, name)
}
disabled={!enableProxy || !hasUpdatePermission}
/>
<AddEntryToTableField
addEntry={this.addProxyExclude}
disabled={!enableProxy || !hasUpdatePermission}
buttonLabel={t("proxy-settings.add-proxy-exclude-button")}
fieldLabel={t("proxy-settings.add-proxy-exclude-textfield")}
errorMessage={t("proxy-settings.add-proxy-exclude-error")}
/>
</div>
);
}
handleProxyPasswordChange = (value: string) => {
this.props.onChange(true, value, "proxyPassword");
};
handleProxyPortChange = (value: string) => {
this.props.onChange(true, value, "proxyPort");
};
handleProxyServerChange = (value: string) => {
this.props.onChange(true, value, "proxyServer");
};
handleProxyUserChange = (value: string) => {
this.props.onChange(true, value, "proxyUser");
};
handleEnableProxyChange = (value: string) => {
this.props.onChange(true, value, "enableProxy");
};
addProxyExclude = (proxyExcludeName: string) => {
if (this.isProxyExcludeMember(proxyExcludeName)) {
return;
}
this.props.onChange(
true,
[...this.props.proxyExcludes, proxyExcludeName],
"proxyExcludes"
);
};
isProxyExcludeMember = (proxyExcludeName: string) => {
return this.props.proxyExcludes.includes(proxyExcludeName);
};
}
export default translate("config")(ProxySettings);
// @flow
import React from "react";
import { translate } from "react-i18next";
import {
Checkbox,
InputField,
Subtitle,
AddEntryToTableField
} from "@scm-manager/ui-components";
import ProxyExcludesTable from "../table/ProxyExcludesTable";
type Props = {
proxyPassword: string,
proxyPort: number,
proxyServer: string,
proxyUser: string,
enableProxy: boolean,
proxyExcludes: string[],
t: string => string,
onChange: (boolean, any, string) => void,
hasUpdatePermission: boolean
};
class ProxySettings extends React.Component<Props> {
render() {
const {
t,
proxyPassword,
proxyPort,
proxyServer,
proxyUser,
enableProxy,
proxyExcludes,
hasUpdatePermission
} = this.props;
return (
<div>
<Subtitle subtitle={t("proxy-settings.name")} />
<div class="columns">
<div class="column is-full">
<Checkbox
checked={enableProxy}
label={t("proxy-settings.enable-proxy")}
onChange={this.handleEnableProxyChange}
disabled={!hasUpdatePermission}
helpText={t("help.enableProxyHelpText")}
/>
</div>
</div>
<div class="columns">
<div class="column is-half">
<InputField
label={t("proxy-settings.proxy-password")}
onChange={this.handleProxyPasswordChange}
value={proxyPassword}
type="password"
disabled={!enableProxy || !hasUpdatePermission}
helpText={t("help.proxyPasswordHelpText")}
/>
</div>
<div class="column is-half">
<InputField
label={t("proxy-settings.proxy-port")}
value={proxyPort}
onChange={this.handleProxyPortChange}
disabled={!enableProxy || !hasUpdatePermission}
helpText={t("help.proxyPortHelpText")}
/>
</div>
</div>
<div class="columns">
<div class="column is-half">
<InputField
label={t("proxy-settings.proxy-server")}
value={proxyServer}
onChange={this.handleProxyServerChange}
disabled={!enableProxy || !hasUpdatePermission}
helpText={t("help.proxyServerHelpText")}
/>
</div>
<div class="column is-half">
<InputField
label={t("proxy-settings.proxy-user")}
value={proxyUser}
onChange={this.handleProxyUserChange}
disabled={!enableProxy || !hasUpdatePermission}
helpText={t("help.proxyUserHelpText")}
/>
</div>
</div>
<div class="columns">
<div class="column is-full">
<ProxyExcludesTable
proxyExcludes={proxyExcludes}
onChange={(isValid, changedValue, name) =>
this.props.onChange(isValid, changedValue, name)
}
disabled={!enableProxy || !hasUpdatePermission}
/>
<AddEntryToTableField
addEntry={this.addProxyExclude}
disabled={!enableProxy || !hasUpdatePermission}
buttonLabel={t("proxy-settings.add-proxy-exclude-button")}
fieldLabel={t("proxy-settings.add-proxy-exclude-textfield")}
errorMessage={t("proxy-settings.add-proxy-exclude-error")}
/>
</div>
</div>
</div>
);
}
handleProxyPasswordChange = (value: string) => {
this.props.onChange(true, value, "proxyPassword");
};
handleProxyPortChange = (value: string) => {
this.props.onChange(true, value, "proxyPort");
};
handleProxyServerChange = (value: string) => {
this.props.onChange(true, value, "proxyServer");
};
handleProxyUserChange = (value: string) => {
this.props.onChange(true, value, "proxyUser");
};
handleEnableProxyChange = (value: string) => {
this.props.onChange(true, value, "enableProxy");
};
addProxyExclude = (proxyExcludeName: string) => {
if (this.isProxyExcludeMember(proxyExcludeName)) {
return;
}
this.props.onChange(
true,
[...this.props.proxyExcludes, proxyExcludeName],
"proxyExcludes"
);
};
isProxyExcludeMember = (proxyExcludeName: string) => {
return this.props.proxyExcludes.includes(proxyExcludeName);
};
}
export default translate("config")(ProxySettings);

View File

@@ -1,86 +1,86 @@
// @flow
import React from "react";
import { translate } from "react-i18next";
import { Route } from "react-router";
import { ExtensionPoint } from "@scm-manager/ui-extensions";
import type { Links } from "@scm-manager/ui-types";
import { Page, Navigation, NavLink, Section } from "@scm-manager/ui-components";
import GlobalConfig from "./GlobalConfig";
import type { History } from "history";
import {connect} from "react-redux";
import {compose} from "redux";
import { getLinks } from "../../modules/indexResource";
type Props = {
links: Links,
// context objects
t: string => string,
match: any,
history: History
};
class Config extends React.Component<Props> {
stripEndingSlash = (url: string) => {
if (url.endsWith("/")) {
return url.substring(0, url.length - 2);
}
return url;
};
matchedUrl = () => {
return this.stripEndingSlash(this.props.match.url);
};
render() {
const { links, t } = this.props;
const url = this.matchedUrl();
const extensionProps = {
links,
url
};
return (
<Page>
<div className="columns">
<div className="column is-three-quarters">
<Route path={url} exact component={GlobalConfig} />
<ExtensionPoint name="config.route"
props={extensionProps}
renderAll={true}
/>
</div>
<div className="column">
<Navigation>
<Section label={t("config.navigation-title")}>
<NavLink
to={`${url}`}
label={t("global-config.navigation-label")}
/>
<ExtensionPoint name="config.navigation"
props={extensionProps}
renderAll={true}
/>
</Section>
</Navigation>
</div>
</div>
</Page>
);
}
}
const mapStateToProps = (state: any) => {
const links = getLinks(state);
return {
links
};
};
export default compose(
connect(mapStateToProps),
translate("config")
)(Config);
// @flow
import React from "react";
import { translate } from "react-i18next";
import { Route } from "react-router";
import { ExtensionPoint } from "@scm-manager/ui-extensions";
import type { Links } from "@scm-manager/ui-types";
import { Page, Navigation, NavLink, Section } from "@scm-manager/ui-components";
import GlobalConfig from "./GlobalConfig";
import type { History } from "history";
import {connect} from "react-redux";
import {compose} from "redux";
import { getLinks } from "../../modules/indexResource";
type Props = {
links: Links,
// context objects
t: string => string,
match: any,
history: History
};
class Config extends React.Component<Props> {
stripEndingSlash = (url: string) => {
if (url.endsWith("/")) {
return url.substring(0, url.length - 2);
}
return url;
};
matchedUrl = () => {
return this.stripEndingSlash(this.props.match.url);
};
render() {
const { links, t } = this.props;
const url = this.matchedUrl();
const extensionProps = {
links,
url
};
return (
<Page>
<div className="columns">
<div className="column is-three-quarters">
<Route path={url} exact component={GlobalConfig} />
<ExtensionPoint name="config.route"
props={extensionProps}
renderAll={true}
/>
</div>
<div className="column is-one-quarter">
<Navigation>
<Section label={t("config.navigation-title")}>
<NavLink
to={`${url}`}
label={t("global-config.navigation-label")}
/>
<ExtensionPoint name="config.navigation"
props={extensionProps}
renderAll={true}
/>
</Section>
</Navigation>
</div>
</div>
</Page>
);
}
}
const mapStateToProps = (state: any) => {
const links = getLinks(state);
return {
links
};
};
export default compose(
connect(mapStateToProps),
translate("config")
)(Config);

View File

@@ -1,33 +1,33 @@
// @flow
import React from "react";
import { translate } from "react-i18next";
import GroupRow from "./GroupRow";
import type { Group } from "@scm-manager/ui-types";
type Props = {
t: string => string,
groups: Group[]
};
class GroupTable extends React.Component<Props> {
render() {
const { groups, t } = this.props;
return (
<table className="table is-hoverable is-fullwidth">
<thead>
<tr>
<th>{t("group.name")}</th>
<th className="is-hidden-mobile">{t("group.description")}</th>
</tr>
</thead>
<tbody>
{groups.map((group, index) => {
return <GroupRow key={index} group={group} />;
})}
</tbody>
</table>
);
}
}
export default translate("groups")(GroupTable);
// @flow
import React from "react";
import { translate } from "react-i18next";
import GroupRow from "./GroupRow";
import type { Group } from "@scm-manager/ui-types";
type Props = {
t: string => string,
groups: Group[]
};
class GroupTable extends React.Component<Props> {
render() {
const { groups, t } = this.props;
return (
<table className="card-table table is-hoverable is-fullwidth">
<thead>
<tr>
<th>{t("group.name")}</th>
<th className="is-hidden-mobile">{t("group.description")}</th>
</tr>
</thead>
<tbody>
{groups.map((group, index) => {
return <GroupRow key={index} group={group} />;
})}
</tbody>
</table>
);
}
}
export default translate("groups")(GroupTable);

View File

@@ -1,67 +1,68 @@
//@flow
import React from "react";
import type { RepositoryGroup } from "@scm-manager/ui-types";
import injectSheet from "react-jss";
import classNames from "classnames";
import RepositoryEntry from "./RepositoryEntry";
const styles = {
pointer: {
cursor: "pointer"
},
repoGroup: {
marginBottom: "1em"
}
};
type Props = {
group: RepositoryGroup,
// context props
classes: any
};
type State = {
collapsed: boolean
};
class RepositoryGroupEntry extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
collapsed: false
};
}
toggleCollapse = () => {
this.setState(prevState => ({
collapsed: !prevState.collapsed
}));
};
render() {
const { group, classes } = this.props;
const { collapsed } = this.state;
const icon = collapsed ? "fa-angle-right" : "fa-angle-down";
let content = null;
if (!collapsed) {
content = group.repositories.map((repository, index) => {
return <RepositoryEntry repository={repository} key={index} />;
});
}
return (
<div className={classes.repoGroup}>
<h2>
<span className={classes.pointer} onClick={this.toggleCollapse}>
<i className={classNames("fa", icon)} /> {group.name}
</span>
</h2>
<hr />
{content}
</div>
);
}
}
export default injectSheet(styles)(RepositoryGroupEntry);
//@flow
import React from "react";
import type { RepositoryGroup } from "@scm-manager/ui-types";
import injectSheet from "react-jss";
import classNames from "classnames";
import RepositoryEntry from "./RepositoryEntry";
const styles = {
pointer: {
cursor: "pointer",
fontSize: "1.5rem"
},
repoGroup: {
marginBottom: "1em"
}
};
type Props = {
group: RepositoryGroup,
// context props
classes: any
};
type State = {
collapsed: boolean
};
class RepositoryGroupEntry extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
collapsed: false
};
}
toggleCollapse = () => {
this.setState(prevState => ({
collapsed: !prevState.collapsed
}));
};
render() {
const { group, classes } = this.props;
const { collapsed } = this.state;
const icon = collapsed ? "fa-angle-right" : "fa-angle-down";
let content = null;
if (!collapsed) {
content = group.repositories.map((repository, index) => {
return <RepositoryEntry repository={repository} key={index} />;
});
}
return (
<div className={classes.repoGroup}>
<h2>
<span className={classes.pointer} onClick={this.toggleCollapse}>
<i className={classNames("fa", icon)} /> {group.name}
</span>
</h2>
<hr />
{content}
</div>
);
}
}
export default injectSheet(styles)(RepositoryGroupEntry);

View File

@@ -1,31 +1,31 @@
// @flow
import React from "react";
import { Link } from "react-router-dom";
import type { User } from "@scm-manager/ui-types";
type Props = {
user: User
};
export default class UserRow extends React.Component<Props> {
renderLink(to: string, label: string) {
return <Link to={to}>{label}</Link>;
}
render() {
const { user } = this.props;
const to = `/user/${user.name}`;
return (
<tr>
<td className="is-hidden-mobile">{this.renderLink(to, user.name)}</td>
<td>{this.renderLink(to, user.displayName)}</td>
<td>
<a href={`mailto: ${user.mail}`}>{user.mail}</a>
</td>
<td className="is-hidden-mobile">
<input type="checkbox" id="admin" checked={user.admin} readOnly />
</td>
</tr>
);
}
}
// @flow
import React from "react";
import { Link } from "react-router-dom";
import type { User } from "@scm-manager/ui-types";
type Props = {
user: User
};
export default class UserRow extends React.Component<Props> {
renderLink(to: string, label: string) {
return <Link to={to}>{label}</Link>;
}
render() {
const { user } = this.props;
const to = `/user/${user.name}`;
return (
<tr>
<td className="is-hidden-mobile">{this.renderLink(to, user.name)}</td>
<td>{this.renderLink(to, user.displayName)}</td>
<td>
<a href={`mailto: ${user.mail}`}>{user.mail}</a>
</td>
<td className="is-hidden-mobile">
<input type="checkbox" id="admin" checked={user.admin} readOnly />
</td>
</tr>
);
}
}

View File

@@ -1,35 +1,37 @@
// @flow
import React from "react";
import { translate } from "react-i18next";
import UserRow from "./UserRow";
import type { User } from "@scm-manager/ui-types";
type Props = {
t: string => string,
users: User[]
};
class UserTable extends React.Component<Props> {
render() {
const { users, t } = this.props;
return (
<table className="table is-hoverable is-fullwidth">
<thead>
<tr>
<th className="is-hidden-mobile">{t("user.name")}</th>
<th>{t("user.displayName")}</th>
<th>{t("user.mail")}</th>
<th className="is-hidden-mobile">{t("user.admin")}</th>
</tr>
</thead>
<tbody>
{users.map((user, index) => {
return <UserRow key={index} user={user} />;
})}
</tbody>
</table>
);
}
}
export default translate("users")(UserTable);
// @flow
import React from "react";
import { translate } from "react-i18next";
import UserRow from "./UserRow";
import type { User } from "@scm-manager/ui-types";
type Props = {
t: string => string,
users: User[]
};
;
class UserTable extends React.Component<Props> {
render() {
const { users, t } = this.props;
return (
<table className="card-table table is-hoverable is-fullwidth">
<thead>
<tr>
<th className="is-hidden-mobile">{t("user.name")}</th>
<th>{t("user.displayName")}</th>
<th>{t("user.mail")}</th>
<th className="is-hidden-mobile">{t("user.admin")}</th>
</tr>
</thead>
<tbody>
{users.map((user, index) => {
return <UserRow key={index} user={user} />;
})}
</tbody>
</table>
);
}
}
export default translate("users")(UserTable);

View File

@@ -1,143 +1,143 @@
// @flow
import React from "react";
import type { History } from "history";
import { connect } from "react-redux";
import { translate } from "react-i18next";
import {
fetchUsersByPage,
fetchUsersByLink,
getUsersFromState,
selectListAsCollection,
isPermittedToCreateUsers,
isFetchUsersPending,
getFetchUsersFailure
} from "../modules/users";
import { Page, Paginator } from "@scm-manager/ui-components";
import { UserTable } from "./../components/table";
import type { User, PagedCollection } from "@scm-manager/ui-types";
import CreateUserButton from "../components/buttons/CreateUserButton";
import { getUsersLink } from "../../modules/indexResource";
type Props = {
users: User[],
loading: boolean,
error: Error,
canAddUsers: boolean,
list: PagedCollection,
page: number,
usersLink: string,
// context objects
t: string => string,
history: History,
// dispatch functions
fetchUsersByPage: (link: string, page: number) => void,
fetchUsersByLink: (link: string) => void
};
class Users extends React.Component<Props> {
componentDidMount() {
this.props.fetchUsersByPage(this.props.usersLink, this.props.page);
}
onPageChange = (link: string) => {
this.props.fetchUsersByLink(link);
};
/**
* reflect page transitions in the uri
*/
componentDidUpdate() {
const { page, list } = this.props;
if (list && (list.page || list.page === 0)) {
// backend starts paging by 0
const statePage: number = list.page + 1;
if (page !== statePage) {
this.props.history.push(`/users/${statePage}`);
}
}
}
render() {
const { users, loading, error, t } = this.props;
return (
<Page
title={t("users.title")}
subtitle={t("users.subtitle")}
loading={loading || !users}
error={error}
>
<UserTable users={users} />
{this.renderPaginator()}
{this.renderCreateButton()}
</Page>
);
}
renderPaginator() {
const { list } = this.props;
if (list) {
return <Paginator collection={list} onPageChange={this.onPageChange} />;
}
return null;
}
renderCreateButton() {
if (this.props.canAddUsers) {
return <CreateUserButton />;
} else {
return;
}
}
}
const getPageFromProps = props => {
let page = props.match.params.page;
if (page) {
page = parseInt(page, 10);
} else {
page = 1;
}
return page;
};
const mapStateToProps = (state, ownProps) => {
const users = getUsersFromState(state);
const loading = isFetchUsersPending(state);
const error = getFetchUsersFailure(state);
const usersLink = getUsersLink(state);
const page = getPageFromProps(ownProps);
const canAddUsers = isPermittedToCreateUsers(state);
const list = selectListAsCollection(state);
return {
users,
loading,
error,
canAddUsers,
list,
page,
usersLink
};
};
const mapDispatchToProps = dispatch => {
return {
fetchUsersByPage: (link: string, page: number) => {
dispatch(fetchUsersByPage(link, page));
},
fetchUsersByLink: (link: string) => {
dispatch(fetchUsersByLink(link));
}
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(translate("users")(Users));
// @flow
import React from "react";
import type { History } from "history";
import { connect } from "react-redux";
import { translate } from "react-i18next";
import {
fetchUsersByPage,
fetchUsersByLink,
getUsersFromState,
selectListAsCollection,
isPermittedToCreateUsers,
isFetchUsersPending,
getFetchUsersFailure
} from "../modules/users";
import { Page, Paginator } from "@scm-manager/ui-components";
import { UserTable } from "./../components/table";
import type { User, PagedCollection } from "@scm-manager/ui-types";
import CreateUserButton from "../components/buttons/CreateUserButton";
import { getUsersLink } from "../../modules/indexResource";
type Props = {
users: User[],
loading: boolean,
error: Error,
canAddUsers: boolean,
list: PagedCollection,
page: number,
usersLink: string,
// context objects
t: string => string,
history: History,
// dispatch functions
fetchUsersByPage: (link: string, page: number) => void,
fetchUsersByLink: (link: string) => void
};
class Users extends React.Component<Props> {
componentDidMount() {
this.props.fetchUsersByPage(this.props.usersLink, this.props.page);
}
onPageChange = (link: string) => {
this.props.fetchUsersByLink(link);
};
/**
* reflect page transitions in the uri
*/
componentDidUpdate() {
const { page, list } = this.props;
if (list && (list.page || list.page === 0)) {
// backend starts paging by 0
const statePage: number = list.page + 1;
if (page !== statePage) {
this.props.history.push(`/users/${statePage}`);
}
}
}
render() {
const { users, loading, error, t } = this.props;
return (
<Page
title={t("users.title")}
subtitle={t("users.subtitle")}
loading={loading || !users}
error={error}
>
<UserTable users={users} />
{this.renderPaginator()}
{this.renderCreateButton()}
</Page>
);
}
renderPaginator() {
const { list } = this.props;
if (list) {
return <Paginator collection={list} onPageChange={this.onPageChange} />;
}
return null;
}
renderCreateButton() {
if (this.props.canAddUsers) {
return <CreateUserButton />;
} else {
return;
}
}
}
const getPageFromProps = props => {
let page = props.match.params.page;
if (page) {
page = parseInt(page, 10);
} else {
page = 1;
}
return page;
};
const mapStateToProps = (state, ownProps) => {
const users = getUsersFromState(state);
const loading = isFetchUsersPending(state);
const error = getFetchUsersFailure(state);
const usersLink = getUsersLink(state);
const page = getPageFromProps(ownProps);
const canAddUsers = isPermittedToCreateUsers(state);
const list = selectListAsCollection(state);
return {
users,
loading,
error,
canAddUsers,
list,
page,
usersLink
};
};
const mapDispatchToProps = dispatch => {
return {
fetchUsersByPage: (link: string, page: number) => {
dispatch(fetchUsersByPage(link, page));
},
fetchUsersByLink: (link: string) => {
dispatch(fetchUsersByLink(link));
}
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(translate("users")(Users));