Add treeView to visualize changes in transaction
Test: N/A Change-Id: Ida61733f1cc73b3bee4d3963b1bc17dfe2b626fc
This commit is contained in:
@@ -57,7 +57,7 @@ import LocalStore from './localstore.js'
|
||||
import DataAdb from './DataAdb.vue'
|
||||
import FileType from './mixins/FileType.js'
|
||||
|
||||
const APP_NAME = "Winscope";
|
||||
const APP_NAME = "Winscope"
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
:filter="hierarchyFilter"
|
||||
:flattened="store.flattened"
|
||||
:items-clickable="true"
|
||||
:useGlobalCollapsedState="true"
|
||||
ref="hierarchy"
|
||||
/>
|
||||
</md-card>
|
||||
@@ -52,6 +53,7 @@
|
||||
:item="selectedTree"
|
||||
:filter="propertyFilter"
|
||||
:collapseChildren="true"
|
||||
:useGlobalCollapsedState="true"
|
||||
/>
|
||||
</md-card>
|
||||
</md-card-content>
|
||||
|
||||
@@ -31,7 +31,11 @@
|
||||
</md-table-toolbar>
|
||||
|
||||
<div class="scrollBody" ref="tableBody">
|
||||
<md-table-row v-for="transaction in filteredData" :key="transaction.timestamp">
|
||||
<md-table-row
|
||||
v-for="transaction in filteredData"
|
||||
:key="transaction.timestamp"
|
||||
@click="transactionSelected(transaction)"
|
||||
>
|
||||
<md-table-cell>{{transaction.time}}</md-table-cell>
|
||||
|
||||
<div v-if="transaction.type == 'transaction'">
|
||||
@@ -49,9 +53,24 @@
|
||||
</div>
|
||||
|
||||
</md-table>
|
||||
|
||||
<md-card class="changes">
|
||||
<md-content md-tag="md-toolbar" md-elevation="0" class="card-toolbar md-transparent md-dense">
|
||||
<h2 class="md-title" style="flex: 1">Changes</h2>
|
||||
</md-content>
|
||||
<div class="changes-content">
|
||||
<tree-view :item="selectedTree" :useGlobalCollapsedState="true" />
|
||||
</div>
|
||||
</md-card>
|
||||
|
||||
</md-card-content>
|
||||
</template>
|
||||
<script>
|
||||
import TreeView from './TreeView.vue';
|
||||
|
||||
import { transform_json } from './transform.js';
|
||||
import { stableIdCompatibilityFixup } from './utils/utils.js'
|
||||
|
||||
export default {
|
||||
name: 'transactionsview',
|
||||
props: ['data'],
|
||||
@@ -71,6 +90,7 @@ export default {
|
||||
transactionTypes: Array.from(transactionTypes),
|
||||
selectedTransactionTypes: [],
|
||||
searchInput: "",
|
||||
selectedTree: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -95,6 +115,47 @@ export default {
|
||||
|
||||
},
|
||||
methods: {
|
||||
removeNullFields(changeObject) {
|
||||
for (const key in changeObject) {
|
||||
if (changeObject[key] === null) {
|
||||
delete changeObject[key];
|
||||
}
|
||||
}
|
||||
|
||||
return changeObject;
|
||||
},
|
||||
transactionSelected(transaction) {
|
||||
let obj = this.removeNullFields(transaction.obj);
|
||||
let name = transaction.type;
|
||||
|
||||
if (transaction.type == "transaction") {
|
||||
name = "changes";
|
||||
obj = {};
|
||||
|
||||
const [surfaceChanges, displayChanges] =
|
||||
this.aggregateTransactions(transaction.transactions);
|
||||
|
||||
for (const changeId in surfaceChanges) {
|
||||
this.removeNullFields(surfaceChanges[changeId]);
|
||||
}
|
||||
for (const changeId in displayChanges) {
|
||||
this.removeNullFields(displayChanges[changeId]);
|
||||
}
|
||||
|
||||
if (Object.keys(surfaceChanges).length > 0) {
|
||||
obj.surfaceChanges = surfaceChanges;
|
||||
}
|
||||
|
||||
if (Object.keys(displayChanges).length > 0) {
|
||||
obj.displayChanges = displayChanges;
|
||||
}
|
||||
}
|
||||
|
||||
const transactionUnique = transaction.timestamp;
|
||||
this.selectedTree = transform_json(obj, name, transactionUnique, {
|
||||
formatter: () => {}
|
||||
});
|
||||
},
|
||||
filterTransactions(condition) {
|
||||
return (entry) => {
|
||||
if (entry.type == "transaction") {
|
||||
@@ -110,7 +171,27 @@ export default {
|
||||
}
|
||||
};
|
||||
},
|
||||
summarizeTranscations(transactions) {
|
||||
mergeChanges(a, b) {
|
||||
const res = {};
|
||||
|
||||
for (const key in a) {
|
||||
if (a[key] !== null && a.hasOwnProperty(key)) {
|
||||
res[key] = a[key];
|
||||
}
|
||||
}
|
||||
|
||||
for (const key in b) {
|
||||
if (b[key] !== null && key !== 'id' && b.hasOwnProperty(key)) {
|
||||
if (res.hasOwnProperty(key)) {
|
||||
throw new Error(`Merge failed – key '${key}' already present`);
|
||||
}
|
||||
res[key] = b[key];
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
aggregateTransactions(transactions) {
|
||||
const surfaceChanges = {};
|
||||
const displayChanges = {};
|
||||
|
||||
@@ -120,12 +201,12 @@ export default {
|
||||
switch (transaction.type) {
|
||||
case "surfaceChange":
|
||||
surfaceChanges[obj.id] =
|
||||
Object.assign(surfaceChanges[obj.id] ?? {}, obj);
|
||||
this.mergeChanges(surfaceChanges[obj.id] ?? {}, obj);
|
||||
break;
|
||||
|
||||
case "displayChange":
|
||||
displayChanges[obj.id] =
|
||||
Object.assign(displayChanges[obj.id] ?? {}, obj);
|
||||
this.mergeChanges(displayChanges[obj.id] ?? {}, obj);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -133,31 +214,50 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
const summary = [];
|
||||
return [surfaceChanges, displayChanges];
|
||||
},
|
||||
summarizeTranscations(transactions) {
|
||||
const ids = {
|
||||
"surfaceChange": new Set(),
|
||||
"displayChange": new Set(),
|
||||
};
|
||||
|
||||
const surfaceChangesId = Object.keys(surfaceChanges);
|
||||
if (surfaceChangesId.length > 0) {
|
||||
summary.push(`surfaceChanges: ${surfaceChangesId.join(', ')}`);
|
||||
for (const transaction of transactions) {
|
||||
ids[transaction.type].add(transaction.obj.id);
|
||||
}
|
||||
|
||||
const displayChangesIds = Object.keys(displayChanges);
|
||||
if (displayChangesIds.length > 0) {
|
||||
summary.push(`displayChanges: ${displayChangesIds.join(', ')}`);
|
||||
const summary = [];
|
||||
|
||||
if (ids.surfaceChange.size > 0) {
|
||||
summary.push(`surfaceChanges: ${[...ids.surfaceChange].join(', ')}`);
|
||||
}
|
||||
|
||||
if (ids.displayChange.size > 0) {
|
||||
summary.push(`displayChanges: ${[...ids.displayChange].join(', ')}`);
|
||||
}
|
||||
|
||||
return summary.join(" | ");
|
||||
}
|
||||
},
|
||||
},
|
||||
components: {
|
||||
'tree-view': TreeView,
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
/* .transaction-table {
|
||||
width: 100%;
|
||||
} */
|
||||
.container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.transaction-table,
|
||||
.changes {
|
||||
flex: 1;
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
.scrollBody {
|
||||
/* width: 100%; */
|
||||
max-height: 75vh;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
:initial-depth="depth + 1"
|
||||
:collapse="collapseChildren"
|
||||
:collapseChildren="collapseChildren"
|
||||
:useGlobalCollapsedState="useGlobalCollapsedState"
|
||||
ref="children"
|
||||
/>
|
||||
</div>
|
||||
@@ -98,6 +99,14 @@ export default {
|
||||
"initial-depth",
|
||||
"collapse",
|
||||
"collapseChildren",
|
||||
// Allows collapse state to be tracked by Vuex so that collapse state of
|
||||
// items with same stableId can remain consisten accross time and easily
|
||||
// toggled from anywhere in the app.
|
||||
// Should be true if you are using the same TreeView to display multiple
|
||||
// trees throughout the component's lifetime to make sure same nodes are
|
||||
// toggled when switching back and forth between trees.
|
||||
// If true, requires all nodes in tree to have a stableId.
|
||||
"useGlobalCollapsedState",
|
||||
],
|
||||
data() {
|
||||
const isCollapsedByDefault = this.collapse ?? false;
|
||||
@@ -106,14 +115,19 @@ export default {
|
||||
isChildSelected: false,
|
||||
clickTimeout: null,
|
||||
isCollapsedByDefault,
|
||||
localCollapsedState: isCollapsedByDefault,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
setCollapseValue(isCollapsed) {
|
||||
if (this.useGlobalCollapsedState) {
|
||||
this.$store.commit('setCollapsedState', {
|
||||
item: this.item,
|
||||
isCollapsed,
|
||||
});
|
||||
} else {
|
||||
this.localCollapsedState = isCollapsed;
|
||||
}
|
||||
},
|
||||
toggleTree() {
|
||||
this.setCollapseValue(!this.isCollapsed);
|
||||
@@ -236,8 +250,12 @@ export default {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.useGlobalCollapsedState) {
|
||||
return this.$store.getters.collapsedStateStoreFor(this.item) ??
|
||||
this.isCollapsedByDefault;
|
||||
}
|
||||
|
||||
return this.localCollapsedState;
|
||||
},
|
||||
isSelected() {
|
||||
return this.selected === this.item;
|
||||
|
||||
Reference in New Issue
Block a user