diff --git a/frontend/src/components/c-authorship-file.vue b/frontend/src/components/c-authorship-file.vue
new file mode 100644
index 0000000000..6d7bbf781f
--- /dev/null
+++ b/frontend/src/components/c-authorship-file.vue
@@ -0,0 +1,424 @@
+
+.file(v-bind:ref="file.path")
+ .title(
+ v-bind:class="{'sticky': file.active}",
+ v-bind:ref="`${file.path}-title`"
+ )
+ span.caret(v-on:click="toggleFileActiveProperty(file)")
+ .tooltip(
+ v-show="file.active",
+ v-on:mouseover="onTitleTooltipHover(`${file.path}-hide-file-tooltip`, `${file.path}-title`)",
+ v-on:mouseout="resetTitleTooltip(`${file.path}-hide-file-tooltip`, `${file.path}-title`)"
+ )
+ font-awesome-icon(icon="caret-down", fixed-width)
+ span.tooltip-text(v-bind:ref="`${file.path}-hide-file-tooltip`") Click to hide file details
+ .tooltip(
+ v-show="!file.active",
+ v-on:mouseover="onTitleTooltipHover(`${file.path}-show-file-tooltip`, `${file.path}-title`)",
+ v-on:mouseout="resetTitleTooltip(`${file.path}-show-file-tooltip`, `${file.path}-title`)"
+ )
+ font-awesome-icon(icon="caret-right", fixed-width)
+ span.tooltip-text(v-bind:ref="`${file.path}-show-file-tooltip`") Click to show file details
+ span.index {{ index + 1 }}.
+ span.path
+ span(
+ v-bind:class="{'selected-parameter':\
+ filesSortType === 'path' || filesSortType === 'fileName'}"
+ ) {{ getFirstPartOfPath(file) }}
+ span.in(v-if="filesSortType === 'fileName'") in
+ span(v-if="filesSortType === 'fileName'") {{ getSecondPartOfPath(file) }}
+ span.fileTypeLabel(
+ v-if="!file.isBinary && !file.isIgnored",
+ v-bind:style="{\
+ 'background-color': fileTypeColors[file.fileType],\
+ 'color': getFontColor(fileTypeColors[file.fileType])\
+ }",
+ v-bind:class="{'selected-label':\
+ filesSortType === 'linesOfCode' || filesSortType === 'fileType'}"
+ )
+ span(
+ v-bind:class="{'selected-parameter':\
+ filesSortType === 'linesOfCode' || filesSortType === 'fileType'}"
+ ) {{ getFirstPartOfLabel(file) }}
+ span {{ getSecondPartOfLabel(file) }}
+ span.fileTypeLabel.binary(v-if='file.isBinary') binary
+ span.ignored-tag.fileTypeLabel(
+ v-if='file.isIgnored'
+ ) ignored ({{ file.lineCount }})
+ span.icons
+ a(
+ v-bind:class="!isBrokenLink(getHistoryLink(file)) ? '' : 'broken-link'",
+ v-bind:href="getHistoryLink(file)", target="_blank"
+ )
+ .tooltip(
+ v-on:mouseover="onTitleTooltipHover(`${file.path}-view-history-tooltip`, `${file.path}-title`)",
+ v-on:mouseout="resetTitleTooltip(`${file.path}-view-history-tooltip`, `${file.path}-title`)"
+ )
+ font-awesome-icon.button(icon="history")
+ span.tooltip-text(
+ v-bind:ref="`${file.path}-view-history-tooltip`"
+ ) {{getLinkMessage(getHistoryLink(file), 'Click to view the history view of file')}}
+ a(
+ v-if='!file.isBinary',
+ v-bind:class="!isBrokenLink(getBlameLink(file)) ? '' : 'broken-link'",
+ v-bind:href="getBlameLink(file)", target="_blank",
+ title="click to view the blame view of file"
+ )
+ .tooltip(
+ v-on:mouseover="onTitleTooltipHover(`${file.path}-view-blame-tooltip`, `${file.path}-title`)",
+ v-on:mouseout="resetTitleTooltip(`${file.path}-view-blame-tooltip`, `${file.path}-title`)"
+ )
+ font-awesome-icon.button(icon="user-edit")
+ span.tooltip-text(
+ v-bind:ref="`${file.path}-view-blame-tooltip`"
+ ) {{getLinkMessage(getBlameLink(file), 'Click to view the blame view of file')}}
+ .author-breakdown(v-if="info.isMergeGroup")
+ .author-breakdown__legend(
+ v-for="author in getAuthors(file)",
+ v-bind:key="author"
+ )
+ font-awesome-icon(
+ icon="circle",
+ v-bind:style="{ 'color': authorColors[author] }"
+ )
+ span {{ author }}
+ pre.file-content(v-if="file.isBinary", v-show="file.active")
+ .binary-segment
+ .indicator BIN
+ .bin-text Binary file not shown.
+ pre.file-content(v-else-if="file.isIgnored", v-show="file.active")
+ .ignored-segment
+ .ignore-text File is ignored.
+ pre.hljs.file-content(v-else-if="file.wasCodeLoaded", v-show="file.active")
+ c-segment-collection(v-bind:segments="file.segments", v-bind:path="file.path")
+
+
+
+
+
diff --git a/frontend/src/mixin/dynamicTooltipMixin.ts b/frontend/src/mixin/dynamicTooltipMixin.ts
index 5d504c9f8f..c5ecbb5554 100644
--- a/frontend/src/mixin/dynamicTooltipMixin.ts
+++ b/frontend/src/mixin/dynamicTooltipMixin.ts
@@ -3,17 +3,26 @@ import { defineComponent } from 'vue';
export default defineComponent({
methods: {
onTooltipHover(refName: string): void {
- const tooltipTextElement = (this.$refs[refName] as HTMLElement[])[0];
+ const tooltipTextElement = this.getElementByRef(refName);
if (this.isElementAboveViewport(tooltipTextElement)) {
tooltipTextElement.classList.add('bottom-aligned');
}
},
resetTooltip(refName: string): void {
- const tooltipTextElement = (this.$refs[refName] as HTMLElement[])[0];
+ const tooltipTextElement = this.getElementByRef(refName);
tooltipTextElement.classList.remove('bottom-aligned');
},
isElementAboveViewport(el: Element): boolean {
return el.getBoundingClientRect().top <= 0;
},
+ /**
+ * Note: this.$refs[refName] can be an array of HTMLElements
+ * if the ref is on a v-for loop, else it will be a single HTMLElement.
+ */
+ getElementByRef(refName: string): HTMLElement {
+ return Array.isArray(this.$refs[refName])
+ ? (this.$refs[refName] as HTMLElement[])[0]
+ : this.$refs[refName] as HTMLElement;
+ },
},
});
diff --git a/frontend/src/views/c-authorship.vue b/frontend/src/views/c-authorship.vue
index b901e8f4fe..d404ecbed3 100644
--- a/frontend/src/views/c-authorship.vue
+++ b/frontend/src/views/c-authorship.vue
@@ -99,99 +99,11 @@
.files(v-if="isLoaded")
.empty(v-if="info.files.length === 0") nothing to see here :(
- template(v-for="(file, i) in selectedFiles", v-bind:key="file.path")
- .file(v-bind:ref="file.path")
- .title(
- v-bind:class="{'sticky':\ file.active}",
- v-bind:ref="`${file.path}-title`"
- )
- span.caret(v-on:click="toggleFileActiveProperty(file)")
- .tooltip(
- v-show="file.active",
- v-on:mouseover="onTitleTooltipHover(`${file.path}-hide-file-tooltip`, `${file.path}-title`)",
- v-on:mouseout="resetTitleTooltip(`${file.path}-hide-file-tooltip`, `${file.path}-title`)"
- )
- font-awesome-icon(icon="caret-down", fixed-width)
- span.tooltip-text(v-bind:ref="`${file.path}-hide-file-tooltip`") Click to hide file details
- .tooltip(
- v-show="!file.active",
- v-on:mouseover="onTitleTooltipHover(`${file.path}-show-file-tooltip`, `${file.path}-title`)",
- v-on:mouseout="resetTitleTooltip(`${file.path}-show-file-tooltip`, `${file.path}-title`)"
- )
- font-awesome-icon(icon="caret-right", fixed-width)
- span.tooltip-text(v-bind:ref="`${file.path}-show-file-tooltip`") Click to show file details
- span.index {{ i + 1 }}.
- span.path
- span(
- v-bind:class="{'selected-parameter':\
- this.filesSortType === 'path' || this.filesSortType === 'fileName'}"
- ) {{ getFirstPartOfPath(file) }}
- span.in(v-if="this.filesSortType === 'fileName'") in
- span(v-if="this.filesSortType === 'fileName'") {{ getSecondPartOfPath(file) }}
- span.fileTypeLabel(
- v-if="!file.isBinary && !file.isIgnored",
- v-bind:style="{\
- 'background-color': fileTypeColors[file.fileType],\
- 'color': getFontColor(fileTypeColors[file.fileType])\
- }",
- v-bind:class="{'selected-label':\
- this.filesSortType === 'linesOfCode' || this.filesSortType === 'fileType'}"
- )
- span(
- v-bind:class="{'selected-parameter':\
- this.filesSortType === 'linesOfCode' || this.filesSortType === 'fileType'}"
- ) {{ getFirstPartOfLabel(file) }}
- span {{ getSecondPartOfLabel(file) }}
- span.fileTypeLabel.binary(v-if='file.isBinary') binary
- span.ignored-tag.fileTypeLabel(
- v-if='file.isIgnored'
- ) ignored ({{ file.lineCount }})
- span.icons
- a(
- v-bind:class="!isBrokenLink(getHistoryLink(file)) ? '' : 'broken-link'",
- v-bind:href="getHistoryLink(file)", target="_blank"
- )
- .tooltip(
- v-on:mouseover="onTitleTooltipHover(`${file.path}-view-history-tooltip`, `${file.path}-title`)",
- v-on:mouseout="resetTitleTooltip(`${file.path}-view-history-tooltip`, `${file.path}-title`)"
- )
- font-awesome-icon.button(icon="history")
- span.tooltip-text(
- v-bind:ref="`${file.path}-view-history-tooltip`"
- ) {{getLinkMessage(getHistoryLink(file), 'Click to view the history view of file')}}
- a(
- v-if='!file.isBinary',
- v-bind:class="!isBrokenLink(getBlameLink(file)) ? '' : 'broken-link'",
- v-bind:href="getBlameLink(file)", target="_blank",
- title="click to view the blame view of file"
- )
- .tooltip(
- v-on:mouseover="onTitleTooltipHover(`${file.path}-view-blame-tooltip`, `${file.path}-title`)",
- v-on:mouseout="resetTitleTooltip(`${file.path}-view-blame-tooltip`, `${file.path}-title`)"
- )
- font-awesome-icon.button(icon="user-edit")
- span.tooltip-text(
- v-bind:ref="`${file.path}-view-blame-tooltip`"
- ) {{getLinkMessage(getBlameLink(file), 'Click to view the blame view of file')}}
- .author-breakdown(v-if="info.isMergeGroup")
- .author-breakdown__legend(
- v-for="author in getAuthors(file)",
- v-bind:key="author"
- )
- font-awesome-icon(
- icon="circle",
- v-bind:style="{ 'color': authorColors[author] }"
- )
- span {{ author }}
- pre.file-content(v-if="file.isBinary", v-show="file.active")
- .binary-segment
- .indicator BIN
- .bin-text Binary file not shown.
- pre.file-content(v-else-if="file.isIgnored", v-show="file.active")
- .ignored-segment
- .ignore-text File is ignored.
- pre.hljs.file-content(v-else-if="file.wasCodeLoaded", v-show="file.active")
- c-segment-collection(v-bind:segments="file.segments", v-bind:path="file.path")
+ template(v-for="(file, index) in selectedFiles", v-bind:key="file.path")
+ c-authorship-file(v-bind:file="file", v-bind:index="index",
+ v-bind:files-sort-type="this.filesSortType", v-bind:info="this.info",
+ v-bind:author-colors="this.authorColors", v-bind:file-type-colors="this.fileTypeColors",
+ @toggle-file-active-property="toggleFileActiveProperty")