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 @@ + + + + + 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")