Skip to content

Commit

Permalink
[#1929] Add dynamic positioning support for tooltips (#2056)
Browse files Browse the repository at this point in the history
Currently, most tooltips are shown above buttons and text. 
When these tooltips appear at the top of the viewport, 
part of the tooltips will not be rendered.

Let's implement changes such that these tooltips appear below the
text or button, when appearing at the top of the viewport.
  • Loading branch information
pratham31012002 authored Nov 7, 2023
1 parent 056fa5f commit 54596ed
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 50 deletions.
109 changes: 83 additions & 26 deletions frontend/src/components/c-summary-charts.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,89 +21,119 @@
v-bind:class=" { warn: repo[0].name === '-' }"
) {{ getAuthorDisplayName(repo) }} ({{ repo[0].name }})
.summary-charts__title--contribution
.tooltip
.tooltip(
v-on:mouseover="onTooltipHover(`summary-charts-${i}-total-contribution`)",
v-on:mouseout="resetTooltip(`summary-charts-${i}-total-contribution`)"
)
| [{{ getGroupTotalContribution(repo) }} lines]
span.tooltip-text(
v-if="filterGroupSelection === 'groupByRepos' && !isChartGroupWidgetMode"
) Total contribution of group
)(v-bind:ref="`summary-charts-${i}-total-contribution`") Total contribution of group
span.tooltip-text(
v-else-if="filterGroupSelection === 'groupByAuthors' && !isChartGroupWidgetMode"
) Total contribution of author
)(v-bind:ref="`summary-charts-${i}-total-contribution`") Total contribution of author
a(
v-if="!isGroupMerged(getGroupName(repo)) && !isChartGroupWidgetMode",
v-on:click="handleMergeGroup(getGroupName(repo))"
)
.tooltip
.tooltip(
v-on:mouseover="onTooltipHover(`summary-charts-${i}-merge-group`)",
v-on:mouseout="resetTooltip(`summary-charts-${i}-merge-group`)"
)
font-awesome-icon.icon-button(:icon="['fas', 'chevron-up']")
span.tooltip-text Click to merge group
span.tooltip-text(v-bind:ref="`summary-charts-${i}-merge-group`") Click to merge group
a(
v-if="isGroupMerged(getGroupName(repo)) && !isChartGroupWidgetMode",
v-on:click="handleExpandGroup(getGroupName(repo))"
)
.tooltip
.tooltip(
v-on:mouseover="onTooltipHover(`summary-charts-${i}-expand-group`)",
v-on:mouseout="resetTooltip(`summary-charts-${i}-expand-group`)"
)
font-awesome-icon.icon-button(:icon="['fas', 'chevron-down']")
span.tooltip-text Click to expand group
span.tooltip-text(v-bind:ref="`summary-charts-${i}-expand-group`") Click to expand group
a(
v-if="filterGroupSelection === 'groupByRepos'",
v-bind:class="!isBrokenLink(getRepoLink(repo[0])) ? '' : 'broken-link'",
v-bind:href="getRepoLink(repo[0])", target="_blank"
)
.tooltip
.tooltip(
v-on:mouseover="onTooltipHover(`summary-charts-${i}-repo-link`)",
v-on:mouseout="resetTooltip(`summary-charts-${i}-repo-link`)"
)
font-awesome-icon.icon-button(:icon="getRepoIcon(repo[0])")
span.tooltip-text(
v-if="!isChartGroupWidgetMode",
v-bind:ref="`summary-charts-${i}-repo-link`"
) {{getGroupRepoLinkMessage(repo[0])}}
a(
v-else-if="filterGroupSelection === 'groupByAuthors'",
v-bind:class="!isBrokenLink(getAuthorProfileLink(repo[0], repo[0].name)) ? '' : 'broken-link'",
v-bind:href="getAuthorProfileLink(repo[0], repo[0].name)", target="_blank"
)
.tooltip
.tooltip(
v-on:mouseover="onTooltipHover(`summary-charts-${i}-author-link`)",
v-on:mouseout="resetTooltip(`summary-charts-${i}-author-link`)"
)
font-awesome-icon.icon-button(icon="user")
span.tooltip-text(
v-if="!isChartGroupWidgetMode",
v-bind:ref="`summary-charts-${i}-author-link`"
) {{getAuthorProfileLinkMessage(repo[0])}}
template(v-if="isGroupMerged(getGroupName(repo))")
a(
v-if="filterGroupSelection !== 'groupByAuthors' && !isChartGroupWidgetMode",
onclick="deactivateAllOverlays()",
v-on:click="openTabAuthorship(repo[0], repo, 0, isGroupMerged(getGroupName(repo)))"
)
.tooltip
.tooltip(
v-on:mouseover="onTooltipHover(`summary-charts-${i}-group-code`)",
v-on:mouseout="resetTooltip(`summary-charts-${i}-group-code`)"
)
font-awesome-icon.icon-button(
icon="code",
v-bind:class="{ 'active-icon': isSelectedTab(repo[0].name, repo[0].repoName, 'authorship', true) }"
)
span.tooltip-text Click to view group's code
span.tooltip-text(v-bind:ref="`summary-charts-${i}-group-code`") Click to view group's code
a(
v-if="!isChartGroupWidgetMode",
onclick="deactivateAllOverlays()",
v-on:click="openTabZoom(repo[0], filterSinceDate, filterUntilDate, isGroupMerged(getGroupName(repo)))"
)
.tooltip
.tooltip(
v-on:mouseover="onTooltipHover(`summary-charts-${i}-commit-breakdown`)",
v-on:mouseout="resetTooltip(`summary-charts-${i}-commit-breakdown`)"
)
font-awesome-icon.icon-button(
icon="list-ul",
v-bind:class="{ 'active-icon': isSelectedTab(repo[0].name, repo[0].repoName, 'zoom', true) }"
)
span.tooltip-text Click to view breakdown of commits
span.tooltip-text(v-bind:ref="`summary-charts-${i}-commit-breakdown`") Click to view breakdown of commits
a(
v-if="isChartGroupWidgetMode && !isChartWidgetMode",
v-bind:href="getReportLink()", target="_blank"
)
.tooltip
.tooltip(
v-on:mouseover="onTooltipHover(`summary-charts-${i}-commit-breakdown-group-widget`)",
v-on:mouseout="resetTooltip(`summary-charts-${i}-commit-breakdown-group-widget`)"
)
font-awesome-icon.icon-button(
icon="arrow-up-right-from-square",
)
span.tooltip-text(
v-if="!isChartGroupWidgetMode",
v-bind:ref="`summary-charts-${i}-commit-breakdown-group-widget`"
) Click to view breakdown of commits on RepoSense
a(
v-if="!isChartGroupWidgetMode",
v-on:click="getEmbeddedIframe(i)"
)
.tooltip(v-bind:id="'tooltip-' + i")
.tooltip(v-bind:id="'tooltip-' + i",
v-on:mouseover="onTooltipHover(`summary-charts-${i}-copy-iframe`)",
v-on:mouseout="resetTooltip(`summary-charts-${i}-copy-iframe`)"
)
font-awesome-icon.icon-button(icon="clipboard")
span.tooltip-text Click to copy iframe link for group
span.tooltip-text(v-bind:ref="`summary-charts-${i}-copy-iframe`") Click to copy iframe link for group

.tooltip.summary-chart__title--percentile(
v-if="sortGroupSelection.includes('totalCommits')"
Expand Down Expand Up @@ -143,61 +173,87 @@
v-bind:class="!isBrokenLink(getRepoLink(user)) ? '' : 'broken-link'",
v-bind:href="getRepoLink(user)", target="_blank"
)
.tooltip
.tooltip(
v-on:mouseover="onTooltipHover(`repo-${i}-author-${j}-repo-link`)",
v-on:mouseout="resetTooltip(`repo-${i}-author-${j}-repo-link`)"
)
font-awesome-icon.icon-button(:icon="getRepoIcon(repo[0])")
span.tooltip-text(
v-if="!isChartGroupWidgetMode",
v-bind:ref="`repo-${i}-author-${j}-repo-link`"
) {{getRepoLinkMessage(user)}}
a(
v-if="filterGroupSelection !== 'groupByAuthors'",
v-bind:class="!isBrokenLink(getAuthorProfileLink(user, user.name)) ? '' : 'broken-link'",
v-bind:href="getAuthorProfileLink(user, user.name)", target="_blank"
)
.tooltip
.tooltip(
v-on:mouseover="onTooltipHover(`repo-${i}-author-${j}-author-link`)",
v-on:mouseout="resetTooltip(`repo-${i}-author-${j}-author-link`)"
)
font-awesome-icon.icon-button(icon="user")
span.tooltip-text(
v-if="!isChartGroupWidgetMode",
v-bind:ref="`repo-${i}-author-${j}-author-link`"
) {{getAuthorProfileLinkMessage(user)}}
a(
v-if="!isChartGroupWidgetMode",
onclick="deactivateAllOverlays()",
v-on:click="openTabAuthorship(user, repo, j, isGroupMerged(getGroupName(repo)))"
)
.tooltip
.tooltip(
v-on:mouseover="onTooltipHover(`repo-${i}-author-${j}-author-contribution`)",
v-on:mouseout="resetTooltip(`repo-${i}-author-${j}-author-contribution`)"
)
font-awesome-icon.icon-button(
icon="code",
v-bind:class="{ 'active-icon': isSelectedTab(user.name, user.repoName, 'authorship', false) }"
)
span.tooltip-text Click to view author's contribution.
span.tooltip-text(
v-bind:ref="`repo-${i}-author-${j}-author-contribution`"
) Click to view author's contribution.
a(
v-if="!isChartGroupWidgetMode",
onclick="deactivateAllOverlays()",
v-on:click="openTabZoom(user, filterSinceDate, filterUntilDate, isGroupMerged(getGroupName(repo)))"
)
.tooltip
.tooltip(
v-on:mouseover="onTooltipHover(`repo-${i}-author-${j}-commit-breakdown`)",
v-on:mouseout="resetTooltip(`repo-${i}-author-${j}-commit-breakdown`)"
)
font-awesome-icon.icon-button(
icon="list-ul",
v-bind:class="{ 'active-icon': isSelectedTab(user.name, user.repoName, 'zoom', false) }"
)
span.tooltip-text Click to view breakdown of commits
span.tooltip-text(
v-bind:ref="`repo-${i}-author-${j}-commit-breakdown`"
) Click to view breakdown of commits
a(
v-if="isChartGroupWidgetMode",
v-bind:href="getReportLink()", target="_blank"
)
.tooltip
.tooltip(
v-on:mouseover="onTooltipHover(`repo-${i}-author-${j}-commit-breakdown-group-widget`)",
v-on:mouseout="resetTooltip(`repo-${i}-author-${j}-commit-breakdown-group-widget`)"
)
font-awesome-icon.icon-button(
icon="arrow-up-right-from-square",
)
span.tooltip-text(
v-if="!isChartGroupWidgetMode",
v-bind:ref="`repo-${i}-author-${j}-commit-breakdown-group-widget`"
) Click to view breakdown of commits on RepoSense
a(
v-if="!isChartGroupWidgetMode",
v-on:click="getEmbeddedIframe(i , j)"
)
.tooltip(v-bind:id="'tooltip-' + i + '-' + j")
.tooltip(
v-bind:id="'tooltip-' + i + '-' + j",
v-on:mouseover="onTooltipHover(`repo-${i}-author-${j}-iframe-link`)",
v-on:mouseout="resetTooltip(`repo-${i}-author-${j}-iframe-link`)"
)
font-awesome-icon.icon-button(icon="clipboard")
span.tooltip-text Click to copy iframe link
span.tooltip-text(v-bind:ref="`repo-${i}-author-${j}-iframe-link`") Click to copy iframe link
.tooltip.summary-chart__title--percentile(
v-if="filterGroupSelection === 'groupByNone' && sortGroupSelection.includes('totalCommits')"
) {{ getPercentile(j) }} %&nbsp
Expand Down Expand Up @@ -239,6 +295,7 @@ import { defineComponent } from 'vue';
import { mapState } from 'vuex';
import brokenLinkDisabler from '../mixin/brokenLinkMixin';
import tooltipPositioner from '../mixin/dynamicTooltipMixin';
import cRamp from './c-ramp.vue';
import cStackedBarChart from './c-stacked-bar-chart.vue';
import { Bar, Repo, User } from '../types/types';
Expand All @@ -252,7 +309,7 @@ export default defineComponent({
cRamp,
cStackedBarChart,
},
mixins: [brokenLinkDisabler],
mixins: [brokenLinkDisabler, tooltipPositioner],
props: {
checkedFileTypes: {
type: Array<string>,
Expand Down
19 changes: 19 additions & 0 deletions frontend/src/mixin/dynamicTooltipMixin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { defineComponent } from 'vue';

export default defineComponent({
methods: {
onTooltipHover(refName: string): void {
const tooltipTextElement = (this.$refs[refName] as HTMLElement[])[0];
if (this.isElementAboveViewport(tooltipTextElement)) {
tooltipTextElement.classList.add('bottom-aligned');
}
},
resetTooltip(refName: string): void {
const tooltipTextElement = (this.$refs[refName] as HTMLElement[])[0];
tooltipTextElement.classList.remove('bottom-aligned');
},
isElementAboveViewport(el: Element): boolean {
return el.getBoundingClientRect().top <= 0;
},
},
});
37 changes: 16 additions & 21 deletions frontend/src/views/c-authorship.vue
Original file line number Diff line number Diff line change
Expand Up @@ -148,18 +148,28 @@
v-bind:class="!isBrokenLink(getHistoryLink(file)) ? '' : 'broken-link'",
v-bind:href="getHistoryLink(file)", target="_blank"
)
.tooltip
.tooltip(
v-on:mouseover="onTooltipHover(`${file.path}-view-history-tooltip`)",
v-on:mouseout="resetTooltip(`${file.path}-view-history-tooltip`)"
)
font-awesome-icon.button(icon="history")
span.tooltip-text {{getLinkMessage(getHistoryLink(file), 'Click to view the history view of file')}}
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
.tooltip(
v-on:mouseover="onTooltipHover(`${file.path}-view-blame-tooltip`)",
v-on:mouseout="resetTooltip(`${file.path}-view-blame-tooltip`)"
)
font-awesome-icon.button(icon="user-edit")
span.tooltip-text {{getLinkMessage(getBlameLink(file), 'Click to view the blame view of file')}}
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)",
Expand All @@ -186,6 +196,7 @@ import { defineComponent } from 'vue';
import { mapState } from 'vuex';
import minimatch from 'minimatch';
import brokenLinkDisabler from '../mixin/brokenLinkMixin';
import tooltipPositioner from '../mixin/dynamicTooltipMixin';
import cSegmentCollection from '../components/c-segment-collection.vue';
import Segment from '../utils/segment';
import getNonRepeatingColor from '../utils/random-color-generator';
Expand Down Expand Up @@ -229,7 +240,7 @@ export default defineComponent({
components: {
cSegmentCollection,
},
mixins: [brokenLinkDisabler],
mixins: [brokenLinkDisabler, tooltipPositioner],
emits: [
'deactivate-tab',
],
Expand Down Expand Up @@ -488,22 +499,6 @@ export default defineComponent({
}
},
onTooltipHover(refName: string): void {
const tooltipTextElement = (this.$refs[refName] as HTMLElement[])[0];
if (this.isElementAboveViewport(tooltipTextElement)) {
tooltipTextElement.classList.add('bottom-aligned');
}
},
resetTooltip(refName: string): void {
const tooltipTextElement = (this.$refs[refName] as HTMLElement[])[0];
tooltipTextElement.classList.remove('bottom-aligned');
},
isElementAboveViewport(el: Element): boolean {
return el.getBoundingClientRect().top <= 0;
},
isUnknownAuthor(name: string): boolean {
return name === '-';
},
Expand Down
12 changes: 9 additions & 3 deletions frontend/src/views/c-zoom.vue
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,14 @@
v-if="slice.messageBody !== ''",
v-on:click="toggleSelectedCommitMessageBody(slice)"
)
.tooltip
.tooltip(
v-on:mouseover="onTooltipHover(`${slice.hash}-show-hide-message-body`)",
v-on:mouseout="resetTooltip(`${slice.hash}-show-hide-message-body`)"
)
font-awesome-icon.commit-message--button(icon="ellipsis-h")
span.tooltip-text Click to show/hide the commit message body
span.tooltip-text(
v-bind:ref="`${slice.hash}-show-hide-message-body`"
) Click to show/hide the commit message body
.body(v-if="slice.messageBody !== ''", v-show="slice.isOpen")
pre {{ slice.messageBody }}
.dashed-border
Expand All @@ -145,6 +150,7 @@ import { defineComponent } from 'vue';
import { mapState } from 'vuex';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import brokenLinkDisabler from '../mixin/brokenLinkMixin';
import tooltipPositioner from '../mixin/dynamicTooltipMixin';
import cRamp from '../components/c-ramp.vue';
import cStackedBarChart from '../components/c-stacked-bar-chart.vue';
import User from '../utils/user';
Expand Down Expand Up @@ -177,7 +183,7 @@ export default defineComponent({
cRamp,
cStackedBarChart,
},
mixins: [brokenLinkDisabler],
mixins: [brokenLinkDisabler, tooltipPositioner],
data() {
return {
...zoomInitialState(),
Expand Down

0 comments on commit 54596ed

Please sign in to comment.