Fix event display indexing & availability (#1144)

* Fix event display indexing & availability

* Key events by when-added key

* BlockInfo passes KeyedEvent
This commit is contained in:
Jaco Greeff 2019-05-13 16:45:56 +02:00 committed by GitHub
parent df8a8671e0
commit 573a500cdd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 109 additions and 130 deletions

View File

@ -22,13 +22,17 @@ class Events extends React.PureComponent<Props> {
return null;
}
const events = value.map((record, index) => ({
key: `${index}`, record
}));
return (
<section>
<h1>{t('events')}</h1>
<div className='explorer--BlockByHash-flexable ui--flex-medium'>
<EventsDisplay
eventClassName='explorer--BlockByHash-block'
value={value}
events={events}
/>
</div>
</section>

View File

@ -3,49 +3,34 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { I18nProps } from '@polkadot/ui-app/types';
import { KeyedEvent } from './types';
import React from 'react';
import { EventRecord } from '@polkadot/types';
import { Event as EventDisplay } from '@polkadot/ui-app';
import { formatNumber } from '@polkadot/util';
import translate from './translate';
type Props = I18nProps & {
value?: Array<EventRecord>,
emptyLabel?: React.ReactNode,
events: Array<KeyedEvent>,
eventClassName?: string,
withoutIndex?: boolean
};
class Events extends React.PureComponent<Props> {
render () {
const { emptyLabel, eventClassName, value, t } = this.props;
const { emptyLabel, events, t } = this.props;
if (!value || value.length === 0) {
if (!events || events.length === 0) {
return emptyLabel || t('no events available');
}
return value
.filter(({ event }) => event) // event.section !== 'system')
.map((event, index) => {
const rendered = this.renderEvent(event, index);
return eventClassName
? (
<div
className={eventClassName}
key={index}
>
{rendered}
</div>
)
: rendered;
});
return events.map(this.renderEvent);
}
private renderEvent = ({ event, phase }: EventRecord, index: number) => {
const { withoutIndex } = this.props;
private renderEvent = ({ key, record: { event, phase } }: KeyedEvent) => {
const { eventClassName, withoutIndex } = this.props;
const extIndex = !withoutIndex && phase.type === 'ApplyExtrinsic'
? phase.asApplyExtrinsic
: -1;
@ -55,34 +40,35 @@ class Events extends React.PureComponent<Props> {
}
return (
<article
className='explorer--Container'
key={index}
<div
className={eventClassName}
key={key}
>
<div className='header'>
<h3>
{event.section}.{event.method}&nbsp;{
extIndex !== -1
? `(#${formatNumber(extIndex)})`
: ''
}
</h3>
</div>
<details>
<summary>
{
event.meta && event.meta.documentation
? event.meta.documentation.join(' ')
: 'Details'
}
</summary>
<EventDisplay
className='details'
value={event}
/>
</details>
</article>
<article className='explorer--Container'>
<div className='header'>
<h3>
{event.section}.{event.method}&nbsp;{
extIndex !== -1
? `(#${formatNumber(extIndex)})`
: ''
}
</h3>
</div>
<details>
<summary>
{
event.meta && event.meta.documentation
? event.meta.documentation.join(' ')
: 'Details'
}
</summary>
<EventDisplay
className='details'
value={event}
/>
</details>
</article>
</div>
);
}
}

View File

@ -1,70 +0,0 @@
// Copyright 2017-2019 @polkadot/app-explorer authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { I18nProps } from '@polkadot/ui-app/types';
import React from 'react';
import { EventRecord } from '@polkadot/types';
import { withCalls, withMulti } from '@polkadot/ui-api';
import { stringToU8a } from '@polkadot/util';
import { xxhashAsHex } from '@polkadot/util-crypto';
import { MAX_ITEMS } from './BlockHeaders';
import Events from './Events';
import translate from './translate';
type Props = I18nProps & {
system_events?: Array<EventRecord>
};
type State = {
prevEventHash: string;
recentEvents: Array<EventRecord>;
};
class EventsRecent extends React.PureComponent<Props, State> {
state: State = {
prevEventHash: '',
recentEvents: []
};
static getDerivedStateFromProps ({ system_events = [] }: Props, prevState: State): State | null {
const prevEventHash = xxhashAsHex(stringToU8a(JSON.stringify(system_events)));
if (prevEventHash === prevState.prevEventHash) {
return null;
}
const recentEvents = system_events
.filter(({ event }) => event.section !== 'system')
.concat(prevState.recentEvents)
.filter((_, index) => index < MAX_ITEMS);
return {
prevEventHash,
recentEvents
};
}
render () {
const { t } = this.props;
const { recentEvents } = this.state;
return (
<div>
<Events
emptyLabel={t('no recent non-system events available')}
value={recentEvents}
withoutIndex
/>
</div>
);
}
}
export default withMulti(
EventsRecent,
translate,
withCalls<Props>('query.system.events')
);

View File

@ -3,20 +3,23 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { I18nProps } from '@polkadot/ui-app/types';
import { KeyedEvent } from './types';
import React from 'react';
import BlockHeaders from './BlockHeaders';
import EventsRecent from './EventsRecent';
import Events from './Events';
import Query from './Query';
import Summary from './Summary';
import translate from './translate';
type Props = I18nProps & {};
type Props = I18nProps & {
events: Array<KeyedEvent>
};
class Main extends React.PureComponent<Props> {
render () {
const { t } = this.props;
const { events, t } = this.props;
return (
<>
@ -29,7 +32,7 @@ class Main extends React.PureComponent<Props> {
</div>
<div className='column'>
<h1>{t('recent events')}</h1>
<EventsRecent />
<Events events={events} />
</div>
</div>
</>

View File

@ -3,23 +3,33 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { AppProps, BareProps, I18nProps } from '@polkadot/ui-app/types';
import { KeyedEvent } from './types';
import './index.css';
import React from 'react';
import { Route, Switch } from 'react-router';
import { EventRecord } from '@polkadot/types';
import { withCalls, withMulti } from '@polkadot/ui-api';
import Tabs, { TabItem } from '@polkadot/ui-app/Tabs';
import uiSettings from '@polkadot/ui-settings';
import translate from './translate';
import { stringToU8a } from '@polkadot/util';
import { xxhashAsHex } from '@polkadot/util-crypto';
import { MAX_ITEMS } from './BlockHeaders';
import BlockInfo from './BlockInfo';
import Main from './Main';
import NodeInfo from './NodeInfo';
import translate from './translate';
type Props = AppProps & BareProps & I18nProps;
type Props = AppProps & BareProps & I18nProps & {
system_events?: Array<EventRecord>
};
type State = {
items: Array<TabItem>
items: Array<TabItem>,
prevEventHash: string;
recentEvents: Array<KeyedEvent>;
};
class ExplorerApp extends React.Component<Props, State> {
@ -43,7 +53,31 @@ class ExplorerApp extends React.Component<Props, State> {
name: 'node',
text: t('Node info')
}
]
],
prevEventHash: '',
recentEvents: []
};
}
// assign the events on the index - this way we keep a record of these, even when swapping
// tabs withing this app, all the events as received will be shown
static getDerivedStateFromProps ({ system_events = [] }: Props, prevState: State): State | null {
const prevEventHash = xxhashAsHex(stringToU8a(JSON.stringify(system_events)));
if (prevEventHash === prevState.prevEventHash) {
return null;
}
const recentEvents = system_events
.filter(({ event }) => event.section !== 'system')
.map((record, index) => ({ key: `${Date.now()}-${index}`, record }))
.concat(prevState.recentEvents)
.filter((_, index) => index < MAX_ITEMS);
return {
items: prevState.items,
prevEventHash,
recentEvents
};
}
@ -67,11 +101,23 @@ class ExplorerApp extends React.Component<Props, State> {
<Route path={`${basePath}/query/:value`} component={BlockInfo} />
<Route path={`${basePath}/query`} component={BlockInfo} />
<Route path={`${basePath}/node`} component={NodeInfo} />
<Route component={Main} />
<Route component={this.renderMain} />
</Switch>
</main>
);
}
private renderMain = () => {
const { recentEvents } = this.state;
return (
<Main events={recentEvents} />
);
}
}
export default translate(ExplorerApp);
export default withMulti(
ExplorerApp,
translate,
withCalls<Props>('query.system.events')
);

View File

@ -0,0 +1,10 @@
// Copyright 2017-2019 @polkadot/app-explorer authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { EventRecord } from '@polkadot/types';
export type KeyedEvent = {
key: string,
record: EventRecord
};