Просмотр исходного кода

[192-webreport] Added coloring to matches

Evgeni 4 лет назад
Родитель
Сommit
2a5db58806

+ 28 - 6
report-viewer/src/components/CodePanel.vue

@@ -1,12 +1,12 @@
 <template>
   <div class="code-container">
-    <LineOfCode v-for="(line, index) in lines" :key="index" :is-blurred="isBlurred(index)" :line-number="index" :text="line"
+    <LineOfCode v-for="(line, index) in lines" :key="index" :color="coloringArray[index]" :line-number="index" :text="line"
     :id="panelId.concat(index)"/>
   </div>
 </template>
 
 <script>
-import {computed, defineComponent} from "vue";
+import {ref, defineComponent, watchEffect} from "vue";
 import LineOfCode from "./LineOfCode";
 
 export default defineComponent({
@@ -17,7 +17,7 @@ export default defineComponent({
       type: Array,
       required: true
     },
-    notBlurred: {
+    coloring: {
       type: Array
     },
     panelId: {
@@ -25,11 +25,33 @@ export default defineComponent({
     }
   },
   setup(props) {
-    const isBlurred = (index) => {
-      return !props.notBlurred.includes(index)
+    console.log(JSON.stringify(props.coloring))
+    const coloringArray = ref({})
+    props.coloring.forEach(m => {
+      for (let i = m.start; i <= m.end; i++) {
+        coloringArray.value[i] = m.color
+      }
+    })
+    for(let i = 0; i < props.lines.length; i++) {
+      if(!coloringArray.value[i]) {
+        coloringArray.value[i] = "#ECECEC"
+      }
     }
+    watchEffect(() => {
+      coloringArray.value = {}
+      props.coloring.forEach(m => {
+        for (let i = m.start; i <= m.end; i++) {
+          coloringArray.value[i] = m.color
+        }
+      })
+      for(let i = 0; i < props.lines.length; i++) {
+        if(!coloringArray.value[i]) {
+          coloringArray.value[i] = "#ECECEC"
+        }
+      }
+    })
     return {
-      isBlurred
+      coloringArray
     }
   }
 })

+ 27 - 0
report-viewer/src/components/FilesSelection.vue

@@ -0,0 +1,27 @@
+<template>
+
+</template>
+
+<script>
+import { defineComponent} from "vue";
+
+export default defineComponent({
+  name: "FilesSelection",
+  props: {
+    matches: {
+      type: Object,
+      required: true
+    }
+  },
+  setup() {
+
+    return {
+
+    }
+  }
+})
+</script>
+
+<style scoped>
+
+</style>

+ 17 - 6
report-viewer/src/components/LineOfCode.vue

@@ -1,9 +1,11 @@
 <template>
-<pre id="line" v-bind:class="{ blurred : isBlurred }">{{ lineNumber }} {{ text }}</pre>
+  <div class="line-wrap" :style="{background : color}">
+<pre :id="text" v-bind:class="{ blurred : isBlurred }" >{{ lineNumber }} {{ text }}</pre>
+  </div>
 </template>
 
 <script>
-import { defineComponent } from "vue";
+import { defineComponent, onMounted } from "vue";
 
 export default defineComponent({
   name: "LineOfCode",
@@ -16,12 +18,16 @@ export default defineComponent({
       type: Number,
       required: true
     },
-    isBlurred: {
-      type: Boolean,
-      required: true
+    color: {
+      type: String,
+      required:true
     },
+    startOfMatch: {
+      type: Number
+    }
   },
   setup(props) {
+    document.getEleme
     return {
 
     }
@@ -33,11 +39,16 @@ export default defineComponent({
 pre {
   margin: 0;
   padding: 0;
-  font-size: large;
+  float: left;
+
 }
 .blurred {
   filter: blur(2px);
   -webkit-filter: blur(2px);
 }
+.line-wrap {
+  width: 200%;
+}
+
 
 </style>

+ 4 - 28
report-viewer/src/components/MatchList.vue

@@ -17,7 +17,7 @@
       </th>
       <th>Tokens</th>
     </tr>
-    <tr class="selectable-row" v-for="match in groupedMatches[selectedSplit[0]][selectedSplit[1]]" :key="match.start_in_first + match.end_in_first"
+    <tr class="selectable-row" v-for="match in matches[selectedSplit[0]][selectedSplit[1]]" :key="match.start_in_first + match.end_in_first"
         @click="this.$emit('matchSelected', $event, match.start_in_first, match.end_in_first, match.start_in_second, match.end_in_second)">
       <td>{{ match.start_in_first }} - {{ match.end_in_first }}</td>
       <td>{{ match.start_in_second }} - {{ match.end_in_second }}</td>
@@ -49,37 +49,15 @@ export default defineComponent({
   setup(props) {
     const SEPARATOR = " - "
 
-    const generateColour = () => {
-      let color = "#";
-      for (let i = 0; i < 3; i++)
-        color += ("0" + Math.floor(((1 + Math.random()) * Math.pow(16, 2)) / 2).toString(16)).slice(-2);
-      return color;
-    }
-
-    const groupedMatches = ref(props.matches.reduce( (acc, val) => {
-      let name = val.first_file_name
-      let subname = val.second_file_name
-      if(!acc[name]) {
-        acc[name] = {}
-      }
-      if(!acc[name][subname]) {
-        acc[name][subname] = []
-      }
-      let newVal = {...val, color: generateColour()}
-      acc[name][subname].push(newVal)
-      return acc;
-    }, {})
-    )
-
     const generatedSelectOptions = ref([])
-    Object.keys(groupedMatches.value).forEach( (key) => {
-      Object.keys(groupedMatches.value[key]).forEach( (subkey) => {
+    Object.keys(props.matches).forEach( (key) => {
+      Object.keys(props.matches[key]).forEach( (subkey) => {
         generatedSelectOptions.value.push(key + SEPARATOR + subkey)
       })
     })
 
     let selected = ref(generatedSelectOptions.value[0]);
-    let selectedSplit = selected.value.split(SEPARATOR)
+    let selectedSplit = ref(selected.value.split(SEPARATOR))
 
 
     watchEffect(() => {
@@ -90,8 +68,6 @@ export default defineComponent({
       selected,
       selectedSplit,
       generatedSelectOptions,
-      groupedMatches,
-
       SEPARATOR
     }
   }

+ 32 - 0
report-viewer/src/utils/Utils.ts

@@ -0,0 +1,32 @@
+export function convertToFilesByName(files: Array<Record<string, unknown>>): Record<string, unknown> {
+    return files.reduce( (acc: Record<string, unknown>, val: Record<string, unknown>) => {
+        if(!acc[val.file_name as string]) {
+            acc[val.file_name as string] = []
+        }
+        acc[val.file_name as string] = val.lines
+        return acc;
+    }, {})
+}
+
+export function generateColoringArray(array: Array<Record<string, unknown>>, fileToConsider: number): Array<Record<string, unknown>> {
+    switch (fileToConsider) {
+        case 1:
+            return array.map( m => {
+                //Add connection to second panel via m.start_in_second
+                return { start: m.start_in_first, end: m.end_in_first, color: m.color}
+            })
+        case 2:
+            return array.map( m => {
+                return { start: m.start_in_second, end: m.end_in_second, color: m.color}
+            })
+        default:
+            return []
+    }
+}
+
+export function generateColor(): string {
+    let color = "#";
+    for (let i = 0; i < 3; i++)
+        color += ("0" + Math.floor(((1 + Math.random()) * Math.pow(16, 2)) / 2).toString(16)).slice(-2);
+    return color;
+}

+ 34 - 38
report-viewer/src/views/ComparisonView.vue

@@ -11,14 +11,14 @@
     <TextInformation label="Match percentage:" value="75.34%" :has-additional-info="false"/>
     <MatchList :submission1="json.first_submission_id"
                :submission2="json.second_submission_id"
-               :matches="json.matches"
+               :matches="groupedMatches"
                 @selection-changed="selectFiles"
                 @match-selected="selectMatch"/>
   </div>
   <div id="rightPanel" v-bind:class="{extended : hideLeftPanel}">
     <button id="show-button" v-bind:class="{hidden : !hideLeftPanel}" @click="togglePanel"><img src="@/assets/double_arrow_white_24dp.svg" alt="hide"></button>
-    <CodePanel :lines="filesOfFirst[selectedFileOfFirst]" :not-blurred="notBlurredInFirst" panel-id="1"/>
-    <CodePanel :lines="filesOfSecond[selectedFileOfSecond]" :not-blurred="notBlurredInSecond" panel-id="2"/>
+    <CodePanel id="codePanel1" :lines="filesOfFirst[selectedFileOfFirst]" :coloring="coloringFirst" panel-id="1"/>
+    <CodePanel :lines="filesOfSecond[selectedFileOfSecond]"  :coloring="coloringSecond" panel-id="2"/>
   </div>
 </div>
 </template>
@@ -28,6 +28,7 @@ import { defineComponent, ref } from "vue";
 import TextInformation from "@/components/TextInformation";
 import MatchList from "@/components/MatchList";
 import CodePanel from "@/components/CodePanel";
+import {convertToFilesByName, generateColoringArray, generateColor} from "@/utils/Utils";
 
 export default defineComponent({
   name: "ComparisonView",
@@ -38,57 +39,52 @@ export default defineComponent({
     }
   },
   setup(props) {
-    const selectedFileOfFirst = ref(0)
-    const selectedFileOfSecond = ref(0)
-    const hideLeftPanel = ref(false)
-    const notBlurredInFirst = ref([])
-    const notBlurredInSecond = ref([])
     const json = JSON.parse(props.jsonString)
 
-    const filesOfFirst = json.files_of_first_submission.reduce( (acc, val) => {
-      if(!acc[val.file_name]) {
-        acc[val.file_name] = []
-      }
-      acc[val.file_name] = val.lines
-      return acc
-    }, {})
-    const filesOfSecond = json.files_of_second_submission.reduce( (acc, val) => {
-      if(!acc[val.file_name]) {
-        acc[val.file_name] = []
-      }
-      acc[val.file_name] = val.lines
-      return acc
-    }, {})
+    const filesOfFirst = convertToFilesByName(json.files_of_first_submission)
+    const filesOfSecond = convertToFilesByName(json.files_of_second_submission)
+    const selectedFileOfFirst = ref(Object.keys(filesOfFirst)[0])
+    const selectedFileOfSecond = ref(Object.keys(filesOfSecond)[0])
+
+    const groupedMatches = ref(json.matches.reduce( (acc, val) => {
+          let name = val.first_file_name
+          let subname = val.second_file_name
+          if(!acc[name]) {
+            acc[name] = {}
+          }
+          if(!acc[name][subname]) {
+            acc[name][subname] = []
+          }
+          let newVal = {...val, color: generateColor()}
+          acc[name][subname].push(newVal)
+          return acc;
+        }, {})
+    )
+
+    let coloringFirst = ref(generateColoringArray(groupedMatches.value[selectedFileOfFirst.value][selectedFileOfSecond.value], 1))
+    let coloringSecond = ref(generateColoringArray(groupedMatches.value[selectedFileOfFirst.value][selectedFileOfSecond.value], 2))
 
     const selectFiles = (e , file1, file2) => {
-      console.log(file1, " ", file2)
       selectedFileOfFirst.value = file1
       selectedFileOfSecond.value = file2
+      coloringFirst.value = generateColoringArray(groupedMatches.value[selectedFileOfFirst.value][selectedFileOfSecond.value], 1)
+      coloringSecond.value = generateColoringArray(groupedMatches.value[selectedFileOfFirst.value][selectedFileOfSecond.value], 2)
     }
 
     const selectMatch = (e, s1, e1, s2, e2) => {
-      let notBlurred1 = []
-      let notBlurred2 = []
-      for (let i = s1; i <= e1; i++) {
-        notBlurred1.push(i)
-      }
-      notBlurredInFirst.value = notBlurred1
-      for (let i = s2; i <= e2; i++) {
-        notBlurred2.push(i)
-      }
-      notBlurredInSecond.value = notBlurred2
-      document.getElementById("1".concat(notBlurred1[0])).scrollIntoView()
-      document.getElementById("2".concat(notBlurred2[0])).scrollIntoView()
+      document.getElementById("1".concat(s1)).scrollIntoView()
+      document.getElementById("2".concat(s2)).scrollIntoView()
     }
 
+
+    const hideLeftPanel = ref(false)
     const togglePanel = () => {
-      console.log("hiding showing panel")
       hideLeftPanel.value = !hideLeftPanel.value
     }
 
     return {
       json, filesOfFirst, filesOfSecond, selectedFileOfFirst, selectedFileOfSecond, hideLeftPanel,
-      notBlurredInFirst, notBlurredInSecond,
+      coloringFirst, coloringSecond, groupedMatches,
       selectFiles,
       selectMatch,
       togglePanel
@@ -157,7 +153,7 @@ export default defineComponent({
   border: none;
   border-top-right-radius: 10px;
   border-bottom-right-radius: 10px;
-  height: 5%;
+  height: 100%;
   width: 1%;
 }
 

+ 117 - 0
report-viewer/src/views/ComparisonViewV2.vue

@@ -0,0 +1,117 @@
+<template>
+  <div class="container">
+    <div class="left-drawers">
+      <div id="basicInfo" class="drawer">
+        <p class="drawer-title">Basic Info</p>
+      </div>
+      <div id="matches" class="drawer">
+        <p class="drawer-title">Matches</p>
+      </div>
+    </div>
+    <CodePanel :lines="filesOfFirst[selectedFileOfFirst]" :not-blurred="[]" panel-id="1"/>
+    <CodePanel :lines="filesOfSecond[selectedFileOfSecond]" :not-blurred="[]" panel-id="2"/>
+  </div>
+</template>
+
+<script>
+import {defineComponent, ref} from "vue";
+import CodePanel from "../components/CodePanel";
+import {convertToFilesByName} from "@/utils/Utils";
+
+export default defineComponent({
+  name: "ComparisonViewV2",
+  components: { CodePanel },
+  props: {
+    jsonString: {
+      type: String
+    }
+  },
+  setup(props) {
+    const json = JSON.parse(props.jsonString)
+    const selectedFileOfFirst = ref("Jumpbox12.java")
+    const selectedFileOfSecond = ref("Jumpbox21.java")
+
+    const filesOfFirst = convertToFilesByName(json.files_of_first_submission)
+    const filesOfSecond = convertToFilesByName(json.files_of_second_submission)
+
+    const generateColour = () => {
+      let color = "#";
+      for (let i = 0; i < 3; i++)
+        color += ("0" + Math.floor(((1 + Math.random()) * Math.pow(16, 2)) / 2).toString(16)).slice(-2);
+      return color;
+    }
+
+    const groupedMatches = ref(json.matches.reduce( (acc, val) => {
+          let name = val.first_file_name
+          let subname = val.second_file_name
+          if(!acc[name]) {
+            acc[name] = {}
+          }
+          if(!acc[name][subname]) {
+            acc[name][subname] = []
+          }
+          let newVal = {...val, color: generateColour()}
+          acc[name][subname].push(newVal)
+          return acc;
+        }, {})
+    )
+
+    return {
+      selectedFileOfFirst,
+      selectedFileOfSecond,
+      filesOfFirst,
+      filesOfSecond
+    }
+  }
+})
+</script>
+
+<style scoped>
+.container {
+  display: flex;
+  flex-wrap: nowrap;
+  align-items: stretch;
+  background: #ECECEC;
+  height: 100%;
+}
+
+.left-drawers {
+  display: flex;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  align-items: stretch;
+  height: 100%;
+}
+
+.drawer {
+  display: flex;
+  flex-wrap: nowrap;
+  border-top-right-radius: 10px;
+  border-bottom-right-radius: 10px;
+  padding-right: 5%;
+}
+
+.drawer-title {
+  writing-mode: vertical-lr;
+  text-align: center;
+  color: white;
+  padding: 0;
+  margin: 0;
+}
+
+#matches {
+  background: #777777;
+  height: 50%;
+}
+
+#basicInfo {
+  background: #FF5353;
+  height: 50%;
+}
+
+#basicInfo:hover {
+  position: absolute;
+  left: 0;
+  z-index: 1000;
+}
+</style>