Improve ux on overview

This commit is contained in:
Eduard Heimbuch
2020-11-19 10:57:33 +01:00
committed by René Pfeuffer
parent 0aa82887d2
commit 237c48356a
7 changed files with 77 additions and 49 deletions

View File

@@ -21,13 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
import React from "react"; import React, { FC } from "react";
import { withRouter, RouteComponentProps } from "react-router-dom"; import { useHistory, useLocation } from "react-router-dom";
import classNames from "classnames"; import classNames from "classnames";
import { Button, DropDown, urls } from "./index"; import { Button, DropDown, urls } from "./index";
import { FilterInput } from "./forms"; import { FilterInput } from "./forms";
type Props = RouteComponentProps & { type Props = {
showCreateButton: boolean; showCreateButton: boolean;
currentGroup: string; currentGroup: string;
groups: string[]; groups: string[];
@@ -35,41 +35,36 @@ type Props = RouteComponentProps & {
groupSelected: (namespace: string) => void; groupSelected: (namespace: string) => void;
label?: string; label?: string;
testId?: string; testId?: string;
searchPlaceholder?: string;
filterPlaceholder?: string;
}; };
class OverviewPageActions extends React.Component<Props> { const OverviewPageActions: FC<Props> = ({
render() { groups,
const { history, currentGroup, groups, location, link, testId, groupSelected } = this.props; currentGroup,
const groupSelector = groups && ( showCreateButton,
<div className={"column is-flex"}> link,
<DropDown groupSelected,
className={"is-fullwidth"} label,
options={groups} testId,
preselectedOption={currentGroup} searchPlaceholder,
optionSelected={groupSelected} filterPlaceholder
/> }) => {
</div> const history = useHistory();
); const location = useLocation();
const groupSelector = groups && (
<div className={"column is-flex"}>
<DropDown
className={"is-fullwidth"}
options={groups}
preselectedOption={currentGroup}
optionSelected={groupSelected}
placeholder={filterPlaceholder}
/>
</div>
);
return ( const renderCreateButton = () => {
<div className={"columns is-tablet"}>
{groupSelector}
<div className={"column"}>
<FilterInput
value={urls.getQueryStringFromLocation(location)}
filter={filter => {
history.push(`/${link}/?q=${filter}`);
}}
testId={testId + "-filter"}
/>
</div>
{this.renderCreateButton()}
</div>
);
}
renderCreateButton() {
const { showCreateButton, link, label } = this.props;
if (showCreateButton) { if (showCreateButton) {
return ( return (
<div className={classNames("input-button", "control", "column")}> <div className={classNames("input-button", "control", "column")}>
@@ -78,7 +73,24 @@ class OverviewPageActions extends React.Component<Props> {
); );
} }
return null; return null;
} };
}
export default withRouter(OverviewPageActions); return (
<div className={"columns is-tablet"}>
{groupSelector}
<div className={"column"}>
<FilterInput
placeholder={searchPlaceholder}
value={urls.getQueryStringFromLocation(location)}
filter={filter => {
history.push(`/${link}/?q=${filter}`);
}}
testId={testId + "-filter"}
/>
</div>
{renderCreateButton()}
</div>
);
};
export default OverviewPageActions;

View File

@@ -32,6 +32,7 @@ type Props = {
preselectedOption?: string; preselectedOption?: string;
className?: string; className?: string;
disabled?: boolean; disabled?: boolean;
placeholder?: string;
}; };
const FullWidthSelect = styled.select` const FullWidthSelect = styled.select`
@@ -40,7 +41,7 @@ const FullWidthSelect = styled.select`
class DropDown extends React.Component<Props> { class DropDown extends React.Component<Props> {
render() { render() {
const { options, optionValues, preselectedOption, className, disabled } = this.props; const { options, optionValues, preselectedOption, className, disabled, placeholder } = this.props;
if (preselectedOption && options.filter(o => o === preselectedOption).length === 0) { if (preselectedOption && options.filter(o => o === preselectedOption).length === 0) {
options.push(preselectedOption); options.push(preselectedOption);
@@ -48,7 +49,12 @@ class DropDown extends React.Component<Props> {
return ( return (
<div className={classNames(className, "select", disabled ? "disabled" : "")}> <div className={classNames(className, "select", disabled ? "disabled" : "")}>
<FullWidthSelect value={preselectedOption ? preselectedOption : ""} onChange={this.change} disabled={disabled}> <FullWidthSelect
value={preselectedOption ? preselectedOption : ""}
onChange={this.change}
disabled={disabled}
placeholder={placeholder}
>
{options.map((option, index) => { {options.map((option, index) => {
const value = optionValues && optionValues[index] ? optionValues[index] : option; const value = optionValues && optionValues[index] ? optionValues[index] : option;
return ( return (

View File

@@ -65,7 +65,7 @@ const FilterInput: FC<Props> = ({ filter, value, testId, placeholder }) => {
<FixedHeightInput <FixedHeightInput
className="input" className="input"
type="search" type="search"
placeholder={placeholder || t("filterEntries")} placeholder={placeholder || t("overviewAction.filterEntries")}
value={stateValue} value={stateValue}
onChange={event => setStateValue(event.target.value)} onChange={event => setStateValue(event.target.value)}
/> />

View File

@@ -42,7 +42,9 @@
"title": "Repositories", "title": "Repositories",
"subtitle": "Übersicht aller verfügbaren Repositories", "subtitle": "Übersicht aller verfügbaren Repositories",
"noRepositories": "Keine Repositories gefunden.", "noRepositories": "Keine Repositories gefunden.",
"createButton": "Repository erstellen" "createButton": "Repository erstellen",
"searchRepository": "Repository suchen",
"filterNamespace": "Namespace filtern"
}, },
"create": { "create": {
"title": "Repository erstellen", "title": "Repository erstellen",

View File

@@ -42,7 +42,9 @@
"title": "Repositories", "title": "Repositories",
"subtitle": "Overview of available repositories", "subtitle": "Overview of available repositories",
"noRepositories": "No repositories found.", "noRepositories": "No repositories found.",
"createButton": "Create Repository" "createButton": "Create Repository",
"searchRepository": "Search repository",
"filterNamespace": "Filter by namespace"
}, },
"create": { "create": {
"title": "Create Repository", "title": "Create Repository",

View File

@@ -22,22 +22,26 @@
* SOFTWARE. * SOFTWARE.
*/ */
import React from "react"; import React from "react";
import { Link } from "react-router-dom"; import {Link} from "react-router-dom";
import { CardColumnGroup, RepositoryEntry } from "@scm-manager/ui-components"; import {CardColumnGroup, Icon, RepositoryEntry} from "@scm-manager/ui-components";
import { RepositoryGroup } from "@scm-manager/ui-types"; import {RepositoryGroup} from "@scm-manager/ui-types";
import { Icon } from "@scm-manager/ui-components"; import {WithTranslation, withTranslation} from "react-i18next";
import { WithTranslation, withTranslation } from "react-i18next"; import styled from "styled-components";
type Props = WithTranslation & { type Props = WithTranslation & {
group: RepositoryGroup; group: RepositoryGroup;
}; };
const SizedIcon = styled(Icon)`
font-size: 1.33rem;
`;
class RepositoryGroupEntry extends React.Component<Props> { class RepositoryGroupEntry extends React.Component<Props> {
render() { render() {
const { group, t } = this.props; const { group, t } = this.props;
const settingsLink = group.namespace?._links?.permissions && ( const settingsLink = group.namespace?._links?.permissions && (
<Link to={`/namespace/${group.name}/settings`}> <Link to={`/namespace/${group.name}/settings`}>
<Icon color={"is-link"} name={"cog"} title={t("repositoryOverview.settings.tooltip")} /> <SizedIcon color={"is-link"} name={"cog"} title={t("repositoryOverview.settings.tooltip")} />
</Link> </Link>
); );
const namespaceHeader = ( const namespaceHeader = (

View File

@@ -126,6 +126,8 @@ class Overview extends React.Component<Props> {
link="repos" link="repos"
label={t("overview.createButton")} label={t("overview.createButton")}
testId="repository-overview" testId="repository-overview"
searchPlaceholder={t("overview.searchRepository")}
filterPlaceholder={t("overview.filterNamespace")}
/> />
</PageActions> </PageActions>
</Page> </Page>