Merge pull request #1435 from scm-manager/feature/improve_ux_on_overview

Improve ux on overview
This commit is contained in:
René Pfeuffer
2020-11-24 13:57:25 +01:00
committed by GitHub
11 changed files with 94 additions and 48 deletions

View File

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

@@ -25,6 +25,9 @@
"setPermissionsNavLink": "Berechtigungen"
}
},
"overview": {
"searchGroup": "Gruppe suchen"
},
"add-group": {
"title": "Gruppe erstellen",
"subtitle": "Erstellen einer neuen Gruppe"

View File

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

View File

@@ -30,6 +30,9 @@
"noUsers": "Keine Benutzer gefunden.",
"createButton": "Benutzer erstellen"
},
"overview": {
"searchUser": "Benutzer suchen"
},
"singleUser": {
"errorTitle": "Fehler",
"errorSubtitle": "Unbekannter Benutzer Fehler",

View File

@@ -25,6 +25,9 @@
"setPermissionsNavLink": "Permissions"
}
},
"overview": {
"searchGroup": "Search group"
},
"add-group": {
"title": "Create Group",
"subtitle": "Create a new group"

View File

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

View File

@@ -44,6 +44,9 @@
"setApiKeyNavLink": "API Keys"
}
},
"overview": {
"searchUser": "Search user"
},
"createUser": {
"title": "Create User",
"subtitle": "Create a new user"

View File

@@ -92,7 +92,12 @@ class Groups extends React.Component<Props> {
{this.renderGroupTable()}
{this.renderCreateButton()}
<PageActions>
<OverviewPageActions showCreateButton={canAddGroups} link="groups" label={t("create-group-button.label")} />
<OverviewPageActions
showCreateButton={canAddGroups}
link="groups"
label={t("create-group-button.label")}
searchPlaceholder={t("overview.searchGroup")}
/>
</PageActions>
</Page>
);

View File

@@ -23,21 +23,25 @@
*/
import React from "react";
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 { Icon } from "@scm-manager/ui-components";
import { WithTranslation, withTranslation } from "react-i18next";
import styled from "styled-components";
type Props = WithTranslation & {
group: RepositoryGroup;
};
const SizedIcon = styled(Icon)`
font-size: 1.33rem;
`;
class RepositoryGroupEntry extends React.Component<Props> {
render() {
const { group, t } = this.props;
const settingsLink = group.namespace?._links?.permissions && (
<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>
);
const namespaceHeader = (

View File

@@ -101,8 +101,12 @@ class Overview extends React.Component<Props> {
}
};
getNamespaceFilterPlaceholder = () => {
return this.props.t("overview.allNamespaces");
};
namespaceSelected = (newNamespace: string) => {
if (newNamespace === "") {
if (newNamespace === this.getNamespaceFilterPlaceholder()) {
this.props.history.push("/repos/");
} else {
this.props.history.push(`/repos/${newNamespace}/`);
@@ -111,8 +115,10 @@ class Overview extends React.Component<Props> {
render() {
const { error, loading, showCreateButton, namespace, namespaces, t } = this.props;
const namespacesToRender = namespaces ? ["", ...namespaces._embedded.namespaces.map(n => n.namespace).sort()] : [];
const namespaceFilterPlaceholder = this.getNamespaceFilterPlaceholder();
const namespacesToRender = namespaces
? [namespaceFilterPlaceholder, ...namespaces._embedded.namespaces.map(n => n.namespace).sort()]
: [];
return (
<Page title={t("overview.title")} subtitle={t("overview.subtitle")} loading={loading} error={error}>
@@ -126,6 +132,7 @@ class Overview extends React.Component<Props> {
link="repos"
label={t("overview.createButton")}
testId="repository-overview"
searchPlaceholder={t("overview.searchRepository")}
/>
</PageActions>
</Page>

View File

@@ -93,7 +93,12 @@ class Users extends React.Component<Props> {
{this.renderUserTable()}
{this.renderCreateButton()}
<PageActions>
<OverviewPageActions showCreateButton={canAddUsers} link="users" label={t("users.createButton")} />
<OverviewPageActions
showCreateButton={canAddUsers}
link="users"
label={t("users.createButton")}
searchPlaceholder={t("overview.searchUser")}
/>
</PageActions>
</Page>
);