Initial commit

This commit is contained in:
2020-07-20 21:51:24 -04:00
commit 1bb466762f
30 changed files with 15407 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true

View File

@@ -0,0 +1,25 @@
{
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"@vue/typescript/recommended"
],
"parserOptions": {
"ecmaVersion": 2020
},
"rules": {},
"overrides": [
{
"files": [
"**/__tests__/*.{j,t}s?(x)",
"**/tests/unit/**/*.spec.{j,t}s?(x)"
],
"env": {
"jest": true
}
}
]
}

22
toolbox-web/.gitignore vendored Normal file
View File

@@ -0,0 +1,22 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

29
toolbox-web/README.md Normal file
View File

@@ -0,0 +1,29 @@
# toolbox-web
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Run your unit tests
```
npm run test:unit
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

View File

@@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

14852
toolbox-web/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

61
toolbox-web/package.json Normal file
View File

@@ -0,0 +1,61 @@
{
"name": "toolbox-web",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.19.2",
"core-js": "^3.6.5",
"vue": "^2.6.11",
"vue-class-component": "^7.2.3",
"vue-property-decorator": "^8.4.2",
"vue-router": "^3.2.0",
"vuetify": "^2.2.11",
"vuex": "^3.4.0"
},
"devDependencies": {
"@types/jest": "^24.0.19",
"@typescript-eslint/eslint-plugin": "^2.33.0",
"@typescript-eslint/parser": "^2.33.0",
"@vue/cli-plugin-babel": "~4.4.0",
"@vue/cli-plugin-eslint": "~4.4.0",
"@vue/cli-plugin-router": "~4.4.0",
"@vue/cli-plugin-typescript": "~4.4.0",
"@vue/cli-plugin-unit-jest": "~4.4.0",
"@vue/cli-plugin-vuex": "~4.4.0",
"@vue/cli-service": "~4.4.0",
"@vue/eslint-config-standard": "^5.1.2",
"@vue/eslint-config-typescript": "^5.0.2",
"@vue/test-utils": "^1.0.3",
"eslint": "^6.7.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^6.2.2",
"sass": "^1.19.0",
"sass-loader": "^8.0.0",
"typescript": "~3.9.3",
"vue-cli-plugin-vuetify": "~2.0.7",
"vue-template-compiler": "^2.6.11",
"vuetify-loader": "^1.3.0",
"vuex-class": "^0.3.2",
"vuex-module-decorators": "^0.17.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
],
"jest": {
"preset": "@vue/cli-plugin-unit-jest/presets/typescript-and-babel"
},
"jsconfig": {
"experimentalDecorators": true
}
}

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
</body>
</html>

69
toolbox-web/src/App.vue Normal file
View File

@@ -0,0 +1,69 @@
<template>
<v-app>
<v-navigation-drawer app>
<v-list dense>
<v-list-item link to="/">
<v-list-item-action>
<v-icon>mdi-apps</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>Home</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item link v-for="tool in tools" :key="tool.name" :to="`/tool/${tool.name}`">
<v-list-item-action>
<v-icon>{{ tool.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>{{ tool.name }}</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-navigation-drawer>
<v-app-bar color="lime" app>
<v-toolbar-title>Toolbox</v-toolbar-title>
</v-app-bar>
<v-main>
<v-container fluid>
<router-view></router-view>
</v-container>
</v-main>
<v-footer app>
<span class="monospace">{{ status }}</span>
</v-footer>
</v-app>
</template>
<script lang="ts">
import Vue from 'vue'
import {Component} from 'vue-property-decorator'
import {namespace} from 'vuex-class'
import {Tool} from '@/models';
import {tools} from "@/tools";
const def = namespace('def')
@Component
export default class App extends Vue {
@def.State
public status!: string
public tools: Tool[] = tools;
}
</script>
<style>
html, body {
padding: 0;
margin: 0;
overflow: hidden !important;
}
.monospace {
font-family: monospace;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

View File

@@ -0,0 +1,51 @@
<template>
<v-container>
<p>Run with <code>perf record -F997 --call-graph dwarf -q &lt;program&gt;</code></p>
<v-file-input :loading="loading" label="perf.data" id="flamegraph-upload" @change="onUpload()"></v-file-input>
<object v-if="key" type="image/svg+xml" :data="getGraphUrl()"></object>
</v-container>
</template>
<script lang="ts">
import Vue from 'vue'
import {Component} from 'vue-property-decorator'
import {namespace} from 'vuex-class'
import {toolByName} from '@/tools'
import axios from 'axios'
import {FlameGraphResult} from "@/models";
import {API_URL} from "@/config";
const def = namespace('def')
@Component
export default class FlameGraph extends Vue {
public tool = toolByName('FlameGraph')
public key: string | null = null
public loading = false
getGraphUrl() {
return `${API_URL}/flame_graph/${this.key}`
}
onUpload() {
this.loading = true;
const formData = new FormData();
const input = document.getElementById('flamegraph-upload') as any;
formData.append('file', input.files[0]);
axios.post('http://localhost:8000/flame_graph', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(resp => {
const result = resp.data as FlameGraphResult
this.key = result.key
this.loading = false;
})
}
}
</script>

View File

@@ -0,0 +1,21 @@
<template>
<div>
<v-row>
<v-col>
<v-card max-width="344" to="/tool/FlameGraph">
<v-img :src="require('@/assets/FlameGraph.png')" height="200px"></v-img>
<v-card-title>FlameGraph</v-card-title>
<v-card-subtitle><i>perf</i> profiling data visualization</v-card-subtitle>
</v-card>
</v-col>
</v-row>
</div>
</template>
<script>
export default {
name: 'Home',
components: {}
}
</script>

View File

@@ -0,0 +1 @@
export const API_URL = "http://localhost:8000"

14
toolbox-web/src/main.ts Normal file
View File

@@ -0,0 +1,14 @@
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import vuetify from './plugins/vuetify'
Vue.config.productionTip = false
new Vue({
router,
store,
vuetify,
render: h => h(App)
}).$mount('#app')

11
toolbox-web/src/models.ts Normal file
View File

@@ -0,0 +1,11 @@
export interface Tool {
icon?: string
name: string
}
export interface FlameGraphResult {
key: string
script_err: string
fold_err: string
graph_err: string
}

View File

@@ -0,0 +1,7 @@
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
Vue.use(Vuetify)
export default new Vuetify({
})

View File

@@ -0,0 +1,18 @@
import Vue from 'vue'
import VueRouter, {RouteConfig} from 'vue-router'
import Home from '../components/Home.vue'
import FlameGraph from '@/components/FlameGraph.vue'
Vue.use(VueRouter)
const routes: Array<RouteConfig> = [
{path: '/', component: Home},
{path: '/tool/FlameGraph', component: FlameGraph}
]
const router = new VueRouter({
mode: 'history',
routes
})
export default router

13
toolbox-web/src/shims-tsx.d.ts vendored Normal file
View File

@@ -0,0 +1,13 @@
import Vue, { VNode } from 'vue'
declare global {
namespace JSX {
// tslint:disable no-empty-interface
interface Element extends VNode {}
// tslint:disable no-empty-interface
interface ElementClass extends Vue {}
interface IntrinsicElements {
[elem: string]: any;
}
}
}

4
toolbox-web/src/shims-vue.d.ts vendored Normal file
View File

@@ -0,0 +1,4 @@
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}

View File

@@ -0,0 +1,13 @@
import {VuexModule, Module, Mutation, Action} from 'vuex-module-decorators'
@Module({namespaced: true, name: 'def'})
class DefaultModule extends VuexModule {
public status = '>'
@Mutation
public setStatus(newStatus: string): void {
this.status = newStatus
}
}
export default DefaultModule

View File

@@ -0,0 +1,11 @@
import Vue from 'vue'
import Vuex from 'vuex'
import DefaultModule from '@/store/DefaultModule'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
def: DefaultModule
}
})

9
toolbox-web/src/tools.ts Normal file
View File

@@ -0,0 +1,9 @@
import {Tool} from "@/models";
export const tools: Tool[] = [
{name: "FlameGraph", icon: "mdi-bug"}
]
export const toolByName = (name: string) => {
return tools.find(t => t.name == name)
}

View File

@@ -0,0 +1,12 @@
import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'
describe('HelloWorld.vue', () => {
it('renders props.msg when passed', () => {
const msg = 'new message'
const wrapper = shallowMount(HelloWorld, {
propsData: { msg }
})
expect(wrapper.text()).toMatch(msg)
})
})

41
toolbox-web/tsconfig.json Normal file
View File

@@ -0,0 +1,41 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env",
"jest",
"vuetify"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}

View File

@@ -0,0 +1,5 @@
module.exports = {
transpileDependencies: [
'vuetify'
]
}