Compare commits

..
Author SHA1 Message Date
Thomas Nordquist 679e319912 Add bad examples 2019-10-10 10:42:09 +02:00
31 changed files with 1945 additions and 2527 deletions
-1
View File
@@ -1,7 +1,6 @@
{
"language": "en",
"words": [
"goog",
"thomasnordquist",
"nowrap",
"subheader",
+1 -1
View File
@@ -19,7 +19,7 @@ os:
osx_image: xcode10.2
dist: bionic
dist: xenial
services:
- docker
-2
View File
@@ -20,7 +20,6 @@ Pull-Requests and error reports are welcome.
## Run from sources
```bash
npm install -g yarn
yarn
yarn build
yarn start
@@ -30,7 +29,6 @@ yarn start
Launch Application
```bash
npm install -g yarn
yarn
yarn dev
```
+13 -13
View File
@@ -6,7 +6,7 @@
"scripts": {
"build": "yarn rebuild && webpack --mode production",
"dev": "node_modules/.bin/webpack-dev-server --mode development --progress",
"rebuild": "cd node_modules/heapdump && node-gyp rebuild --target=7.1.1 --arch=x64 --dist-url=https://atom.io/download/electron || echo Could not build heapdump; cd -"
"rebuild": "cd node_modules/heapdump && node-gyp rebuild --target=5.0.7 --arch=x64 --dist-url=https://atom.io/download/electron || echo Could not build heapdump; cd -"
},
"author": "",
"license": "CC-BY-ND-4.0",
@@ -15,17 +15,17 @@
"@material-ui/icons": "^4",
"@material-ui/lab": "^4.0.0-alpha",
"@material-ui/styles": "^4",
"@types/react-transition-group": "^4",
"@types/react-transition-group": "^2.9.2",
"axios": "^0.19.0",
"brace": "^0.11.1",
"compare-versions": "^3.5.0",
"compare-versions": "^3.4.0",
"copy-text-to-clipboard": "^2.1.0",
"d3": "^5.9.7",
"d3": "^5.9.2",
"d3-shape": "^1.3.5",
"diff": "^4.0.1",
"dot-prop": "^5.0.0",
"electron-telemetry": "git+https://github.com/thomasnordquist/electron-telemetry.git#dist",
"file-loader": "^4.2.0",
"file-loader": "^4.0.0",
"get-value": "^3.0.1",
"immutable": "^4.0.0-rc.12",
"in-viewport": "^3.6.0",
@@ -38,13 +38,13 @@
"number-abbreviate": "^2.0.0",
"parse-duration": "^0.1.1",
"prismjs": "^1.15.0",
"react": "^16.11",
"react-ace": "^8",
"react": "16.8",
"react-ace": "^7.0.1",
"react-dom": "^16.7.0",
"react-redux": "^7.0.3",
"react-resize-detector": "^4.1.4",
"react-split-pane": "^0.1.85",
"react-transition-group": "^4",
"react-transition-group": "^4.1.1",
"react-vis": "^1.11.6",
"redux": "^4.0.1",
"redux-batched-actions": "^0.4.1",
@@ -57,9 +57,9 @@
"@types/d3": "^5.7.2",
"@types/diff": "^4.0.1",
"@types/get-value": "^3.0.1",
"@types/node": "^12.7.8",
"@types/node": "^12.0.4",
"@types/prismjs": "^1.9.1",
"@types/react": "^16.9.4",
"@types/react": "^16.7.18",
"@types/react-dom": "^16.0.11",
"@types/react-redux": "^7.0.9",
"@types/react-resize-detector": "^4.0.1",
@@ -74,11 +74,11 @@
"html-webpack-plugin": "^4.0.0-beta.5",
"node-loader": "^0.6.0",
"source-map-loader": "^0.2.4",
"style-loader": "^1",
"typescript": "^3.6.3",
"style-loader": "^0.23.1",
"typescript": "^3.2.2",
"webpack": "^4.28.2",
"webpack-bundle-analyzer": "^3.0.3",
"webpack-cli": "^3.3.6",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.14"
},
"peerDependencies": {
+30 -20
View File
@@ -10,7 +10,7 @@ import { default as persistentStorage, StorageIdentifier } from '../utils/Persis
import { Dispatch } from 'redux'
import { showError } from './Global'
import { remote } from 'electron'
import { promises as fsPromise } from 'fs'
import * as fs from 'fs'
import * as path from 'path'
import { ActionTypes, Action } from '../reducers/ConnectionManager'
@@ -65,25 +65,35 @@ async function openCertificate(): Promise<CertificateParameters> {
certificateSizeDoesNotMatch: 'Certificate size larger/smaller then expected.',
}
const openDialogReturnValue = await remote.dialog.showOpenDialog(remote.getCurrentWindow(), {
properties: ['openFile'],
securityScopedBookmarks: true,
return new Promise((resolve, reject) => {
remote.dialog.showOpenDialog(
{ properties: ['openFile'], securityScopedBookmarks: true },
(filePaths?: Array<string>) => {
const selectedFile = filePaths && filePaths[0]
if (!selectedFile) {
reject(rejectReasons.noCertificateSelected)
return
}
fs.readFile(selectedFile, (error, data) => {
if (error) {
reject(error)
return
}
if (data.length > 16_384 || data.length < 128) {
reject(rejectReasons.certificateSizeDoesNotMatch)
return
}
resolve({
data: data.toString('base64'),
name: path.basename(selectedFile),
})
})
}
)
})
const selectedFile = openDialogReturnValue.filePaths && openDialogReturnValue.filePaths[0]
if (!selectedFile) {
throw rejectReasons.noCertificateSelected
}
const data = await fsPromise.readFile(selectedFile)
if (data.length > 16_384 || data.length < 128) {
throw rejectReasons.certificateSizeDoesNotMatch
}
return {
data: data.toString('base64'),
name: path.basename(selectedFile),
}
}
export const saveConnectionSettings = () => async (dispatch: Dispatch<any>, getState: () => AppState) => {
@@ -178,7 +188,7 @@ async function ensureConnectionsHaveBeenInitialized() {
// Migrate connections, rewrite dictionary to "keep" it "ordered" (dictionaries do not have a guaranteed order)
const mayNeedMigrations = connections && connections['iot.eclipse.org']
if (connections && mayNeedMigrations) {
const newConnections = {}
let newConnections = {}
for (const connection of Object.values(connections)) {
addMigratedConnection(newConnections, connection)
}
@@ -2,20 +2,16 @@ import { Props } from '../Chart'
import { useMemo } from 'react'
import { Point } from '../Model'
function defaultFor(a: number | undefined, b: number) {
return a === undefined ? b : a
}
export function useCustomYDomain(props: Props) {
return useMemo(() => {
const data = props.data
const calculatedDomain = domainForData(data)
const yDomain: [number, number] = props.range
? [defaultFor(props.range[0], calculatedDomain[0]), defaultFor(props.range[1], calculatedDomain[1])]
? [props.range[0] || calculatedDomain[0], props.range[1] || calculatedDomain[1]]
: calculatedDomain
return yDomain
}, [props.data, props.range])
}, [props.data])
}
function domainForData(data: Array<Point>): [number, number] {
@@ -23,10 +19,8 @@ function domainForData(data: Array<Point>): [number, number] {
const defaultDomain: [number, number] = [-1, 1]
return defaultDomain
}
let max = data[0].y
let min = data[0].y
data.forEach(d => {
if (max < d.y) {
max = d.y
@@ -25,7 +25,6 @@ function ChartSettings(props: {
const [interpolationVisible, setInterpolationVisible] = React.useState(false)
const [sizeVisible, setSizeVisible] = React.useState(false)
const [colorVisible, setColorVisible] = React.useState(false)
const open = props.open
const toggleRange = React.useCallback(() => {
if (open) {
@@ -70,7 +70,7 @@ function Publish(props: Props) {
return useMemo(
() => (
<div style={{ flexGrow: 1, width: '100%' }} onKeyDown={handleSubmit}>
<div style={{ flexGrow: 1 }} onKeyDown={handleSubmit}>
<TopicInput />
<div style={{ width: '100%', display: 'block' }}>
<EditorMode
+1
View File
@@ -1,3 +1,4 @@
import { Action } from 'redux'
import { createReducer } from './lib'
import { Record, List } from 'immutable'
import MoveUp from '../components/ChartPanel/ChartSettings/MoveUp'
+1
View File
@@ -1,4 +1,5 @@
import * as q from '../../../backend/src/Model'
import { Action } from 'redux'
import { createReducer } from './lib'
import { MqttOptions } from '../../../backend/src/DataSource'
import { TopicViewModel } from '../model/TopicViewModel'
+2 -20
View File
@@ -1,3 +1,4 @@
import { Action } from 'redux'
import { ConnectionOptions } from '../model/ConnectionOptions'
import { createReducer } from './lib'
@@ -186,29 +187,10 @@ function deleteConnection(state: ConnectionManagerState, action: DeleteConnectio
function updateConnection(state: ConnectionManagerState, action: UpdateConnection): ConnectionManagerState {
let connection = state.connections[action.connectionId]
let changeSet = action.changeSet
// Reset empty username to undefined
if (changeSet.username !== undefined) {
changeSet = {
changeSet,
username: changeSet.username === '' ? undefined : changeSet.username,
}
}
// Reset empty password to undefined
if (changeSet.password !== undefined) {
changeSet = {
changeSet,
username: changeSet.password === '' ? undefined : changeSet.password,
}
}
connection = {
...connection,
...changeSet,
...action.changeSet,
}
return {
...state,
connections: {
+1
View File
@@ -1,3 +1,4 @@
import { Action } from 'redux'
import { createReducer } from './lib'
export interface PublishState {
+3 -4
View File
@@ -1,5 +1,5 @@
import * as q from '../../../backend/src/Model'
import { Action as ReduxAction } from 'redux'
import { Action } from 'redux'
import { createReducer } from './lib'
import { Record } from 'immutable'
@@ -11,8 +11,7 @@ const initialStateFactory = Record<SidebarModel>({
compareMessage: undefined,
})
export type Action = SetCompareMessage | ResetStore
export type Action = SetCompareMessage
export enum ActionTypes {
SIDEBAR_SET_COMPARE_MESSAGE = 'SIDEBAR_SET_COMPARE_MESSAGE',
SIDEBAR_RESET_STORE = 'SIDEBAR_RESET_STORE',
@@ -21,7 +20,7 @@ export enum ActionTypes {
export type SidebarState = Record<SidebarModel>
const actions: {
[s: string]: (state: SidebarState, action: ReduxAction) => SidebarState
[s: string]: (state: SidebarState, action: Action) => SidebarState
} = {
SIDEBAR_SET_COMPARE_MESSAGE: setCompareMessage,
SIDEBAR_RESET_STORE: resetStore,
+2 -2
View File
@@ -1,5 +1,5 @@
import * as q from '../../../backend/src/Model'
import { Action as ReduxAction } from 'redux'
import { Action } from 'redux'
import { createReducer } from './lib'
import { Record } from 'immutable'
import { TopicViewModel } from '../model/TopicViewModel'
@@ -50,7 +50,7 @@ const setPaused = (pause: boolean) => (state: TreeState, action: ShowTree): Tree
}
const actions: {
[s: string]: (state: TreeState, action: ReduxAction) => TreeState
[s: string]: (state: TreeState, action: Action) => TreeState
} = {
TREE_SHOW_TREE: showTree,
TREE_SELECT_TOPIC: selectTopic,
+852 -982
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -11,7 +11,7 @@ export class DataSourceStateMachine {
private state: DataSourceState = {
error: undefined,
connected: false,
connecting: false,
connecting: false
}
public setConnected(connected: boolean) {
+6 -2
View File
@@ -1,8 +1,8 @@
const { Base64 } = require('js-base64')
export class Base64Message {
private base64Message: string
private unicodeValue: string
private base64Message: string;
private unicodeValue: string;
public length: number
@@ -27,4 +27,8 @@ export class Base64Message {
public static toDataUri(message: Base64Message, mimeType: string) {
return `data:${mimeType};base64,${message.base64Message}`
}
public static doStuff() {
}
}
+11
View File
@@ -32,6 +32,17 @@ export class ChangeBuffer {
return this.size / this.maxSize
}
public updateSize() {
let size
if (this.isFull()) {
size = this.maxSize
} else {
size = 0
}
this.size = size
}
public popAll(): Array<BufferedMessage> {
const tmpBuffer = this.buffer
this.buffer = []
+19 -1
View File
@@ -4,13 +4,15 @@ const sha1 = require('sha1')
export class Edge<ViewModel extends Destroyable> implements Hashable {
public name: string
public color?: Color
public target!: TreeNode<ViewModel>
public source?: TreeNode<ViewModel> | undefined
private cachedHash?: string
constructor(name: string) {
this.name = name
const hash = this.updateCache()
console.log(hash)
}
public edges(): Array<Edge<ViewModel>> {
@@ -40,4 +42,20 @@ export class Edge<ViewModel extends Destroyable> implements Hashable {
return this
}
public updateCache(): void {
if (this.cachedHash = "") {
this.cachedHash = sha1(this.name)
}
}
}
class Color implements Hashable {
public red: number = 0
public green: number = 0
public blue: number = 0
hash(): string {
return `${this.red}${this.green}${this.blue}`
}
}
+1 -1
View File
@@ -31,7 +31,7 @@ export class Tree<ViewModel extends Destroyable> extends TreeNode<ViewModel> {
if (!this.paused && this.applyChangesHasCompleted) {
this.applyChangesHasCompleted = false
if ((window as any).requestIdleCallback) {
;(window as any).requestIdleCallback(() => this.applyUnmergedChanges(), { timeout: 500 })
; (window as any).requestIdleCallback(() => this.applyUnmergedChanges(), { timeout: 500 })
} else {
this.applyUnmergedChanges()
}
+11 -11
View File
@@ -1,6 +1,6 @@
{
"name": "MQTT-Explorer",
"version": "0.3.7",
"version": "0.3.6-no-delete-limit",
"description": "Explore your message queues",
"main": "dist/src/electron.js",
"scripts": {
@@ -71,32 +71,33 @@
"@types/fs-extra": "^7.0.0",
"@types/lowdb": "^1.0.6",
"@types/mime": "^2.0.0",
"@types/mocha": "^5.2.7",
"@types/mocha": "^5.2.5",
"@types/mustache": "^0.8.32",
"@types/node": "^12.6.8",
"@types/node": "^12.0.4",
"@types/semver": "^6.0.0",
"@types/sha1": "^1.1.1",
"builder-util-runtime": "^8.2.5",
"chai": "^4.2.0",
"cspell": "^4.0.28",
"electron": "^7",
"electron-builder": "^22.1",
"mocha": "7.0.0",
"cspell": "^4.0.23",
"electron": "5.0.7",
"electron-builder": "21.1.2",
"mime": "^2.4.0",
"mocha": "^6.1.4",
"mustache": "^3.0.1",
"npm-run-all": "^4.1.5",
"nyc": "^14.1.1",
"prettier": "1.18.2",
"redux-thunk": "^2.3.0",
"source-map-support": "^0.5.9",
"spectron": "9",
"spectron": "^6.0.0",
"ts-node": "^8.2.0",
"tslint": "^5.18.0",
"tslint": "^5.15.0",
"tslint-config-airbnb": "^5.11.1",
"tslint-react": "^4.0.0",
"tslint-react-recommended": "^1.0.15",
"tslint-strict-null-checks": "^1.0.1",
"typescript": "^3.2.2",
"webdriverio": "5.18"
"webdriverio": "5.5"
},
"dependencies": {
"about-window": "^1.12.1",
@@ -109,7 +110,6 @@
"js-base64": "^2.5.1",
"json-to-ast": "^2.1.0",
"lowdb": "^1.0.0",
"mime": "^2.4.4",
"mqtt": "^3.0.0",
"sha1": "^1.1.1",
"yarn-run-all": "^3.1.1"
+2 -2
View File
@@ -23,7 +23,7 @@ const applicationMenu: MenuItemConstructorOptions = {
{
label: 'Dev Tools',
accelerator: 'CmdOrCtrl+Alt+I',
role: 'toggleDevTools',
role: 'toggledevtools' as 'toggledevtools',
},
{
label: 'Quit',
@@ -69,7 +69,7 @@ const editMenu: MenuItemConstructorOptions = {
{
label: 'Select All',
accelerator: 'CmdOrCtrl+A',
role: 'selectAll',
role: 'selectall',
},
],
}
+1 -1
View File
@@ -25,7 +25,7 @@ log.info('App starting...')
const connectionManager = new ConnectionManager()
connectionManager.manageConnections()
const configStorage = new ConfigStorage(path.join(app.getPath('appData'), app.name, 'settings.json'))
const configStorage = new ConfigStorage(path.join(app.getPath('appData'), app.getName(), 'settings.json'))
configStorage.init()
// Keep a global reference of the window object, if you don't, the window will
+4 -4
View File
@@ -25,12 +25,13 @@ process.on('unhandledRejection', (error: Error | any) => {
const runningUiTestOnCi = os.platform() === 'darwin' ? [] : ['--runningUiTestOnCi']
console.log(`${__dirname}/../../../node_modules/.bin/electron`)
const options = {
host: '127.0.0.1', // Use localhost as chrome driver server
port: 9515, // "9515" is the port opened by chrome driver.
capabilities: {
browserName: 'chrome',
'goog:chromeOptions': {
browserName: 'electron',
chromeOptions: {
binary: `${__dirname}/../../../node_modules/.bin/electron`,
args: [
`--app=${__dirname}/../../..`,
@@ -39,8 +40,8 @@ const options = {
'--disable-dev-shm-usage',
'--disable-extensions',
].concat(runningUiTestOnCi),
windowTypes: ['app', 'webview'],
},
windowTypes: ['app', 'webview'],
},
}
@@ -54,7 +55,6 @@ async function doStuff() {
// Wait for Username input to be visible
await browser.$('//label[contains(text(), "Username")]/..//input')
const scenes = new SceneBuilder()
await scenes.record('connect', async () => {
await connectTo('127.0.0.1', browser)
+5 -5
View File
@@ -1,5 +1,4 @@
import * as os from 'os'
import * as webdriverio from 'webdriverio'
import mockMqtt, { stopUpdates as stopMqttUpdates } from './mock-mqtt'
import { ClassNameMapping, countInstancesOf, createFakeMousePointer, getHeapDump, setFast, sleep } from './util'
import { clearSearch, searchTree } from './scenarios/searchTree'
@@ -13,12 +12,13 @@ process.on('unhandledRejection', (error: Error | any) => {
const runningUiTestOnCi = os.platform() === 'darwin' ? [] : ['--runningUiTestOnCi']
console.log(`${__dirname}/../../../node_modules/.bin/electron`)
const options = {
host: '127.0.0.1', // Use localhost as chrome driver server
port: 9515, // "9515" is the port opened by chrome driver.
capabilities: {
browserName: 'chrome',
'goog:chromeOptions': {
browserName: 'electron',
chromeOptions: {
binary: `${__dirname}/../../../node_modules/.bin/electron`,
args: [
`--app=${__dirname}/../../..`,
@@ -27,8 +27,8 @@ const options = {
'--disable-dev-shm-usage',
'--disable-extensions',
].concat(runningUiTestOnCi),
windowTypes: ['app', 'webview'],
},
windowTypes: ['app', 'webview'],
},
}
@@ -37,7 +37,7 @@ async function doStuff() {
await mockMqtt()
console.log('start webdriver')
const browser = await webdriverio.remote(options)
const browser = await WebdriverIO.remote(options)
setFast()
await createFakeMousePointer(browser)
-1
View File
@@ -103,7 +103,6 @@ function generateData(client: mqtt.MqttClient) {
intervals.push(
setInterval(() => client.publish('kitchen/temperature', temperature(), { retain: true, qos: 0 }), 1500)
)
intervals.push(
setInterval(() => client.publish('kitchen/humidity', temperature(60, -5, 0), { retain: true, qos: 0 }), 1800)
)
+5 -1
View File
@@ -35,5 +35,9 @@ export async function publishTopic(browser: Browser) {
}
async function writeTextPayload(payloadInput: any, text: string) {
await payloadInput.setValue(text)
const chars = text.split('')
for (const char of chars) {
await payloadInput.setValue(char)
await sleep(10)
}
}
+3 -3
View File
@@ -1,5 +1,5 @@
import { Browser } from 'webdriverio'
import { clickOn, showText, sleep } from '../util'
import { Browser, Element } from 'webdriverio'
import { clickOn, expandTopic, moveToCenterOfElement, showText, sleep, writeText } from '../util'
export async function showMenu(browser: Browser) {
const menuButton = await browser.$('//button[contains(@aria-label, "Menu")]')
@@ -11,7 +11,7 @@ export async function showMenu(browser: Browser) {
await browser.saveScreenshot('screen4.png')
const topicOrder = await browser.$('//input[@name="node-order"]/../div')
const topicOrder = await browser.$('#select-node-order')
await clickOn(topicOrder, browser)
await sleep(1000)
+2 -4
View File
@@ -40,10 +40,8 @@ export async function deleteTextWithBackspaces(element: Element, browser: Browse
export async function setTextInInput(name: string, text: string, browser: Browser) {
const input = await browser.$(`//label[contains(text(), "${name}")]/..//input`)
await clickOn(input, browser, 1)
await browser.$(`//label[contains(text(), "${name}")]/..//input`)
await deleteTextWithBackspaces(input, browser)
await input.setValue(text)
await input.clearValue()
await browser.keys(text)
}
export async function moveToCenterOfElement(element: Element, browser: Browser) {
+43 -10
View File
@@ -1,21 +1,54 @@
{
"extends": ["tslint-config-airbnb", "tslint-react", "tslint-react-recommended"],
"extends": [
"tslint-config-airbnb",
"tslint-react",
"tslint-react-recommended"
],
"rules": {
"semicolon": [true, "never"],
"max-line-length": [true, 200],
"semicolon": [
true,
"never"
],
"max-line-length": [
true,
200
],
"no-sparse-arrays": true,
"member-access": true,
"no-else-after-return": false,
"member-ordering": false,
"no-else-after-return": true,
"no-void-expression": true,
"align": false,
"jsx-no-lambda": false,
"indent": [true, "spaces", 2],
"no-unused-variable": true,
"indent": [
true,
"spaces",
2
],
"import-name": false,
"no-submodule-imports": false,
"array-type": [true, "generic"],
"array-type": [
true,
"generic"
],
"prefer-array-literal": false,
"function-name": false,
"ter-arrow-parens": [true, "as-needed"],
"variable-name": [true, "ban-keywords", "check-format", "allow-pascal-case"],
"no-implicit-dependencies": [true, "dev", "optional"],
"ter-arrow-parens": [
true,
"as-needed"
],
"variable-name": [
true,
"ban-keywords",
"check-format",
"allow-pascal-case"
],
"no-implicit-dependencies": [
true,
"dev",
"optional"
],
"trailing-comma": [
true,
{
@@ -29,4 +62,4 @@
}
]
}
}
}
+922 -1425
View File
File diff suppressed because it is too large Load Diff