Skip to content

Commit

Permalink
Merge pull request #2001 from botpress/f_debugger_ui
Browse files Browse the repository at this point in the history
feat(emulator):  Debugger summary UI
  • Loading branch information
slvnperron committed Jun 26, 2019
2 parents c84a9c5 + aaca68a commit d9faafe
Show file tree
Hide file tree
Showing 14 changed files with 221 additions and 133 deletions.
4 changes: 2 additions & 2 deletions modules/code-editor/src/views/full/style.scss
Expand Up @@ -25,15 +25,15 @@

.tabsContainer {
display: 'flex';
height: 30px;
height: 35px;
padding-left: 0px;
}

.tab {
background: #fff;
width: fit-content;
color: #333;
height: 30px;
height: 35px;
display: flex;
padding: 10px 10px 0px 10px;

Expand Down
19 changes: 11 additions & 8 deletions modules/extensions/src/views/lite/components/debugger/index.tsx
@@ -1,5 +1,6 @@
import { Tab, Tabs } from '@blueprintjs/core'
import '@blueprintjs/core/lib/css/blueprint.css'
import * as sdk from 'botpress/sdk'
import _ from 'lodash'
import ms from 'ms'
import nanoid from 'nanoid'
Expand All @@ -9,13 +10,13 @@ import { MdBugReport } from 'react-icons/md'
import Settings from './settings'
import style from './style.scss'
import { loadSettings } from './utils'
import { Decision } from './views/Decision'
import Dialog from './views/Dialog'
import { Entities } from './views/Entities'
import { Flow } from './views/Flow'
import { Inspector } from './views/Inspector'
import { Intents } from './views/Intents'
import NLU from './views/NLU'
import { Slots } from './views/Slots'
import { Suggestions } from './views/Suggestions'
import EventNotFound from './EventNotFound'
import FetchingEvent from './FetchingEvent'
import Header from './Header'
Expand Down Expand Up @@ -75,7 +76,12 @@ export class Debugger extends React.Component<Props, State> {
}

if (settings.updateToLastMessage) {
this.props.store.bp.events.on('guest.webchat.message', async m => await this.updateLastMessage(m.incomingEventId))
this.props.store.bp.events.on('guest.webchat.message', async (m: Partial<sdk.IO.IncomingEvent>) => {
if (m.payload.type !== 'session_reset') {
// @ts-ignore
await this.updateLastMessage(m.incomingEventId)
}
})
}
}

Expand Down Expand Up @@ -175,11 +181,8 @@ export class Debugger extends React.Component<Props, State> {
renderSummary() {
return (
<div>
<Decision decision={this.state.event.decision} />
<Intents nlu={this.state.event.nlu} />
<Entities nlu={this.state.event.nlu} />
<Suggestions suggestions={this.state.event.suggestions} />
<Slots nlu={this.state.event.nlu} />
<Dialog suggestions={this.state.event.suggestions} decision={this.state.event.decision} />
<NLU nluData={this.state.event.nlu} />
</div>
)
}
Expand Down
27 changes: 26 additions & 1 deletion modules/extensions/src/views/lite/components/debugger/style.scss
Expand Up @@ -6,7 +6,32 @@
}

.block {
margin-bottom: 10px;
margin-bottom: 15px;
padding: 15px;
background: #f5f5f5;
color: #353535;
.subSection {
margin: 10px 5px;
h5 {
margin-bottom: 5px;
}
strong {
color: #0e5a8a; //blueprint primary
text-transform: capitalize;
}
ul {
padding-left: 15px;
li {
line-height: 1.5em;
}
}
}
.summaryTable {
width: 100%;
th {
color: #5c7080; //blueprint gray-1
}
}
}

.hovering {
Expand Down
Expand Up @@ -10,6 +10,8 @@ interface CssExports {
'inspectorContainer': string;
'notFound': string;
'splash': string;
'subSection': string;
'summaryTable': string;
}
declare var cssExports: CssExports;
export = cssExports;

This file was deleted.

@@ -0,0 +1,52 @@
import { Colors, H4, H5, Icon, Position, Tooltip } from '@blueprintjs/core'
import * as sdk from 'botpress/sdk'
import React, { SFC } from 'react'

import style from '../style.scss'
import { formatConfidence } from '../utils'

interface Props {
suggestions: sdk.IO.Suggestion[]
decision: sdk.IO.Suggestion
}

const Decision: SFC<{ decision: sdk.IO.Suggestion }> = props => (
<div className={style.subSection}>
<H5 color={Colors.DARK_GRAY5}>Decision</H5>
<div>
<strong>{props.decision.sourceDetails}</strong>&nbsp;
<Tooltip content={props.decision.decision.reason} position={Position.RIGHT}>
<Icon color={Colors.GRAY3} icon="info-sign" />
</Tooltip>
</div>
</div>
)

const Suggestions: SFC<{ suggestions: sdk.IO.Suggestion[] }> = props => (
<div className={style.subSection}>
<H5 color={Colors.DARK_GRAY5}>Suggestions</H5>
<ul>
{props.suggestions.map(sugg => (
<li key={sugg.source}>
{sugg.sourceDetails}: {formatConfidence(sugg.confidence)}%
</li>
))}
</ul>
</div>
)

const Dialog: SFC<Props> = props => {
if (!props.decision) {
return null
}

return (
<div className={style.block}>
<H4>Dialog manager</H4>
<Decision decision={props.decision} />
{props.suggestions && props.suggestions.length > 0 && <Suggestions suggestions={props.suggestions} />}
</div>
)
}

export default Dialog
@@ -1,29 +1,33 @@
import { H5, Pre } from '@blueprintjs/core'
import React from 'react'
import { Colors, H5, HTMLTable } from '@blueprintjs/core'
import * as sdk from 'botpress/sdk'
import React, { SFC } from 'react'

import style from '../style.scss'

export const Entities = props => {
const { entities } = props.nlu
if (!entities || !entities.length) {
return null
}

return (
<div className={style.block}>
<H5>Entities</H5>
<Pre>
<ul>
{entities.map(x => {
return (
<li key={x.name}>
{x.name} ({x.type}
): {x.data.value}
</li>
)
})}
</ul>
</Pre>
</div>
)
}
export const Entities: SFC<{ entities: sdk.NLU.Entity[] }> = props => (
<div className={style.subSection}>
<H5 color={Colors.DARK_GRAY5}>Entities</H5>
<HTMLTable condensed className={style.summaryTable}>
<thead>
<tr>
<th>Type</th>
<th>Source</th>
<th>Normalized value</th>
<th>Unit</th>
</tr>
</thead>
<tbody>
{props.entities.map(entity => (
<tr>
<td>
@{entity.type}.{entity.name}
</td>
<td>{entity.meta.source}</td>
<td>{entity.data.value}</td>
<td>{entity.data.unit}</td>
</tr>
))}
</tbody>
</HTMLTable>
</div>
)
@@ -1,28 +1,30 @@
import { H5, Pre } from '@blueprintjs/core'
import { Colors, H5 } from '@blueprintjs/core'
import React from 'react'

import style from '../style.scss'
import { formatConfidence } from '../utils'

export const Intents = props => {
const { intent, intents, includedContexts } = props.nlu
if (!intent || !intents) {
const { intent, intents } = props
if (!intent || !intents || !intents.length) {
return null
}

return (
<div className={style.block}>
<H5>Intent</H5>
<small>Contexts: {(includedContexts || []).join(', ')}</small>
<Pre>
{intents.map(i => {
const content = `${formatConfidence(i.confidence)} % -${i.name}`
if (i.name === intent.name) {
return <strong>{content}</strong>
}
return <div>{content}</div>
})}
</Pre>
<div className={style.subSection}>
<H5 color={Colors.DARK_GRAY5}>Intents</H5>
{intents.length > 1 && (
<ul>
{intents.map(i => {
let content: string | JSX.Element = `${i.name}: ${formatConfidence(i.confidence)} %`
if (i.name === intent.name) {
content = <strong>{content}</strong>
}
return <li>{content}</li>
})}
</ul>
)}
{intents.length === 1 && <strong>{`${intent.name}: ${formatConfidence(intent.confidence)} %`}</strong>}
</div>
)
}
@@ -0,0 +1,23 @@
import { H4 } from '@blueprintjs/core'
import * as sdk from 'botpress/sdk'
import _ from 'lodash'
import React, { SFC } from 'react'

import style from '../style.scss'

import { Entities } from './Entities'
import { Intents } from './Intents'
import { Slots } from './Slots'

const NLU: SFC<{ nluData: sdk.IO.EventUnderstanding }> = ({ nluData }) => {
return (
<div className={style.block}>
<H4>Understanding</H4>
<Intents intents={nluData.intents} intent={nluData.intent} />
{nluData.entities.length > 0 && <Entities entities={nluData.entities} />}
{nluData.slots && !_.isEmpty(nluData.slots) && <Slots slots={nluData.slots} />}
</div>
)
}

export default NLU

0 comments on commit d9faafe

Please sign in to comment.