Rework demo video

This commit is contained in:
Thomas Nordquist
2019-03-04 16:13:09 +01:00
parent 9c15e392d1
commit 016bf5dfcd
16 changed files with 337 additions and 99 deletions

View File

@@ -94,7 +94,6 @@ const style = (theme: Theme) => {
} }
const before = { const before = {
margin: '0 2px 0 -9px', margin: '0 2px 0 -9px',
// width: '8px',
} }
return { return {
additions: { additions: {

View File

@@ -0,0 +1,44 @@
import * as React from 'react'
import { Theme, withStyles } from '@material-ui/core'
interface Props {
keyboardKey: string
classes: any
}
class Key extends React.Component<Props, {}> {
constructor(props: any) {
super(props)
this.state = { location: 'bottom' }
}
public render() {
return (
<div className={this.props.classes.keyStyle}>
<div className={this.props.classes.keyTextStyle}>{this.props.keyboardKey}</div>
</div>
)
}
}
const style = (theme: Theme) => ({
keyStyle: {
display: 'inline-block' as 'inline-block',
width: '1em',
height: '1em',
backgroundColor: '#bbb',
borderRadius: '10%',
verticalAlign: 'middle' as 'middle',
textAlign: 'center' as 'center',
textShadow: '1px 1px rgba(255,255,255,0.45)',
boxShadow: '0.08em 0.15em 0.01em 0px rgba(100,100,100,0.75)',
},
keyTextStyle: {
marginTop: '0.65em',
fontSize: '0.4em',
fontWeight: 'bold' as 'bold',
},
})
export default withStyles(style)(Key)

View File

@@ -0,0 +1,78 @@
import * as React from 'react'
import { Theme, withStyles } from '@material-ui/core'
interface State {
enabled: boolean
target: {x: number, y: number}
position: {x: number, y: number}
stepSizeX: number,
stepSizeY: number,
}
class Demo extends React.Component<{}, State> {
private timer: any
private frameInterval = 20
constructor(props: any) {
super(props)
this.state = { enabled: false, target: { x: 0, y: 0 }, position: { x: 0, y: 0 }, stepSizeX: 1, stepSizeY: 1 }
}
public componentDidMount() {
(window as any).demo.enableMouse = () => {
this.setState({ enabled: true })
}
(window as any).demo.moveMouse = (x: number, y: number, animationTime: number) => {
const stepSizeX = Math.abs(this.state.position.x - x) / (animationTime / this.frameInterval)
const stepSizeY = Math.abs(this.state.position.y - y) / (animationTime / this.frameInterval)
this.setState({ stepSizeX, stepSizeY, enabled: true, target: { x, y } })
this.moveCloser()
}
}
private moveCloser(steps: number = 0) {
const steSizeX = Math.min(this.state.stepSizeX, Math.abs(this.state.position.x - this.state.target.x))
const steSizeY = Math.min(this.state.stepSizeY, Math.abs(this.state.position.y - this.state.target.y))
const dirX = this.state.position.x > this.state.target.x ? -1 : 1
const dirY = this.state.position.y > this.state.target.y ? -1 : 1
if (steSizeX <= 0.1 && steSizeY <= 0.1) {
this.timer && clearTimeout(this.timer)
return
}
this.setState({
position: {
x: this.state.position.x + (dirX * steSizeX),
y: this.state.position.y + (dirY * steSizeY),
},
})
this.timer = setTimeout(() => {
this.moveCloser(steps + 1)
}, this.frameInterval)
}
public render() {
if (!this.state.enabled) {
return null
}
const style = {
width: '32px',
height: '32px',
position: 'fixed' as 'fixed',
zIndex: 1000000,
filter: 'invert(100%)',
left: this.state.position.x + 2,
top: this.state.position.y + 2,
}
return (
<img src="../cursor.png" style={style} />
)
}
}
const style = (theme: Theme) => {}
export default withStyles(style)(Demo)

View File

@@ -0,0 +1,91 @@
import * as React from 'react'
import { Theme, withStyles } from '@material-ui/core'
import Key from './Key';
interface State {
message?: string
keys: string[]
location: string
}
class Demo extends React.Component<{classes: any}, State> {
private timer: any
constructor(props: any) {
super(props)
this.state = { location: 'bottom', keys: [] }
}
private clearTimer() {
this.timer && clearTimeout(this.timer)
}
public componentDidMount() {
(window as any).demo.showMessage = (message: string, location: string, duration: number, keys: string[] = []) => {
this.clearTimer()
this.setState({ message, location, keys })
this.timer = setTimeout(() => this.setState({ message: undefined }), duration)
}
(window as any).demo.hideMessage = () => {
this.clearTimer()
this.setState({ message: undefined })
}
}
public render() {
const positions: {[s: string]: number} = {
top: 0,
bottom: -65,
middle: -32,
}
const style = {
position: 'fixed' as 'fixed',
left: '5vw',
zIndex: 1000000,
margin: '30vw auto 50vw',
right: '5vw',
bottom: `${positions[this.state.location]}vh`,
}
const style2 = {
textAlign: 'center' as 'center',
fontSize: '4em',
color: 'white',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
borderRadius: '16px',
}
if (!this.state.message) {
return null
}
let keys: any[] = []
if (this.state.keys.length > 0) {
keys = this.state.keys.map(key => [<Key key={key} keyboardKey={key} />])
.reduce((prev, current) => {
return [prev, '+' as any, current]
})
}
return (
<div style={style}>
<div style={style2}>
<span>{this.state.message}</span>
{keys.length > 0 ? <div className={this.props.classes.keysStyle}>{keys}</div> : null}
</div>
</div>
)
}
}
const style = (theme: Theme) => ({
keysStyle: {
fontSize: '1em',
display: 'inline-block' as 'inline-block',
transform: 'translateY(0.3em) translateX(0.8em)',
},
})
export default withStyles(style)(Demo)

View File

@@ -0,0 +1,14 @@
import * as React from 'react'
import ShowText from './ShowText'
import Mouse from './Mouse';
(window as any).demo = {}
export default function render(props: any) {
return (
<span>
<ShowText />
<Mouse />
</span>
)
}

View File

@@ -11,6 +11,7 @@ import reducers from './reducers'
import App from './App' import App from './App'
import { Provider } from 'react-redux' import { Provider } from 'react-redux'
import { createStore, applyMiddleware, compose } from 'redux' import { createStore, applyMiddleware, compose } from 'redux'
import Demo from './components/demo'
const composeEnhancers = /*(window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || */ compose const composeEnhancers = /*(window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || */ compose
const store = createStore( const store = createStore(
@@ -41,6 +42,7 @@ ReactDOM.render(
<MuiThemeProvider theme={theme}> <MuiThemeProvider theme={theme}>
<Provider store={store}> <Provider store={store}>
<App /> <App />
<Demo />
</Provider> </Provider>
</MuiThemeProvider>, </MuiThemeProvider>,
document.getElementById('app'), document.getElementById('app'),

3
src/spec/KeyCode.ts Normal file
View File

@@ -0,0 +1,3 @@
export const Control = '\uE009'
export const Unknown = '\uE000'
export const Plus = '\uE025'

View File

@@ -87,16 +87,19 @@ function generateData(client: mqtt.MqttClient) {
let state = true let state = true
intervals.push(setInterval(() => { intervals.push(setInterval(() => {
state = !state state = !state
const js = {
tags:{
entityId: 33512,
entityType: 'person',
host: 'd44ad81e10f9',
server: 'http://localhost/dataActuality',
status: state ? 'live' : 'inactive',
},
timestamp: Date.now(),
}
client.publish( client.publish(
'actuality/showcase', `{ 'actuality/showcase',
"tags":{ JSON.stringify(js),
"entityId": 33512,
"entityType":"person",
"host":"d44ad81e10f9",
"server":" 'http://localhost/dataActuality',
"status":"${state ? 'live' : 'inactive'}"},
"timestamp":${Date.now()}
}`.replace(/\s/g, ''),
{ retain: true, qos: 0 }, { retain: true, qos: 0 },
) )
}, 2102)) }, 2102))

View File

@@ -1,4 +1,4 @@
import { clickOn, sleep, writeText } from '../util' import { clickOn, writeTextToInput } from '../util'
import { Browser } from 'webdriverio' import { Browser } from 'webdriverio'
export async function connectTo(host: string, browser: Browser<void>) { export async function connectTo(host: string, browser: Browser<void>) {
@@ -9,12 +9,3 @@ export async function connectTo(host: string, browser: Browser<void>) {
const connectButton = await browser.$('//button/span[contains(text(),"Connect")]') const connectButton = await browser.$('//button/span[contains(text(),"Connect")]')
clickOn(connectButton, browser) clickOn(connectButton, browser)
} }
async function writeTextToInput(name: string, text: string, browser: Browser<void>, wait: boolean = true) {
const input = await browser.$(`//label[contains(text(), "${name}")]/..//input`)
await clickOn(input, browser, 1)
wait && await sleep(500)
input.clearValue()
wait && await sleep(300)
await writeText(text, browser)
}

View File

@@ -1,4 +1,4 @@
import { clickOn, sleep, writeText, expandTopic } from '../util' import { clickOn } from '../util'
import { Browser } from 'webdriverio' import { Browser } from 'webdriverio'
export async function copyTopicToClipboard(browser: Browser<void>) { export async function copyTopicToClipboard(browser: Browser<void>) {

View File

@@ -0,0 +1,29 @@
import { clickOn, writeTextToInput, sleep } from '../util'
import { Browser } from 'webdriverio'
export async function showAdvancedConnectionSettings(browser: Browser<void>) {
const advancedSettingsButton = await browser.$('//button/span[contains(text(),"Advanced")]')
const addButton = await browser.$('//button/span[contains(text(),"Add")]')
await clickOn(advancedSettingsButton, browser)
await writeTextToInput('Subscription', 'garden/#', browser, false)
await clickOn(addButton, browser)
await writeTextToInput('Subscription', 'livingroom/#', browser, false)
await clickOn(addButton, browser)
await deleteFirstSubscribedTopic(browser)
await deleteFirstSubscribedTopic(browser)
await sleep(1000)
const backButton = await browser.$('//button/span[contains(text(),"Back")]')
await clickOn(backButton, browser)
const connectButton = await browser.$('//button/span[contains(text(),"Connect")]')
await clickOn(connectButton, browser)
}
async function deleteFirstSubscribedTopic(browser: Browser<void>) {
const deleteButton = await browser.$('//*[contains(@class,"topicList")]//button')
await clickOn(deleteButton, browser)
}

View File

@@ -17,6 +17,9 @@ export async function showJsonFormatting(browser: Browser<void>) {
await sleep(300) await sleep(300)
await clickOn(formatJsonButton, browser) await clickOn(formatJsonButton, browser)
await sleep(1200) await sleep(1200)
const sidebarDrawer = await browser.$('//*[contains(@class, "Sidebar")]')
await sidebarDrawer.scrollIntoView()
} }
async function writeTextPayload(payloadInput: any, text: string) { async function writeTextPayload(payloadInput: any, text: string) {

View File

@@ -1,5 +1,5 @@
import { clickOn, sleep, writeText, expandTopic } from '../util'
import { Browser } from 'webdriverio' import { Browser } from 'webdriverio'
import { expandTopic, sleep } from '../util'
export async function showJsonPreview(browser: Browser<void>) { export async function showJsonPreview(browser: Browser<void>) {
await expandTopic('actuality/showcase', browser) await expandTopic('actuality/showcase', browser)

View File

@@ -0,0 +1,11 @@
import { sleep, showKeys, showText } from '../util'
import { Browser } from 'webdriverio'
export async function showZoomLevel(browser: Browser<void>) {
await showKeys('Zoom in', 2000, browser, 'top', ['Ctrl', '+'])
await sleep(2000)
await showKeys('Zoom out', 2000, browser, 'middle', ['Ctrl', '-'])
await sleep(2000)
await showKeys('Reset zoom level', 2000, browser, 'bottom', ['Ctrl', 'Zero'])
await sleep(2000)
}

View File

@@ -1,4 +1,4 @@
import { Element, Browser } from 'webdriverio' import { Browser, Element } from 'webdriverio'
export { expandTopic } from './expandTopic' export { expandTopic } from './expandTopic'
export function sleep(ms: number, required = false) { export function sleep(ms: number, required = false) {
@@ -26,47 +26,28 @@ export async function delteTextWithBackspaces(element: Element<void>, browser: B
} }
} }
export async function writeTextToInput(name: string, text: string, browser: Browser<void>, wait: boolean = true) {
const input = await browser.$(`//label[contains(text(), "${name}")]/..//input`)
await clickOn(input, browser, 1)
wait && await sleep(500)
input.clearValue()
wait && await sleep(300)
await writeText(text, browser)
}
export async function moveToCenterOfElement(element: Element<void>, browser: Browser<void>) { export async function moveToCenterOfElement(element: Element<void>, browser: Browser<void>) {
const { x, y } = await element.getLocation() const { x, y } = await element.getLocation()
const { width, height } = await element.getSize() const { width, height } = await element.getSize()
const js = `{ const targetX = x + width / 2
const targetX = ${x + width / 2} const targetY = y + height / 2
const targetY = ${y + height / 2}
const duration = 500 const duration = 500
const maxStepSize = 10 const js = `window.demo.moveMouse(${targetX}, ${targetY}, ${duration});`
const e = document.getElementById("bier")
const top = parseFloat(e.style.top)
const left = parseFloat(e.style.left)
const deltaY = targetY - top
const deltaX = targetX - left
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
const steps = Math.ceil(distance / maxStepSize)
const stepX = deltaX / steps
const stepY = deltaY / steps
let currentStep = 0
function getCloser() {
e.style.left = String(left + (stepX * currentStep)) + 'px'
e.style.top = String(top + (stepY * currentStep)) + 'px'
if (currentStep < steps) {
setTimeout(() => {
currentStep += 1
if (currentStep === steps) {
e.style.left = String(targetX + 5) + 'px'
e.style.top = String(targetY + 1) + 'px'
} else {
getCloser()
}
}, duration/steps)
}
}
getCloser()
}`
await browser.execute(js) await browser.execute(js)
await sleep(550, true) await sleep(duration + 500, true)
await element.moveTo() await element.moveTo()
} }
@@ -84,47 +65,25 @@ export async function clickOn(element: Element<void>, browser: Browser<void>, cl
} }
export async function createFakeMousePointer(browser: Browser<void>) { export async function createFakeMousePointer(browser: Browser<void>) {
const addCursorImage = 'const i=document.createElement("img");' const js = 'window.demo.enableMouse();'
+ 'i.src="../cursor.png";'
+ 'i.width="32";'
+ 'i.height="32";'
+ 'i.id="bier";'
+ 'i.style="position: fixed; z-index:10000000; filter: invert(100%);left: 0px; top: 0px;";'
+ 'document.body.appendChild(i)'
await browser.execute(addCursorImage) await browser.execute(js)
} }
export async function showText(text: string, duration: number = 0, browser: Browser<void>, location: 'top' | 'bottom' | 'middle' = 'bottom') { export async function showText(text: string, duration: number = 0, browser: Browser<void>, location: 'top' | 'bottom' | 'middle' = 'bottom', keys = []) {
const positions = { const js = `window.demo.showMessage('${text}', '${location}', ${duration});`
top: 0,
bottom: -65, browser.execute(js)
middle: -32,
} }
const js = `
const postition = "${positions[location]}vh" export async function showKeys(text: string, duration: number = 0, browser: Browser<void>, location: 'top' | 'bottom' | 'middle' = 'bottom', keys: string[] = []) {
let previousDiv = document.getElementById('tests-text-overlay') const js = `window.demo.showMessage('${text}', '${location}', ${duration}, ${JSON.stringify(keys)});`
previousDiv && previousDiv.remove()
let div = document.createElement('div')
div.id = "tests-text-overlay"
div.style = "background-color: rgba(0, 0, 0, 0.8);position: fixed;left: 5vw;z-index: 1000000;margin: 30vw auto 50vw;border-radius: 16px;right: 5vw;bottom: "+ postition +";"
let div2 = document.createElement('div')
div2.style = "text-align: center;font-size: 4em;color: white;"
div2.innerHTML = \`${text}\`
div.appendChild(div2)
document.body.appendChild(div)
if (${duration} > 0) {
setTimeout(() => div.remove(), ${duration})
}
`
browser.execute(js) browser.execute(js)
} }
export async function hideText(browser: Browser<void>) { export async function hideText(browser: Browser<void>) {
const js = ` const js = 'window.demo.hideMessage();'
let previousDiv = document.getElementById('tests-text-overlay')
previousDiv && previousDiv.remove()
`
browser.execute(js) browser.execute(js)
await sleep(600) await sleep(600)
} }

View File

@@ -3,13 +3,6 @@ import * as webdriverio from 'webdriverio'
import mockMqtt, { stop } from './mock-mqtt' import mockMqtt, { stop } from './mock-mqtt'
import { clearOldTopics } from './scenarios/clearOldTopics' import { clearOldTopics } from './scenarios/clearOldTopics'
import { clearSearch, searchTree } from './scenarios/searchTree' import { clearSearch, searchTree } from './scenarios/searchTree'
import {
clickOnHistory,
createFakeMousePointer,
hideText,
showText,
sleep,
} from './util'
import { connectTo } from './scenarios/connect' import { connectTo } from './scenarios/connect'
import { copyTopicToClipboard } from './scenarios/copyTopicToClipboard' import { copyTopicToClipboard } from './scenarios/copyTopicToClipboard'
import { copyValueToClipboard } from './scenarios/copyValueToClipboard' import { copyValueToClipboard } from './scenarios/copyValueToClipboard'
@@ -20,6 +13,15 @@ import { showJsonPreview } from './scenarios/showJsonPreview'
import { showMenu } from './scenarios/showMenu' import { showMenu } from './scenarios/showMenu'
import { showNumericPlot } from './scenarios/showNumericPlot' import { showNumericPlot } from './scenarios/showNumericPlot'
import { showOffDiffCapability } from './scenarios/showOffDiffCapability' import { showOffDiffCapability } from './scenarios/showOffDiffCapability'
import { showZoomLevel } from './scenarios/showZoomLevel'
import { showAdvancedConnectionSettings } from './scenarios/showAdvancedConnectionSettings'
import {
clickOnHistory,
createFakeMousePointer,
hideText,
showText,
sleep,
} from './util'
process.on('unhandledRejection', (error: Error) => { process.on('unhandledRejection', (error: Error) => {
console.error('unhandledRejection', error.message, error.stack) console.error('unhandledRejection', error.message, error.stack)
@@ -51,6 +53,7 @@ async function doStuff() {
await createFakeMousePointer(browser) await createFakeMousePointer(browser)
await connectTo('127.0.0.1', browser) await connectTo('127.0.0.1', browser)
await sleep(1000) await sleep(1000)
await sleep(1000) await sleep(1000)
@@ -103,10 +106,18 @@ async function doStuff() {
await sleep(2000) await sleep(2000)
await disconnect(browser) await disconnect(browser)
await showText('Customize Subscriptions', 3000, browser, 'top')
await showAdvancedConnectionSettings(browser)
await showText('Keyboard shortcuts', 1750, browser, 'middle')
await sleep(1750)
await showZoomLevel(browser)
await showText('The End', 3000, browser, 'middle')
await sleep(3000) await sleep(3000)
browser.closeWindow() browser.closeWindow()
stop() stop()
} }