[Client] workout - add checkbox to select data on chart - fix #116

This commit is contained in:
Sam 2021-11-28 14:11:30 +01:00
parent 7d2248ec8c
commit 5201362ac4
3 changed files with 100 additions and 1 deletions

View File

@ -23,6 +23,7 @@
{{ $t('workouts.DURATION') }} {{ $t('workouts.DURATION') }}
</label> </label>
</div> </div>
<div id="chart-legend" />
<LineChart <LineChart
v-bind="lineChartProps" v-bind="lineChartProps"
class="line-chart" class="line-chart"
@ -55,6 +56,7 @@
import { LineChart, useLineChart } from 'vue-chart-3' import { LineChart, useLineChart } from 'vue-chart-3'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { htmlLegendPlugin } from '@/components/Workout/WorkoutChart/legend'
import { TUnit } from '@/types/units' import { TUnit } from '@/types/units'
import { IUserProfile } from '@/types/user' import { IUserProfile } from '@/types/user'
import { import {
@ -187,11 +189,18 @@
}, },
}, },
}, },
legend: {
display: false,
},
htmlLegend: {
containerID: 'chart-legend',
},
}, },
})) }))
const { lineChartProps } = useLineChart({ const { lineChartProps } = useLineChart({
chartData, chartData,
options, options,
plugins: [htmlLegendPlugin],
}) })
function updateDisplayDistance() { function updateDisplayDistance() {
@ -237,6 +246,33 @@
font-size: 0.85em; font-size: 0.85em;
font-style: italic; font-style: italic;
} }
#chart-legend {
display: flex;
justify-content: center;
ul {
display: flex;
margin-bottom: 0;
padding: 0;
li {
cursor: pointer;
display: flex;
font-size: 0.85em;
padding: 0 $default-padding * 0.5;
span {
border-radius: 50%;
border-style: solid;
border-width: 1.5px;
height: 10px;
margin-top: 4px;
margin-left: 2px;
width: 10px;
}
}
}
}
} }
@media screen and (max-width: $small-limit) { @media screen and (max-width: $small-limit) {

View File

@ -0,0 +1,63 @@
import { Chart, LegendItem } from 'chart.js'
const getOrCreateLegendList = (id: string): HTMLUListElement => {
const legendContainer = document.getElementById(id)
if (legendContainer) {
let listContainer = legendContainer.querySelector('ul')
if (!listContainer) {
listContainer = document.createElement('ul')
legendContainer.appendChild(listContainer)
}
return listContainer
}
throw new Error('No legend container')
}
export const htmlLegendPlugin = {
id: 'htmlLegend',
afterUpdate(
chart: Chart,
args: Record<string, unknown>,
options: Record<string, string>
): void {
const ul = getOrCreateLegendList(options.containerID)
while (ul.firstChild) {
ul.firstChild.remove()
}
const legendItems = chart.options.plugins?.legend?.labels?.generateLabels
? chart.options.plugins?.legend?.labels?.generateLabels(chart)
: []
legendItems.forEach((item: LegendItem) => {
const li = document.createElement('li')
li.onclick = () => {
chart.setDatasetVisibility(
item.datasetIndex,
!chart.isDatasetVisible(item.datasetIndex)
)
chart.update()
}
const checkBox = document.createElement('input')
if (checkBox) {
checkBox.type = 'checkbox'
checkBox.id = item.text
checkBox.checked = !item.hidden
}
const text = document.createTextNode(item.text)
const boxSpan = document.createElement('span')
if (boxSpan) {
boxSpan.style.background = `${item.fillStyle}`
boxSpan.style.borderColor = `${item.strokeStyle}`
}
li.appendChild(checkBox)
li.appendChild(text)
li.appendChild(boxSpan)
ul.appendChild(li)
})
},
}

View File

@ -52,7 +52,7 @@
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import NotFound from '@/components/Common/NotFound.vue' import NotFound from '@/components/Common/NotFound.vue'
import WorkoutChart from '@/components/Workout/WorkoutChart.vue' import WorkoutChart from '@/components/Workout/WorkoutChart/index.vue'
import WorkoutDetail from '@/components/Workout/WorkoutDetail/index.vue' import WorkoutDetail from '@/components/Workout/WorkoutDetail/index.vue'
import WorkoutNotes from '@/components/Workout/WorkoutNotes.vue' import WorkoutNotes from '@/components/Workout/WorkoutNotes.vue'
import WorkoutSegments from '@/components/Workout/WorkoutSegments.vue' import WorkoutSegments from '@/components/Workout/WorkoutSegments.vue'