From 4d181a574a2634564720611b970bb06aae56ecff Mon Sep 17 00:00:00 2001 From: Janika Kefel Date: Wed, 19 Dec 2018 13:28:04 +0100 Subject: [PATCH] More UI changes --- scm-ui/public/images/blib.jpg | Bin 20857 -> 48965 bytes scm-ui/src/containers/ProfileInfo.js | 112 ++--- scm-ui/src/groups/components/table/Details.js | 138 +++--- .../src/groups/components/table/GroupRow.js | 50 +-- .../repos/components/RepositoryDetailTable.js | 110 ++--- .../src/repos/components/RepositoryDetails.js | 59 +-- .../repos/components/list/RepositoryEntry.js | 221 +++++---- .../components/list/RepositoryEntryLink.js | 69 +-- .../components/list/RepositoryGroupEntry.js | 9 + scm-ui/src/repos/containers/BranchSelector.js | 177 ++++---- .../components/CreatePermissionForm.js | 256 ++++++----- .../permissions/components/TypeSelector.js | 84 ++-- .../permissions/containers/Permissions.js | 418 +++++++++--------- .../containers/SinglePermission.js | 352 +++++++-------- scm-ui/src/users/components/UserForm.js | 382 ++++++++-------- scm-ui/src/users/components/table/Details.js | 132 +++--- scm-ui/styles/scm.scss | 214 +++++---- 17 files changed, 1425 insertions(+), 1358 deletions(-) diff --git a/scm-ui/public/images/blib.jpg b/scm-ui/public/images/blib.jpg index 5fa47ab2bce8d10728f613ac4ffe51d58ae41c6f..55c2ea62d819dea0b585e00050a10ffdb6114084 100644 GIT binary patch literal 48965 zcmeFZbzD`?_AtB;-Q6uI-7VeSDIpvVorjWE6qIfxR1gpZM7l*#KtK=)>5vcsK?D(y ze)j?M`@Q!*_xHS?=a2V!zXN;rnzh!~U;HgE zKLiP21aURsB>=)C;C&RloNl3<wg7v9JkA z@o{kQNhyelNr{Om2yxEB_uF~muQ3D{8ygo7mjDlsfCLW@j|36nk(_5C{BH_4Z374~ zfLtIK8Nvu45kim&A*VB-F0oEKATpqosF1S&3XBM#W|2@((apv{QPK?;}D!WV8VLQhl?1*mrSTnJu*-q9(25?fb6}Ydc4l zc8u-)BGU`&UXFg)6;&~D@V|AZsJ?4#d5;imAy8VBGnvrQP=(J#xWG?@0!rY;NQ^3Q zJ&6P%!E^n=O+jYcd3boTf&nSiTWE^~4IuzJtMH2

6hTJ0&9#AK1cA5&pddY`;V} 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 SNRuJN4B;i^d{6y{fB)HK?k9`@ literal 20857 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 azA8 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