mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-07 14:05:44 +01:00
Added first UI changes
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
BIN
scm-ui/public/images/scmManagerHero.jpg
Normal file
BIN
scm-ui/public/images/scmManagerHero.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 125 KiB |
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -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));
|
||||||
|
|||||||
10277
scm-ui/styles/scm.css
10277
scm-ui/styles/scm.css
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user