web: diplay results in new /analysis route

This commit is contained in:
Soufiane Fariss
2024-08-15 16:10:41 +02:00
parent cf91503dc3
commit 8dcb7a473e
9 changed files with 181 additions and 163 deletions

View File

@@ -1,4 +1,5 @@
<template>
<Toast position="bottom-center" group="bc" />
<header>
<div class="wrapper">
<BannerHeader />

View File

@@ -71,22 +71,7 @@ const currentSource = ref("");
const functionCapabilities = ref([]);
onMounted(() => {
const cacheKey = "functionCapabilities";
let cachedData = sessionStorage.getItem(cacheKey);
if (cachedData) {
// If the data is already in sessionStorage, parse it and use it
functionCapabilities.value = JSON.parse(cachedData);
} else {
// Parse function capabilities and cache the result in sessionStorage
functionCapabilities.value = parseFunctionCapabilities(props.data);
try {
sessionStorage.setItem(cacheKey, JSON.stringify(functionCapabilities.value));
} catch (e) {
console.warn("Failed to store parsed data in sessionStorage:", e);
// If storing fails (e.g., due to storage limits), we can still continue with the parsed data
}
}
functionCapabilities.value = parseFunctionCapabilities(props.data);
});
/*

View File

@@ -7,7 +7,7 @@
filterMode="lenient"
sortField="pid"
:sortOrder="1"
rowHover="true"
:rowHover="true"
>
<Column field="processname" header="Process" expander>
<template #body="slotProps">

View File

@@ -156,8 +156,6 @@
</template>
</ContextMenu>
<Toast />
<!-- Source code dialog -->
<Dialog v-model:visible="sourceDialogVisible" style="width: 50vw">
<highlightjs autodetect :code="currentSource" />
@@ -325,23 +323,7 @@ const showSource = (source) => {
};
onMounted(() => {
const cacheKey = "ruleMatches";
const cachedData = sessionStorage.getItem(cacheKey);
if (cachedData) {
// If cached data exists, parse and use it
treeData.value = JSON.parse(cachedData);
} else {
// If no cached data, parse the rules and store in sessionStorage
treeData.value = parseRules(props.data.rules, props.data.meta.flavor, props.data.meta.analysis.layout);
// Store the parsed data in sessionStorage
try {
sessionStorage.setItem(cacheKey, JSON.stringify(treeData.value));
} catch (e) {
console.warn("Failed to store parsed data in sessionStorage:", e);
// If storing fails (e.g., due to storage limits), we can still continue with the parsed data
}
}
treeData.value = parseRules(props.data.rules, props.data.meta.flavor, props.data.meta.analysis.layout);
});
</script>

View File

@@ -1,11 +1,8 @@
import { ref, readonly } from "vue";
import { useToast } from "primevue/usetoast";
import { isGzipped, decompressGzip, readFileAsText } from "@/utils/fileUtils";
export function useRdocLoader() {
const toast = useToast();
const rdocData = ref(null);
const isValidVersion = ref(false);
const MIN_SUPPORTED_VERSION = "7.0.0";
/**
@@ -47,6 +44,14 @@ export function useRdocLoader() {
throw new Error(`HTTP error! status: ${response.status}`);
}
data = await response.json();
} else if (source instanceof File) {
let fileContent;
if (await isGzipped(source)) {
fileContent = await decompressGzip(source);
} else {
fileContent = await readFileAsText(source);
}
data = JSON.parse(fileContent);
} else if (typeof source === "object") {
// Direct JSON object (Preview options)
data = source;
@@ -55,8 +60,6 @@ export function useRdocLoader() {
}
if (checkVersion(data)) {
rdocData.value = data;
isValidVersion.value = true;
toast.add({
severity: "success",
summary: "Success",
@@ -64,9 +67,7 @@ export function useRdocLoader() {
life: 3000,
group: "bc" // bottom-center
});
} else {
rdocData.value = null;
isValidVersion.value = false;
return data;
}
} catch (error) {
console.error("Error loading JSON:", error);
@@ -78,11 +79,10 @@ export function useRdocLoader() {
group: "bc" // bottom-center
});
}
return null;
};
return {
rdocData: readonly(rdocData),
isValidVersion: readonly(isValidVersion),
loadRdoc
};
}

View File

@@ -1,6 +1,9 @@
import { createRouter, createWebHashHistory } from "vue-router";
import ImportView from "../views/ImportView.vue";
import NotFoundView from "../views/NotFoundView.vue";
import ImportView from "@/views/ImportView.vue";
import NotFoundView from "@/views/NotFoundView.vue";
import AnalysisView from "@/views/AnalysisView.vue";
import { rdocStore } from "@/store/rdocStore";
const router = createRouter({
history: createWebHashHistory(import.meta.env.BASE_URL),
@@ -10,6 +13,20 @@ const router = createRouter({
name: "home",
component: ImportView
},
{
path: "/analysis",
name: "analysis",
component: AnalysisView,
beforeEnter: (to, from, next) => {
if (rdocStore.data.value === null) {
// No rdoc loaded, redirect to home page
next({ name: "home" });
} else {
// rdoc is loaded, proceed to analysis page
next();
}
}
},
// 404 Route - This should be the last route
{
path: "/:pathMatch(.*)*",

View File

@@ -0,0 +1,11 @@
import { ref } from "vue";
export const rdocStore = {
data: ref(null),
setData(newData) {
this.data.value = newData;
},
clearData() {
this.data.value = null;
}
};

View File

@@ -0,0 +1,74 @@
<template>
<MetadataPanel :data="doc" />
<SettingsPanel
:flavor="doc.meta.flavor"
:library-rule-matches-count="libraryRuleMatchesCount"
@update:show-capabilities-by-function-or-process="updateShowCapabilitiesByFunctionOrProcess"
@update:show-library-rules="updateShowLibraryRules"
@update:show-namespace-chart="updateShowNamespaceChart"
@update:show-column-filters="updateShowColumnFilters"
/>
<RuleMatchesTable
v-if="!showCapabilitiesByFunctionOrProcess && !showNamespaceChart"
:data="doc"
:show-library-rules="showLibraryRules"
:show-column-filters="showColumnFilters"
/>
<FunctionCapabilities
v-if="doc.meta.flavor === 'static' && showCapabilitiesByFunctionOrProcess && !showNamespaceChart"
:data="doc"
:show-library-rules="showLibraryRules"
/>
<ProcessCapabilities
v-else-if="doc.meta.flavor === 'dynamic' && showCapabilitiesByFunctionOrProcess && !showNamespaceChart"
:data="doc"
:show-capabilities-by-process="showCapabilitiesByFunctionOrProcess"
:show-library-rules="showLibraryRules"
/>
<NamespaceChart v-else-if="showNamespaceChart" :data="doc" />
</template>
<script setup>
import { ref, computed } from "vue";
// Componenets
import MetadataPanel from "@/components/MetadataPanel.vue";
import SettingsPanel from "@/components/SettingsPanel.vue";
import RuleMatchesTable from "@/components/RuleMatchesTable.vue";
import FunctionCapabilities from "@/components/FunctionCapabilities.vue";
import ProcessCapabilities from "@/components/ProcessCapabilities.vue";
import NamespaceChart from "@/components/NamespaceChart.vue";
// Import loaded rdoc
import { rdocStore } from "@/store/rdocStore";
const doc = rdocStore.data.value;
// Viewing options
const showCapabilitiesByFunctionOrProcess = ref(false);
const showLibraryRules = ref(false);
const showNamespaceChart = ref(false);
const showColumnFilters = ref(false);
// Count library rules
const libraryRuleMatchesCount = computed(() => {
if (!doc || !doc.rules) return 0;
return Object.values(rdocStore.data.value.rules).filter((rule) => rule.meta.lib).length;
});
// Event handlers to update variables
const updateShowCapabilitiesByFunctionOrProcess = (value) => {
showCapabilitiesByFunctionOrProcess.value = value;
};
const updateShowLibraryRules = (value) => {
showLibraryRules.value = value;
};
const updateShowNamespaceChart = (value) => {
showNamespaceChart.value = value;
};
const updateShowColumnFilters = (value) => {
showColumnFilters.value = value;
};
</script>

View File

@@ -1,130 +1,78 @@
<template>
<DescriptionPanel />
<UploadOptions
@load-from-local="loadFromLocal"
@load-from-url="loadFromURL"
@load-demo-static="loadDemoDataStatic"
@load-demo-dynamic="loadDemoDataDynamic"
/>
</template>
<script setup>
import { ref, computed, onMounted } from "vue";
import { watch } from "vue";
// componenets
import DescriptionPanel from "@/components/DescriptionPanel.vue";
import UploadOptions from "@/components/UploadOptions.vue";
import MetadataPanel from "@/components/MetadataPanel.vue";
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 demo data
import demoRdocStatic from "@testfiles/rd/al-khaser_x64.exe_.json";
import demoRdocDynamic from "@testfiles/rd/0000a65749f5902c4d82ffa701198038f0b4870b00a27cfca109f8f933476d82.json";
// import router utils
import { useRouter, useRoute } from "vue-router";
const router = useRouter();
const route = useRoute();
// import rdoc loader function
import { useRdocLoader } from "@/composables/useRdocLoader";
const { rdocData, isValidVersion, loadRdoc } = useRdocLoader();
const { loadRdoc } = useRdocLoader();
import { isGzipped, decompressGzip, readFileAsText } from "@/utils/fileUtils";
const showCapabilitiesByFunctionOrProcess = ref(false);
const showLibraryRules = ref(false);
const showNamespaceChart = ref(false);
const showColumnFilters = ref(false);
const libraryRuleMatchesCount = computed(() => {
if (!rdocData.value || !rdocData.value.rules) return 0;
return Object.values(rdocData.value.rules).filter((rule) => rule.meta.lib).length;
});
const updateShowCapabilitiesByFunctionOrProcess = (value) => {
showCapabilitiesByFunctionOrProcess.value = value;
};
const updateShowLibraryRules = (value) => {
showLibraryRules.value = value;
};
const updateShowNamespaceChart = (value) => {
showNamespaceChart.value = value;
};
const updateShowColumnFilters = (value) => {
showColumnFilters.value = value;
};
// import rdoc store
import { rdocStore } from "@/store/rdocStore";
const loadFromLocal = async (event) => {
const file = event.files[0];
let fileContent;
if (await isGzipped(file)) {
fileContent = await decompressGzip(file);
} else {
fileContent = await readFileAsText(file);
const result = await loadRdoc(event.files[0]);
if (result) {
rdocStore.setData(result);
router.push("/analysis");
}
const jsonData = JSON.parse(fileContent);
loadRdoc(jsonData);
};
const loadFromURL = (url) => {
loadRdoc(url);
};
const loadDemoDataStatic = () => {
loadRdoc(demoRdocStatic);
};
const loadDemoDataDynamic = () => {
loadRdoc(demoRdocDynamic);
};
onMounted(() => {
// Clear out sessionStorage to prevent stale data from being used
sessionStorage.clear();
// Check if the URL contains a rdoc parameter and load the data from that URL
const urlParams = new URLSearchParams(window.location.search);
const encodedRdocURL = urlParams.get("rdoc");
if (encodedRdocURL) {
const rdocURL = decodeURIComponent(encodedRdocURL);
loadFromURL(rdocURL);
const loadFromURL = async (url) => {
const result = await loadRdoc(url);
if (result) {
rdocStore.setData(result);
router.push({ name: "analysis", query: { rdoc: url } });
}
});
};
const loadDemoDataStatic = async () => {
const result = await loadRdoc(demoRdocStatic);
if (result) {
rdocStore.setData(demoRdocStatic);
router.push("/analysis");
}
};
const loadDemoDataDynamic = async () => {
const result = await loadRdoc(demoRdocDynamic);
if (result) {
rdocStore.setData(demoRdocDynamic);
router.push("/analysis");
}
};
// Watch for changes in the rdoc query parameter
watch(
() => route.query.rdoc,
(rdocURL) => {
if (rdocURL) {
// Clear the query parameter
router.replace({ query: {} });
loadFromURL(decodeURIComponent(rdocURL));
}
},
{ immediate: true }
);
</script>
<template>
<Panel v-if="!rdocData || !isValidVersion">
<DescriptionPanel />
<UploadOptions
@load-from-local="loadFromLocal"
@load-from-url="loadFromURL"
@load-demo-static="loadDemoDataStatic"
@load-demo-dynamic="loadDemoDataDynamic"
/>
</Panel>
<Toast position="bottom-center" group="bc" />
<template v-if="rdocData && isValidVersion">
<MetadataPanel :data="rdocData" />
<SettingsPanel
:flavor="rdocData.meta.flavor"
:library-rule-matches-count="libraryRuleMatchesCount"
@update:show-capabilities-by-function-or-process="updateShowCapabilitiesByFunctionOrProcess"
@update:show-library-rules="updateShowLibraryRules"
@update:show-namespace-chart="updateShowNamespaceChart"
@update:show-column-filters="updateShowColumnFilters"
/>
<RuleMatchesTable
v-if="!showCapabilitiesByFunctionOrProcess && !showNamespaceChart"
:data="rdocData"
:show-library-rules="showLibraryRules"
:show-column-filters="showColumnFilters"
/>
<FunctionCapabilities
v-if="rdocData.meta.flavor === 'static' && showCapabilitiesByFunctionOrProcess && !showNamespaceChart"
:data="rdocData"
:show-library-rules="showLibraryRules"
/>
<ProcessCapabilities
v-else-if="rdocData.meta.flavor === 'dynamic' && showCapabilitiesByFunctionOrProcess && !showNamespaceChart"
:data="rdocData"
:show-capabilities-by-process="showCapabilitiesByFunctionOrProcess"
:show-library-rules="showLibraryRules"
/>
<NamespaceChart v-else-if="showNamespaceChart" :data="rdocData" />
</template>
</template>