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:
parent
df8a8671e0
commit
573a500cdd
@ -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>
|
||||
|
||||
@ -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} {
|
||||
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} {
|
||||
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>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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')
|
||||
);
|
||||
@ -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>
|
||||
</>
|
||||
|
||||
@ -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')
|
||||
);
|
||||
|
||||
10
packages/app-explorer/src/types.ts
Normal file
10
packages/app-explorer/src/types.ts
Normal 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
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user