Move Composite logs to uPlot (#334)

This commit is contained in:
Piotr Rogowski 2021-12-21 23:39:38 +01:00 committed by GitHub
parent e27db357ce
commit f94eded413
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 109 additions and 376 deletions

231
package-lock.json generated
View File

@ -24,7 +24,6 @@
"react-scripts": "^4.0.3", "react-scripts": "^4.0.3",
"react-table-drag-select": "^0.3.1", "react-table-drag-select": "^0.3.1",
"recharts": "^2.1.8", "recharts": "^2.1.8",
"timechart": "^1.0.0-beta.4",
"uplot": "^1.6.18", "uplot": "^1.6.18",
"uplot-react": "^1.1.1" "uplot-react": "^1.1.1"
}, },
@ -32,7 +31,7 @@
"@craco/craco": "^6.4.3", "@craco/craco": "^6.4.3",
"@speedy-tuner/eslint-config": "^0.1.3", "@speedy-tuner/eslint-config": "^0.1.3",
"@types/d3": "^7.0.0", "@types/d3": "^7.0.0",
"@types/node": "^17.0.1", "@types/node": "^17.0.2",
"@types/pako": "^1.0.2", "@types/pako": "^1.0.2",
"@types/react": "^17.0.37", "@types/react": "^17.0.37",
"@types/react-dom": "^17.0.11", "@types/react-dom": "^17.0.11",
@ -3759,9 +3758,9 @@
"integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ=="
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "17.0.1", "version": "17.0.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.1.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.2.tgz",
"integrity": "sha512-NXKvBVUzIbs6ylBwmOwHFkZS2EXCcjnqr8ZCRNaXBkHAf+3mn/rPcJxwrzuc6movh8fxQAsUUfYklJ/EG+hZqQ==" "integrity": "sha512-JepeIUPFDARgIs0zD/SKPgFsJEAF0X5/qO80llx59gOxFTboS9Amv3S+QfB7lqBId5sFXJ99BN0J6zFRvL9dDA=="
}, },
"node_modules/@types/normalize-package-data": { "node_modules/@types/normalize-package-data": {
"version": "2.4.1", "version": "2.4.1",
@ -7068,97 +7067,6 @@
"type": "^1.0.1" "type": "^1.0.1"
} }
}, },
"node_modules/d3-array": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.1.1.tgz",
"integrity": "sha512-33qQ+ZoZlli19IFiQx4QEpf2CBEayMRzhlisJHSCsSUbDXv6ZishqS1x7uFVClKG4Wr7rZVHvaAttoLow6GqdQ==",
"dependencies": {
"internmap": "1 - 2"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-axis": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz",
"integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-color": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.0.1.tgz",
"integrity": "sha512-6/SlHkDOBLyQSJ1j1Ghs82OIUXpKWlR0hCsw0XrLSQhuUPuCSmLQ1QPH98vpnQxMUQM2/gfAkUEWsupVpd9JGw==",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-format": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
"integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-interpolate": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
"integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
"dependencies": {
"d3-color": "1 - 3"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-scale": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
"integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
"dependencies": {
"d3-array": "2.10.0 - 3",
"d3-format": "1 - 3",
"d3-interpolate": "1.2.0 - 3",
"d3-time": "2.1.1 - 3",
"d3-time-format": "2 - 4"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-selection": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-time": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.0.0.tgz",
"integrity": "sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==",
"dependencies": {
"d3-array": "2 - 3"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-time-format": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
"integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
"dependencies": {
"d3-time": "1 - 3"
},
"engines": {
"node": ">=12"
}
},
"node_modules/damerau-levenshtein": { "node_modules/damerau-levenshtein": {
"version": "1.0.7", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz",
@ -10008,11 +9916,6 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/gl-matrix": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
"integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="
},
"node_modules/glob": { "node_modules/glob": {
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
@ -11001,14 +10904,6 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/internmap": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
"integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
"engines": {
"node": ">=12"
}
},
"node_modules/ip": { "node_modules/ip": {
"version": "1.1.5", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
@ -20920,24 +20815,6 @@
"resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="
}, },
"node_modules/timechart": {
"version": "1.0.0-beta.4",
"resolved": "https://registry.npmjs.org/timechart/-/timechart-1.0.0-beta.4.tgz",
"integrity": "sha512-mWziioRsw9ClrqGV4UhqbXTCYTSHkQLWNn77P4LSLI1jKw/UN/RR/jwE8TerjcWOWz/rHVgZsKbu01UKTCmWQQ==",
"dependencies": {
"d3-axis": "^3.0.0",
"d3-color": "^3.0.1",
"d3-scale": "^4.0.2",
"d3-selection": "^3.0.0",
"gl-matrix": "^3.3.0",
"tslib": "^2.2.0"
}
},
"node_modules/timechart/node_modules/tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"node_modules/timers-browserify": { "node_modules/timers-browserify": {
"version": "2.0.12", "version": "2.0.12",
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz",
@ -26394,9 +26271,9 @@
"integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ=="
}, },
"@types/node": { "@types/node": {
"version": "17.0.1", "version": "17.0.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.1.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.2.tgz",
"integrity": "sha512-NXKvBVUzIbs6ylBwmOwHFkZS2EXCcjnqr8ZCRNaXBkHAf+3mn/rPcJxwrzuc6movh8fxQAsUUfYklJ/EG+hZqQ==" "integrity": "sha512-JepeIUPFDARgIs0zD/SKPgFsJEAF0X5/qO80llx59gOxFTboS9Amv3S+QfB7lqBId5sFXJ99BN0J6zFRvL9dDA=="
}, },
"@types/normalize-package-data": { "@types/normalize-package-data": {
"version": "2.4.1", "version": "2.4.1",
@ -29071,70 +28948,6 @@
"type": "^1.0.1" "type": "^1.0.1"
} }
}, },
"d3-array": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.1.1.tgz",
"integrity": "sha512-33qQ+ZoZlli19IFiQx4QEpf2CBEayMRzhlisJHSCsSUbDXv6ZishqS1x7uFVClKG4Wr7rZVHvaAttoLow6GqdQ==",
"requires": {
"internmap": "1 - 2"
}
},
"d3-axis": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz",
"integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw=="
},
"d3-color": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.0.1.tgz",
"integrity": "sha512-6/SlHkDOBLyQSJ1j1Ghs82OIUXpKWlR0hCsw0XrLSQhuUPuCSmLQ1QPH98vpnQxMUQM2/gfAkUEWsupVpd9JGw=="
},
"d3-format": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
"integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA=="
},
"d3-interpolate": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
"integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
"requires": {
"d3-color": "1 - 3"
}
},
"d3-scale": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
"integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
"requires": {
"d3-array": "2.10.0 - 3",
"d3-format": "1 - 3",
"d3-interpolate": "1.2.0 - 3",
"d3-time": "2.1.1 - 3",
"d3-time-format": "2 - 4"
}
},
"d3-selection": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ=="
},
"d3-time": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.0.0.tgz",
"integrity": "sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==",
"requires": {
"d3-array": "2 - 3"
}
},
"d3-time-format": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
"integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
"requires": {
"d3-time": "1 - 3"
}
},
"damerau-levenshtein": { "damerau-levenshtein": {
"version": "1.0.7", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz",
@ -31292,11 +31105,6 @@
"resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
"integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
}, },
"gl-matrix": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
"integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="
},
"glob": { "glob": {
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
@ -32050,11 +31858,6 @@
"side-channel": "^1.0.4" "side-channel": "^1.0.4"
} }
}, },
"internmap": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
"integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="
},
"ip": { "ip": {
"version": "1.1.5", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
@ -39727,26 +39530,6 @@
"resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="
}, },
"timechart": {
"version": "1.0.0-beta.4",
"resolved": "https://registry.npmjs.org/timechart/-/timechart-1.0.0-beta.4.tgz",
"integrity": "sha512-mWziioRsw9ClrqGV4UhqbXTCYTSHkQLWNn77P4LSLI1jKw/UN/RR/jwE8TerjcWOWz/rHVgZsKbu01UKTCmWQQ==",
"requires": {
"d3-axis": "^3.0.0",
"d3-color": "^3.0.1",
"d3-scale": "^4.0.2",
"d3-selection": "^3.0.0",
"gl-matrix": "^3.3.0",
"tslib": "^2.2.0"
},
"dependencies": {
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}
}
},
"timers-browserify": { "timers-browserify": {
"version": "2.0.12", "version": "2.0.12",
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz",

View File

@ -45,7 +45,6 @@
"react-scripts": "^4.0.3", "react-scripts": "^4.0.3",
"react-table-drag-select": "^0.3.1", "react-table-drag-select": "^0.3.1",
"recharts": "^2.1.8", "recharts": "^2.1.8",
"timechart": "^1.0.0-beta.4",
"uplot": "^1.6.18", "uplot": "^1.6.18",
"uplot-react": "^1.1.1" "uplot-react": "^1.1.1"
}, },
@ -53,7 +52,7 @@
"@craco/craco": "^6.4.3", "@craco/craco": "^6.4.3",
"@speedy-tuner/eslint-config": "^0.1.3", "@speedy-tuner/eslint-config": "^0.1.3",
"@types/d3": "^7.0.0", "@types/d3": "^7.0.0",
"@types/node": "^17.0.1", "@types/node": "^17.0.2",
"@types/pako": "^1.0.2", "@types/pako": "^1.0.2",
"@types/react": "^17.0.37", "@types/react": "^17.0.37",
"@types/react-dom": "^17.0.11", "@types/react-dom": "^17.0.11",

View File

@ -1,29 +0,0 @@
import {
Popover,
Space,
Typography,
} from 'antd';
import { QuestionCircleOutlined } from '@ant-design/icons';
const { Text, Title } = Typography;
const CanvasHelp = () => (
<div style={{ marginTop: -20, marginBottom: 10, textAlign: 'left', marginLeft: 20 }}>
<Popover
placement="bottom"
content={
<Space direction="vertical">
<Title level={5}>Navigation</Title>
<Text>Pinch to zoom</Text>
<Text>Drag to pan</Text>
<Text>Ctrl + wheel scroll to zoom X axis</Text>
<Text>Hold Shift to speed up zoom 5 times</Text>
</Space>
}
>
<QuestionCircleOutlined />
</Popover>
</div>
);
export default CanvasHelp;

View File

@ -66,8 +66,15 @@ const Diagnose = ({ ui, config, loadedLogs }: { ui: UIState, config: Config, loa
const contentRef = useRef<HTMLDivElement | null>(null); const contentRef = useRef<HTMLDivElement | null>(null);
const margin = 30; const margin = 30;
const [canvasWidth, setCanvasWidth] = useState(0); const [canvasWidth, setCanvasWidth] = useState(0);
const [canvasHeight, setCanvasHeight] = useState(0);
const sidebarWidth = 250; const sidebarWidth = 250;
const calculateCanvasWidth = useCallback(() => setCanvasWidth((contentRef.current?.clientWidth || 0) - margin), []); const calculateCanvasSize = useCallback(() => {
setCanvasWidth((contentRef.current?.clientWidth || 0) - margin);
if (window.innerHeight > 600) {
setCanvasHeight(Math.round((window.innerHeight - 250) / 2));
}
}, []);
const siderProps = { const siderProps = {
width: sidebarWidth, width: sidebarWidth,
collapsible: true, collapsible: true,
@ -75,7 +82,6 @@ const Diagnose = ({ ui, config, loadedLogs }: { ui: UIState, config: Config, loa
collapsed: ui.sidebarCollapsed, collapsed: ui.sidebarCollapsed,
onCollapse: (collapsed: boolean) => { onCollapse: (collapsed: boolean) => {
store.dispatch({ type: 'ui/sidebarCollapsed', payload: collapsed }); store.dispatch({ type: 'ui/sidebarCollapsed', payload: collapsed });
setTimeout(calculateCanvasWidth, 1);
}, },
}; };
const [logs, setLogs] = useState<CompositeLogEntry[]>(); const [logs, setLogs] = useState<CompositeLogEntry[]>();
@ -113,15 +119,15 @@ const Diagnose = ({ ui, config, loadedLogs }: { ui: UIState, config: Config, loa
}; };
loadData(); loadData();
calculateCanvasWidth(); calculateCanvasSize();
window.addEventListener('resize', calculateCanvasWidth); window.addEventListener('resize', calculateCanvasSize);
return () => { return () => {
controller.abort(); controller.abort();
window.removeEventListener('resize', calculateCanvasWidth); window.removeEventListener('resize', calculateCanvasSize);
}; };
}, [calculateCanvasWidth, loadedLogs]); }, [calculateCanvasSize, loadedLogs, ui.sidebarCollapsed]);
return ( return (
<> <>
@ -146,18 +152,18 @@ const Diagnose = ({ ui, config, loadedLogs }: { ui: UIState, config: Config, loa
{toothLogs && logs {toothLogs && logs
? ?
( (
<> <Space direction="vertical" size="large">
<ToothCanvas <ToothCanvas
data={toothLogs!} data={toothLogs!}
width={canvasWidth} width={canvasWidth}
height={canvasWidth * 0.3} height={canvasHeight}
/> />
<CompositeCanvas <CompositeCanvas
data={logs!} data={logs!}
width={canvasWidth} width={canvasWidth}
height={canvasWidth * 0.3} height={canvasHeight}
/> />
</> </Space>
) )
: :
<Space <Space

View File

@ -1,16 +1,13 @@
import { import {
useEffect, useEffect,
useRef, useState,
} from 'react'; } from 'react';
import { Grid } from 'antd'; import { Grid } from 'antd';
import TimeChart from 'timechart'; import UplotReact from 'uplot-react';
import { EventsPlugin } from 'timechart/dist/lib/plugins_extra/events'; import uPlot from 'uplot';
import touchZoomPlugin from '../../utils/uPlot/touchZoomPlugin';
import LandscapeNotice from '../Dialog/LandscapeNotice'; import LandscapeNotice from '../Dialog/LandscapeNotice';
import { import { CompositeLogEntry } from '../../utils/logs/TriggerLogsParser';
CompositeLogEntry,
EntryType,
} from '../../utils/logs/TriggerLogsParser';
import CanvasHelp from '../CanvasHelp';
import { Colors } from '../../utils/colors'; import { Colors } from '../../utils/colors';
const { useBreakpoint } = Grid; const { useBreakpoint } = Grid;
@ -21,108 +18,94 @@ interface Props {
height: number; height: number;
}; };
interface DataPoint {
x: number;
y: number;
}
const CompositeCanvas = ({ data, width, height }: Props) => { const CompositeCanvas = ({ data, width, height }: Props) => {
const { sm } = useBreakpoint(); const { sm } = useBreakpoint();
const canvasRef = useRef<HTMLDivElement | null>(null); const [options, setOptions] = useState<uPlot.Options>();
const [plotData, setPlotData] = useState<uPlot.AlignedData>();
useEffect(() => { useEffect(() => {
let chart: TimeChart; const xData: number[] = [];
const markers: { x: number, name: string }[] = []; const secondary: (number | null)[] = [];
const primary: DataPoint[] = []; const primary: (number | null)[] = [];
const secondary: DataPoint[] = []; const sync: (number | null)[] = [];
const sync: DataPoint[] = [];
data.forEach((entry, index) => { data.forEach((entry, index) => {
if (entry.type === EntryType.MARKER) { const prevSecondary = data[index - 1] ? data[index - 1].secondaryLevel : 0;
markers.push({ const currentSecondary = (entry.secondaryLevel + 3) * 2; // apply scale
x: index,
name: '',
});
}
if (entry.type === EntryType.TRIGGER) { const prevPrimary = data[index - 1] ? data[index - 1].primaryLevel : 0;
const prevSecondary = data[index - 1] ? data[index - 1].secondaryLevel : 0; const currentPrimary = (entry.primaryLevel + 1) * 2;
const currentSecondary = (entry.secondaryLevel + 3) * 2; // apply scale
const prevPrimary = data[index - 1] ? data[index - 1].primaryLevel : 0; const prevSync = data[index - 1] ? data[index - 1].sync : 0;
const currentPrimary = (entry.primaryLevel + 1) * 2; // apply scale const currentSync = entry.sync;
const prevSync = data[index - 1] ? data[index - 1].sync : 0; // base data
const currentSync = entry.sync; xData.push(index);
secondary.push(currentSecondary);
primary.push(currentPrimary);
sync.push(currentSync);
// make it square // make it square
if (prevSecondary !== currentSecondary) { if (prevSecondary !== currentSecondary || prevPrimary !== currentPrimary || prevSync !== currentSync) {
secondary.push({ secondary.push(currentSecondary);
x: index - 1, primary.push(currentPrimary);
y: currentSecondary, sync.push(currentSync);
}); xData.push(index + 1);
}
secondary.push({
x: index,
y: currentSecondary,
});
if (prevPrimary !== currentPrimary) {
primary.push({
x: index - 1,
y: currentPrimary,
});
}
primary.push({
x: index,
y: currentPrimary,
});
if (prevSync !== currentSync) {
sync.push({
x: index - 1,
y: currentSync,
});
}
sync.push({
x: index,
y: currentSync,
});
} }
}); });
const series = [{ setPlotData([
name: 'Secondary', xData,
color: Colors.GREEN, [...secondary],
data: secondary, [...primary],
}, { [...sync],
name: 'Primary', ]);
color: Colors.BLUE,
data: primary,
}, {
name: 'Sync',
color: Colors.RED,
data: sync,
}];
if (canvasRef.current && sm) { setOptions({
chart = new TimeChart(canvasRef.current, { width,
series, height,
lineWidth: 2, scales: {
tooltip: true, x: { time: false },
legend: false, },
zoom: { series: [
x: { autoRange: true }, {
label: 'Event',
}, },
yRange: { min: -1, max: 9 }, {
tooltipXLabel: 'Event', label: 'Secondary',
plugins: { points: { show: false },
events: new EventsPlugin(markers), stroke: Colors.GREEN,
scale: '',
value: (_self, rawValue) => (rawValue / 2) - 3,
width: 2,
}, },
}); {
} label: 'Primary',
points: { show: false },
return () => chart && chart.dispose(); stroke: Colors.ACCENT,
scale: '',
value: (_self, rawValue) => (rawValue / 2) - 1,
width: 2,
},
{
label: 'Sync',
points: { show: false },
stroke: Colors.RED,
scale: '',
width: 2,
},
],
axes: [
{
stroke: Colors.TEXT,
grid: { stroke: Colors.MAIN_LIGHT },
},
],
cursor: {
drag: { y: false },
},
plugins: [touchZoomPlugin()],
});
}, [data, width, height, sm]); }, [data, width, height, sm]);
if (!sm) { if (!sm) {
@ -130,14 +113,10 @@ const CompositeCanvas = ({ data, width, height }: Props) => {
} }
return ( return (
<> <UplotReact
<CanvasHelp /> options={options!}
<div data={plotData!}
ref={canvasRef} />
style={{ width, height }}
className="log-canvas"
/>
</>
); );
}; };

View File

@ -11,7 +11,6 @@ import {
ToothLogEntry, ToothLogEntry,
EntryType, EntryType,
} from '../../utils/logs/TriggerLogsParser'; } from '../../utils/logs/TriggerLogsParser';
import CanvasHelp from '../CanvasHelp';
import { Colors } from '../../utils/colors'; import { Colors } from '../../utils/colors';
import 'uplot/dist/uPlot.min.css'; import 'uplot/dist/uPlot.min.css';
@ -47,7 +46,6 @@ const ToothCanvas = ({ data, width, height }: Props) => {
]); ]);
setOptions({ setOptions({
title: 'Tooth logs',
width, width,
height, height,
scales: { scales: {
@ -91,13 +89,10 @@ const ToothCanvas = ({ data, width, height }: Props) => {
} }
return ( return (
<> <UplotReact
<CanvasHelp /> options={options!}
<UplotReact data={plotData!}
options={options!} />
data={plotData!}
/>
</>
); );
}; };