Commit 4b013e34 authored by James Long's avatar James Long Committed by Commit Bot

Migrate android dependency visualization to Vue SFCs

Vue SFCs (Single File Components) offer many benefits (see website:
https://vuejs.org/v2/guide/single-file-components.html). This highly
mechanical CL migrates the current Vue components to SFCs by taking the
following steps:

For each file in src/vue_components:
* Rename the file to .vue.
* Move the `template` field into a <template/> tag.
* Move the imports to the top of a <script/> tag.
* Assign the rest of the component to a const in the <script/> tag.
* `export default` the previous const at the end of the <script/> tag.
Caveat: Sometimes ${} notation was used to insert constants into the
template literals. This cannot be done in the <template/> tags, so
constants are redeclared as a computed property of the component.

For each of the .css files:
* If the selector is for part of a component, move it into a scoped
<style/> tag in that component.
* If the selector is part of a component, but affects a child of that
component (eg. autocomplete or d3's auto-generated svg elements), move
it into a non-scoped <style/> tag in that component.

Bug: 1093962
Change-Id: Id4b6307109cb06bbe195e7ac5668b08782cd487b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2293180
Commit-Queue: James Long <yjlong@google.com>
Reviewed-by: default avatarMohamed Heikal <mheikal@chromium.org>
Reviewed-by: default avatarSamuel Huang <huangs@chromium.org>
Cr-Commit-Position: refs/heads/master@{#788358}
parent 45e89ddc
......@@ -47,6 +47,11 @@ npm run serve-dist
```
This command will open a simple HTTP server serving the contents of the `dist/` directory.
To build and serve, you can execute the two commands together:
```
npm run build && npm run serve-dist
```
**To view the visualization, open `localhost:8888/package_view.html`.**
### Miscellaneous
......
......@@ -2,23 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {ClassGraphPage} from './vue_components/class_graph_page.js';
// For ease of development, we serve our testing data on localhost:8888. This
// should be changed as we find other ways to serve the assets (eg. user upload
// or hosted externally).
const LOCALHOST = 'http://localhost:8888';
import Vue from 'vue';
import ClassGraphPage from './vue_components/class_graph_page.vue';
import * as d3 from 'd3';
import './common.css';
document.addEventListener('DOMContentLoaded', () => {
d3.json(`${LOCALHOST}/json_graph.txt`).then(data => {
new ClassGraphPage({
new Vue({
el: '#class-graph-page',
propsData: {
graphJson: data.class_graph,
},
render: createElement => createElement(
ClassGraphPage,
{
props: {
graphJson: data.class_graph,
},
},
),
});
});
});
/* Copyright 2020 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
#page-container {
display: flex;
flex-direction: column;
}
#page-controls {
display: flex;
flex-direction: row;
height: 15vh;
}
#graph-and-node-details-container {
display: flex;
flex-direction: row;
}
.selected-node-details {
display: flex;
flex-direction: column;
min-width: 400px;
}
.url-generator {
display: flex;
flex-direction: row;
}
.user-input-group {
display: flex;
flex-direction: column;
}
.filter-items {
overflow: hidden;
overflow-y: scroll;
min-width: 100px;
margin-right: 20px;
}
#graph-svg {
background-color: #eee;
}
.graph-edges line {
stroke: #999;
stroke-opacity: 0.6;
}
.graph-nodes circle {
stroke: #fff;
stroke-width: 1.5px;
}
.graph-labels text {
font-family: sans-serif;
font-size: 12px;
}
.graph-nodes circle.locked {
stroke: #000;
stroke-width: 3;
}
#filter-input {
width: 500px;
}
.autocomplete-result-list {
background: #fff;
box-sizing: content-box;
list-style: none;
max-height: 600px;
overflow-y: auto;
padding: 0;
}
.autocomplete-result:hover,
.autocomplete-result[aria-selected=true] {
background-color:rgba(0, 0, 0, 0.1)
}
/* Copyright 2020 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
#node-details-container {
display: flex;
flex-direction: column;
}
.package-details-panel {
max-height: 400px;
overflow: hidden;
overflow-y: scroll;
}
\ No newline at end of file
......@@ -2,24 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {PackageGraphPage} from './vue_components/package_graph_page.js';
// For ease of development, we serve our testing data on localhost:8888. This
// should be changed as we find other ways to serve the assets (eg. user upload
// or hosted externally).
const LOCALHOST = 'http://localhost:8888';
import Vue from 'vue';
import PackageGraphPage from './vue_components/package_graph_page.vue';
import * as d3 from 'd3';
import './common.css';
import './package.css';
document.addEventListener('DOMContentLoaded', () => {
d3.json(`${LOCALHOST}/json_graph.txt`).then(data => {
new PackageGraphPage({
new Vue({
el: '#package-graph-page',
propsData: {
graphJson: data.package_graph,
},
render: createElement => createElement(
PackageGraphPage,
{
props: {
graphJson: data.package_graph,
},
},
),
});
});
});
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
import {CUSTOM_EVENTS} from '../vue_custom_events.js';
<template>
<div id="page-container">
<div id="page-controls">
<GraphFilterInput
:node-ids="this.pageModel.getNodeIds()"
@[CUSTOM_EVENTS.FILTER_SUBMITTED]="this.addNodeToFilter"
></GraphFilterInput>
<GraphFilterItems
:node-filter-data="this.pageModel.nodeFilterData"
@[CUSTOM_EVENTS.FILTER_ELEMENT_CLICKED]="this.removeNodeFromFilter"
></GraphFilterItems>
<GraphInboundInput
:inbound-depth-data="this.pageModel.inboundDepthData"
@[CUSTOM_EVENTS.INBOUND_DEPTH_UPDATED]="this.setInboundDepth"
></GraphInboundInput>
<GraphOutboundInput
:outbound-depth-data="this.pageModel.outboundDepthData"
@[CUSTOM_EVENTS.OUTBOUND_DEPTH_UPDATED]="this.setOutboundDepth"
></GraphOutboundInput>
</div>
<div id="graph-and-node-details-container">
<GraphVisualization
:graph-data-update-ticker="this.graphDataUpdateTicker"
:page-model="this.pageModel"
@[CUSTOM_EVENTS.NODE_CLICKED]="graphNodeClicked"
></GraphVisualization>
<div id="node-details-container">
<GraphSelectedNodeDetails
:selected-node-details-data="this.pageModel.selectedNodeDetailsData"
@[CUSTOM_EVENTS.ADD_TO_FILTER_CLICKED]="addNodeToFilter"
@[CUSTOM_EVENTS.REMOVE_FROM_FILTER_CLICKED]="removeNodeFromFilter"
></GraphSelectedNodeDetails>
<LinkToGraph
v-if="this.pageModel.selectedNodeDetailsData.selectedNode !== null"
:filter="
[this.pageModel.selectedNodeDetailsData.selectedNode.packageName]"
:graph-type="PagePathName.PACKAGE"
:text="'View ' +
this.pageModel.selectedNodeDetailsData.selectedNode.packageName"
></LinkToGraph>
</div>
</div>
<PageUrlGenerator
:page-path-name="this.pagePathName"
:node-filter-data="this.pageModel.nodeFilterData"
></PageUrlGenerator>
</div>
</template>
import {GraphFilterInput} from './graph_filter_input.js';
import {GraphFilterItems} from './graph_filter_items.js';
import {GraphInboundInput} from './graph_inbound_input.js';
import {GraphOutboundInput} from './graph_outbound_input.js';
import {GraphSelectedNodeDetails} from './graph_selected_node_details.js';
import {GraphVisualization} from './graph_visualization.js';
import {LinkToGraph} from './link_to_graph.js';
import {PageUrlGenerator} from './page_url_generator.js';
<script>
import {CUSTOM_EVENTS} from '../vue_custom_events.js';
import {PagePathName, generateFilterFromUrl} from '../url_processor.js';
import {generateFilterFromUrl} from '../url_processor.js';
import {GraphNode} from '../graph_model.js';
import {PageModel} from '../page_model.js';
import {PagePathName} from '../url_processor.js';
import {parseClassGraphModelFromJson} from '../process_graph_json.js';
import Vue from 'vue';
import GraphFilterInput from './graph_filter_input.vue';
import GraphFilterItems from './graph_filter_items.vue';
import GraphInboundInput from './graph_inbound_input.vue';
import GraphOutboundInput from './graph_outbound_input.vue';
import GraphSelectedNodeDetails from './graph_selected_node_details.vue';
import GraphVisualization from './graph_visualization.vue';
import LinkToGraph from './link_to_graph.vue';
import PageUrlGenerator from './page_url_generator.vue';
const ClassGraphPage = Vue.component('class-graph-page', {
const ClassGraphPage = {
components: {
'graph-filter-input': GraphFilterInput,
'graph-filter-items': GraphFilterItems,
'graph-inbound-input': GraphInboundInput,
'graph-outbound-input': GraphOutboundInput,
'graph-selected-node-details': GraphSelectedNodeDetails,
'graph-visualization': GraphVisualization,
'link-to-graph': LinkToGraph,
'page-url-generator': PageUrlGenerator,
GraphFilterInput,
GraphFilterItems,
GraphInboundInput,
GraphOutboundInput,
GraphSelectedNodeDetails,
GraphVisualization,
LinkToGraph,
PageUrlGenerator,
},
props: ['graphJson'],
......@@ -57,6 +104,10 @@ const ClassGraphPage = Vue.component('class-graph-page', {
graphDataUpdateTicker: 0,
};
},
computed: {
CUSTOM_EVENTS: () => CUSTOM_EVENTS,
PagePathName: () => PagePathName,
},
/**
* Parses out data from the current URL to initialize the visualization with.
*/
......@@ -125,55 +176,32 @@ const ClassGraphPage = Vue.component('class-graph-page', {
this.pageModel.selectedNodeDetailsData.selectedNode = node;
},
},
template: `
<div id="page-container">
<div id="page-controls">
<graph-filter-input
:node-ids="this.pageModel.getNodeIds()"
@${CUSTOM_EVENTS.FILTER_SUBMITTED}="this.addNodeToFilter"
></graph-filter-input>
<graph-filter-items
:node-filter-data="this.pageModel.nodeFilterData"
@${CUSTOM_EVENTS.FILTER_ELEMENT_CLICKED}="this.removeNodeFromFilter"
></graph-filter-items>
<graph-inbound-input
:inbound-depth-data="this.pageModel.inboundDepthData"
@${CUSTOM_EVENTS.INBOUND_DEPTH_UPDATED}="this.setInboundDepth"
></graph-inbound-input>
<graph-outbound-input
:outbound-depth-data="this.pageModel.outboundDepthData"
@${CUSTOM_EVENTS.OUTBOUND_DEPTH_UPDATED}="this.setOutboundDepth"
></graph-outbound-input>
</div>
<div id="graph-and-node-details-container">
<graph-visualization
:graph-data-update-ticker="this.graphDataUpdateTicker"
:page-model="this.pageModel"
@${CUSTOM_EVENTS.NODE_CLICKED}="graphNodeClicked"
></graph-visualization>
<div id="node-details-container">
<graph-selected-node-details
:selected-node-details-data="this.pageModel.selectedNodeDetailsData"
@${CUSTOM_EVENTS.ADD_TO_FILTER_CLICKED}="addNodeToFilter"
@${CUSTOM_EVENTS.REMOVE_FROM_FILTER_CLICKED}="removeNodeFromFilter"
></graph-selected-node-details>
<link-to-graph
v-if="this.pageModel.selectedNodeDetailsData.selectedNode !== null"
:filter="
[this.pageModel.selectedNodeDetailsData.selectedNode.packageName]"
graph-type="${PagePathName.PACKAGE}"
:text="'View ' +
this.pageModel.selectedNodeDetailsData.selectedNode.packageName"
></link-to-graph>
</div>
</div>
<page-url-generator
:page-path-name="this.pagePathName"
:node-filter-data="this.pageModel.nodeFilterData"
></page-url-generator>
</div>`,
});
export {
ClassGraphPage,
};
export default ClassGraphPage;
</script>
<style>
.user-input-group {
display: flex;
flex-direction: column;
}
</style>
<style scoped>
#page-container {
display: flex;
flex-direction: column;
}
#page-controls {
display: flex;
flex-direction: row;
height: 15vh;
}
#graph-and-node-details-container {
display: flex;
flex-direction: row;
}
</style>
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<template>
<div class="user-input-group">
<label for="filter-input">Add node to filter (exact name):</label>
<Autocomplete
id="filter-input"
ref="autocomplete"
:search="search"
@submit="onSelectOption"
></Autocomplete>
</div>
</template>
<script>
import {CUSTOM_EVENTS} from '../vue_custom_events.js';
import Autocomplete from '@trevoreyre/autocomplete-vue';
......@@ -10,7 +23,9 @@ const GraphFilterInput = {
components: {
Autocomplete,
},
props: {'nodeIds': Array},
props: {
'nodeIds': Array
},
methods: {
search: function(searchTerm) {
return this.nodeIds.filter(name => {
......@@ -26,18 +41,27 @@ const GraphFilterInput = {
this.$refs.autocomplete.value = '';
},
},
template: `
<div class="user-input-group">
<label for="filter-input">Add node to filter (exact name):</label>
<autocomplete
id="filter-input"
ref="autocomplete"
:search="search"
@submit="onSelectOption"
></autocomplete>
</div>`,
};
export {
GraphFilterInput,
};
export default GraphFilterInput;
</script>
<style>
#filter-input {
width: 500px;
}
.autocomplete-result-list {
background: #fff;
box-sizing: content-box;
list-style: none;
max-height: 600px;
overflow-y: auto;
padding: 0;
}
.autocomplete-result:hover,
.autocomplete-result[aria-selected=true] {
background-color: rgba(0, 0, 0, 0.1);
}
</style>
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<template>
<ul class="filter-items">
<li @click="removeFilter" v-for="node in nodeList">
{{node}}
</li>
</ul>
</template>
<script>
import {CUSTOM_EVENTS} from '../vue_custom_events.js';
const GraphFilterItems = {
......@@ -15,14 +24,16 @@ const GraphFilterItems = {
this.$emit(CUSTOM_EVENTS.FILTER_ELEMENT_CLICKED, filterText.trim());
},
},
template: `
<ul class="filter-items">
<li @click="removeFilter" v-for="node in nodeList">
{{node}}
</li>
</ul>`,
};
export {
GraphFilterItems,
};
export default GraphFilterItems;
</script>
<style scoped>
.filter-items {
overflow: hidden;
overflow-y: scroll;
min-width: 100px;
margin-right: 20px;
}
</style>
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<template>
<div class="user-input-group">
<label for="filter-inbound">Change inbound (blue) depth:</label>
<input v-model.number="inboundDepth" type="number" id="filter-inbound">
<button @click="submitInbound" type="button">Update Inbound</button>
</div>
</template>
<script>
import {CUSTOM_EVENTS} from '../vue_custom_events.js';
const GraphInboundInput = {
......@@ -14,14 +23,7 @@ const GraphInboundInput = {
this.$emit(CUSTOM_EVENTS.INBOUND_DEPTH_UPDATED, this.inboundDepth);
},
},
template: `
<div class="user-input-group">
<label for="filter-inbound">Change inbound (blue) depth:</label>
<input v-model.number="inboundDepth" type="number" id="filter-inbound">
<button @click="submitInbound" type="button">Update Inbound</button>
</div>`,
};
export {
GraphInboundInput,
};
export default GraphInboundInput;
</script>
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<template>
<div class="user-input-group">
<label for="filter-outbound">Change outbound (yellow) depth:</label>
<input v-model.number="outboundDepth" type="number" id="filter-outbound">
<button @click="submitOutbound" type="button">Update Outbound</button>
</div>
</template>
<script>
import {CUSTOM_EVENTS} from '../vue_custom_events.js';
const GraphOutboundInput = {
......@@ -14,14 +23,7 @@ const GraphOutboundInput = {
this.$emit(CUSTOM_EVENTS.OUTBOUND_DEPTH_UPDATED, this.outboundDepth);
},
},
template: `
<div class="user-input-group">
<label for="filter-outbound">Change outbound (yellow) depth:</label>
<input v-model.number="outboundDepth" type="number" id="filter-outbound">
<button @click="submitOutbound" type="button">Update Outbound</button>
</div>`,
};
export {
GraphOutboundInput,
};
export default GraphOutboundInput;
</script>
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<template>
<div class="selected-node-details">
<template v-if="selectedNode !== null">
<ul>
<li>Name: {{selectedNode.id}}</li>
<li>Display Name: {{selectedNode.displayName}}</li>
<li v-for="(value, key) in selectedNode.visualizationState">
{{key}}: {{value}}
</li>
</ul>
<button
v-if="selectedNode.visualizationState.selectedByFilter"
@click="removeSelectedFromFilter">
Remove from filter
</button>
<button v-else @click="addSelectedToFilter">Add to filter</button>
</template>
<div v-else>Click a node for more details.</div>
</div>
</template>
<script>
import {CUSTOM_EVENTS} from '../vue_custom_events.js';
const GraphSelectedNodeDetails = {
......@@ -18,27 +40,15 @@ const GraphSelectedNodeDetails = {
CUSTOM_EVENTS.REMOVE_FROM_FILTER_CLICKED, this.selectedNode.id);
},
},
template: `
<div class="selected-node-details">
<template v-if="selectedNode !== null">
<ul>
<li>Name: {{selectedNode.id}}</li>
<li>Display Name: {{selectedNode.displayName}}</li>
<li v-for="(value, key) in selectedNode.visualizationState">
{{key}}: {{value}}
</li>
</ul>
<button
v-if="selectedNode.visualizationState.selectedByFilter"
@click="removeSelectedFromFilter">
Remove from filter
</button>
<button v-else @click="addSelectedToFilter">Add to filter</button>
</template>
<div v-else>Click a node for more details.</div>
</div>`,
};
export {
GraphSelectedNodeDetails,
};
export default GraphSelectedNodeDetails;
</script>
<style scoped>
.selected-node-details {
display: flex;
flex-direction: column;
min-width: 400px;
}
</style>
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<template>
<svg id="graph-svg" width="960" height="600"></svg>
</template>
<script>
import {CUSTOM_EVENTS} from '../vue_custom_events.js';
import {GraphView} from '../graph_view.js';
......@@ -28,12 +33,35 @@ const GraphVisualization = {
this.graphView.updateGraphData(this.pageModel.getDataForD3());
},
},
template: `
<div id="graph-container">
<svg id="graph-svg" width="960" height="600"></svg>
</div>`,
};
export {
GraphVisualization,
};
export default GraphVisualization;
</script>
<style>
.graph-edges line {
stroke: #999;
stroke-opacity: 0.6;
}
.graph-nodes circle {
stroke: #fff;
stroke-width: 1.5px;
}
.graph-labels text {
font-family: sans-serif;
font-size: 12px;
}
.graph-nodes circle.locked {
stroke: #000;
stroke-width: 3;
}
</style>
<style scoped>
#graph-svg {
background-color: #eee;
}
</style>
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<template>
<a :href="this.url">{{this.text}}</a>
</template>
<script>
import {generateUrlFromFilter} from '../url_processor.js';
const LinkToGraph = {
......@@ -15,9 +20,7 @@ const LinkToGraph = {
return generateUrlFromFilter(document.URL, this.graphType, this.filter);
},
},
template: `<a :href="this.url">{{this.text}}</a>`,
};
export {
LinkToGraph,
};
export default LinkToGraph;
</script>
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
import {shortenClassName} from '../chrome_hooks.js';
<template>
<div
v-if="selectedPackage !== null"
class="package-details-panel"
>
<LinkToGraph
:filter="classesInSelectedPackage"
:graphType="PagePathName.CLASS"
text="Class graph with all classes in this package"
></LinkToGraph>
<ul>
<li v-for="classObj in classesWithShortNames">
<LinkToGraph
:filter="[classObj.name]"
:graphType="PagePathName.CLASS"
:text="classObj.shortName"
></LinkToGraph>
</li>
</ul>
</div>
</template>
<script>
import {PagePathName} from '../url_processor.js';
import {LinkToGraph} from './link_to_graph.js';
import {shortenClassName} from '../chrome_hooks.js';
import LinkToGraph from './link_to_graph.vue';
const PackageDetailsPanel = {
components: {
'link-to-graph': LinkToGraph,
LinkToGraph,
},
props: ['selectedPackage'],
computed: {
PagePathName: () => PagePathName,
classesInSelectedPackage: function() {
return this.selectedPackage.classNames;
},
......@@ -22,28 +47,15 @@ const PackageDetailsPanel = {
}));
},
},
template: `
<div
v-if="this.selectedPackage !== null"
class="package-details-panel"
>
<link-to-graph
:filter="this.classesInSelectedPackage"
graphType=${PagePathName.CLASS}
text="Class graph with all classes in this package"
></link-to-graph>
<ul>
<li v-for="classObj in this.classesWithShortNames">
<link-to-graph
:filter="[classObj.name]"
graphType=${PagePathName.CLASS}
:text="classObj.shortName"
></link-to-graph>
</li>
</ul>
</div>`,
};
export {
PackageDetailsPanel,
};
export default PackageDetailsPanel;
</script>
<style scoped>
.package-details-panel {
max-height: 400px;
overflow: hidden;
overflow-y: scroll;
}
</style>
\ No newline at end of file
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
import {CUSTOM_EVENTS} from '../vue_custom_events.js';
<template>
<div id="page-container">
<div id="page-controls">
<GraphFilterInput
:node-ids="this.pageModel.getNodeIds()"
@[CUSTOM_EVENTS.FILTER_SUBMITTED]="this.addNodeToFilter"
></GraphFilterInput>
<GraphFilterItems
:node-filter-data="this.pageModel.nodeFilterData"
@[CUSTOM_EVENTS.FILTER_ELEMENT_CLICKED]="this.removeNodeFromFilter"
></GraphFilterItems>
<GraphInboundInput
:inbound-depth-data="this.pageModel.inboundDepthData"
@[CUSTOM_EVENTS.INBOUND_DEPTH_UPDATED]="this.setInboundDepth"
></GraphInboundInput>
<GraphOutboundInput
:outbound-depth-data="this.pageModel.outboundDepthData"
@[CUSTOM_EVENTS.OUTBOUND_DEPTH_UPDATED]="this.setOutboundDepth"
></GraphOutboundInput>
</div>
<div id="graph-and-node-details-container">
<GraphVisualization
:graph-data-update-ticker="this.graphDataUpdateTicker"
:page-model="this.pageModel"
@[CUSTOM_EVENTS.NODE_CLICKED]="graphNodeClicked"
></GraphVisualization>
<div id="node-details-container">
<GraphSelectedNodeDetails
:selected-node-details-data="this.pageModel.selectedNodeDetailsData"
@[CUSTOM_EVENTS.ADD_TO_FILTER_CLICKED]="addNodeToFilter"
@[CUSTOM_EVENTS.REMOVE_FROM_FILTER_CLICKED]="removeNodeFromFilter"
></GraphSelectedNodeDetails>
<PackageDetailsPanel
:selected-package=
"this.pageModel.selectedNodeDetailsData.selectedNode"
></PackageDetailsPanel>
</div>
</div>
<PageUrlGenerator
:page-path-name="this.pagePathName"
:node-filter-data="this.pageModel.nodeFilterData"
></PageUrlGenerator>
</div>
</template>
import {GraphFilterInput} from './graph_filter_input.js';
import {GraphFilterItems} from './graph_filter_items.js';
import {GraphInboundInput} from './graph_inbound_input.js';
import {GraphOutboundInput} from './graph_outbound_input.js';
import {GraphSelectedNodeDetails} from './graph_selected_node_details.js';
import {GraphVisualization} from './graph_visualization.js';
import {PackageDetailsPanel} from './package_details_panel.js';
import {PageUrlGenerator} from './page_url_generator.js';
<script>
import {CUSTOM_EVENTS} from '../vue_custom_events.js';
import {PagePathName, generateFilterFromUrl} from '../url_processor.js';
import {generateFilterFromUrl} from '../url_processor.js';
import {GraphNode} from '../graph_model.js';
import {PageModel} from '../page_model.js';
import {PagePathName} from '../url_processor.js';
import {parsePackageGraphModelFromJson} from '../process_graph_json.js';
import Vue from 'vue';
import GraphFilterInput from './graph_filter_input.vue';
import GraphFilterItems from './graph_filter_items.vue';
import GraphInboundInput from './graph_inbound_input.vue';
import GraphOutboundInput from './graph_outbound_input.vue';
import GraphSelectedNodeDetails from './graph_selected_node_details.vue';
import GraphVisualization from './graph_visualization.vue';
import PackageDetailsPanel from './package_details_panel.vue';
import PageUrlGenerator from './page_url_generator.vue';
const PackageGraphPage = Vue.component('package-graph-page', {
const PackageGraphPage = {
components: {
'graph-filter-input': GraphFilterInput,
'graph-filter-items': GraphFilterItems,
'graph-inbound-input': GraphInboundInput,
'graph-outbound-input': GraphOutboundInput,
'graph-selected-node-details': GraphSelectedNodeDetails,
'graph-visualization': GraphVisualization,
'package-details-panel': PackageDetailsPanel,
'page-url-generator': PageUrlGenerator,
GraphFilterInput,
GraphFilterItems,
GraphInboundInput,
GraphOutboundInput,
GraphSelectedNodeDetails,
GraphVisualization,
PackageDetailsPanel,
PageUrlGenerator,
},
props: ['graphJson'],
......@@ -57,6 +100,9 @@ const PackageGraphPage = Vue.component('package-graph-page', {
graphDataUpdateTicker: 0,
};
},
computed: {
CUSTOM_EVENTS: () => CUSTOM_EVENTS,
},
/**
* Parses out data from the current URL to initialize the visualization with.
*/
......@@ -127,51 +173,37 @@ const PackageGraphPage = Vue.component('package-graph-page', {
this.pageModel.selectedNodeDetailsData.selectedNode = node;
},
},
template: `
<div id="page-container">
<div id="page-controls">
<graph-filter-input
:node-ids="this.pageModel.getNodeIds()"
@${CUSTOM_EVENTS.FILTER_SUBMITTED}="this.addNodeToFilter"
></graph-filter-input>
<graph-filter-items
:node-filter-data="this.pageModel.nodeFilterData"
@${CUSTOM_EVENTS.FILTER_ELEMENT_CLICKED}="this.removeNodeFromFilter"
></graph-filter-items>
<graph-inbound-input
:inbound-depth-data="this.pageModel.inboundDepthData"
@${CUSTOM_EVENTS.INBOUND_DEPTH_UPDATED}="this.setInboundDepth"
></graph-inbound-input>
<graph-outbound-input
:outbound-depth-data="this.pageModel.outboundDepthData"
@${CUSTOM_EVENTS.OUTBOUND_DEPTH_UPDATED}="this.setOutboundDepth"
></graph-outbound-input>
</div>
<div id="graph-and-node-details-container">
<graph-visualization
:graph-data-update-ticker="this.graphDataUpdateTicker"
:page-model="this.pageModel"
@${CUSTOM_EVENTS.NODE_CLICKED}="graphNodeClicked"
></graph-visualization>
<div id="node-details-container">
<graph-selected-node-details
:selected-node-details-data="this.pageModel.selectedNodeDetailsData"
@${CUSTOM_EVENTS.ADD_TO_FILTER_CLICKED}="addNodeToFilter"
@${CUSTOM_EVENTS.REMOVE_FROM_FILTER_CLICKED}="removeNodeFromFilter"
></graph-selected-node-details>
<package-details-panel
:selected-package=
"this.pageModel.selectedNodeDetailsData.selectedNode"
></package-details-panel>
</div>
</div>
<page-url-generator
:page-path-name="this.pagePathName"
:node-filter-data="this.pageModel.nodeFilterData"
></page-url-generator>
</div>`,
});
export {
PackageGraphPage,
};
export default PackageGraphPage;
</script>
<style>
.user-input-group {
display: flex;
flex-direction: column;
}
</style>
<style scoped>
#page-container {
display: flex;
flex-direction: column;
}
#page-controls {
display: flex;
flex-direction: row;
height: 15vh;
}
#graph-and-node-details-container {
display: flex;
flex-direction: row;
}
#node-details-container {
display: flex;
flex-direction: column;
}
</style>
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<template>
<div class="url-generator">
<button @click="generateUrl">Generate Current URL</button>
<input type="text" readonly ref="input">
</div>
</template>
<script>
import {generateUrlFromFilter} from '../url_processor.js';
const PageUrlGenerator = {
......@@ -21,13 +29,14 @@ const PageUrlGenerator = {
this.$refs.input.select();
},
},
template: `
<div class="url-generator">
<button @click="generateUrl">Generate Current URL</button>
<input type="text" readonly ref="input">
</div>`,
};
export {
PageUrlGenerator,
};
export default PageUrlGenerator;
</script>
<style scoped>
.url-generator {
display: flex;
flex-direction: row;
}
</style>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment