Merged in feature/page_actions (pull request #198)

Feature/page actions
This commit is contained in:
Philipp Czora
2019-02-21 10:31:32 +00:00
8 changed files with 147 additions and 14 deletions

View File

@@ -4,6 +4,8 @@ import Loading from "./../Loading";
import ErrorNotification from "./../ErrorNotification"; import ErrorNotification from "./../ErrorNotification";
import Title from "./Title"; import Title from "./Title";
import Subtitle from "./Subtitle"; import Subtitle from "./Subtitle";
import injectSheet from "react-jss";
import classNames from "classnames";
type Props = { type Props = {
title?: string, title?: string,
@@ -11,17 +13,26 @@ type Props = {
loading?: boolean, loading?: boolean,
error?: Error, error?: Error,
showContentOnError?: boolean, showContentOnError?: boolean,
children: React.Node children: React.Node,
// context props
classes: Object
};
const styles = {
spacing: {
marginTop: "1.25rem",
textAlign: "right"
}
}; };
class Page extends React.Component<Props> { class Page extends React.Component<Props> {
render() { render() {
const { title, error, subtitle } = this.props; const { error } = this.props;
return ( return (
<section className="section"> <section className="section">
<div className="container"> <div className="container">
<Title title={title} /> {this.renderPageHeader()}
<Subtitle subtitle={subtitle} />
<ErrorNotification error={error} /> <ErrorNotification error={error} />
{this.renderContent()} {this.renderContent()}
</div> </div>
@@ -29,16 +40,55 @@ class Page extends React.Component<Props> {
); );
} }
renderPageHeader() {
const { title, subtitle, children, classes } = this.props;
let content = null;
let pageActionsExists = false;
React.Children.forEach(children, child => {
if (child && child.type.name === "PageActions") {
content = child;
pageActionsExists = true;
}
});
let underline = pageActionsExists ? (
<hr className="header-with-actions" />
) : null;
return (
<>
<div className="columns">
<div className="column">
<Title title={title} />
<Subtitle subtitle={subtitle} />
</div>
<div className="column is-two-fifths">
<div className={classNames(classes.spacing, "is-mobile-create-button-spacing")}>{content}</div>
</div>
</div>
{underline}
</>
);
}
renderContent() { renderContent() {
const { loading, children, showContentOnError, error } = this.props; const { loading, children, showContentOnError, error } = this.props;
if (error && !showContentOnError) { if (error && !showContentOnError) {
return null; return null;
} }
if (loading) { if (loading) {
return <Loading />; return <Loading />;
} }
return children;
let content = [];
React.Children.forEach(children, child => {
if (child && child.type.name !== "PageActions") {
content.push(child);
}
});
return content;
} }
} }
export default Page; export default injectSheet(styles)(Page);

View File

@@ -0,0 +1,28 @@
//@flow
import * as React from "react";
import Loading from "./../Loading";
type Props = {
loading?: boolean,
error?: Error,
children: React.Node
};
class PageActions extends React.Component<Props> {
render() {
return <>{this.renderContent()}</>;
}
renderContent() {
const { loading, children, error } = this.props;
if (error) {
return null;
}
if (loading) {
return <Loading />;
}
return children;
}
}
export default PageActions;

View File

@@ -9,7 +9,7 @@ class Subtitle extends React.Component<Props> {
render() { render() {
const { subtitle } = this.props; const { subtitle } = this.props;
if (subtitle) { if (subtitle) {
return <h1 className="subtitle">{subtitle}</h1>; return <h2 className="subtitle">{subtitle}</h2>;
} }
return null; return null;
} }

View File

@@ -3,6 +3,7 @@
export { default as Footer } from "./Footer.js"; export { default as Footer } from "./Footer.js";
export { default as Header } from "./Header.js"; export { default as Header } from "./Header.js";
export { default as Page } from "./Page.js"; export { default as Page } from "./Page.js";
export { default as PageActions } from "./PageActions.js";
export { default as Subtitle } from "./Subtitle.js"; export { default as Subtitle } from "./Subtitle.js";
export { default as Title } from "./Title.js"; export { default as Title } from "./Title.js";

View File

@@ -5,7 +5,12 @@ import { translate } from "react-i18next";
import type { Group } from "@scm-manager/ui-types"; import type { Group } from "@scm-manager/ui-types";
import type { PagedCollection } from "@scm-manager/ui-types"; import type { PagedCollection } from "@scm-manager/ui-types";
import type { History } from "history"; import type { History } from "history";
import { Page, Paginator } from "@scm-manager/ui-components"; import {
Page,
PageActions,
Button,
Paginator
} from "@scm-manager/ui-components";
import { GroupTable } from "./../components/table"; import { GroupTable } from "./../components/table";
import CreateGroupButton from "../components/buttons/CreateGroupButton"; import CreateGroupButton from "../components/buttons/CreateGroupButton";
@@ -73,6 +78,13 @@ class Groups extends React.Component<Props> {
<GroupTable groups={groups} /> <GroupTable groups={groups} />
{this.renderPaginator()} {this.renderPaginator()}
{this.renderCreateButton()} {this.renderCreateButton()}
<PageActions>
<Button
label={t("create-group-button.label")}
link="/groups/add"
color="primary"
/>
</PageActions>
</Page> </Page>
); );
} }

View File

@@ -14,7 +14,13 @@ import {
isFetchReposPending isFetchReposPending
} from "../modules/repos"; } from "../modules/repos";
import { translate } from "react-i18next"; import { translate } from "react-i18next";
import { CreateButton, Page, Paginator } from "@scm-manager/ui-components"; import {
Page,
PageActions,
Button,
CreateButton,
Paginator
} from "@scm-manager/ui-components";
import RepositoryList from "../components/list"; import RepositoryList from "../components/list";
import { withRouter } from "react-router-dom"; import { withRouter } from "react-router-dom";
import type { History } from "history"; import type { History } from "history";
@@ -67,6 +73,13 @@ class Overview extends React.Component<Props> {
error={error} error={error}
> >
{this.renderList()} {this.renderList()}
<PageActions>
<Button
label={t("overview.createButton")}
link="/repos/create"
color="primary"
/>
</PageActions>
</Page> </Page>
); );
} }
@@ -89,10 +102,7 @@ class Overview extends React.Component<Props> {
const { showCreateButton, t } = this.props; const { showCreateButton, t } = this.props;
if (showCreateButton) { if (showCreateButton) {
return ( return (
<CreateButton <CreateButton label={t("overview.createButton")} link="/repos/create" />
label={t("overview.createButton")}
link="/repos/create"
/>
); );
} }
return null; return null;

View File

@@ -14,7 +14,13 @@ import {
getFetchUsersFailure getFetchUsersFailure
} from "../modules/users"; } from "../modules/users";
import { Page, CreateButton, Paginator } from "@scm-manager/ui-components"; import {
Page,
PageActions,
Button,
CreateButton,
Paginator
} from "@scm-manager/ui-components";
import { UserTable } from "./../components/table"; import { UserTable } from "./../components/table";
import type { User, PagedCollection } from "@scm-manager/ui-types"; import type { User, PagedCollection } from "@scm-manager/ui-types";
import { getUsersLink } from "../../modules/indexResource"; import { getUsersLink } from "../../modules/indexResource";
@@ -72,6 +78,13 @@ class Users extends React.Component<Props> {
<UserTable users={users} /> <UserTable users={users} />
{this.renderPaginator()} {this.renderPaginator()}
{this.renderCreateButton()} {this.renderCreateButton()}
<PageActions>
<Button
label={t("users.createButton")}
link="/users/add"
color="primary"
/>
</PageActions>
</Page> </Page>
); );
} }

View File

@@ -40,6 +40,25 @@ $info: $blue;
.main { .main {
min-height: calc(100vh - 260px); min-height: calc(100vh - 260px);
} }
// shown in top section when pageactions set
hr.header-with-actions {
margin-top: -10px;
@media screen and (max-width: 768px) {
display: none;
}
}
.is-mobile-create-button-spacing {
@media screen and (max-width: 768px) {
border: 2px solid #e9f7fd;
padding: 1em 1em;
margin-top: 0 !important;
width: 100%;
text-align: center !important;
}
}
.footer { .footer {
height: 50px; height: 50px;
} }