diff --git a/scm-ui/public/images/blib.jpg b/scm-ui/public/images/blib.jpg index 5fa47ab2bc..55c2ea62d8 100644 Binary files a/scm-ui/public/images/blib.jpg and b/scm-ui/public/images/blib.jpg differ diff --git a/scm-ui/src/containers/ProfileInfo.js b/scm-ui/src/containers/ProfileInfo.js index 5d350d8619..7baf2a9921 100644 --- a/scm-ui/src/containers/ProfileInfo.js +++ b/scm-ui/src/containers/ProfileInfo.js @@ -1,56 +1,56 @@ -// @flow -import React from "react"; -import AvatarWrapper from "../repos/components/changesets/AvatarWrapper"; -import type { Me } from "@scm-manager/ui-types"; -import { MailLink } from "@scm-manager/ui-components"; -import { compose } from "redux"; -import { translate } from "react-i18next"; - -type Props = { - me: Me, - - // Context props - t: string => string -}; -type State = {}; - -class ProfileInfo extends React.Component { - render() { - const { me, t } = this.props; - return ( - <> - -
-
-

- { - // TODO: add avatar - } -

-
-
-
- - - - - - - - - - - - - - - -
{t("profile.username")}{me.name}
{t("profile.displayName")}{me.displayName}
{t("profile.mail")} - -
- - ); - } -} - -export default compose(translate("commons"))(ProfileInfo); +// @flow +import React from "react"; +import AvatarWrapper from "../repos/components/changesets/AvatarWrapper"; +import type { Me } from "@scm-manager/ui-types"; +import { MailLink } from "@scm-manager/ui-components"; +import { compose } from "redux"; +import { translate } from "react-i18next"; + +type Props = { + me: Me, + + // Context props + t: string => string +}; +type State = {}; + +class ProfileInfo extends React.Component { + render() { + const { me, t } = this.props; + return ( + <> + +
+
+

+ { + // TODO: add avatar + } +

+
+
+
+ + + + + + + + + + + + + + + +
{t("profile.username")}{me.name}
{t("profile.displayName")}{me.displayName}
{t("profile.mail")} + +
+ + ); + } +} + +export default compose(translate("commons"))(ProfileInfo); diff --git a/scm-ui/src/groups/components/table/Details.js b/scm-ui/src/groups/components/table/Details.js index 097822a1f3..eb4c3fa0d5 100644 --- a/scm-ui/src/groups/components/table/Details.js +++ b/scm-ui/src/groups/components/table/Details.js @@ -1,69 +1,69 @@ -//@flow -import React from "react"; -import type { Group } from "@scm-manager/ui-types"; -import { translate } from "react-i18next"; -import GroupMember from "./GroupMember"; -import { DateFromNow } from "@scm-manager/ui-components"; - -type Props = { - group: Group, - t: string => string -}; - -class Details extends React.Component { - render() { - const { group, t } = this.props; - return ( - - - - - - - - - - - - - - - - - - - - - - - {this.renderMembers()} - -
{t("group.name")}{group.name}
{t("group.description")}{group.description}
{t("group.type")}{group.type}
{t("group.creationDate")} - -
{t("group.lastModified")} - -
- ); - } - - renderMembers() { - if (this.props.group.members.length > 0) { - return ( - - - {this.props.t("group.members")} -
    - {this.props.group._embedded.members.map((member, index) => { - return ; - })} -
- - - ); - } else { - return; - } - } -} - -export default translate("groups")(Details); +//@flow +import React from "react"; +import type { Group } from "@scm-manager/ui-types"; +import { translate } from "react-i18next"; +import GroupMember from "./GroupMember"; +import { DateFromNow } from "@scm-manager/ui-components"; + +type Props = { + group: Group, + t: string => string +}; + +class Details extends React.Component { + render() { + const { group, t } = this.props; + return ( + + + + + + + + + + + + + + + + + + + + + + + {this.renderMembers()} + +
{t("group.name")}{group.name}
{t("group.description")}{group.description}
{t("group.type")}{group.type}
{t("group.creationDate")} + +
{t("group.lastModified")} + +
+ ); + } + + renderMembers() { + if (this.props.group.members.length > 0) { + return ( + + + {this.props.t("group.members")} +
    + {this.props.group._embedded.members.map((member, index) => { + return ; + })} +
+ + + ); + } else { + return; + } + } +} + +export default translate("groups")(Details); diff --git a/scm-ui/src/groups/components/table/GroupRow.js b/scm-ui/src/groups/components/table/GroupRow.js index 32a8f946df..ccff8bd193 100644 --- a/scm-ui/src/groups/components/table/GroupRow.js +++ b/scm-ui/src/groups/components/table/GroupRow.js @@ -1,25 +1,25 @@ -// @flow -import React from "react"; -import { Link } from "react-router-dom"; -import type { Group } from "@scm-manager/ui-types"; - -type Props = { - group: Group -}; - -export default class GroupRow extends React.Component { - renderLink(to: string, label: string) { - return {label}; - } - - render() { - const { group } = this.props; - const to = `/group/${group.name}`; - return ( - - {this.renderLink(to, group.name)} - {group.description} - - ); - } -} +// @flow +import React from "react"; +import { Link } from "react-router-dom"; +import type { Group } from "@scm-manager/ui-types"; + +type Props = { + group: Group +}; + +export default class GroupRow extends React.Component { + renderLink(to: string, label: string) { + return {label}; + } + + render() { + const { group } = this.props; + const to = `/group/${group.name}`; + return ( + + {this.renderLink(to, group.name)} + {group.description} + + ); + } +} diff --git a/scm-ui/src/repos/components/RepositoryDetailTable.js b/scm-ui/src/repos/components/RepositoryDetailTable.js index db5f9abbc1..ca63398670 100644 --- a/scm-ui/src/repos/components/RepositoryDetailTable.js +++ b/scm-ui/src/repos/components/RepositoryDetailTable.js @@ -1,55 +1,55 @@ -//@flow -import React from "react"; -import type { Repository } from "@scm-manager/ui-types"; -import { MailLink, DateFromNow } from "@scm-manager/ui-components"; -import { translate } from "react-i18next"; - -type Props = { - repository: Repository, - // context props - t: string => string -}; - -class RepositoryDetailTable extends React.Component { - render() { - const { repository, t } = this.props; - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{t("repository.name")}{repository.name}
{t("repository.type")}{repository.type}
{t("repository.contact")} - -
{t("repository.description")}{repository.description}
{t("repository.creationDate")} - -
{t("repository.lastModified")} - -
- ); - } -} - -export default translate("repos")(RepositoryDetailTable); +//@flow +import React from "react"; +import type { Repository } from "@scm-manager/ui-types"; +import { MailLink, DateFromNow } from "@scm-manager/ui-components"; +import { translate } from "react-i18next"; + +type Props = { + repository: Repository, + // context props + t: string => string +}; + +class RepositoryDetailTable extends React.Component { + render() { + const { repository, t } = this.props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{t("repository.name")}{repository.name}
{t("repository.type")}{repository.type}
{t("repository.contact")} + +
{t("repository.description")}{repository.description}
{t("repository.creationDate")} + +
{t("repository.lastModified")} + +
+ ); + } +} + +export default translate("repos")(RepositoryDetailTable); diff --git a/scm-ui/src/repos/components/RepositoryDetails.js b/scm-ui/src/repos/components/RepositoryDetails.js index 99c88fec94..02d7f2f5ac 100644 --- a/scm-ui/src/repos/components/RepositoryDetails.js +++ b/scm-ui/src/repos/components/RepositoryDetails.js @@ -1,29 +1,30 @@ -//@flow -import React from "react"; -import type { Repository } from "@scm-manager/ui-types"; -import RepositoryDetailTable from "./RepositoryDetailTable"; -import { ExtensionPoint } from "@scm-manager/ui-extensions"; - -type Props = { - repository: Repository -}; - -class RepositoryDetails extends React.Component { - render() { - const { repository } = this.props; - return ( -
- -
- -
-
- ); - } -} - -export default RepositoryDetails; +//@flow +import React from "react"; +import type { Repository } from "@scm-manager/ui-types"; +import RepositoryDetailTable from "./RepositoryDetailTable"; +import { ExtensionPoint } from "@scm-manager/ui-extensions"; + +type Props = { + repository: Repository +}; + +class RepositoryDetails extends React.Component { + render() { + const { repository } = this.props; + return ( +
+ +
+
+ +
+
+ ); + } +} + +export default RepositoryDetails; diff --git a/scm-ui/src/repos/components/list/RepositoryEntry.js b/scm-ui/src/repos/components/list/RepositoryEntry.js index bc170144aa..571e53488e 100644 --- a/scm-ui/src/repos/components/list/RepositoryEntry.js +++ b/scm-ui/src/repos/components/list/RepositoryEntry.js @@ -1,113 +1,108 @@ -//@flow -import React from "react"; -import { Link } from "react-router-dom"; -import injectSheet from "react-jss"; -import type { Repository } from "@scm-manager/ui-types"; -import { DateFromNow } from "@scm-manager/ui-components"; -import RepositoryEntryLink from "./RepositoryEntryLink"; -import classNames from "classnames"; -import RepositoryAvatar from "./RepositoryAvatar"; - -const styles = { - outer: { - position: "relative" - }, - overlay: { - position: "absolute", - left: 0, - top: 0, - bottom: 0, - right: 0 - }, - inner: { - position: "relative", - pointerEvents: "none", - zIndex: 1 - }, - innerLink: { - pointerEvents: "all" - } -}; - -type Props = { - repository: Repository, - // context props - classes: any -}; - -class RepositoryEntry extends React.Component { - createLink = (repository: Repository) => { - return `/repo/${repository.namespace}/${repository.name}`; - }; - - renderChangesetsLink = (repository: Repository, repositoryLink: string) => { - if (repository._links["changesets"]) { - return ( - - ); - } - return null; - }; - - renderSourcesLink = (repository: Repository, repositoryLink: string) => { - if (repository._links["sources"]) { - return ( - - ); - } - return null; - }; - - renderModifyLink = (repository: Repository, repositoryLink: string) => { - if (repository._links["update"]) { - return ( - - ); - } - return null; - }; - - render() { - const { repository, classes } = this.props; - const repositoryLink = this.createLink(repository); - return ( -
- -
-
- -
-
-
-

- {repository.name} -
- {repository.description} -

-
- -
-
-
- ); - } -} - -export default injectSheet(styles)(RepositoryEntry); +//@flow +import React from "react"; +import { Link } from "react-router-dom"; +import injectSheet from "react-jss"; +import type { Repository } from "@scm-manager/ui-types"; +import { DateFromNow } from "@scm-manager/ui-components"; +import RepositoryEntryLink from "./RepositoryEntryLink"; +import classNames from "classnames"; +import RepositoryAvatar from "./RepositoryAvatar"; + +const styles = { + overlay: { + position: "absolute", + height: "calc(120px - 1.5rem)", + width: "calc(50% - 3rem)" + }, + inner: { + position: "relative", + pointerEvents: "none", + zIndex: 1 + }, + innerLink: { + pointerEvents: "all" + } +}; + +type Props = { + repository: Repository, + // context props + classes: any +}; + +class RepositoryEntry extends React.Component { + createLink = (repository: Repository) => { + return `/repo/${repository.namespace}/${repository.name}`; + }; + + renderChangesetsLink = (repository: Repository, repositoryLink: string) => { + if (repository._links["changesets"]) { + return ( + + ); + } + return null; + }; + + renderSourcesLink = (repository: Repository, repositoryLink: string) => { + if (repository._links["sources"]) { + return ( + + ); + } + return null; + }; + + renderModifyLink = (repository: Repository, repositoryLink: string) => { + if (repository._links["update"]) { + return ( + + ); + } + return null; + }; + + render() { + const { repository, classes } = this.props; + const repositoryLink = this.createLink(repository); + return ( +
+ +
+
+ +
+
+
+

+ {repository.name} +
+ {repository.description} +

+
+ +
+
+
+ ); + } +} + +export default injectSheet(styles)(RepositoryEntry); diff --git a/scm-ui/src/repos/components/list/RepositoryEntryLink.js b/scm-ui/src/repos/components/list/RepositoryEntryLink.js index 289ec7d326..e4fa2a623c 100644 --- a/scm-ui/src/repos/components/list/RepositoryEntryLink.js +++ b/scm-ui/src/repos/components/list/RepositoryEntryLink.js @@ -1,34 +1,35 @@ -//@flow -import React from "react"; -import { Link } from "react-router-dom"; -import injectSheet from "react-jss"; -import classNames from "classnames"; - -const styles = { - link: { - pointerEvents: "all" - } -}; - -type Props = { - to: string, - iconClass: string, - - // context props - classes: any -}; - -class RepositoryEntryLink extends React.Component { - render() { - const { to, iconClass, classes } = this.props; - return ( - - - - - - ); - } -} - -export default injectSheet(styles)(RepositoryEntryLink); +//@flow +import React from "react"; +import { Link } from "react-router-dom"; +import injectSheet from "react-jss"; +import classNames from "classnames"; + +const styles = { + link: { + pointerEvents: "all", + marginRight: "1.25rem !important" + } +}; + +type Props = { + to: string, + iconClass: string, + + // context props + classes: any +}; + +class RepositoryEntryLink extends React.Component { + render() { + const { to, iconClass, classes } = this.props; + return ( + + + + + + ); + } +} + +export default injectSheet(styles)(RepositoryEntryLink); diff --git a/scm-ui/src/repos/components/list/RepositoryGroupEntry.js b/scm-ui/src/repos/components/list/RepositoryGroupEntry.js index 785a00f8ab..aa38fd8501 100644 --- a/scm-ui/src/repos/components/list/RepositoryGroupEntry.js +++ b/scm-ui/src/repos/components/list/RepositoryGroupEntry.js @@ -12,6 +12,12 @@ const styles = { }, repoGroup: { marginBottom: "1em" + }, + wrapper: { + padding: "0 0.75rem" + }, + clearfix: { + clear: "both" } }; @@ -59,7 +65,10 @@ class RepositoryGroupEntry extends React.Component {
+
{content} +
+
); } diff --git a/scm-ui/src/repos/containers/BranchSelector.js b/scm-ui/src/repos/containers/BranchSelector.js index 2183e13b69..7952c8ad22 100644 --- a/scm-ui/src/repos/containers/BranchSelector.js +++ b/scm-ui/src/repos/containers/BranchSelector.js @@ -1,87 +1,90 @@ -// @flow - -import React from "react"; -import type { Branch } from "@scm-manager/ui-types"; -import DropDown from "../components/DropDown"; -import { translate } from "react-i18next"; -import injectSheet from "react-jss"; -import { compose } from "redux"; -import classNames from "classnames"; - -const styles = { - zeroflex: { - flexGrow: 0 - } -}; - -type Props = { - branches: Branch[], // TODO: Use generics? - selected: (branch?: Branch) => void, - selectedBranch: string, - - // context props - classes: Object, - t: string => string -}; - -type State = { selectedBranch?: Branch }; - -class BranchSelector extends React.Component { - constructor(props: Props) { - super(props); - this.state = {}; - } - - componentDidMount() { - this.props.branches - .filter(branch => branch.name === this.props.selectedBranch) - .forEach(branch => this.setState({ selectedBranch: branch })); - } - - render() { - const { branches, classes, t } = this.props; - - if (branches) { - return ( -
-
- -
-
-
-
- b.name)} - optionSelected={this.branchSelected} - preselectedOption={ - this.state.selectedBranch - ? this.state.selectedBranch.name - : "" - } - /> -
-
-
-
- ); - } else { - return null; - } - } - - branchSelected = (branchName: string) => { - const { branches, selected } = this.props; - const branch = branches.find(b => b.name === branchName); - - selected(branch); - this.setState({ selectedBranch: branch }); - }; -} - -export default compose( - injectSheet(styles), - translate("repos") -)(BranchSelector); +// @flow + +import React from "react"; +import type { Branch } from "@scm-manager/ui-types"; +import DropDown from "../components/DropDown"; +import { translate } from "react-i18next"; +import injectSheet from "react-jss"; +import { compose } from "redux"; +import classNames from "classnames"; + +const styles = { + zeroflex: { + flexGrow: 0 + }, + wrapper: { + padding: "1rem 1.5rem 0.25rem 1.5rem", + border: "1px solid #eee", + borderRadius: "5px 5px 0 0" + } +}; + +type Props = { + branches: Branch[], // TODO: Use generics? + selected: (branch?: Branch) => void, + selectedBranch: string, + + // context props + classes: Object, + t: string => string +}; + +type State = { selectedBranch?: Branch }; + +class BranchSelector extends React.Component { + constructor(props: Props) { + super(props); + this.state = {}; + } + + componentDidMount() { + this.props.branches + .filter(branch => branch.name === this.props.selectedBranch) + .forEach(branch => this.setState({ selectedBranch: branch })); + } + + render() { + const { branches, classes, t } = this.props; + + if (branches) { + return ( +
+
+ +
+
+
+
+ b.name)} + optionSelected={this.branchSelected} + preselectedOption={ + this.state.selectedBranch + ? this.state.selectedBranch.name + : "" + } + /> +
+
+
+
+ ); + } else { + return null; + } + } + + branchSelected = (branchName: string) => { + const { branches, selected } = this.props; + const branch = branches.find(b => b.name === branchName); + + selected(branch); + this.setState({ selectedBranch: branch }); + }; +} + +export default compose( + injectSheet(styles), + translate("repos") +)(BranchSelector); diff --git a/scm-ui/src/repos/permissions/components/CreatePermissionForm.js b/scm-ui/src/repos/permissions/components/CreatePermissionForm.js index a674f6b41f..2828835acf 100644 --- a/scm-ui/src/repos/permissions/components/CreatePermissionForm.js +++ b/scm-ui/src/repos/permissions/components/CreatePermissionForm.js @@ -1,122 +1,134 @@ -// @flow -import React from "react"; -import {translate} from "react-i18next"; -import {Checkbox, InputField, SubmitButton} from "@scm-manager/ui-components"; -import TypeSelector from "./TypeSelector"; -import type {PermissionCollection, PermissionCreateEntry} from "@scm-manager/ui-types"; -import * as validator from "./permissionValidation"; - -type Props = { - t: string => string, - createPermission: (permission: PermissionCreateEntry) => void, - loading: boolean, - currentPermissions: PermissionCollection -}; - -type State = { - name: string, - type: string, - groupPermission: boolean, - valid: boolean -}; - -class CreatePermissionForm extends React.Component { - constructor(props: Props) { - super(props); - - this.state = { - name: "", - type: "READ", - groupPermission: false, - valid: true - }; - } - - render() { - const { t, loading } = this.props; - const { name, type, groupPermission } = this.state; - - return ( -
-

- {t("permission.add-permission.add-permission-heading")} -

-
- - - - - -
- ); - } - - submit = e => { - this.props.createPermission({ - name: this.state.name, - type: this.state.type, - groupPermission: this.state.groupPermission - }); - this.removeState(); - e.preventDefault(); - }; - - removeState = () => { - this.setState({ - name: "", - type: "READ", - groupPermission: false, - valid: true - }); - }; - - handleTypeChange = (type: string) => { - this.setState({ - type: type - }); - }; - - handleNameChange = (name: string) => { - this.setState({ - name: name, - valid: validator.isPermissionValid( - name, - this.state.groupPermission, - this.props.currentPermissions - ) - }); - }; - handleGroupPermissionChange = (groupPermission: boolean) => { - this.setState({ - groupPermission: groupPermission, - valid: validator.isPermissionValid( - this.state.name, - groupPermission, - this.props.currentPermissions - ) - }); - }; -} - -export default translate("repos")(CreatePermissionForm); +// @flow +import React from "react"; +import {translate} from "react-i18next"; +import {Checkbox, InputField, SubmitButton} from "@scm-manager/ui-components"; +import TypeSelector from "./TypeSelector"; +import type {PermissionCollection, PermissionCreateEntry} from "@scm-manager/ui-types"; +import * as validator from "./permissionValidation"; + +type Props = { + t: string => string, + createPermission: (permission: PermissionCreateEntry) => void, + loading: boolean, + currentPermissions: PermissionCollection +}; + +type State = { + name: string, + type: string, + groupPermission: boolean, + valid: boolean +}; + +class CreatePermissionForm extends React.Component { + constructor(props: Props) { + super(props); + + this.state = { + name: "", + type: "READ", + groupPermission: false, + valid: true + }; + } + + render() { + const { t, loading } = this.props; + const { name, type, groupPermission } = this.state; + + return ( +
+
+

+ {t("permission.add-permission.add-permission-heading")} +

+
+
+
+ + + +
+
+ +
+
+
+
+ +
+
+
+
+ ); + } + + submit = e => { + this.props.createPermission({ + name: this.state.name, + type: this.state.type, + groupPermission: this.state.groupPermission + }); + this.removeState(); + e.preventDefault(); + }; + + removeState = () => { + this.setState({ + name: "", + type: "READ", + groupPermission: false, + valid: true + }); + }; + + handleTypeChange = (type: string) => { + this.setState({ + type: type + }); + }; + + handleNameChange = (name: string) => { + this.setState({ + name: name, + valid: validator.isPermissionValid( + name, + this.state.groupPermission, + this.props.currentPermissions + ) + }); + }; + handleGroupPermissionChange = (groupPermission: boolean) => { + this.setState({ + groupPermission: groupPermission, + valid: validator.isPermissionValid( + this.state.name, + groupPermission, + this.props.currentPermissions + ) + }); + }; +} + +export default translate("repos")(CreatePermissionForm); diff --git a/scm-ui/src/repos/permissions/components/TypeSelector.js b/scm-ui/src/repos/permissions/components/TypeSelector.js index de1950fa78..bec2c5b278 100644 --- a/scm-ui/src/repos/permissions/components/TypeSelector.js +++ b/scm-ui/src/repos/permissions/components/TypeSelector.js @@ -1,42 +1,42 @@ -// @flow -import React from "react"; -import { translate } from "react-i18next"; -import { Select } from "@scm-manager/ui-components"; - -type Props = { - t: string => string, - handleTypeChange: string => void, - type: string, - label?: string, - helpText?: string, - loading?: boolean -}; - -class TypeSelector extends React.Component { - render() { - const { type, handleTypeChange, loading, label, helpText } = this.props; - const types = ["READ", "OWNER", "WRITE"]; - - return ( - + ); + } + + createSelectOptions(types: string[]) { + return types.map(type => { + return { + label: type, + value: type + }; + }); + } +} + +export default translate("repos")(TypeSelector); diff --git a/scm-ui/src/repos/permissions/containers/Permissions.js b/scm-ui/src/repos/permissions/containers/Permissions.js index ee9ac281a5..05c780dc6d 100644 --- a/scm-ui/src/repos/permissions/containers/Permissions.js +++ b/scm-ui/src/repos/permissions/containers/Permissions.js @@ -1,209 +1,209 @@ -//@flow -import React from "react"; -import { connect } from "react-redux"; -import { translate } from "react-i18next"; -import { - fetchPermissions, - getFetchPermissionsFailure, - isFetchPermissionsPending, - getPermissionsOfRepo, - hasCreatePermission, - createPermission, - isCreatePermissionPending, - getCreatePermissionFailure, - createPermissionReset, - getDeletePermissionsFailure, - getModifyPermissionsFailure, - modifyPermissionReset, - deletePermissionReset -} from "../modules/permissions"; -import { Loading, ErrorPage } from "@scm-manager/ui-components"; -import type { - Permission, - PermissionCollection, - PermissionCreateEntry -} from "@scm-manager/ui-types"; -import SinglePermission from "./SinglePermission"; -import CreatePermissionForm from "../components/CreatePermissionForm"; -import type { History } from "history"; -import { getPermissionsLink } from "../../modules/repos"; - -type Props = { - namespace: string, - repoName: string, - loading: boolean, - error: Error, - permissions: PermissionCollection, - hasPermissionToCreate: boolean, - loadingCreatePermission: boolean, - permissionsLink: string, - - //dispatch functions - fetchPermissions: (link: string, namespace: string, repoName: string) => void, - createPermission: ( - link: string, - permission: PermissionCreateEntry, - namespace: string, - repoName: string, - callback?: () => void - ) => void, - createPermissionReset: (string, string) => void, - modifyPermissionReset: (string, string) => void, - deletePermissionReset: (string, string) => void, - // context props - t: string => string, - match: any, - history: History -}; - -class Permissions extends React.Component { - componentDidMount() { - const { - fetchPermissions, - namespace, - repoName, - modifyPermissionReset, - createPermissionReset, - deletePermissionReset, - permissionsLink - } = this.props; - - createPermissionReset(namespace, repoName); - modifyPermissionReset(namespace, repoName); - deletePermissionReset(namespace, repoName); - fetchPermissions(permissionsLink, namespace, repoName); - } - - createPermission = (permission: Permission) => { - this.props.createPermission( - this.props.permissionsLink, - permission, - this.props.namespace, - this.props.repoName - ); - }; - - render() { - const { - loading, - error, - permissions, - t, - namespace, - repoName, - loadingCreatePermission, - hasPermissionToCreate - } = this.props; - if (error) { - return ( - - ); - } - - if (loading || !permissions) { - return ; - } - - const createPermissionForm = hasPermissionToCreate ? ( - this.createPermission(permission)} - loading={loadingCreatePermission} - currentPermissions={permissions} - /> - ) : null; - - return ( -
- - - - - - - - - - {permissions.map(permission => { - return ( - - ); - })} - -
{t("permission.name")} - {t("permission.group-permission")} - {t("permission.type")} -
- {createPermissionForm} -
- ); - } -} - -const mapStateToProps = (state, ownProps) => { - const namespace = ownProps.namespace; - const repoName = ownProps.repoName; - const error = - getFetchPermissionsFailure(state, namespace, repoName) || - getCreatePermissionFailure(state, namespace, repoName) || - getDeletePermissionsFailure(state, namespace, repoName) || - getModifyPermissionsFailure(state, namespace, repoName); - const loading = isFetchPermissionsPending(state, namespace, repoName); - const permissions = getPermissionsOfRepo(state, namespace, repoName); - const loadingCreatePermission = isCreatePermissionPending( - state, - namespace, - repoName - ); - const hasPermissionToCreate = hasCreatePermission(state, namespace, repoName); - const permissionsLink = getPermissionsLink(state, namespace, repoName); - return { - namespace, - repoName, - error, - loading, - permissions, - hasPermissionToCreate, - loadingCreatePermission, - permissionsLink - }; -}; - -const mapDispatchToProps = dispatch => { - return { - fetchPermissions: (link: string, namespace: string, repoName: string) => { - dispatch(fetchPermissions(link, namespace, repoName)); - }, - createPermission: ( - link: string, - permission: PermissionCreateEntry, - namespace: string, - repoName: string, - callback?: () => void - ) => { - dispatch(createPermission(link, permission, namespace, repoName, callback)); - }, - createPermissionReset: (namespace: string, repoName: string) => { - dispatch(createPermissionReset(namespace, repoName)); - }, - modifyPermissionReset: (namespace: string, repoName: string) => { - dispatch(modifyPermissionReset(namespace, repoName)); - }, - deletePermissionReset: (namespace: string, repoName: string) => { - dispatch(deletePermissionReset(namespace, repoName)); - } - }; -}; - -export default connect( - mapStateToProps, - mapDispatchToProps -)(translate("repos")(Permissions)); +//@flow +import React from "react"; +import { connect } from "react-redux"; +import { translate } from "react-i18next"; +import { + fetchPermissions, + getFetchPermissionsFailure, + isFetchPermissionsPending, + getPermissionsOfRepo, + hasCreatePermission, + createPermission, + isCreatePermissionPending, + getCreatePermissionFailure, + createPermissionReset, + getDeletePermissionsFailure, + getModifyPermissionsFailure, + modifyPermissionReset, + deletePermissionReset +} from "../modules/permissions"; +import { Loading, ErrorPage } from "@scm-manager/ui-components"; +import type { + Permission, + PermissionCollection, + PermissionCreateEntry +} from "@scm-manager/ui-types"; +import SinglePermission from "./SinglePermission"; +import CreatePermissionForm from "../components/CreatePermissionForm"; +import type { History } from "history"; +import { getPermissionsLink } from "../../modules/repos"; + +type Props = { + namespace: string, + repoName: string, + loading: boolean, + error: Error, + permissions: PermissionCollection, + hasPermissionToCreate: boolean, + loadingCreatePermission: boolean, + permissionsLink: string, + + //dispatch functions + fetchPermissions: (link: string, namespace: string, repoName: string) => void, + createPermission: ( + link: string, + permission: PermissionCreateEntry, + namespace: string, + repoName: string, + callback?: () => void + ) => void, + createPermissionReset: (string, string) => void, + modifyPermissionReset: (string, string) => void, + deletePermissionReset: (string, string) => void, + // context props + t: string => string, + match: any, + history: History +}; + +class Permissions extends React.Component { + componentDidMount() { + const { + fetchPermissions, + namespace, + repoName, + modifyPermissionReset, + createPermissionReset, + deletePermissionReset, + permissionsLink + } = this.props; + + createPermissionReset(namespace, repoName); + modifyPermissionReset(namespace, repoName); + deletePermissionReset(namespace, repoName); + fetchPermissions(permissionsLink, namespace, repoName); + } + + createPermission = (permission: Permission) => { + this.props.createPermission( + this.props.permissionsLink, + permission, + this.props.namespace, + this.props.repoName + ); + }; + + render() { + const { + loading, + error, + permissions, + t, + namespace, + repoName, + loadingCreatePermission, + hasPermissionToCreate + } = this.props; + if (error) { + return ( + + ); + } + + if (loading || !permissions) { + return ; + } + + const createPermissionForm = hasPermissionToCreate ? ( + this.createPermission(permission)} + loading={loadingCreatePermission} + currentPermissions={permissions} + /> + ) : null; + + return ( +
+ + + + + + + + + + {permissions.map(permission => { + return ( + + ); + })} + +
{t("permission.name")} + {t("permission.group-permission")} + {t("permission.type")} +
+ {createPermissionForm} +
+ ); + } +} + +const mapStateToProps = (state, ownProps) => { + const namespace = ownProps.namespace; + const repoName = ownProps.repoName; + const error = + getFetchPermissionsFailure(state, namespace, repoName) || + getCreatePermissionFailure(state, namespace, repoName) || + getDeletePermissionsFailure(state, namespace, repoName) || + getModifyPermissionsFailure(state, namespace, repoName); + const loading = isFetchPermissionsPending(state, namespace, repoName); + const permissions = getPermissionsOfRepo(state, namespace, repoName); + const loadingCreatePermission = isCreatePermissionPending( + state, + namespace, + repoName + ); + const hasPermissionToCreate = hasCreatePermission(state, namespace, repoName); + const permissionsLink = getPermissionsLink(state, namespace, repoName); + return { + namespace, + repoName, + error, + loading, + permissions, + hasPermissionToCreate, + loadingCreatePermission, + permissionsLink + }; +}; + +const mapDispatchToProps = dispatch => { + return { + fetchPermissions: (link: string, namespace: string, repoName: string) => { + dispatch(fetchPermissions(link, namespace, repoName)); + }, + createPermission: ( + link: string, + permission: PermissionCreateEntry, + namespace: string, + repoName: string, + callback?: () => void + ) => { + dispatch(createPermission(link, permission, namespace, repoName, callback)); + }, + createPermissionReset: (namespace: string, repoName: string) => { + dispatch(createPermissionReset(namespace, repoName)); + }, + modifyPermissionReset: (namespace: string, repoName: string) => { + dispatch(modifyPermissionReset(namespace, repoName)); + }, + deletePermissionReset: (namespace: string, repoName: string) => { + dispatch(deletePermissionReset(namespace, repoName)); + } + }; +}; + +export default connect( + mapStateToProps, + mapDispatchToProps +)(translate("repos")(Permissions)); diff --git a/scm-ui/src/repos/permissions/containers/SinglePermission.js b/scm-ui/src/repos/permissions/containers/SinglePermission.js index 9426fbcd9f..62380128be 100644 --- a/scm-ui/src/repos/permissions/containers/SinglePermission.js +++ b/scm-ui/src/repos/permissions/containers/SinglePermission.js @@ -1,176 +1,176 @@ -// @flow -import React from "react"; -import type { Permission } from "@scm-manager/ui-types"; -import { translate } from "react-i18next"; -import { - modifyPermission, - isModifyPermissionPending, - deletePermission, - isDeletePermissionPending -} from "../modules/permissions"; -import { connect } from "react-redux"; -import type { History } from "history"; -import { Checkbox } from "@scm-manager/ui-components"; -import DeletePermissionButton from "../components/buttons/DeletePermissionButton"; -import TypeSelector from "../components/TypeSelector"; - -type Props = { - submitForm: Permission => void, - modifyPermission: (Permission, string, string) => void, - permission: Permission, - t: string => string, - namespace: string, - repoName: string, - match: any, - history: History, - loading: boolean, - deletePermission: (Permission, string, string) => void, - deleteLoading: boolean -}; - -type State = { - permission: Permission -}; - -class SinglePermission extends React.Component { - constructor(props: Props) { - super(props); - - this.state = { - permission: { - name: "", - type: "READ", - groupPermission: false, - _links: {} - } - }; - } - - componentDidMount() { - const { permission } = this.props; - if (permission) { - this.setState({ - permission: { - name: permission.name, - type: permission.type, - groupPermission: permission.groupPermission, - _links: permission._links - } - }); - } - } - - deletePermission = () => { - this.props.deletePermission( - this.props.permission, - this.props.namespace, - this.props.repoName - ); - }; - - render() { - const { permission } = this.state; - const { loading, namespace, repoName } = this.props; - const typeSelector = - this.props.permission._links && this.props.permission._links.update ? ( - - - - ) : ( - {permission.type} - ); - - return ( - - {permission.name} - - - - {typeSelector} - - - - - ); - } - - handleTypeChange = (type: string) => { - this.setState({ - permission: { - ...this.state.permission, - type: type - } - }); - this.modifyPermission(type); - }; - - modifyPermission = (type: string) => { - let permission = this.state.permission; - permission.type = type; - this.props.modifyPermission( - permission, - this.props.namespace, - this.props.repoName - ); - }; - - createSelectOptions(types: string[]) { - return types.map(type => { - return { - label: type, - value: type - }; - }); - } -} - -const mapStateToProps = (state, ownProps) => { - const permission = ownProps.permission; - const loading = isModifyPermissionPending( - state, - ownProps.namespace, - ownProps.repoName, - permission - ); - const deleteLoading = isDeletePermissionPending( - state, - ownProps.namespace, - ownProps.repoName, - permission - ); - - return { loading, deleteLoading }; -}; - -const mapDispatchToProps = dispatch => { - return { - modifyPermission: ( - permission: Permission, - namespace: string, - repoName: string - ) => { - dispatch(modifyPermission(permission, namespace, repoName)); - }, - deletePermission: ( - permission: Permission, - namespace: string, - repoName: string - ) => { - dispatch(deletePermission(permission, namespace, repoName)); - } - }; -}; -export default connect( - mapStateToProps, - mapDispatchToProps -)(translate("repos")(SinglePermission)); +// @flow +import React from "react"; +import type { Permission } from "@scm-manager/ui-types"; +import { translate } from "react-i18next"; +import { + modifyPermission, + isModifyPermissionPending, + deletePermission, + isDeletePermissionPending +} from "../modules/permissions"; +import { connect } from "react-redux"; +import type { History } from "history"; +import { Checkbox } from "@scm-manager/ui-components"; +import DeletePermissionButton from "../components/buttons/DeletePermissionButton"; +import TypeSelector from "../components/TypeSelector"; + +type Props = { + submitForm: Permission => void, + modifyPermission: (Permission, string, string) => void, + permission: Permission, + t: string => string, + namespace: string, + repoName: string, + match: any, + history: History, + loading: boolean, + deletePermission: (Permission, string, string) => void, + deleteLoading: boolean +}; + +type State = { + permission: Permission +}; + +class SinglePermission extends React.Component { + constructor(props: Props) { + super(props); + + this.state = { + permission: { + name: "", + type: "READ", + groupPermission: false, + _links: {} + } + }; + } + + componentDidMount() { + const { permission } = this.props; + if (permission) { + this.setState({ + permission: { + name: permission.name, + type: permission.type, + groupPermission: permission.groupPermission, + _links: permission._links + } + }); + } + } + + deletePermission = () => { + this.props.deletePermission( + this.props.permission, + this.props.namespace, + this.props.repoName + ); + }; + + render() { + const { permission } = this.state; + const { loading, namespace, repoName } = this.props; + const typeSelector = + this.props.permission._links && this.props.permission._links.update ? ( + + + + ) : ( + {permission.type} + ); + + return ( + + {permission.name} + + + + {typeSelector} + + + + + ); + } + + handleTypeChange = (type: string) => { + this.setState({ + permission: { + ...this.state.permission, + type: type + } + }); + this.modifyPermission(type); + }; + + modifyPermission = (type: string) => { + let permission = this.state.permission; + permission.type = type; + this.props.modifyPermission( + permission, + this.props.namespace, + this.props.repoName + ); + }; + + createSelectOptions(types: string[]) { + return types.map(type => { + return { + label: type, + value: type + }; + }); + } +} + +const mapStateToProps = (state, ownProps) => { + const permission = ownProps.permission; + const loading = isModifyPermissionPending( + state, + ownProps.namespace, + ownProps.repoName, + permission + ); + const deleteLoading = isDeletePermissionPending( + state, + ownProps.namespace, + ownProps.repoName, + permission + ); + + return { loading, deleteLoading }; +}; + +const mapDispatchToProps = dispatch => { + return { + modifyPermission: ( + permission: Permission, + namespace: string, + repoName: string + ) => { + dispatch(modifyPermission(permission, namespace, repoName)); + }, + deletePermission: ( + permission: Permission, + namespace: string, + repoName: string + ) => { + dispatch(deletePermission(permission, namespace, repoName)); + } + }; +}; +export default connect( + mapStateToProps, + mapDispatchToProps +)(translate("repos")(SinglePermission)); diff --git a/scm-ui/src/users/components/UserForm.js b/scm-ui/src/users/components/UserForm.js index 2003d22c89..8e417d7ae4 100644 --- a/scm-ui/src/users/components/UserForm.js +++ b/scm-ui/src/users/components/UserForm.js @@ -1,184 +1,198 @@ -// @flow -import React from "react"; -import { translate } from "react-i18next"; -import type { User } from "@scm-manager/ui-types"; -import { - Checkbox, - InputField, - PasswordConfirmation, - SubmitButton, - validation as validator -} from "@scm-manager/ui-components"; -import * as userValidator from "./userValidation"; - -type Props = { - submitForm: User => void, - user?: User, - loading?: boolean, - t: string => string -}; - -type State = { - user: User, - mailValidationError: boolean, - nameValidationError: boolean, - displayNameValidationError: boolean -}; - -class UserForm extends React.Component { - constructor(props: Props) { - super(props); - - this.state = { - user: { - name: "", - displayName: "", - mail: "", - password: "", - admin: false, - active: true, - _links: {} - }, - mailValidationError: false, - displayNameValidationError: false, - nameValidationError: false - }; - } - - componentDidMount() { - const { user } = this.props; - if (user) { - this.setState({ user: { ...user } }); - } - } - - isFalsy(value) { - if (!value) { - return true; - } - return false; - } - - isValid = () => { - const user = this.state.user; - const passwordValid = this.props.user ? !this.isFalsy(user.password) : true; - return !( - this.state.nameValidationError || - this.state.mailValidationError || - this.state.displayNameValidationError || - this.isFalsy(user.name) || - this.isFalsy(user.displayName) || - this.isFalsy(user.mail) || - passwordValid - ); - }; - - submit = (event: Event) => { - event.preventDefault(); - if (this.isValid()) { - this.props.submitForm(this.state.user); - } - }; - - render() { - const { loading, t } = this.props; - const user = this.state.user; - - let nameField = null; - let passwordChangeField = null; - if (!this.props.user) { - nameField = ( - - ); - - passwordChangeField = ( - - ); - } - return ( -
- {nameField} - - - {passwordChangeField} - - - - - ); - } - - handleUsernameChange = (name: string) => { - this.setState({ - nameValidationError: !validator.isNameValid(name), - user: { ...this.state.user, name } - }); - }; - - handleDisplayNameChange = (displayName: string) => { - this.setState({ - displayNameValidationError: !userValidator.isDisplayNameValid( - displayName - ), - user: { ...this.state.user, displayName } - }); - }; - - handleEmailChange = (mail: string) => { - this.setState({ - mailValidationError: !validator.isMailValid(mail), - user: { ...this.state.user, mail } - }); - }; - - handlePasswordChange = (password: string) => { - this.setState({ - user: { ...this.state.user, password } - }); - }; - - handleAdminChange = (admin: boolean) => { - this.setState({ user: { ...this.state.user, admin } }); - }; - - handleActiveChange = (active: boolean) => { - this.setState({ user: { ...this.state.user, active } }); - }; -} - -export default translate("users")(UserForm); +// @flow +import React from "react"; +import { translate } from "react-i18next"; +import type { User } from "@scm-manager/ui-types"; +import { + Checkbox, + InputField, + PasswordConfirmation, + SubmitButton, + validation as validator +} from "@scm-manager/ui-components"; +import * as userValidator from "./userValidation"; + +type Props = { + submitForm: User => void, + user?: User, + loading?: boolean, + t: string => string +}; + +type State = { + user: User, + mailValidationError: boolean, + nameValidationError: boolean, + displayNameValidationError: boolean +}; + +class UserForm extends React.Component { + constructor(props: Props) { + super(props); + + this.state = { + user: { + name: "", + displayName: "", + mail: "", + password: "", + admin: false, + active: true, + _links: {} + }, + mailValidationError: false, + displayNameValidationError: false, + nameValidationError: false + }; + } + + componentDidMount() { + const { user } = this.props; + if (user) { + this.setState({ user: { ...user } }); + } + } + + isFalsy(value) { + if (!value) { + return true; + } + return false; + } + + isValid = () => { + const user = this.state.user; + const passwordValid = this.props.user ? !this.isFalsy(user.password) : true; + return !( + this.state.nameValidationError || + this.state.mailValidationError || + this.state.displayNameValidationError || + this.isFalsy(user.name) || + this.isFalsy(user.displayName) || + this.isFalsy(user.mail) || + passwordValid + ); + }; + + submit = (event: Event) => { + event.preventDefault(); + if (this.isValid()) { + this.props.submitForm(this.state.user); + } + }; + + render() { + const { loading, t } = this.props; + const user = this.state.user; + + let nameField = null; + let passwordChangeField = null; + if (!this.props.user) { + nameField = ( + + ); + + passwordChangeField = ( + + ); + } + return ( +
+
+
+ {nameField} + +
+
+ +
+
+
+
+ {passwordChangeField} + + +
+
+
+
+ +
+
+
+ ); + } + + handleUsernameChange = (name: string) => { + this.setState({ + nameValidationError: !validator.isNameValid(name), + user: { ...this.state.user, name } + }); + }; + + handleDisplayNameChange = (displayName: string) => { + this.setState({ + displayNameValidationError: !userValidator.isDisplayNameValid( + displayName + ), + user: { ...this.state.user, displayName } + }); + }; + + handleEmailChange = (mail: string) => { + this.setState({ + mailValidationError: !validator.isMailValid(mail), + user: { ...this.state.user, mail } + }); + }; + + handlePasswordChange = (password: string) => { + this.setState({ + user: { ...this.state.user, password } + }); + }; + + handleAdminChange = (admin: boolean) => { + this.setState({ user: { ...this.state.user, admin } }); + }; + + handleActiveChange = (active: boolean) => { + this.setState({ user: { ...this.state.user, active } }); + }; +} + +export default translate("users")(UserForm); diff --git a/scm-ui/src/users/components/table/Details.js b/scm-ui/src/users/components/table/Details.js index c967e4d0b4..1db5d2154c 100644 --- a/scm-ui/src/users/components/table/Details.js +++ b/scm-ui/src/users/components/table/Details.js @@ -1,66 +1,66 @@ -//@flow -import React from "react"; -import type { User } from "@scm-manager/ui-types"; -import { translate } from "react-i18next"; -import { Checkbox, MailLink, DateFromNow } from "@scm-manager/ui-components"; - -type Props = { - user: User, - t: string => string -}; - -class Details extends React.Component { - render() { - const { user, t } = this.props; - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{t("user.name")}{user.name}
{t("user.displayName")}{user.displayName}
{t("user.mail")} - -
{t("user.admin")} - -
{t("user.active")} - -
{t("user.type")}{user.type}
{t("user.creationDate")} - -
{t("user.lastModified")} - -
- ); - } -} - -export default translate("users")(Details); +//@flow +import React from "react"; +import type { User } from "@scm-manager/ui-types"; +import { translate } from "react-i18next"; +import { Checkbox, MailLink, DateFromNow } from "@scm-manager/ui-components"; + +type Props = { + user: User, + t: string => string +}; + +class Details extends React.Component { + render() { + const { user, t } = this.props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{t("user.name")}{user.name}
{t("user.displayName")}{user.displayName}
{t("user.mail")} + +
{t("user.admin")} + +
{t("user.active")} + +
{t("user.type")}{user.type}
{t("user.creationDate")} + +
{t("user.lastModified")} + +
+ ); + } +} + +export default translate("users")(Details); diff --git a/scm-ui/styles/scm.scss b/scm-ui/styles/scm.scss index 9b8f613a21..91be016bab 100644 --- a/scm-ui/styles/scm.scss +++ b/scm-ui/styles/scm.scss @@ -61,6 +61,123 @@ $fa-font-path: "webfonts"; // NEW STYLES +//typography +.subtitle { + color: #666; +} +.has-border-white { + border-color: #fff !important; +} +// buttons +.button{ + padding-left: 1.5em; + padding-right: 1.5em; + height:2.5rem; + + &.is-primary { + background-color: $mint; +} +} + +// multiline Columns +.columns.is-multiline { + + .column.is-half{ + width: calc(50% - .75rem); + + &:nth-child(odd){ + margin-right: 1.5rem; + } + } + @media screen and (max-width:768px) { + .column.is-half{ + width: 100%; + + &:nth-child(odd){ + margin-right: 0; + } + } + } +} + +// 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: #98d8f3; + box-shadow: none; +} +/*.input[disabled], .textarea[disabled] { + + background-color: #ddd; + border-color: #ccc; + box-shadow: none; + color: #aaa; +}*/ + +// 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; +} + // dark hero colors .hero.is-dark { background-color: #002e4b; @@ -77,33 +194,13 @@ $fa-font-path: "webfonts"; color: #fff; } } -// footer colors + + +// footer .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 { @@ -150,13 +247,13 @@ $fa-font-path: "webfonts"; border-right: 1px solid #eee; &.is-active { - color: #33B2E8; + color: $blue; background-color: #fff; &:before{ position: relative; content: " "; - background: #33B2E8; + background: $blue; height: 53px; width: 2px; display: block; @@ -173,69 +270,4 @@ $fa-font-path: "webfonts"; 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; - -} \ No newline at end of file