Skip to content

Commit

Permalink
feature: show namespace chart
Browse files Browse the repository at this point in the history
  • Loading branch information
fariss committed Aug 1, 2024
1 parent 4fe7f78 commit b229048
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 11 deletions.
6 changes: 6 additions & 0 deletions webui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions webui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"dependencies": {
"@highlightjs/vue-plugin": "^2.1.0",
"@primevue/themes": "^4.0.0-rc.2",
"plotly.js-dist": "^2.34.0",
"primeflex": "^3.3.1",
"primeicons": "^7.0.0",
"primevue": "^4.0.0-rc.2",
Expand Down
133 changes: 133 additions & 0 deletions webui/src/components/NamespaceChart.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<template>
<div ref="chartRef" class="namespace-chart"></div>
</template>

<script setup>
import { ref, onMounted, watch } from 'vue'
import Plotly from 'plotly.js-dist'
const props = defineProps({
data: {
type: Object,
required: true
}
})
const chartRef = ref(null)
const createSunburstData = (rules) => {
const data = {
ids: [],
labels: [],
parents: [],
values: []
}
const addNamespace = (namespace, value) => {
const parts = namespace.split('/')
let currentId = ''
let parent = ''
parts.forEach((part, index) => {
currentId = currentId ? `${currentId}/${part}` : part
if (!data.ids.includes(currentId)) {
data.ids.push(currentId)
data.labels.push(part)
data.parents.push(parent)
data.values.push(0)
}
const valueIndex = data.ids.indexOf(currentId)
data.values[valueIndex] += value
parent = currentId
})
return parent
}
Object.entries(rules).forEach(([ruleName, rule]) => {
if (rule.meta.lib) return // Skip library rules
const namespace = rule.meta.namespace || 'root'
const parent = addNamespace(namespace, rule.matches.length)
// Add the rule itself
data.ids.push(ruleName)
data.labels.push(rule.meta.name)
data.parents.push(parent)
data.values.push(rule.matches.length)
})
return data
}
const renderChart = () => {
if (!chartRef.value) return
const sunburstData = createSunburstData(props.data.rules)
const layout = {
margin: { l: 0, r: 0, b: 0, t: 0 },
sunburstcolorway: [
'#636efa',
'#EF553B',
'#00cc96',
'#ab63fa',
'#19d3f3',
'#e763fa',
'#FECB52',
'#FFA15A',
'#FF6692',
'#B6E880'
],
extendsunburstcolorway: true
}
const config = {
responsive: true
}
Plotly.newPlot(
chartRef.value,
[
{
type: 'sunburst',
ids: sunburstData.ids,
labels: sunburstData.labels,
parents: sunburstData.parents,
values: sunburstData.values,
outsidetextfont: { size: 20, color: '#377eb8' },
leaf: { opacity: 0.5 },
marker: { line: { width: 2 } },
branchvalues: 'total'
}
],
layout,
config
)
return sunburstData
}
onMounted(() => {
const data = renderChart()
console.log(data)
})
watch(
() => props.data,
() => {
renderChart()
},
{ deep: true }
)
</script>

<style scoped>
.namespace-chart {
width: 100%;
height: 600px;
}
</style>
28 changes: 20 additions & 8 deletions webui/src/components/SettingsPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,26 @@
v-model="showCapabilitiesByFunctionOrProcess"
inputId="showCapabilitiesByFunctionOrProcess"
:binary="true"
:disabled="showNamespaceChart"
/>
<label for="showCapabilitiesByFunctionOrProcess">{{ capabilitiesLabel }}</label>
</div>
<div class="flex flex-row align-items-center gap-2">
<Checkbox v-model="showLibraryRules" inputId="showLibraryRules" :binary="true" />
<Checkbox
v-model="showLibraryRules"
inputId="showLibraryRules"
:binary="true"
:disabled="showNamespaceChart"
/>
<label for="showLibraryRules">
<span v-if="libraryRuleMatchesCount > 1">
Show {{ libraryRuleMatchesCount }} library rule matches
</span>
<span v-if="libraryRuleMatchesCount > 1"> Show {{ libraryRuleMatchesCount }} library rule matches </span>
<span v-else>Show 1 library rule match</span>
</label>
</div>
<div class="flex flex-row align-items-center gap-2">
<Checkbox v-model="showNamespaceChart" inputId="showNamespaceChart" :binary="true" />
<label for="showNamespaceChart"> Show namespace chart </label>
</div>
</div>
</template>
</Card>
Expand All @@ -41,16 +49,16 @@ const props = defineProps({
const showCapabilitiesByFunctionOrProcess = ref(false)
const showLibraryRules = ref(false)
const showNamespaceChart = ref(false)
const emit = defineEmits([
'update:show-capabilities-by-function-or-process',
'update:show-library-rules'
'update:show-library-rules',
'update:show-namespace-chart'
])
const capabilitiesLabel = computed(() => {
return props.flavor === 'static'
? 'Show capabilities by function'
: 'Show capabilities by process'
return props.flavor === 'static' ? 'Show capabilities by function' : 'Show capabilities by process'
})
watch(showCapabilitiesByFunctionOrProcess, (newValue) => {
Expand All @@ -60,4 +68,8 @@ watch(showCapabilitiesByFunctionOrProcess, (newValue) => {
watch(showLibraryRules, (newValue) => {
emit('update:show-library-rules', newValue)
})
watch(showNamespaceChart, (newValue) => {
emit('update:show-namespace-chart', newValue)
})
</script>
14 changes: 11 additions & 3 deletions webui/src/views/ImportView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import RuleMatchesTable from '../components/RuleMatchesTable.vue'
import FunctionCapabilities from '../components/FunctionCapabilities.vue'
import ProcessCapabilities from '../components/ProcessCapabilities.vue'
import SettingsPanel from '../components/SettingsPanel.vue'
import NamespaceChart from '../components/NamespaceChart.vue'
import Toast from 'primevue/toast'
import demoRdocStatic from '../../../tests/data/rd/al-khaser_x64.exe_.json'
Expand All @@ -18,6 +19,7 @@ const { rdocData, isValidVersion, loadRdoc } = useRdocLoader()
const showCapabilitiesByFunctionOrProcess = ref(false)
const showLibraryRules = ref(false)
const showNamespaceChart = ref(true)
const flavor = computed(() => rdocData.value?.meta.flavor)
Expand All @@ -34,6 +36,10 @@ const updateShowLibraryRules = (value) => {
showLibraryRules.value = value
}
const updateShowNamespaceChart = (value) => {
showNamespaceChart.value = value
}
const loadFromLocal = (event) => {
const file = event.files[0]
loadRdoc(file)
Expand Down Expand Up @@ -79,23 +85,25 @@ onMounted(() => {
:library-rule-matches-count="libraryRuleMatchesCount"
@update:show-capabilities-by-function-or-process="updateShowCapabilitiesByFunctionOrProcess"
@update:show-library-rules="updateShowLibraryRules"
@update:show-namespace-chart="updateShowNamespaceChart"
/>
<RuleMatchesTable
v-if="!showCapabilitiesByFunctionOrProcess"
v-if="!showCapabilitiesByFunctionOrProcess && !showNamespaceChart"
:data="rdocData"
:show-library-rules="showLibraryRules"
/>
<FunctionCapabilities
v-if="flavor === 'static' && showCapabilitiesByFunctionOrProcess"
v-if="flavor === 'static' && showCapabilitiesByFunctionOrProcess && !showNamespaceChart"
:data="rdocData"
:show-library-rules="showLibraryRules"
/>
<ProcessCapabilities
v-else-if="flavor === 'dynamic' && showCapabilitiesByFunctionOrProcess"
v-else-if="flavor === 'dynamic' && showCapabilitiesByFunctionOrProcess && !showNamespaceChart"
:data="rdocData"
:show-capabilities-by-process="showCapabilitiesByFunctionOrProcess"
:show-library-rules="showLibraryRules"
/>
<NamespaceChart v-else-if="showNamespaceChart && !showCapabilitiesByFunctionOrProcess" :data="rdocData" />
</template>
</template>

0 comments on commit b229048

Please sign in to comment.