mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-02-10 00:26:52 +01:00
Accessible Search
Committed-by: Rene Pfeuffer <rene.pfeuffer@cloudogu.com> Co-authored-by: Laura Gorzitze <laura.gorzitze@cloudogu.com>
This commit is contained in:
2
gradle/changelog/accessibility_search.yaml
Normal file
2
gradle/changelog/accessibility_search.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
- type: fixed
|
||||
description: Make search accessible
|
||||
@@ -24,37 +24,43 @@
|
||||
|
||||
import React, { FC } from "react";
|
||||
import {
|
||||
Hit,
|
||||
HitProps,
|
||||
DateFromNow,
|
||||
TextHitField,
|
||||
useDateHitFieldValue,
|
||||
useStringHitFieldValue
|
||||
useStringHitFieldValue,
|
||||
} from "@scm-manager/ui-components";
|
||||
import { Link } from "react-router-dom";
|
||||
import { CardList } from "@scm-manager/ui-layout";
|
||||
import { useKeyboardIteratorTarget } from "@scm-manager/ui-shortcuts";
|
||||
import { HighlightedHitField, ValueHitField } from "@scm-manager/ui-types";
|
||||
|
||||
const GroupHit: FC<HitProps> = ({ hit }) => {
|
||||
const ref = useKeyboardIteratorTarget();
|
||||
const name = useStringHitFieldValue(hit, "name");
|
||||
const lastModified = useDateHitFieldValue(hit, "lastModified");
|
||||
const creationDate = useDateHitFieldValue(hit, "creationDate");
|
||||
const date = lastModified || creationDate;
|
||||
const description = hit.fields["description"];
|
||||
|
||||
return (
|
||||
<Hit>
|
||||
<Hit.Content>
|
||||
<Link to={`/group/${name}`}>
|
||||
<Hit.Title>
|
||||
<CardList.Card key={name}>
|
||||
<CardList.Card.Row>
|
||||
<CardList.Card.Title>
|
||||
<Link ref={ref} to={`/group/${name}`}>
|
||||
<TextHitField hit={hit} field="name" />
|
||||
</Hit.Title>
|
||||
</Link>
|
||||
<p>
|
||||
</Link>
|
||||
</CardList.Card.Title>
|
||||
</CardList.Card.Row>
|
||||
{((description as ValueHitField).value || (description as HighlightedHitField).fragments) && (
|
||||
<CardList.Card.Row className="is-size-7 has-text-secondary">
|
||||
<TextHitField hit={hit} field="description" />
|
||||
</p>
|
||||
</Hit.Content>
|
||||
<Hit.Right>
|
||||
</CardList.Card.Row>
|
||||
)}
|
||||
<CardList.Card.Row className="is-size-7 has-text-secondary">
|
||||
<DateFromNow date={date} />
|
||||
</Hit.Right>
|
||||
</Hit>
|
||||
</CardList.Card.Row>
|
||||
</CardList.Card>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ type Props = {
|
||||
const hitComponents: { [name: string]: FC<HitProps> } = {
|
||||
repository: RepositoryHit,
|
||||
user: UserHit,
|
||||
group: GroupHit
|
||||
group: GroupHit,
|
||||
};
|
||||
|
||||
const findComponent = (type: string) => {
|
||||
@@ -73,13 +73,13 @@ const NoHits: FC = () => {
|
||||
};
|
||||
|
||||
const Hits: FC<Props> = ({ type, hits }) => (
|
||||
<div className="panel-block">
|
||||
<>
|
||||
{hits && hits.length > 0 ? (
|
||||
hits.map((hit, c) => <HitComponent key={`${type}_${c}_${hit.score}`} hit={hit} type={type} />)
|
||||
) : (
|
||||
<NoHits />
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
export default Hits;
|
||||
|
||||
@@ -30,17 +30,29 @@ import {
|
||||
DateFromNow,
|
||||
RepositoryAvatar,
|
||||
TextHitField,
|
||||
Hit,
|
||||
HitProps
|
||||
HitProps,
|
||||
} from "@scm-manager/ui-components";
|
||||
import { CardList } from "@scm-manager/ui-layout";
|
||||
import classNames from "classnames";
|
||||
import styled from "styled-components";
|
||||
import { HighlightedHitField, ValueHitField } from "@scm-manager/ui-types";
|
||||
import { useKeyboardIteratorTarget } from "@scm-manager/ui-shortcuts";
|
||||
|
||||
const StyledLink = styled(Link)`
|
||||
gap: 0.5rem;
|
||||
`;
|
||||
|
||||
const RepositoryHit: FC<HitProps> = ({ hit }) => {
|
||||
const ref = useKeyboardIteratorTarget();
|
||||
|
||||
const namespace = useStringHitFieldValue(hit, "namespace");
|
||||
const name = useStringHitFieldValue(hit, "name");
|
||||
const type = useStringHitFieldValue(hit, "type");
|
||||
const lastModified = useDateHitFieldValue(hit, "lastModified");
|
||||
const creationDate = useDateHitFieldValue(hit, "creationDate");
|
||||
const date = lastModified || creationDate;
|
||||
const description = hit.fields["description"];
|
||||
const title = `${namespace}/${name}`;
|
||||
|
||||
// the embedded repository is only a subset of the repository (RepositoryCoordinates),
|
||||
// so we should use the fields to get more information
|
||||
@@ -50,26 +62,27 @@ const RepositoryHit: FC<HitProps> = ({ hit }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Hit>
|
||||
<Hit.Left>
|
||||
<Link to={`/repo/${namespace}/${name}`}>
|
||||
<RepositoryAvatar repository={repository} size={48} />
|
||||
</Link>
|
||||
</Hit.Left>
|
||||
<Hit.Content>
|
||||
<Link to={`/repo/${namespace}/${name}`}>
|
||||
<Hit.Title>
|
||||
{namespace}/{name}
|
||||
</Hit.Title>
|
||||
</Link>
|
||||
<p>
|
||||
<CardList.Card key={title}>
|
||||
<CardList.Card.Row>
|
||||
<CardList.Card.Title>
|
||||
<StyledLink
|
||||
ref={ref}
|
||||
to={`/repo/${namespace}/${name}`}
|
||||
className={classNames("is-flex", "is-justify-content-flex-start", "is-align-items-center")}
|
||||
>
|
||||
<RepositoryAvatar repository={repository} size={16} /> {title}
|
||||
</StyledLink>
|
||||
</CardList.Card.Title>
|
||||
</CardList.Card.Row>
|
||||
{((description as ValueHitField).value || (description as HighlightedHitField).fragments) && (
|
||||
<CardList.Card.Row className="is-size-7 has-text-secondary">
|
||||
<TextHitField hit={hit} field="description" />
|
||||
</p>
|
||||
</Hit.Content>
|
||||
<Hit.Right>
|
||||
</CardList.Card.Row>
|
||||
)}
|
||||
<CardList.Card.Row className="is-size-7 has-text-secondary">
|
||||
<DateFromNow date={date} />
|
||||
</Hit.Right>
|
||||
</Hit>
|
||||
</CardList.Card.Row>
|
||||
</CardList.Card>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ import { QueryResult } from "@scm-manager/ui-types";
|
||||
import Hits from "./Hits";
|
||||
import { LinkPaginator } from "@scm-manager/ui-components";
|
||||
import { Redirect, useLocation } from "react-router-dom";
|
||||
import { CardListBox } from "@scm-manager/ui-layout";
|
||||
import { KeyboardIterator } from "@scm-manager/ui-shortcuts";
|
||||
|
||||
type Props = {
|
||||
result: QueryResult;
|
||||
@@ -50,9 +52,11 @@ const Results: FC<Props> = ({ result, type, page, query }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="panel">
|
||||
<Hits type={type} hits={hits} />
|
||||
</div>
|
||||
<CardListBox>
|
||||
<KeyboardIterator>
|
||||
<Hits type={type} hits={hits} />
|
||||
</KeyboardIterator>
|
||||
</CardListBox>
|
||||
<LinkPaginator collection={result} page={page} filter={query} />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -29,34 +29,43 @@ import {
|
||||
useDateHitFieldValue,
|
||||
useStringHitFieldValue,
|
||||
TextHitField,
|
||||
Hit,
|
||||
HitProps
|
||||
HitProps,
|
||||
} from "@scm-manager/ui-components";
|
||||
import { CardList } from "@scm-manager/ui-layout";
|
||||
import { useKeyboardIteratorTarget } from "@scm-manager/ui-shortcuts";
|
||||
|
||||
const UserHit: FC<HitProps> = ({ hit }) => {
|
||||
const ref = useKeyboardIteratorTarget();
|
||||
const name = useStringHitFieldValue(hit, "name");
|
||||
const mail = useStringHitFieldValue(hit, "mail");
|
||||
const lastModified = useDateHitFieldValue(hit, "lastModified");
|
||||
const creationDate = useDateHitFieldValue(hit, "creationDate");
|
||||
const date = lastModified || creationDate;
|
||||
|
||||
return (
|
||||
<Hit>
|
||||
<Hit.Content>
|
||||
<Link to={`/user/${name}`}>
|
||||
<Hit.Title>
|
||||
<CardList.Card key={name}>
|
||||
<CardList.Card.Row>
|
||||
<CardList.Card.Title>
|
||||
<Link ref={ref} to={`/user/${name}`}>
|
||||
<TextHitField hit={hit} field="name" />
|
||||
</Hit.Title>
|
||||
</Link>
|
||||
<p>
|
||||
<TextHitField hit={hit} field="displayName" /> <
|
||||
<TextHitField hit={hit} field="mail" />
|
||||
>
|
||||
</p>
|
||||
</Hit.Content>
|
||||
<Hit.Right>
|
||||
</Link>
|
||||
</CardList.Card.Title>
|
||||
</CardList.Card.Row>
|
||||
<CardList.Card.Row className="is-size-7 has-text-secondary">
|
||||
<TextHitField hit={hit} field="displayName" />
|
||||
{mail && (
|
||||
<>
|
||||
{" "}
|
||||
<
|
||||
<TextHitField hit={hit} field="mail" />
|
||||
>
|
||||
</>
|
||||
)}
|
||||
</CardList.Card.Row>
|
||||
<CardList.Card.Row className="is-size-7 has-text-secondary">
|
||||
<DateFromNow date={date} />
|
||||
</Hit.Right>
|
||||
</Hit>
|
||||
</CardList.Card.Row>
|
||||
</CardList.Card>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user