- {{ title }}
+
+
+ {{ getFileDisplayName(file) }}
+
-
-
-
+
+
+
-
-
-
+
+ {{ index + 1 }} |
+
+
+
+ |
+
+
+
-
Empty File
+
Empty File
@@ -55,120 +46,87 @@
+
+
diff --git a/report-viewer/src/components/DistributionDiagram.vue b/report-viewer/src/components/DistributionDiagram.vue
index c53e51433..c6ca774d5 100644
--- a/report-viewer/src/components/DistributionDiagram.vue
+++ b/report-viewer/src/components/DistributionDiagram.vue
@@ -22,6 +22,11 @@ const props = defineProps({
distribution: {
type: Object as PropType
,
required: true
+ },
+ xScale: {
+ type: String as PropType<'linear' | 'logarithmic'>,
+ required: false,
+ default: 'linear'
}
})
@@ -69,9 +74,25 @@ const options = computed(() => {
x: {
//Highest count of submissions in a percentage range. We set the diagrams maximum shown value to maxVal + 5,
//otherwise maximum is set to the highest count of submissions and is one bar always reaches the end.
- suggestedMax: maxVal.value + 5,
+ suggestedMax:
+ props.xScale === 'linear'
+ ? maxVal.value + 5
+ : 10 ** Math.ceil(Math.log10(maxVal.value + 5)),
+ type: props.xScale,
ticks: {
- color: graphColors.ticksAndFont.value
+ // ensures that in log mode tick labels are not overlappein
+ minRotation: props.xScale === 'logarithmic' ? 30 : 0,
+ autoSkipPadding: 10,
+ color: graphColors.ticksAndFont.value,
+ // ensures that in log mode ticks are placed evenly appart
+ callback: function (value: any) {
+ if (props.xScale === 'logarithmic' && (value + '').match(/1(0)*[^1-9.]/)) {
+ return value
+ }
+ if (props.xScale !== 'logarithmic') {
+ return value
+ }
+ }
},
grid: {
color: graphColors.gridLines.value
diff --git a/report-viewer/src/components/FilesContainer.vue b/report-viewer/src/components/FilesContainer.vue
index 7fb2952bb..f9fb206dc 100644
--- a/report-viewer/src/components/FilesContainer.vue
+++ b/report-viewer/src/components/FilesContainer.vue
@@ -4,22 +4,21 @@
- Files of {{ anonymous ? filesOwnerDefault : filesOwner }}:
+ Files of
+ {{ fileOwnerDisplayName }}:
$emit('line-selected', match)"
class="mt-1"
/>
@@ -28,107 +27,63 @@
-
-
+defineExpose({
+ scrollTo
+})
+
diff --git a/report-viewer/src/components/LineOfCode.vue b/report-viewer/src/components/LineOfCode.vue
deleted file mode 100644
index 074872e26..000000000
--- a/report-viewer/src/components/LineOfCode.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
{{ lineNumber }} {{ text }}
-
-
-
-
-
-
diff --git a/report-viewer/src/components/MatchList.vue b/report-viewer/src/components/MatchList.vue
index a6f620f6d..aeb218112 100644
--- a/report-viewer/src/components/MatchList.vue
+++ b/report-viewer/src/components/MatchList.vue
@@ -12,7 +12,7 @@
:style="{ background: match.color }"
v-for="[index, match] in matches?.entries()"
v-bind:key="index"
- @click="$emit('matchSelected', $event, match)"
+ @click="$emit('matchSelected', match)"
>
{{ getFileName(match.firstFile) }} - {{ getFileName(match.secondFile) }}: {{ match.tokens }}
diff --git a/report-viewer/src/model/Comparison.ts b/report-viewer/src/model/Comparison.ts
index 650d5daf5..6fafbc60f 100644
--- a/report-viewer/src/model/Comparison.ts
+++ b/report-viewer/src/model/Comparison.ts
@@ -1,6 +1,6 @@
import type { Match } from './Match'
-import type { SubmissionFile } from './SubmissionFile'
-import type { MatchInSingleFile } from './MatchInSingleFile'
+import type { SubmissionFile } from '@/stores/state'
+import { MatchInSingleFile } from './MatchInSingleFile'
import type { MetricType } from './MetricType'
/**
@@ -10,16 +10,16 @@ export class Comparison {
private readonly _firstSubmissionId: string
private readonly _secondSubmissionId: string
private readonly _similarities: Record
- private _filesOfFirstSubmission: Map
- private _filesOfSecondSubmission: Map
+ private _filesOfFirstSubmission: SubmissionFile[]
+ private _filesOfSecondSubmission: SubmissionFile[]
private _allMatches: Array
constructor(
firstSubmissionId: string,
secondSubmissionId: string,
similarities: Record,
- filesOfFirstSubmission: Map,
- filesOfSecondSubmission: Map,
+ filesOfFirstSubmission: SubmissionFile[],
+ filesOfSecondSubmission: SubmissionFile[],
allMatches: Array
) {
this._firstSubmissionId = firstSubmissionId
@@ -33,14 +33,14 @@ export class Comparison {
/**
* @return Map of all files of the first submission
*/
- get filesOfFirstSubmission(): Map {
+ get filesOfFirstSubmission(): SubmissionFile[] {
return this._filesOfFirstSubmission
}
/**
* @return Map of all files of the second submission
*/
- get filesOfSecondSubmission(): Map {
+ get filesOfSecondSubmission(): SubmissionFile[] {
return this._filesOfSecondSubmission
}
@@ -88,34 +88,14 @@ export class Comparison {
private groupMatchesByFileName(index: 1 | 2): Map> {
const acc = new Map>()
- this.allMatches.forEach((val) => {
- const name = index === 1 ? val.firstFile : val.secondFile
+ this._allMatches.forEach((val) => {
+ const name = index === 1 ? (val.firstFile as string) : (val.secondFile as string)
if (!acc.get(name)) {
acc.set(name, [])
}
- if (index === 1) {
- const newVal: MatchInSingleFile = {
- start: val.startInFirst,
- end: val.endInFirst,
- linked_panel: 2,
- linked_file: val.secondFile,
- linked_line: val.startInSecond,
- color: val.color
- }
- acc.get(name)?.push(newVal)
- } else {
- const newVal: MatchInSingleFile = {
- start: val.startInSecond,
- end: val.endInSecond,
- linked_panel: 1,
- linked_file: val.firstFile,
- linked_line: val.startInFirst,
- color: val.color
- }
- acc.get(name)?.push(newVal)
- }
+ acc.get(name)?.push(new MatchInSingleFile(val, index))
})
return acc
}
diff --git a/report-viewer/src/model/Language.ts b/report-viewer/src/model/Language.ts
new file mode 100644
index 000000000..a9b9b91f8
--- /dev/null
+++ b/report-viewer/src/model/Language.ts
@@ -0,0 +1,101 @@
+/**
+ * Enum for the language parsers JPlag supports
+ */
+enum ParserLanguage {
+ JAVA = 'Javac based AST plugin',
+ PYTHON = 'Python3 Parser',
+ CPP = 'C/C++ Scanner [basic markup]',
+ CPP2 = 'C/C++ Parser',
+ C_SHARP = 'C# 6 Parser',
+ EMF_METAMODEL_DYNAMIC = 'emf-dynamic',
+ EMF_METAMODEL = 'EMF metamodel',
+ EMF_MODEL = 'EMF models (dynamically created token set)',
+ GO = 'Go Parser',
+ KOTLIN = 'Kotlin Parser',
+ R_LANG = 'R Parser',
+ RUST = 'Rust Language Module',
+ SCALA = 'Scala parser',
+ SCHEME = 'SchemeR4RS Parser [basic markup]',
+ SWIFT = 'Swift Parser',
+ TEXT = 'Text Parser (naive)',
+ SCXML = 'SCXML (Statechart XML)',
+ LLVM = 'LLVMIR Parser'
+}
+
+/**
+ * Gets the LanguageParser enum value for the given language
+ * @param language String representation of language the files were parsed with
+ * @returns The LanguageParser enum value
+ */
+function getLanguageParser(language: string): ParserLanguage {
+ for (const key in ParserLanguage) {
+ if (ParserLanguage[key as keyof typeof ParserLanguage] === language) {
+ return ParserLanguage[key as keyof typeof ParserLanguage]
+ }
+ }
+
+ throw new Error(`Language ${language} not found`)
+}
+
+/**
+ * Enum for the highlight.js languages
+ * The strings are the names of the languages in highlight.js (https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md)
+ */
+enum HighlightLanguage {
+ JAVA = 'java',
+ PYTHON = 'python',
+ CPP = 'cpp',
+ C_SHARP = 'csharp',
+ XML = 'xml',
+ GO = 'go',
+ KOTLIN = 'kotlin',
+ R_LANG = 'r',
+ RUST = 'rust',
+ SCALA = 'scala',
+ SCHEME = 'scheme',
+ SWIFT = 'swift',
+ TEXT = 'text'
+}
+
+/**
+ * Gets the highlight.js language for the given language
+ * @param language Language the files were parsed with
+ * @returns The language for highlight.js
+ */
+function getHighlightLanguage(language: ParserLanguage | undefined): HighlightLanguage {
+ switch (language) {
+ case ParserLanguage.PYTHON:
+ return HighlightLanguage.PYTHON
+ case ParserLanguage.CPP:
+ case ParserLanguage.CPP2:
+ return HighlightLanguage.CPP
+ case ParserLanguage.C_SHARP:
+ return HighlightLanguage.C_SHARP
+ case ParserLanguage.EMF_METAMODEL:
+ case ParserLanguage.EMF_METAMODEL_DYNAMIC:
+ case ParserLanguage.EMF_MODEL:
+ case ParserLanguage.SCXML:
+ return HighlightLanguage.XML
+ case ParserLanguage.GO:
+ return HighlightLanguage.GO
+ case ParserLanguage.KOTLIN:
+ return HighlightLanguage.KOTLIN
+ case ParserLanguage.R_LANG:
+ return HighlightLanguage.R_LANG
+ case ParserLanguage.RUST:
+ return HighlightLanguage.RUST
+ case ParserLanguage.SCALA:
+ return HighlightLanguage.SCALA
+ case ParserLanguage.SCHEME:
+ return HighlightLanguage.SCHEME
+ case ParserLanguage.SWIFT:
+ return HighlightLanguage.SWIFT
+ case ParserLanguage.TEXT:
+ return HighlightLanguage.TEXT
+ case ParserLanguage.JAVA:
+ default:
+ return HighlightLanguage.JAVA
+ }
+}
+
+export { ParserLanguage, getLanguageParser, HighlightLanguage, getHighlightLanguage }
diff --git a/report-viewer/src/model/MatchInSingleFile.ts b/report-viewer/src/model/MatchInSingleFile.ts
index dc8a129ad..bcaae43c0 100644
--- a/report-viewer/src/model/MatchInSingleFile.ts
+++ b/report-viewer/src/model/MatchInSingleFile.ts
@@ -1,17 +1,43 @@
+import type { Match } from './Match'
+
/**
* Describes a match in a single file.
- * @property start - Starting line of the match.
- * @property end - Ending line of the match.
- * @property linked_panel - The files container containing the file of the second submission to which this is matched.
- * @property linked_file - The file name containing the same match in the second submission.
- * @property linked_line - The start of the match in the second file.
- * @property color - Color of the match.
*/
-export type MatchInSingleFile = {
- start: number
- end: number
- linked_panel: number
- linked_file: string
- linked_line: number
- color: string
+export class MatchInSingleFile {
+ private readonly _match: Match
+ private readonly _index: 1 | 2
+
+ constructor(match: Match, index: 1 | 2) {
+ this._match = match
+ this._index = index
+ }
+
+ /**
+ * The match object.
+ */
+ get match(): Match {
+ return this._match
+ }
+
+ /**
+ * The start line of the match.
+ */
+ get start(): number {
+ if (this._index === 1) {
+ return this._match.startInFirst
+ } else {
+ return this._match.startInSecond
+ }
+ }
+
+ /**
+ * The end line of the match.
+ */
+ get end(): number {
+ if (this._index === 1) {
+ return this._match.endInFirst
+ } else {
+ return this._match.endInSecond
+ }
+ }
}
diff --git a/report-viewer/src/model/Overview.ts b/report-viewer/src/model/Overview.ts
index f4d73e0b3..63b705dde 100644
--- a/report-viewer/src/model/Overview.ts
+++ b/report-viewer/src/model/Overview.ts
@@ -2,6 +2,7 @@ import type { Distribution } from './Distribution'
import type { Cluster } from '@/model/Cluster'
import type { ComparisonListElement } from './ComparisonListElement'
import type { MetricType } from './MetricType'
+import type { ParserLanguage } from './Language'
/**
* Model of the Overview file generated by JPlag
@@ -9,7 +10,7 @@ import type { MetricType } from './MetricType'
export class Overview {
private readonly _submissionFolderPath: Array
private readonly _baseCodeFolderPath: string
- private readonly _language: string
+ private readonly _language: ParserLanguage
private readonly _fileExtensions: Array
private readonly _matchSensitivity: number
private readonly _dateOfExecution: string
@@ -22,7 +23,7 @@ export class Overview {
constructor(
submissionFolderPath: Array,
baseCodeFolderPath: string,
- language: string,
+ language: ParserLanguage,
fileExtensions: Array,
matchSensitivity: number,
dateOfExecution: string,
diff --git a/report-viewer/src/model/SubmissionFile.ts b/report-viewer/src/model/SubmissionFile.ts
deleted file mode 100644
index 26f38667f..000000000
--- a/report-viewer/src/model/SubmissionFile.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-/**
- * File in a submission. Used in the comparison view.
- * @property lines - Code lines of the file.
- * @property collapsed - Indicates whether the file is displayed or not.
- */
-export type SubmissionFile = {
- lines: Array
- collapsed: boolean
-}
diff --git a/report-viewer/src/model/factories/ComparisonFactory.ts b/report-viewer/src/model/factories/ComparisonFactory.ts
index e558f791a..19a1cd4e1 100644
--- a/report-viewer/src/model/factories/ComparisonFactory.ts
+++ b/report-viewer/src/model/factories/ComparisonFactory.ts
@@ -1,6 +1,5 @@
import { Comparison } from '../Comparison'
import type { Match } from '../Match'
-import type { SubmissionFile } from '../SubmissionFile'
import { store } from '@/stores/store'
import { generateColors } from '@/utils/ColorUtils'
import slash from 'slash'
@@ -14,6 +13,7 @@ export class ComparisonFactory extends BaseFactory {
public static getComparison(id1: string, id2: string) {
const filePath = store().getComparisonFileName(id1, id2)
if (!filePath) {
+ console.log(filePath)
throw new Error('Comparison file not specified')
}
@@ -34,9 +34,6 @@ export class ComparisonFactory extends BaseFactory {
const filesOfFirstSubmission = store().filesOfSubmission(firstSubmissionId)
const filesOfSecondSubmission = store().filesOfSubmission(secondSubmissionId)
- const filesOfFirstConverted = this.convertToSubmissionFileList(filesOfFirstSubmission)
- const filesOfSecondConverted = this.convertToSubmissionFileList(filesOfSecondSubmission)
-
const matches = json.matches as Array>
const matchSaturation = 0.8
@@ -49,8 +46,8 @@ export class ComparisonFactory extends BaseFactory {
firstSubmissionId,
secondSubmissionId,
this.extractSimilarities(json),
- filesOfFirstConverted,
- filesOfSecondConverted,
+ filesOfFirstSubmission,
+ filesOfSecondSubmission,
coloredMatches
)
}
@@ -84,25 +81,6 @@ export class ComparisonFactory extends BaseFactory {
return similarities
}
- private static convertToSubmissionFileList(
- files: Array<{ name: string; value: string }>
- ): Map {
- const map = new Map()
- files.forEach((val) => {
- if (!map.get(val.name)) {
- map.set(val.name as string, {
- lines: [],
- collapsed: false
- })
- }
- map.set(val.name as string, {
- lines: val.value.split(/\r?\n/),
- collapsed: false
- })
- })
- return map
- }
-
private static getSubmissionFileListFromLocal(submissionId: string): string[] {
return JSON.parse(this.getLocalFile(`submissionFileIndex.json`)).submission_file_indexes[
submissionId
@@ -114,11 +92,9 @@ export class ComparisonFactory extends BaseFactory {
const fileList = this.getSubmissionFileListFromLocal(submissionId)
for (const filePath of fileList) {
store().saveSubmissionFile({
- name: submissionId,
- file: {
- fileName: slash(filePath),
- data: this.getLocalFile(`files/${filePath}`)
- }
+ submissionId,
+ fileName: slash(filePath),
+ data: this.getLocalFile(`files/${filePath}`)
})
}
} catch (e) {
diff --git a/report-viewer/src/model/factories/OverviewFactory.ts b/report-viewer/src/model/factories/OverviewFactory.ts
index 3504f4bf5..e80e029f0 100644
--- a/report-viewer/src/model/factories/OverviewFactory.ts
+++ b/report-viewer/src/model/factories/OverviewFactory.ts
@@ -4,6 +4,7 @@ import type { Cluster } from '@/model/Cluster'
import { store } from '@/stores/store'
import { Version } from '../Version'
import versionJson from '@/version.json'
+import { getLanguageParser } from '../Language'
import { Distribution } from '../Distribution'
import { MetricType } from '../MetricType'
import { BaseFactory } from './BaseFactory'
@@ -38,7 +39,7 @@ export class OverviewFactory extends BaseFactory {
const submissionFolder = json.submission_folder_path as Array
const baseCodeFolder = json.base_code_folder_path as string
- const language = json.language as string
+ const language = getLanguageParser(json.language as string)
const fileExtensions = json.file_extensions as Array
const matchSensitivity = json.match_sensitivity as number
const dateOfExecution = json.date_of_execution as string
diff --git a/report-viewer/src/stores/state.ts b/report-viewer/src/stores/state.ts
index 3aefba738..c49794467 100644
--- a/report-viewer/src/stores/state.ts
+++ b/report-viewer/src/stores/state.ts
@@ -33,23 +33,27 @@ export interface State {
}
/**
- * Internal representation of a file.
- * @property fileName - The name of the file.
- * @property data - The content of the file.
+ * Internal representation of a single file.
*/
export interface File {
+ /**
+ * The name of the file.
+ */
fileName: string
+ /**
+ * The files content.
+ */
data: string
}
/**
* Internal representation of a single file from a submission.
- * @property name - The name of the file.
- * @property file - The file.
*/
-export interface SubmissionFile {
- name: string
- file: File
+export interface SubmissionFile extends File {
+ /**
+ * The id of the submission.
+ */
+ submissionId: string
}
/**
diff --git a/report-viewer/src/stores/store.ts b/report-viewer/src/stores/store.ts
index d6df2b4c2..9b6512af5 100644
--- a/report-viewer/src/stores/store.ts
+++ b/report-viewer/src/stores/store.ts
@@ -25,15 +25,18 @@ const store = defineStore('store', {
}),
getters: {
/**
- * @param name the name of the submission
+ * @param submissionID the name of the submission
* @returns files in the submission of the given name
*/
- filesOfSubmission: (state) => (name: string) => {
- return Array.from(state.state.submissions[name], ([name, value]) => ({
- name,
- value
- }))
- },
+ filesOfSubmission:
+ (state) =>
+ (submissionId: string): SubmissionFile[] => {
+ return Array.from(state.state.submissions[submissionId], ([name, value]) => ({
+ submissionId,
+ fileName: name,
+ data: value
+ }))
+ },
/**
* @param name the name of the submission
* @returns the display name of the submission
@@ -134,15 +137,15 @@ const store = defineStore('store', {
},
/**
* Saves the given submission file
- * @param submissionFile the submission file to save
+ * @param submissionFile the file to save
*/
saveSubmissionFile(submissionFile: SubmissionFile) {
- if (!this.state.submissions[submissionFile.name]) {
- this.state.submissions[submissionFile.name] = new Map()
+ if (!this.state.submissions[submissionFile.submissionId]) {
+ this.state.submissions[submissionFile.submissionId] = new Map()
}
- this.state.submissions[submissionFile.name].set(
- submissionFile.file.fileName,
- submissionFile.file.data
+ this.state.submissions[submissionFile.submissionId].set(
+ submissionFile.fileName,
+ submissionFile.data
)
},
/**
diff --git a/report-viewer/src/utils/CodeHighlighter.ts b/report-viewer/src/utils/CodeHighlighter.ts
new file mode 100644
index 000000000..6c1d19e85
--- /dev/null
+++ b/report-viewer/src/utils/CodeHighlighter.ts
@@ -0,0 +1,32 @@
+import type { HighlightLanguage } from '@/model/Language'
+import hljs from 'highlight.js'
+
+/**
+ * Hightlights the given code with the given language.
+ * Splits the resulting html into seperate lines.
+ * The returned string is an array of html lines, consisting of spans with the hljs classes and the code.
+ * Source: https://stackoverflow.com/a/70656181
+ * @param code Code to highlight
+ * @param lang Language to highlight the code with
+ * @returns
+ */
+export function highlight(code: string, lang: HighlightLanguage) {
+ const highlightedCode = hljs.highlight(code, { language: lang.valueOf() }).value
+ const openTags: string[] = []
+ const formatedCode = highlightedCode
+ .replace(/(]*>)|(<\/span>)|(\n)/g, (match: string) => {
+ if (match === '\n') {
+ return ''.repeat(openTags.length) + '\n' + openTags.join('')
+ }
+
+ if (match === '') {
+ openTags.pop()
+ } else {
+ openTags.push(match)
+ }
+
+ return match
+ })
+ .split('\n')
+ return formatedCode
+}
diff --git a/report-viewer/src/views/ComparisonView.vue b/report-viewer/src/views/ComparisonView.vue
index 79ad95016..72bf92beb 100644
--- a/report-viewer/src/views/ComparisonView.vue
+++ b/report-viewer/src/views/ComparisonView.vue
@@ -35,26 +35,28 @@
@@ -66,18 +68,18 @@
import type { Match } from '@/model/Match'
import { onMounted, ref, watch, type Ref, computed, onErrorCaptured } from 'vue'
-import { generateLineCodeLink } from '@/utils/ComparisonUtils'
import TextInformation from '@/components/TextInformation.vue'
import MatchList from '@/components/MatchList.vue'
import { ComparisonFactory } from '@/model/factories/ComparisonFactory'
import FilesContainer from '@/components/FilesContainer.vue'
import { store } from '@/stores/store'
import Container from '@/components/ContainerComponent.vue'
-
+import { getHighlightLanguage } from '@/model/Language'
import hljsLightMode from 'highlight.js/styles/vs.css?raw'
import hljsDarkMode from 'highlight.js/styles/vs2015.css?raw'
import { router } from '@/router'
import { MetricType } from '@/model/MetricType'
+import { OverviewFactory } from '@/model/factories/OverviewFactory'
const props = defineProps({
firstId: {
@@ -90,60 +92,31 @@ const props = defineProps({
}
})
+const language = OverviewFactory.getOverview().language
const comparison = computed(() => ComparisonFactory.getComparison(props.firstId, props.secondId))
const filesOfFirst = ref(comparison.value.filesOfFirstSubmission)
const filesOfSecond = ref(comparison.value.filesOfSecondSubmission)
-/**
- * Collapses a file in the first files container.
- * @param title title of the file
- */
-function toggleCollapseFirst(title: string) {
- const file = filesOfFirst.value.get(title)
- if (file) {
- file.collapsed = !file.collapsed
- }
-}
-
-/**
- * Collapses a file in the second files container.
- * @param title title of the file
- */
-function toggleCollapseSecond(title: string) {
- const file = filesOfSecond.value.get(title)
- if (file) {
- file.collapsed = !file.collapsed
- }
-}
+const panel1: Ref
= ref(null)
+const panel2: Ref = ref(null)
/**
* Shows a match in the first files container when clicked on a line in the second files container.
- * @param e The click event
- * @param panel panel number (1 for left, 2 for right)
* @param file (file name)
* @param line (line number)
*/
-
-function showMatchInFirst(e: unknown, panel: number, file: string, line: number) {
- if (!filesOfFirst.value.get(file)?.collapsed) {
- toggleCollapseFirst(file)
- }
- document.getElementById(generateLineCodeLink(panel, file, line))?.scrollIntoView()
+function showMatchInFirst(match: Match) {
+ panel1.value?.scrollTo(match.firstFile, match.startInFirst)
}
/**
* Shows a match in the second files container, when clicked on a line in the second files container.
- * @param e The click event
- * @param panel panel number (1 for left, 2 for right)
* @param file (file name)
* @param line (line number)
*/
-function showMatchInSecond(e: unknown, panel: number, file: string, line: number) {
- if (!filesOfSecond.value.get(file)?.collapsed) {
- toggleCollapseSecond(file)
- }
- document.getElementById(generateLineCodeLink(panel, file, line))?.scrollIntoView()
+function showMatchInSecond(match: Match) {
+ panel2.value?.scrollTo(match.secondFile, match.startInSecond)
}
/**
@@ -151,9 +124,9 @@ function showMatchInSecond(e: unknown, panel: number, file: string, line: number
* @param e The click event
* @param match The match to show
*/
-function showMatch(e: unknown, match: Match) {
- showMatchInFirst(e, 1, match.firstFile, match.startInFirst)
- showMatchInSecond(e, 2, match.secondFile, match.startInSecond)
+function showMatch(match: Match) {
+ showMatchInFirst(match)
+ showMatchInSecond(match)
}
function isAnonymous(id: string) {
diff --git a/report-viewer/src/views/FileUploadView.vue b/report-viewer/src/views/FileUploadView.vue
index be693d572..8d1f8030c 100644
--- a/report-viewer/src/views/FileUploadView.vue
+++ b/report-viewer/src/views/FileUploadView.vue
@@ -190,8 +190,9 @@ async function handleZipFile(file: Blob) {
)
await zip.files[originalFileName].async('string').then((data) => {
store().saveSubmissionFile({
- name: slash(submissionFileName),
- file: { fileName: slash(fullPathFileName), data: data }
+ submissionId: slash(submissionFileName),
+ fileName: slash(fullPathFileName),
+ data: data
})
})
} else {
diff --git a/report-viewer/src/views/OverviewView.vue b/report-viewer/src/views/OverviewView.vue
index 9bd976329..4da8aca4d 100644
--- a/report-viewer/src/views/OverviewView.vue
+++ b/report-viewer/src/views/OverviewView.vue
@@ -27,6 +27,7 @@
Distribution of Comparisons:
@@ -39,6 +40,14 @@
(i: number) => (selectedDistributionDiagramMetric = getMetricFromNumber(i))
"
/>
+ (distributionDiagramScaleX = i == 0 ? 'linear' : 'logarithmic')
+ "
+ />
@@ -77,7 +86,7 @@