Refactor details panel to use React Semantic Components (#98)

This commit is contained in:
czifumasa
2022-04-27 17:20:27 +02:00
committed by GitHub
parent 35259e5767
commit d30c038406
4 changed files with 119 additions and 95 deletions

View File

@@ -1,4 +1,4 @@
import {Checkbox, Form} from 'semantic-ui-react'; import {Item, Checkbox, Form, Header} from 'semantic-ui-react';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import {ParsedQuery} from 'query-string'; import {ParsedQuery} from 'query-string';
@@ -44,12 +44,13 @@ export function ConfigPanel(props: {
onChange: (config: Config) => void; onChange: (config: Config) => void;
}) { }) {
return ( return (
<> <Form className="details">
<Form className="ui segments details"> <Item.Group>
<div className="ui segment"> <Item>
<div className="ui sub header"> <Item.Content>
<Header sub>
<FormattedMessage id="config.colors" defaultMessage="Colors" /> <FormattedMessage id="config.colors" defaultMessage="Colors" />
</div> </Header>
<Form.Field className="no-margin"> <Form.Field className="no-margin">
<Checkbox <Checkbox
radio radio
@@ -97,11 +98,14 @@ export function ConfigPanel(props: {
name="checkboxRadioGroup" name="checkboxRadioGroup"
value="gender" value="gender"
checked={props.config.color === ChartColors.COLOR_BY_SEX} checked={props.config.color === ChartColors.COLOR_BY_SEX}
onClick={() => props.onChange({color: ChartColors.COLOR_BY_SEX})} onClick={() =>
props.onChange({color: ChartColors.COLOR_BY_SEX})
}
/> />
</Form.Field> </Form.Field>
</div> </Item.Content>
</Item>
</Item.Group>
</Form> </Form>
</>
); );
} }

View File

@@ -4,6 +4,7 @@ import {Events} from './events';
import {GedcomEntry} from 'parse-gedcom'; import {GedcomEntry} from 'parse-gedcom';
import {MultilineText} from './multiline-text'; import {MultilineText} from './multiline-text';
import {TranslatedTag} from './translated-tag'; import {TranslatedTag} from './translated-tag';
import {Header, Item} from 'semantic-ui-react';
const EXCLUDED_TAGS = [ const EXCLUDED_TAGS = [
'BIRT', 'BIRT',
@@ -36,9 +37,9 @@ function dataDetails(entry: GedcomEntry) {
} }
return ( return (
<> <>
<div className="ui sub header"> <Header sub>
<TranslatedTag tag={entry.tag} /> <TranslatedTag tag={entry.tag} />
</div> </Header>
<span> <span>
<MultilineText lines={lines} /> <MultilineText lines={lines} />
</span> </span>
@@ -58,7 +59,7 @@ function noteDetails(entry: GedcomEntry) {
function nameDetails(entry: GedcomEntry) { function nameDetails(entry: GedcomEntry) {
return ( return (
<h2 className="ui header"> <Header size="large">
{entry.data {entry.data
.split('/') .split('/')
.filter((name) => !!name) .filter((name) => !!name)
@@ -68,7 +69,7 @@ function nameDetails(entry: GedcomEntry) {
<br /> <br />
</div> </div>
))} ))}
</h2> </Header>
); );
} }
@@ -84,9 +85,9 @@ function getDetails(
) )
.filter((element) => element !== null) .filter((element) => element !== null)
.map((element, index) => ( .map((element, index) => (
<div className="ui segment" key={index}> <Item key={index}>
{element} <Item.Content>{element}</Item.Content>
</div> </Item>
)); ));
} }
@@ -106,9 +107,9 @@ function getOtherDetails(entries: GedcomEntry[]) {
.map((entry) => dataDetails(entry)) .map((entry) => dataDetails(entry))
.filter((element) => element !== null) .filter((element) => element !== null)
.map((element, index) => ( .map((element, index) => (
<div className="ui segment" key={index}> <Item key={index}>
{element} <Item.Content>{element}</Item.Content>
</div> </Item>
)); ));
} }
@@ -124,11 +125,13 @@ export function Details(props: Props) {
.filter(hasData); .filter(hasData);
return ( return (
<div className="ui segments details"> <div className="details">
<Item.Group divided>
{getDetails(entries, ['NAME'], nameDetails)} {getDetails(entries, ['NAME'], nameDetails)}
<Events gedcom={props.gedcom} entries={entries} indi={props.indi} /> <Events gedcom={props.gedcom} entries={entries} indi={props.indi} />
{getOtherDetails(entriesWithData)} {getOtherDetails(entriesWithData)}
{getDetails(entriesWithData, ['NOTE'], noteDetails)} {getDetails(entriesWithData, ['NOTE'], noteDetails)}
</Item.Group>
</div> </div>
); );
} }

View File

@@ -10,6 +10,7 @@ import {Link, useLocation} from 'react-router-dom';
import {MultilineText} from './multiline-text'; import {MultilineText} from './multiline-text';
import {pointerToId} from '../util/gedcom_util'; import {pointerToId} from '../util/gedcom_util';
import {TranslatedTag} from './translated-tag'; import {TranslatedTag} from './translated-tag';
import {Header, Item} from 'semantic-ui-react';
function PersonLink(props: {person: GedcomEntry}) { function PersonLink(props: {person: GedcomEntry}) {
const location = useLocation(); const location = useLocation();
@@ -23,11 +24,11 @@ function PersonLink(props: {person: GedcomEntry}) {
search['indi'] = pointerToId(props.person.pointer); search['indi'] = pointerToId(props.person.pointer);
return ( return (
<div className="meta"> <Item.Meta>
<Link to={{pathname: '/view', search: queryString.stringify(search)}}> <Link to={{pathname: '/view', search: queryString.stringify(search)}}>
{name} {name}
</Link> </Link>
</div> </Item.Meta>
); );
} }
@@ -62,14 +63,14 @@ const FAMILY_EVENT_TAGS = ['MARR', 'DIV'];
function EventHeader(props: {event: EventData}) { function EventHeader(props: {event: EventData}) {
const intl = useIntl(); const intl = useIntl();
return ( return (
<div> <div className="event-header">
<span style={{textTransform: 'uppercase'}} className="ui small header"> <Header as="span" size="small">
<TranslatedTag tag={props.event.type} /> <TranslatedTag tag={props.event.type} />
</span> </Header>
{props.event.date ? ( {props.event.date ? (
<span className="ui sub header right floated"> <Header as="span" textAlign="right" sub>
{formatDateOrRange(props.event.date, intl)} {formatDateOrRange(props.event.date, intl)}
</span> </Header>
) : null} ) : null}
</div> </div>
); );
@@ -176,18 +177,18 @@ function toFamilyEvents(
function Event(props: {event: EventData}) { function Event(props: {event: EventData}) {
return ( return (
<div className="ui attached item"> <Item>
<div className="content"> <Item.Content>
<EventHeader event={props.event} /> <EventHeader event={props.event} />
{!!props.event.age && <div className="meta">{props.event.age}</div>} {!!props.event.age && <Item.Meta>{props.event.age}</Item.Meta>}
{!!props.event.personLink && ( {!!props.event.personLink && (
<PersonLink person={props.event.personLink} /> <PersonLink person={props.event.personLink} />
)} )}
{!!props.event.place && ( {!!props.event.place && (
<div className="description">{props.event.place}</div> <Item.Description>{props.event.place}</Item.Description>
)} )}
{!!props.event.notes.length && ( {!!props.event.notes.length && (
<div className="description"> <Item.Description>
{props.event.notes.map((note, index) => ( {props.event.notes.map((note, index) => (
<div key={index}> <div key={index}>
<MultilineText <MultilineText
@@ -197,10 +198,10 @@ function Event(props: {event: EventData}) {
/> />
</div> </div>
))} ))}
</div> </Item.Description>
)} )}
</div> </Item.Content>
</div> </Item>
); );
} }
@@ -216,11 +217,11 @@ export function Events(props: Props) {
); );
if (events.length) { if (events.length) {
return ( return (
<div className="ui segment divided items"> <>
{events.map((event, index) => ( {events.map((event, index) => (
<Event event={event} key={index} /> <Event event={event} key={index} />
))} ))}
</div> </>
); );
} }
return null; return null;

View File

@@ -143,9 +143,25 @@ div.zoom {
margin-top: 0px; margin-top: 0px;
} }
.ui.segments.details { .details {
margin: 0px !important; padding: 15px 0px;
border: 0px !important; border-bottom: 1px solid rgba(34,36,38,.15);
}
.details .ui.items .item .content {
padding: 0 15px;
}
.details .event-header {
justify-content: space-between;
display: flex;
word-break: break-word;
}
.details .event-header .header {
text-transform: uppercase;
margin: 0;
min-width: 40%;
} }
.ui.form .field.no-margin { .ui.form .field.no-margin {