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,14 +1,22 @@
//@flow //@flow
import React from "react"; import React from "react";
import classNames from "classnames"; import injectSheet from "react-jss";
import classNames from "classnames";
type Props = {
}; type Props = {
};
class HelpIcon extends React.Component<Props> {
render() { const styles = {
return <i className={classNames("fa fa-question has-text-info")} /> textinfo: {
} color: "#98d8f3 !important"
} }
};
export default HelpIcon;
class HelpIcon extends React.Component<Props> {
render() {
const { classes } = this.props;
return <i className={classNames("fa fa-question-circle has-text-info", classes.textinfo)}></i>
}
}
export default injectSheet(styles)(HelpIcon);

View File

@@ -1,11 +1,11 @@
//@flow //@flow
import React from "react"; import React from "react";
import Button, { type ButtonProps } from "./Button"; import Button, { type ButtonProps } from "./Button";
class AddButton extends React.Component<ButtonProps> { class AddButton extends React.Component<ButtonProps> {
render() { render() {
return <Button color="default" {...this.props} />; return <Button color="default" {...this.props} />;
} }
} }
export default AddButton; export default AddButton;

View File

@@ -1,24 +1,27 @@
//@flow //@flow
import React from "react"; import React from "react";
import injectSheet from "react-jss"; import injectSheet from "react-jss";
import AddButton, { type ButtonProps } from "./Button"; import SubmitButton, { type ButtonProps } from "./SubmitButton";
import classNames from "classnames"; import classNames from "classnames";
const styles = { const styles = {
spacing: { spacing: {
margin: "1em 0 0 1em" marginTop: "2em",
} border: "2px solid #e9f7fd",
}; padding: "1em 1em"
}
class CreateButton extends React.Component<ButtonProps> {
render() { };
const { classes } = this.props;
return ( class CreateButton extends React.Component<ButtonProps> {
<div className={classNames("is-pulled-right", classes.spacing)}> render() {
<AddButton {...this.props} /> const { classes } = this.props;
</div> return (
); <div className={classNames("has-text-centered", classes.spacing)}>
} <SubmitButton {...this.props} />
} </div>
);
export default injectSheet(styles)(CreateButton); }
}
export default injectSheet(styles)(CreateButton);

View File

@@ -1,31 +1,31 @@
//@flow //@flow
import * as React from "react"; import * as React from "react";
import Logo from "./../Logo"; import Logo from "./../Logo";
type Props = { type Props = {
children?: React.Node children?: React.Node
}; };
class Header extends React.Component<Props> { class Header extends React.Component<Props> {
render() { render() {
const { children } = this.props; const { children } = this.props;
return ( return (
<section className="hero is-dark is-small"> <section className="hero is-dark is-small">
<div className="hero-body"> <div className="hero-body">
<div className="container"> <div className="container">
<div className="columns is-vcentered"> <div className="columns is-vcentered">
<div className="column"> <div className="column">
<Logo /> <Logo />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div className="hero-foot"> <div className="hero-foot">
<div className="container">{children}</div> <div className="container">{children}</div>
</div> </div>
</section> </section>
); );
} }
} }
export default Header; export default Header;

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

View File

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

View File

@@ -1,47 +1,54 @@
// @flow // @flow
import React from "react"; import React from "react";
import { translate } from "react-i18next"; import { translate } from "react-i18next";
import { Checkbox, InputField, Subtitle } from "@scm-manager/ui-components"; import { Checkbox, InputField, Subtitle } from "@scm-manager/ui-components";
type Props = { type Props = {
baseUrl: string, baseUrl: string,
forceBaseUrl: boolean, forceBaseUrl: boolean,
t: string => string, t: string => string,
onChange: (boolean, any, string) => void, onChange: (boolean, any, string) => void,
hasUpdatePermission: boolean hasUpdatePermission: boolean
}; };
class BaseUrlSettings extends React.Component<Props> { class BaseUrlSettings extends React.Component<Props> {
render() { render() {
const { t, baseUrl, forceBaseUrl, hasUpdatePermission } = this.props; const { t, baseUrl, forceBaseUrl, hasUpdatePermission } = this.props;
return ( return (
<div> <div>
<Subtitle subtitle={t("base-url-settings.name")} /> <Subtitle subtitle={t("base-url-settings.name")} />
<Checkbox <div class="columns">
checked={forceBaseUrl} <div class="column is-half">
label={t("base-url-settings.force-base-url")}
onChange={this.handleForceBaseUrlChange} <Checkbox
disabled={!hasUpdatePermission} checked={forceBaseUrl}
helpText={t("help.forceBaseUrlHelpText")} label={t("base-url-settings.force-base-url")}
/> onChange={this.handleForceBaseUrlChange}
<InputField disabled={!hasUpdatePermission}
label={t("base-url-settings.base-url")} helpText={t("help.forceBaseUrlHelpText")}
onChange={this.handleBaseUrlChange} />
value={baseUrl} </div>
disabled={!hasUpdatePermission} <div class="column is-half">
helpText={t("help.baseUrlHelpText")} <InputField
/> label={t("base-url-settings.base-url")}
</div> onChange={this.handleBaseUrlChange}
); value={baseUrl}
} disabled={!hasUpdatePermission}
helpText={t("help.baseUrlHelpText")}
handleBaseUrlChange = (value: string) => { />
this.props.onChange(true, value, "baseUrl"); </div>
}; </div>
handleForceBaseUrlChange = (value: boolean) => { </div>
this.props.onChange(true, value, "forceBaseUrl"); );
}; }
}
handleBaseUrlChange = (value: string) => {
export default translate("config")(BaseUrlSettings); 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 // @flow
import React from "react"; import React from "react";
import { translate } from "react-i18next"; import { translate } from "react-i18next";
import { Checkbox, InputField } from "@scm-manager/ui-components"; import { Checkbox, InputField } from "@scm-manager/ui-components";
type Props = { type Props = {
realmDescription: string, realmDescription: string,
enableRepositoryArchive: boolean, enableRepositoryArchive: boolean,
disableGroupingGrid: boolean, disableGroupingGrid: boolean,
dateFormat: string, dateFormat: string,
anonymousAccessEnabled: boolean, anonymousAccessEnabled: boolean,
skipFailedAuthenticators: boolean, skipFailedAuthenticators: boolean,
pluginUrl: string, pluginUrl: string,
enabledXsrfProtection: boolean, enabledXsrfProtection: boolean,
defaultNamespaceStrategy: string, defaultNamespaceStrategy: string,
t: string => string, t: string => string,
onChange: (boolean, any, string) => void, onChange: (boolean, any, string) => void,
hasUpdatePermission: boolean hasUpdatePermission: boolean
}; };
class GeneralSettings extends React.Component<Props> { class GeneralSettings extends React.Component<Props> {
render() { render() {
const { const {
t, t,
realmDescription, realmDescription,
enableRepositoryArchive, enableRepositoryArchive,
disableGroupingGrid, disableGroupingGrid,
dateFormat, dateFormat,
anonymousAccessEnabled, anonymousAccessEnabled,
skipFailedAuthenticators, skipFailedAuthenticators,
pluginUrl, pluginUrl,
enabledXsrfProtection, enabledXsrfProtection,
defaultNamespaceStrategy, defaultNamespaceStrategy,
hasUpdatePermission hasUpdatePermission
} = this.props; } = this.props;
return ( return (
<div> <div>
<InputField <div class="columns">
label={t("general-settings.realm-description")} <div class="column is-half">
onChange={this.handleRealmDescriptionChange} <InputField
value={realmDescription} label={t("general-settings.realm-description")}
disabled={!hasUpdatePermission} onChange={this.handleRealmDescriptionChange}
helpText={t("help.realmDescriptionHelpText")} value={realmDescription}
/> disabled={!hasUpdatePermission}
<InputField helpText={t("help.realmDescriptionHelpText")}
label={t("general-settings.date-format")} />
onChange={this.handleDateFormatChange} </div>
value={dateFormat} <div class="column is-half">
disabled={!hasUpdatePermission} <InputField
helpText={t("help.dateFormatHelpText")} label={t("general-settings.date-format")}
/> onChange={this.handleDateFormatChange}
<InputField value={dateFormat}
label={t("general-settings.plugin-url")} disabled={!hasUpdatePermission}
onChange={this.handlePluginUrlChange} helpText={t("help.dateFormatHelpText")}
value={pluginUrl} />
disabled={!hasUpdatePermission} </div>
helpText={t("help.pluginRepositoryHelpText")} </div>
/> <div class="columns">
<InputField <div class="column is-half">
label={t("general-settings.default-namespace-strategy")} <InputField
onChange={this.handleDefaultNamespaceStrategyChange} label={t("general-settings.plugin-url")}
value={defaultNamespaceStrategy} onChange={this.handlePluginUrlChange}
disabled={!hasUpdatePermission} value={pluginUrl}
helpText={t("help.defaultNameSpaceStrategyHelpText")} disabled={!hasUpdatePermission}
/> helpText={t("help.pluginRepositoryHelpText")}
<Checkbox />
checked={enabledXsrfProtection} </div>
label={t("general-settings.enabled-xsrf-protection")} <div class="column is-half">
onChange={this.handleEnabledXsrfProtectionChange} <InputField
disabled={!hasUpdatePermission} label={t("general-settings.default-namespace-strategy")}
helpText={t("help.enableXsrfProtectionHelpText")} onChange={this.handleDefaultNamespaceStrategyChange}
/> value={defaultNamespaceStrategy}
<Checkbox disabled={!hasUpdatePermission}
checked={enableRepositoryArchive} helpText={t("help.defaultNameSpaceStrategyHelpText")}
label={t("general-settings.enable-repository-archive")} />
onChange={this.handleEnableRepositoryArchiveChange} </div>
disabled={!hasUpdatePermission} </div>
helpText={t("help.enableRepositoryArchiveHelpText")} <div class="columns">
/> <div class="column is-half">
<Checkbox <Checkbox
checked={disableGroupingGrid} checked={enabledXsrfProtection}
label={t("general-settings.disable-grouping-grid")} label={t("general-settings.enabled-xsrf-protection")}
onChange={this.handleDisableGroupingGridChange} onChange={this.handleEnabledXsrfProtectionChange}
disabled={!hasUpdatePermission} disabled={!hasUpdatePermission}
helpText={t("help.disableGroupingGridHelpText")} helpText={t("help.enableXsrfProtectionHelpText")}
/> />
<Checkbox </div>
checked={anonymousAccessEnabled} <div class="column is-half">
label={t("general-settings.anonymous-access-enabled")} <Checkbox
onChange={this.handleAnonymousAccessEnabledChange} checked={enableRepositoryArchive}
disabled={!hasUpdatePermission} label={t("general-settings.enable-repository-archive")}
helpText={t("help.allowAnonymousAccessHelpText")} onChange={this.handleEnableRepositoryArchiveChange}
/> disabled={!hasUpdatePermission}
<Checkbox helpText={t("help.enableRepositoryArchiveHelpText")}
checked={skipFailedAuthenticators} />
label={t("general-settings.skip-failed-authenticators")} </div>
onChange={this.handleSkipFailedAuthenticatorsChange} </div>
disabled={!hasUpdatePermission} <div class="columns">
helpText={t("help.skipFailedAuthenticatorsHelpText")} <div class="column is-half">
/> <Checkbox
</div> checked={disableGroupingGrid}
); label={t("general-settings.disable-grouping-grid")}
} onChange={this.handleDisableGroupingGridChange}
disabled={!hasUpdatePermission}
handleRealmDescriptionChange = (value: string) => { helpText={t("help.disableGroupingGridHelpText")}
this.props.onChange(true, value, "realmDescription"); />
}; </div>
handleEnableRepositoryArchiveChange = (value: boolean) => { <div class="column is-half">
this.props.onChange(true, value, "enableRepositoryArchive"); <Checkbox
}; checked={anonymousAccessEnabled}
handleDisableGroupingGridChange = (value: boolean) => { label={t("general-settings.anonymous-access-enabled")}
this.props.onChange(true, value, "disableGroupingGrid"); onChange={this.handleAnonymousAccessEnabledChange}
}; disabled={!hasUpdatePermission}
handleDateFormatChange = (value: string) => { helpText={t("help.allowAnonymousAccessHelpText")}
this.props.onChange(true, value, "dateFormat"); />
}; </div>
handleAnonymousAccessEnabledChange = (value: string) => { </div>
this.props.onChange(true, value, "anonymousAccessEnabled"); <div class="columns">
}; <div class="column is-half">
<Checkbox
handleSkipFailedAuthenticatorsChange = (value: string) => { checked={skipFailedAuthenticators}
this.props.onChange(true, value, "skipFailedAuthenticators"); label={t("general-settings.skip-failed-authenticators")}
}; onChange={this.handleSkipFailedAuthenticatorsChange}
handlePluginUrlChange = (value: string) => { disabled={!hasUpdatePermission}
this.props.onChange(true, value, "pluginUrl"); helpText={t("help.skipFailedAuthenticatorsHelpText")}
}; />
</div>
handleEnabledXsrfProtectionChange = (value: boolean) => { </div>
this.props.onChange(true, value, "enabledXsrfProtection"); </div>
}; );
handleDefaultNamespaceStrategyChange = (value: string) => { }
this.props.onChange(true, value, "defaultNamespaceStrategy");
}; handleRealmDescriptionChange = (value: string) => {
} this.props.onChange(true, value, "realmDescription");
};
export default translate("config")(GeneralSettings); 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 // @flow
import React from "react"; import React from "react";
import { translate } from "react-i18next"; import { translate } from "react-i18next";
import { import {
InputField, InputField,
Subtitle, Subtitle,
validation as validator validation as validator
} from "@scm-manager/ui-components"; } from "@scm-manager/ui-components";
type Props = { type Props = {
loginAttemptLimit: number, loginAttemptLimit: number,
loginAttemptLimitTimeout: number, loginAttemptLimitTimeout: number,
t: string => string, t: string => string,
onChange: (boolean, any, string) => void, onChange: (boolean, any, string) => void,
hasUpdatePermission: boolean hasUpdatePermission: boolean
}; };
type State = { type State = {
loginAttemptLimitError: boolean, loginAttemptLimitError: boolean,
loginAttemptLimitTimeoutError: boolean loginAttemptLimitTimeoutError: boolean
}; };
class LoginAttempt extends React.Component<Props, State> { class LoginAttempt extends React.Component<Props, State> {
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
this.state = { this.state = {
loginAttemptLimitError: false, loginAttemptLimitError: false,
loginAttemptLimitTimeoutError: false loginAttemptLimitTimeoutError: false
}; };
} }
render() { render() {
const { const {
t, t,
loginAttemptLimit, loginAttemptLimit,
loginAttemptLimitTimeout, loginAttemptLimitTimeout,
hasUpdatePermission hasUpdatePermission
} = this.props; } = this.props;
return ( return (
<div> <div>
<Subtitle subtitle={t("login-attempt.name")} /> <Subtitle subtitle={t("login-attempt.name")} />
<InputField <div class="columns">
label={t("login-attempt.login-attempt-limit")} <div class="column is-half">
onChange={this.handleLoginAttemptLimitChange} <InputField
value={loginAttemptLimit} label={t("login-attempt.login-attempt-limit")}
disabled={!hasUpdatePermission} onChange={this.handleLoginAttemptLimitChange}
validationError={this.state.loginAttemptLimitError} value={loginAttemptLimit}
errorMessage={t("validation.login-attempt-limit-invalid")} disabled={!hasUpdatePermission}
helpText={t("help.loginAttemptLimitHelpText")} validationError={this.state.loginAttemptLimitError}
/> errorMessage={t("validation.login-attempt-limit-invalid")}
<InputField helpText={t("help.loginAttemptLimitHelpText")}
label={t("login-attempt.login-attempt-limit-timeout")} />
onChange={this.handleLoginAttemptLimitTimeoutChange} </div>
value={loginAttemptLimitTimeout} <div class="column is-half">
disabled={!hasUpdatePermission} <InputField
validationError={this.state.loginAttemptLimitTimeoutError} label={t("login-attempt.login-attempt-limit-timeout")}
errorMessage={t("validation.login-attempt-limit-timeout-invalid")} onChange={this.handleLoginAttemptLimitTimeoutChange}
helpText={t("help.loginAttemptLimitTimeoutHelpText")} value={loginAttemptLimitTimeout}
/> disabled={!hasUpdatePermission}
</div> validationError={this.state.loginAttemptLimitTimeoutError}
); errorMessage={t("validation.login-attempt-limit-timeout-invalid")}
} helpText={t("help.loginAttemptLimitTimeoutHelpText")}
/>
//TODO: set Error in ConfigForm to disable Submit Button! </div>
handleLoginAttemptLimitChange = (value: string) => { </div>
this.setState({ </div>
...this.state, );
loginAttemptLimitError: !validator.isNumberValid(value) }
});
this.props.onChange( //TODO: set Error in ConfigForm to disable Submit Button!
validator.isNumberValid(value), handleLoginAttemptLimitChange = (value: string) => {
value, this.setState({
"loginAttemptLimit" ...this.state,
); loginAttemptLimitError: !validator.isNumberValid(value)
}; });
this.props.onChange(
handleLoginAttemptLimitTimeoutChange = (value: string) => { validator.isNumberValid(value),
this.setState({ value,
...this.state, "loginAttemptLimit"
loginAttemptLimitTimeoutError: !validator.isNumberValid(value) );
}); };
this.props.onChange(
validator.isNumberValid(value), handleLoginAttemptLimitTimeoutChange = (value: string) => {
value, this.setState({
"loginAttemptLimitTimeout" ...this.state,
); loginAttemptLimitTimeoutError: !validator.isNumberValid(value)
}; });
} this.props.onChange(
validator.isNumberValid(value),
export default translate("config")(LoginAttempt); value,
"loginAttemptLimitTimeout"
);
};
}
export default translate("config")(LoginAttempt);

View File

@@ -1,126 +1,146 @@
// @flow // @flow
import React from "react"; import React from "react";
import { translate } from "react-i18next"; import { translate } from "react-i18next";
import { import {
Checkbox, Checkbox,
InputField, InputField,
Subtitle, Subtitle,
AddEntryToTableField AddEntryToTableField
} from "@scm-manager/ui-components"; } from "@scm-manager/ui-components";
import ProxyExcludesTable from "../table/ProxyExcludesTable"; import ProxyExcludesTable from "../table/ProxyExcludesTable";
type Props = { type Props = {
proxyPassword: string, proxyPassword: string,
proxyPort: number, proxyPort: number,
proxyServer: string, proxyServer: string,
proxyUser: string, proxyUser: string,
enableProxy: boolean, enableProxy: boolean,
proxyExcludes: string[], proxyExcludes: string[],
t: string => string, t: string => string,
onChange: (boolean, any, string) => void, onChange: (boolean, any, string) => void,
hasUpdatePermission: boolean hasUpdatePermission: boolean
}; };
class ProxySettings extends React.Component<Props> { class ProxySettings extends React.Component<Props> {
render() { render() {
const { const {
t, t,
proxyPassword, proxyPassword,
proxyPort, proxyPort,
proxyServer, proxyServer,
proxyUser, proxyUser,
enableProxy, enableProxy,
proxyExcludes, proxyExcludes,
hasUpdatePermission hasUpdatePermission
} = this.props; } = this.props;
return ( return (
<div> <div>
<Subtitle subtitle={t("proxy-settings.name")} /> <Subtitle subtitle={t("proxy-settings.name")} />
<Checkbox <div class="columns">
checked={enableProxy} <div class="column is-full">
label={t("proxy-settings.enable-proxy")} <Checkbox
onChange={this.handleEnableProxyChange} checked={enableProxy}
disabled={!hasUpdatePermission} label={t("proxy-settings.enable-proxy")}
helpText={t("help.enableProxyHelpText")} onChange={this.handleEnableProxyChange}
/> disabled={!hasUpdatePermission}
<InputField helpText={t("help.enableProxyHelpText")}
label={t("proxy-settings.proxy-password")} />
onChange={this.handleProxyPasswordChange} </div>
value={proxyPassword} </div>
type="password" <div class="columns">
disabled={!enableProxy || !hasUpdatePermission} <div class="column is-half">
helpText={t("help.proxyPasswordHelpText")} <InputField
/> label={t("proxy-settings.proxy-password")}
<InputField onChange={this.handleProxyPasswordChange}
label={t("proxy-settings.proxy-port")} value={proxyPassword}
value={proxyPort} type="password"
onChange={this.handleProxyPortChange} disabled={!enableProxy || !hasUpdatePermission}
disabled={!enableProxy || !hasUpdatePermission} helpText={t("help.proxyPasswordHelpText")}
helpText={t("help.proxyPortHelpText")} />
/> </div>
<InputField <div class="column is-half">
label={t("proxy-settings.proxy-server")} <InputField
value={proxyServer} label={t("proxy-settings.proxy-port")}
onChange={this.handleProxyServerChange} value={proxyPort}
disabled={!enableProxy || !hasUpdatePermission} onChange={this.handleProxyPortChange}
helpText={t("help.proxyServerHelpText")} disabled={!enableProxy || !hasUpdatePermission}
/> helpText={t("help.proxyPortHelpText")}
<InputField />
label={t("proxy-settings.proxy-user")} </div>
value={proxyUser} </div>
onChange={this.handleProxyUserChange} <div class="columns">
disabled={!enableProxy || !hasUpdatePermission} <div class="column is-half">
helpText={t("help.proxyUserHelpText")} <InputField
/> label={t("proxy-settings.proxy-server")}
<ProxyExcludesTable value={proxyServer}
proxyExcludes={proxyExcludes} onChange={this.handleProxyServerChange}
onChange={(isValid, changedValue, name) => disabled={!enableProxy || !hasUpdatePermission}
this.props.onChange(isValid, changedValue, name) helpText={t("help.proxyServerHelpText")}
} />
disabled={!enableProxy || !hasUpdatePermission} </div>
/> <div class="column is-half">
<AddEntryToTableField <InputField
addEntry={this.addProxyExclude} label={t("proxy-settings.proxy-user")}
disabled={!enableProxy || !hasUpdatePermission} value={proxyUser}
buttonLabel={t("proxy-settings.add-proxy-exclude-button")} onChange={this.handleProxyUserChange}
fieldLabel={t("proxy-settings.add-proxy-exclude-textfield")} disabled={!enableProxy || !hasUpdatePermission}
errorMessage={t("proxy-settings.add-proxy-exclude-error")} helpText={t("help.proxyUserHelpText")}
/> />
</div> </div>
); </div>
} <div class="columns">
<div class="column is-full">
handleProxyPasswordChange = (value: string) => { <ProxyExcludesTable
this.props.onChange(true, value, "proxyPassword"); proxyExcludes={proxyExcludes}
}; onChange={(isValid, changedValue, name) =>
handleProxyPortChange = (value: string) => { this.props.onChange(isValid, changedValue, name)
this.props.onChange(true, value, "proxyPort"); }
}; disabled={!enableProxy || !hasUpdatePermission}
handleProxyServerChange = (value: string) => { />
this.props.onChange(true, value, "proxyServer"); <AddEntryToTableField
}; addEntry={this.addProxyExclude}
handleProxyUserChange = (value: string) => { disabled={!enableProxy || !hasUpdatePermission}
this.props.onChange(true, value, "proxyUser"); buttonLabel={t("proxy-settings.add-proxy-exclude-button")}
}; fieldLabel={t("proxy-settings.add-proxy-exclude-textfield")}
handleEnableProxyChange = (value: string) => { errorMessage={t("proxy-settings.add-proxy-exclude-error")}
this.props.onChange(true, value, "enableProxy"); />
}; </div>
</div>
addProxyExclude = (proxyExcludeName: string) => { </div>
if (this.isProxyExcludeMember(proxyExcludeName)) { );
return; }
}
this.props.onChange( handleProxyPasswordChange = (value: string) => {
true, this.props.onChange(true, value, "proxyPassword");
[...this.props.proxyExcludes, proxyExcludeName], };
"proxyExcludes" handleProxyPortChange = (value: string) => {
); this.props.onChange(true, value, "proxyPort");
}; };
handleProxyServerChange = (value: string) => {
isProxyExcludeMember = (proxyExcludeName: string) => { this.props.onChange(true, value, "proxyServer");
return this.props.proxyExcludes.includes(proxyExcludeName); };
}; handleProxyUserChange = (value: string) => {
} this.props.onChange(true, value, "proxyUser");
};
export default translate("config")(ProxySettings); 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 // @flow
import React from "react"; import React from "react";
import { translate } from "react-i18next"; import { translate } from "react-i18next";
import { Route } from "react-router"; import { Route } from "react-router";
import { ExtensionPoint } from "@scm-manager/ui-extensions"; import { ExtensionPoint } from "@scm-manager/ui-extensions";
import type { Links } from "@scm-manager/ui-types"; import type { Links } from "@scm-manager/ui-types";
import { Page, Navigation, NavLink, Section } from "@scm-manager/ui-components"; import { Page, Navigation, NavLink, Section } from "@scm-manager/ui-components";
import GlobalConfig from "./GlobalConfig"; import GlobalConfig from "./GlobalConfig";
import type { History } from "history"; import type { History } from "history";
import {connect} from "react-redux"; import {connect} from "react-redux";
import {compose} from "redux"; import {compose} from "redux";
import { getLinks } from "../../modules/indexResource"; import { getLinks } from "../../modules/indexResource";
type Props = { type Props = {
links: Links, links: Links,
// context objects // context objects
t: string => string, t: string => string,
match: any, match: any,
history: History history: History
}; };
class Config extends React.Component<Props> { class Config extends React.Component<Props> {
stripEndingSlash = (url: string) => { stripEndingSlash = (url: string) => {
if (url.endsWith("/")) { if (url.endsWith("/")) {
return url.substring(0, url.length - 2); return url.substring(0, url.length - 2);
} }
return url; return url;
}; };
matchedUrl = () => { matchedUrl = () => {
return this.stripEndingSlash(this.props.match.url); return this.stripEndingSlash(this.props.match.url);
}; };
render() { render() {
const { links, t } = this.props; const { links, t } = this.props;
const url = this.matchedUrl(); const url = this.matchedUrl();
const extensionProps = { const extensionProps = {
links, links,
url url
}; };
return ( return (
<Page> <Page>
<div className="columns"> <div className="columns">
<div className="column is-three-quarters"> <div className="column is-three-quarters">
<Route path={url} exact component={GlobalConfig} /> <Route path={url} exact component={GlobalConfig} />
<ExtensionPoint name="config.route" <ExtensionPoint name="config.route"
props={extensionProps} props={extensionProps}
renderAll={true} renderAll={true}
/> />
</div> </div>
<div className="column"> <div className="column is-one-quarter">
<Navigation> <Navigation>
<Section label={t("config.navigation-title")}> <Section label={t("config.navigation-title")}>
<NavLink <NavLink
to={`${url}`} to={`${url}`}
label={t("global-config.navigation-label")} label={t("global-config.navigation-label")}
/> />
<ExtensionPoint name="config.navigation" <ExtensionPoint name="config.navigation"
props={extensionProps} props={extensionProps}
renderAll={true} renderAll={true}
/> />
</Section> </Section>
</Navigation> </Navigation>
</div> </div>
</div> </div>
</Page> </Page>
); );
} }
} }
const mapStateToProps = (state: any) => { const mapStateToProps = (state: any) => {
const links = getLinks(state); const links = getLinks(state);
return { return {
links links
}; };
}; };
export default compose( export default compose(
connect(mapStateToProps), connect(mapStateToProps),
translate("config") translate("config")
)(Config); )(Config);

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,57 +1,241 @@
@import "bulma/sass/utilities/initial-variables"; @import "bulma/sass/utilities/initial-variables";
@import "bulma/sass/utilities/functions"; @import "bulma/sass/utilities/functions";
$blue: #33B2E8; $blue: #33B2E8;
$mint: #11dfd0;
// $footer-background-color
.is-ellipsis-overflow {
overflow: hidden; // $footer-background-color
text-overflow: ellipsis;
white-space: nowrap; .is-ellipsis-overflow {
} overflow: hidden;
text-overflow: ellipsis;
.has-rounded-border { white-space: nowrap;
border-radius: 0.25rem; }
}
.has-rounded-border {
.is-full-width { border-radius: 0.25rem;
width: 100%; }
}
.is-full-width {
.fitParent { width: 100%;
// TODO get rid of important }
margin: 0 !important;
// 3.8em for line-numbers .fitParent {
padding: 0 0 0 3.8em !important; // TODO get rid of important
} margin: 0 !important;
// 3.8em for line-numbers
.main { padding: 0 0 0 3.8em !important;
min-height: calc(100vh - 260px); }
}
.footer { .main {
height: 50px; min-height: calc(100vh - 260px);
} }
.footer {
// 6. Import the rest of Bulma height: 50px;
@import "bulma/bulma"; }
@import "bulma-tooltip/dist/css/bulma-tooltip";
// 6. Import the rest of Bulma
// import at the end, because we need a lot of stuff from bulma/bulma @import "bulma/bulma";
.box-link-shadow { @import "bulma-tooltip/dist/css/bulma-tooltip";
&:hover,
&:focus { // import at the end, because we need a lot of stuff from bulma/bulma
box-shadow: $box-link-hover-shadow; .box-link-shadow {
} &:hover,
&:active { &:focus {
box-shadow: $box-link-active-shadow; box-shadow: $box-link-hover-shadow;
} }
} &:active {
box-shadow: $box-link-active-shadow;
}
@import "@fortawesome/fontawesome-free/scss/fontawesome.scss"; }
$fa-font-path: "webfonts";
@import "@fortawesome/fontawesome-free/scss/solid.scss";
@import "@fortawesome/fontawesome-free/scss/fontawesome.scss";
@import "diff2html/dist/diff2html"; $fa-font-path: "webfonts";
@import "@fortawesome/fontawesome-free/scss/solid.scss";
@import "diff2html/dist/diff2html";
// NEW STYLES
// dark hero colors
.hero.is-dark {
background-color: #002e4b;
background-image:url(../images/scmManagerHero.jpg);
background-size: cover;
background-position: top center;
.tabs.is-boxed li.is-active a,
.tabs.is-boxed li.is-active a:hover,
.tabs.is-toggle li.is-active a,
.tabs.is-toggle li.is-active a:hover {
background-color: #28b1e8;
border-color: #28b1e8;
color: #fff;
}
}
// footer colors
.footer {
background-color: whitesmoke;
}
//typography
.subtitle {
color: #666;
}
// buttons
.button{
padding-left: 1.5em;
padding-right: 1.5em;
height:2.5rem;
&.is-primary {
background-color: $mint;
}
}
// pagination
.pagination-next, .pagination-link, .pagination-ellipsis{
padding-left: 1.5em;
padding-right: 1.5em;
height:2.5rem;
}
.pagination-previous, .pagination-next {
min-width: 6.75em;
}
// sidebar menu
.aside-background {
bottom: 0;
left: 50%;
position: absolute;
right: 0;
top: 0;
background-color: whitesmoke;
}
.menu {
div{
height: 100%;
/*border: 1px solid #eee;*/
margin-bottom: 1rem;
}
}
.menu-label {
color: #fff;
font-size: 1em;
font-weight: 600;
background-color: #bbb;
border-radius: 5px 5px 0 0;
padding: .5rem 1rem;
text-transform: none;
&:last-child, &:not(:last-child) {
margin-bottom: 0;
}
}
.menu div:first-child .menu-label {
background-color: $blue;
}
.menu-list {
a{
border-radius: 0;
color: #333;
padding: 1rem;
border-top: 1px solid #eee;
border-left: 1px solid #eee;
border-right: 1px solid #eee;
&.is-active {
color: #33B2E8;
background-color: #fff;
&:before{
position: relative;
content: " ";
background: #33B2E8;
height: 53px;
width: 2px;
display: block;
left: -17px;
float: left;
top: -16px;
}
}
}
> li:first-child > a{
border-top: none;
}
li:last-child > a{
border-bottom: 1px solid #eee;
}
}
// tables
.table {
width: 100%;
td {
border-color: #eee;
padding: 1rem
}
}
// card tables
.card-table {
border-collapse: separate;
border-spacing: 0px 5px;
tr{
a{
color: #363636;
}
&:hover {
td {
background-color: whitesmoke;
&:nth-child(4){
background-color: #E1E1E1;
}
}
a{
color: $blue;
}
}
}
td {
border-bottom: 1px solid whitesmoke;
background-color: #fafafa;
padding: 1em 1.25em;
&:first-child{
border-left: 3px solid $mint;
}
&:nth-child(4){
background-color: whitesmoke;
}
}
&.is-hoverable tbody tr:not(.is-selected):hover {
background-color: whitesmoke;
}
thead th {
background-color: transparent;
border: none;
}
}
// forms
.field:not(.is-grouped){
margin-bottom: 1rem;
}
.input, .textarea {
background-color: whitesmoke;
border-color: #efefef;
box-shadow: none;
}
.input[disabled], .textarea[disabled] {
background-color: #ddd;
border-color: #ccc;
box-shadow: none;
color: #aaa;
}