Refactor Chart component (#8622)
* refactor(client): refactor Chart component * Apply review suggestions from @Johann150 Co-authored-by: Johann150 <johann@qwertqwefsday.eu> * fix(client): don't expose values from Chart Co-authored-by: Johann150 <johann@qwertqwefsday.eu>
This commit is contained in:
parent
e0cce893be
commit
88307327e6
|
@ -7,8 +7,13 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, ref, watch, PropType, onUnmounted, shallowRef } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
/* eslint-disable id-denylist --
|
||||
Chart.js has a `data` attribute in most chart definitions, which triggers the
|
||||
id-denylist violation when setting it. This is causing about 60+ lint issues.
|
||||
As this is part of Chart.js's API it makes sense to disable the check here.
|
||||
*/
|
||||
import { defineProps, onMounted, ref, watch, PropType, onUnmounted } from 'vue';
|
||||
import {
|
||||
Chart,
|
||||
ArcElement,
|
||||
|
@ -36,6 +41,46 @@ import * as os from '@/os';
|
|||
import { defaultStore } from '@/store';
|
||||
import MkChartTooltip from '@/components/chart-tooltip.vue';
|
||||
|
||||
const props = defineProps({
|
||||
src: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
args: {
|
||||
type: Object,
|
||||
required: false,
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 90
|
||||
},
|
||||
span: {
|
||||
type: String as PropType<'hour' | 'day'>,
|
||||
required: true,
|
||||
},
|
||||
detailed: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
stacked: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
bar: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
aspectRatio: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
});
|
||||
|
||||
Chart.register(
|
||||
ArcElement,
|
||||
LineElement,
|
||||
|
@ -80,51 +125,9 @@ const getColor = (i) => {
|
|||
return colorSets[i % colorSets.length];
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
src: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
args: {
|
||||
type: Object,
|
||||
required: false,
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 90
|
||||
},
|
||||
span: {
|
||||
type: String as PropType<'hour' | 'day'>,
|
||||
required: true,
|
||||
},
|
||||
detailed: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
stacked: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
bar: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
aspectRatio: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
},
|
||||
|
||||
setup(props) {
|
||||
const now = new Date();
|
||||
let chartInstance: Chart = null;
|
||||
let data: {
|
||||
let chartData: {
|
||||
series: {
|
||||
name: string;
|
||||
type: 'line' | 'area';
|
||||
|
@ -205,13 +208,13 @@ export default defineComponent({
|
|||
// フォントカラー
|
||||
Chart.defaults.color = getComputedStyle(document.documentElement).getPropertyValue('--fg');
|
||||
|
||||
const maxes = data.series.map((x, i) => Math.max(...x.data.map(d => d.y)));
|
||||
const maxes = chartData.series.map((x, i) => Math.max(...x.data.map(d => d.y)));
|
||||
|
||||
chartInstance = new Chart(chartEl.value, {
|
||||
type: props.bar ? 'bar' : 'line',
|
||||
data: {
|
||||
labels: new Array(props.limit).fill(0).map((_, i) => getDate(i).toLocaleString()).slice().reverse(),
|
||||
datasets: data.series.map((x, i) => ({
|
||||
datasets: chartData.series.map((x, i) => ({
|
||||
parsing: false,
|
||||
label: x.name,
|
||||
data: x.data.slice().reverse(),
|
||||
|
@ -373,7 +376,7 @@ export default defineComponent({
|
|||
// TODO
|
||||
};
|
||||
|
||||
const fetchFederationChart = async (): Promise<typeof data> => {
|
||||
const fetchFederationChart = async (): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/federation', { limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
|
@ -423,7 +426,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchApRequestChart = async (): Promise<typeof data> => {
|
||||
const fetchApRequestChart = async (): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/ap-request', { limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
|
@ -445,13 +448,13 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchNotesChart = async (type: string): Promise<typeof data> => {
|
||||
const fetchNotesChart = async (type: string): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/notes', { limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
name: 'All',
|
||||
type: 'line',
|
||||
data: format(type == 'combined'
|
||||
data: format(type === 'combined'
|
||||
? sum(raw.local.inc, negate(raw.local.dec), raw.remote.inc, negate(raw.remote.dec))
|
||||
: sum(raw[type].inc, negate(raw[type].dec))
|
||||
),
|
||||
|
@ -459,7 +462,7 @@ export default defineComponent({
|
|||
}, {
|
||||
name: 'Renotes',
|
||||
type: 'area',
|
||||
data: format(type == 'combined'
|
||||
data: format(type === 'combined'
|
||||
? sum(raw.local.diffs.renote, raw.remote.diffs.renote)
|
||||
: raw[type].diffs.renote
|
||||
),
|
||||
|
@ -467,7 +470,7 @@ export default defineComponent({
|
|||
}, {
|
||||
name: 'Replies',
|
||||
type: 'area',
|
||||
data: format(type == 'combined'
|
||||
data: format(type === 'combined'
|
||||
? sum(raw.local.diffs.reply, raw.remote.diffs.reply)
|
||||
: raw[type].diffs.reply
|
||||
),
|
||||
|
@ -475,7 +478,7 @@ export default defineComponent({
|
|||
}, {
|
||||
name: 'Normal',
|
||||
type: 'area',
|
||||
data: format(type == 'combined'
|
||||
data: format(type === 'combined'
|
||||
? sum(raw.local.diffs.normal, raw.remote.diffs.normal)
|
||||
: raw[type].diffs.normal
|
||||
),
|
||||
|
@ -483,7 +486,7 @@ export default defineComponent({
|
|||
}, {
|
||||
name: 'With file',
|
||||
type: 'area',
|
||||
data: format(type == 'combined'
|
||||
data: format(type === 'combined'
|
||||
? sum(raw.local.diffs.withFile, raw.remote.diffs.withFile)
|
||||
: raw[type].diffs.withFile
|
||||
),
|
||||
|
@ -492,7 +495,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchNotesTotalChart = async (): Promise<typeof data> => {
|
||||
const fetchNotesTotalChart = async (): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/notes', { limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
|
@ -511,7 +514,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchUsersChart = async (total: boolean): Promise<typeof data> => {
|
||||
const fetchUsersChart = async (total: boolean): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/users', { limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
|
@ -539,7 +542,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchActiveUsersChart = async (): Promise<typeof data> => {
|
||||
const fetchActiveUsersChart = async (): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/active-users', { limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
|
@ -591,7 +594,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchDriveChart = async (): Promise<typeof data> => {
|
||||
const fetchDriveChart = async (): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/drive', { limit: props.limit, span: props.span });
|
||||
return {
|
||||
bytes: true,
|
||||
|
@ -627,7 +630,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchDriveFilesChart = async (): Promise<typeof data> => {
|
||||
const fetchDriveFilesChart = async (): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/drive', { limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
|
@ -662,7 +665,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchInstanceRequestsChart = async (): Promise<typeof data> => {
|
||||
const fetchInstanceRequestsChart = async (): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/instance', { host: props.args.host, limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
|
@ -684,7 +687,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchInstanceUsersChart = async (total: boolean): Promise<typeof data> => {
|
||||
const fetchInstanceUsersChart = async (total: boolean): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/instance', { host: props.args.host, limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
|
@ -699,7 +702,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchInstanceNotesChart = async (total: boolean): Promise<typeof data> => {
|
||||
const fetchInstanceNotesChart = async (total: boolean): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/instance', { host: props.args.host, limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
|
@ -714,7 +717,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchInstanceFfChart = async (total: boolean): Promise<typeof data> => {
|
||||
const fetchInstanceFfChart = async (total: boolean): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/instance', { host: props.args.host, limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
|
@ -737,7 +740,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchInstanceDriveUsageChart = async (total: boolean): Promise<typeof data> => {
|
||||
const fetchInstanceDriveUsageChart = async (total: boolean): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/instance', { host: props.args.host, limit: props.limit, span: props.span });
|
||||
return {
|
||||
bytes: true,
|
||||
|
@ -753,7 +756,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchInstanceDriveFilesChart = async (total: boolean): Promise<typeof data> => {
|
||||
const fetchInstanceDriveFilesChart = async (total: boolean): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/instance', { host: props.args.host, limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
|
@ -768,7 +771,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchPerUserNotesChart = async (): Promise<typeof data> => {
|
||||
const fetchPerUserNotesChart = async (): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/user/notes', { userId: props.args.user.id, limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [...(props.args.withoutAll ? [] : [{
|
||||
|
@ -800,7 +803,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchPerUserFollowingChart = async (): Promise<typeof data> => {
|
||||
const fetchPerUserFollowingChart = async (): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/user/following', { userId: props.args.user.id, limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
|
@ -815,7 +818,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchPerUserFollowersChart = async (): Promise<typeof data> => {
|
||||
const fetchPerUserFollowersChart = async (): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/user/following', { userId: props.args.user.id, limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
|
@ -830,7 +833,7 @@ export default defineComponent({
|
|||
};
|
||||
};
|
||||
|
||||
const fetchPerUserDriveChart = async (): Promise<typeof data> => {
|
||||
const fetchPerUserDriveChart = async (): Promise<typeof chartData> => {
|
||||
const raw = await os.api('charts/user/drive', { userId: props.args.user.id, limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
|
@ -859,7 +862,6 @@ export default defineComponent({
|
|||
case 'notes-total': return fetchNotesTotalChart();
|
||||
case 'drive': return fetchDriveChart();
|
||||
case 'drive-files': return fetchDriveFilesChart();
|
||||
|
||||
case 'instance-requests': return fetchInstanceRequestsChart();
|
||||
case 'instance-users': return fetchInstanceUsersChart(false);
|
||||
case 'instance-users-total': return fetchInstanceUsersChart(true);
|
||||
|
@ -879,7 +881,7 @@ export default defineComponent({
|
|||
}
|
||||
};
|
||||
fetching.value = true;
|
||||
data = await fetchData();
|
||||
chartData = await fetchData();
|
||||
fetching.value = false;
|
||||
render();
|
||||
};
|
||||
|
@ -893,13 +895,7 @@ export default defineComponent({
|
|||
onUnmounted(() => {
|
||||
if (disposeTooltipComponent) disposeTooltipComponent();
|
||||
});
|
||||
|
||||
return {
|
||||
chartEl,
|
||||
fetching,
|
||||
};
|
||||
},
|
||||
});
|
||||
/* eslint-enable id-denylist */
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
Loading…
Reference in New Issue