mirror of
https://github.com/go-gitea/gitea
synced 2024-12-22 16:44:26 +00:00
Fix typescript errors in Vue files, fix regression in "Recent Commits" chart (#32649)
- Fix all typescript errors in `.vue` files - Fix regression from https://github.com/go-gitea/gitea/pull/32329 where "Recent Commits" chart would not render. --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
parent
96d3a03a08
commit
1518f4ed12
@ -6,8 +6,17 @@ import {fomanticQuery} from '../modules/fomantic/base.ts';
|
|||||||
|
|
||||||
const {appSubUrl, assetUrlPrefix, pageData} = window.config;
|
const {appSubUrl, assetUrlPrefix, pageData} = window.config;
|
||||||
|
|
||||||
|
type CommitStatus = 'pending' | 'success' | 'error' | 'failure' | 'warning';
|
||||||
|
|
||||||
|
type CommitStatusMap = {
|
||||||
|
[status in CommitStatus]: {
|
||||||
|
name: string,
|
||||||
|
color: string,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// make sure this matches templates/repo/commit_status.tmpl
|
// make sure this matches templates/repo/commit_status.tmpl
|
||||||
const commitStatus = {
|
const commitStatus: CommitStatusMap = {
|
||||||
pending: {name: 'octicon-dot-fill', color: 'yellow'},
|
pending: {name: 'octicon-dot-fill', color: 'yellow'},
|
||||||
success: {name: 'octicon-check', color: 'green'},
|
success: {name: 'octicon-check', color: 'green'},
|
||||||
error: {name: 'gitea-exclamation', color: 'red'},
|
error: {name: 'gitea-exclamation', color: 'red'},
|
||||||
@ -281,18 +290,18 @@ const sfc = {
|
|||||||
return 'octicon-repo';
|
return 'octicon-repo';
|
||||||
},
|
},
|
||||||
|
|
||||||
statusIcon(status) {
|
statusIcon(status: CommitStatus) {
|
||||||
return commitStatus[status].name;
|
return commitStatus[status].name;
|
||||||
},
|
},
|
||||||
|
|
||||||
statusColor(status) {
|
statusColor(status: CommitStatus) {
|
||||||
return commitStatus[status].color;
|
return commitStatus[status].color;
|
||||||
},
|
},
|
||||||
|
|
||||||
reposFilterKeyControl(e) {
|
reposFilterKeyControl(e) {
|
||||||
switch (e.key) {
|
switch (e.key) {
|
||||||
case 'Enter':
|
case 'Enter':
|
||||||
document.querySelector('.repo-owner-name-list li.active a')?.click();
|
document.querySelector<HTMLAnchorElement>('.repo-owner-name-list li.active a')?.click();
|
||||||
break;
|
break;
|
||||||
case 'ArrowUp':
|
case 'ArrowUp':
|
||||||
if (this.activeIndex > 0) {
|
if (this.activeIndex > 0) {
|
||||||
|
@ -14,7 +14,7 @@ export default {
|
|||||||
issueLink: el.getAttribute('data-issuelink'),
|
issueLink: el.getAttribute('data-issuelink'),
|
||||||
locale: {
|
locale: {
|
||||||
filter_changes_by_commit: el.getAttribute('data-filter_changes_by_commit'),
|
filter_changes_by_commit: el.getAttribute('data-filter_changes_by_commit'),
|
||||||
},
|
} as Record<string, string>,
|
||||||
commits: [],
|
commits: [],
|
||||||
hoverActivated: false,
|
hoverActivated: false,
|
||||||
lastReviewCommitSha: null,
|
lastReviewCommitSha: null,
|
||||||
@ -41,16 +41,16 @@ export default {
|
|||||||
this.$el.removeEventListener('keyup', this.onKeyUp);
|
this.$el.removeEventListener('keyup', this.onKeyUp);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onBodyClick(event) {
|
onBodyClick(event: MouseEvent) {
|
||||||
// close this menu on click outside of this element when the dropdown is currently visible opened
|
// close this menu on click outside of this element when the dropdown is currently visible opened
|
||||||
if (this.$el.contains(event.target)) return;
|
if (this.$el.contains(event.target)) return;
|
||||||
if (this.menuVisible) {
|
if (this.menuVisible) {
|
||||||
this.toggleMenu();
|
this.toggleMenu();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onKeyDown(event) {
|
onKeyDown(event: KeyboardEvent) {
|
||||||
if (!this.menuVisible) return;
|
if (!this.menuVisible) return;
|
||||||
const item = document.activeElement;
|
const item = document.activeElement as HTMLElement;
|
||||||
if (!this.$el.contains(item)) return;
|
if (!this.$el.contains(item)) return;
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case 'ArrowDown': // select next element
|
case 'ArrowDown': // select next element
|
||||||
@ -73,7 +73,7 @@ export default {
|
|||||||
if (commitIdx) this.highlight(this.commits[commitIdx]);
|
if (commitIdx) this.highlight(this.commits[commitIdx]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onKeyUp(event) {
|
onKeyUp(event: KeyboardEvent) {
|
||||||
if (!this.menuVisible) return;
|
if (!this.menuVisible) return;
|
||||||
const item = document.activeElement;
|
const item = document.activeElement;
|
||||||
if (!this.$el.contains(item)) return;
|
if (!this.$el.contains(item)) return;
|
||||||
@ -95,7 +95,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
/** Focus given element */
|
/** Focus given element */
|
||||||
focusElem(elem, prevElem) {
|
focusElem(elem: HTMLElement, prevElem: HTMLElement) {
|
||||||
if (elem) {
|
if (elem) {
|
||||||
elem.tabIndex = 0;
|
elem.tabIndex = 0;
|
||||||
if (prevElem) prevElem.tabIndex = -1;
|
if (prevElem) prevElem.tabIndex = -1;
|
||||||
@ -149,7 +149,7 @@ export default {
|
|||||||
window.location.assign(`${this.issueLink}/files/${this.lastReviewCommitSha}..${this.commits.at(-1).id}${this.queryParams}`);
|
window.location.assign(`${this.issueLink}/files/${this.lastReviewCommitSha}..${this.commits.at(-1).id}${this.queryParams}`);
|
||||||
},
|
},
|
||||||
/** Clicking on a single commit opens this specific commit */
|
/** Clicking on a single commit opens this specific commit */
|
||||||
commitClicked(commitId, newWindow = false) {
|
commitClicked(commitId: string, newWindow = false) {
|
||||||
const url = `${this.issueLink}/commits/${commitId}${this.queryParams}`;
|
const url = `${this.issueLink}/commits/${commitId}${this.queryParams}`;
|
||||||
if (newWindow) {
|
if (newWindow) {
|
||||||
window.open(url);
|
window.open(url);
|
||||||
|
@ -8,6 +8,8 @@ import {
|
|||||||
PointElement,
|
PointElement,
|
||||||
LineElement,
|
LineElement,
|
||||||
Filler,
|
Filler,
|
||||||
|
type ChartOptions,
|
||||||
|
type ChartData,
|
||||||
} from 'chart.js';
|
} from 'chart.js';
|
||||||
import {GET} from '../modules/fetch.ts';
|
import {GET} from '../modules/fetch.ts';
|
||||||
import {Line as ChartLine} from 'vue-chartjs';
|
import {Line as ChartLine} from 'vue-chartjs';
|
||||||
@ -16,6 +18,7 @@ import {
|
|||||||
firstStartDateAfterDate,
|
firstStartDateAfterDate,
|
||||||
fillEmptyStartDaysWithZeroes,
|
fillEmptyStartDaysWithZeroes,
|
||||||
type DayData,
|
type DayData,
|
||||||
|
type DayDataObject,
|
||||||
} from '../utils/time.ts';
|
} from '../utils/time.ts';
|
||||||
import {chartJsColors} from '../utils/color.ts';
|
import {chartJsColors} from '../utils/color.ts';
|
||||||
import {sleep} from '../utils.ts';
|
import {sleep} from '../utils.ts';
|
||||||
@ -64,12 +67,12 @@ async function fetchGraphData() {
|
|||||||
}
|
}
|
||||||
} while (response.status === 202);
|
} while (response.status === 202);
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
data.value = await response.json();
|
const dayDataObject: DayDataObject = await response.json();
|
||||||
const weekValues = Object.values(data.value);
|
const weekValues = Object.values(dayDataObject);
|
||||||
const start = weekValues[0].week;
|
const start = weekValues[0].week;
|
||||||
const end = firstStartDateAfterDate(new Date());
|
const end = firstStartDateAfterDate(new Date());
|
||||||
const startDays = startDaysBetween(start, end);
|
const startDays = startDaysBetween(start, end);
|
||||||
data.value = fillEmptyStartDaysWithZeroes(startDays, data.value);
|
data.value = fillEmptyStartDaysWithZeroes(startDays, dayDataObject);
|
||||||
errorText.value = '';
|
errorText.value = '';
|
||||||
} else {
|
} else {
|
||||||
errorText.value = response.statusText;
|
errorText.value = response.statusText;
|
||||||
@ -81,7 +84,7 @@ async function fetchGraphData() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toGraphData(data) {
|
function toGraphData(data: Array<Record<string, any>>): ChartData<'line'> {
|
||||||
return {
|
return {
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
@ -108,10 +111,9 @@ function toGraphData(data) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = {
|
const options: ChartOptions<'line'> = {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
maintainAspectRatio: false,
|
maintainAspectRatio: false,
|
||||||
animation: true,
|
|
||||||
plugins: {
|
plugins: {
|
||||||
legend: {
|
legend: {
|
||||||
display: true,
|
display: true,
|
||||||
|
@ -9,6 +9,9 @@ import {
|
|||||||
PointElement,
|
PointElement,
|
||||||
LineElement,
|
LineElement,
|
||||||
Filler,
|
Filler,
|
||||||
|
type ChartOptions,
|
||||||
|
type ChartData,
|
||||||
|
type Plugin,
|
||||||
} from 'chart.js';
|
} from 'chart.js';
|
||||||
import {GET} from '../modules/fetch.ts';
|
import {GET} from '../modules/fetch.ts';
|
||||||
import zoomPlugin from 'chartjs-plugin-zoom';
|
import zoomPlugin from 'chartjs-plugin-zoom';
|
||||||
@ -22,8 +25,9 @@ import {chartJsColors} from '../utils/color.ts';
|
|||||||
import {sleep} from '../utils.ts';
|
import {sleep} from '../utils.ts';
|
||||||
import 'chartjs-adapter-dayjs-4/dist/chartjs-adapter-dayjs-4.esm';
|
import 'chartjs-adapter-dayjs-4/dist/chartjs-adapter-dayjs-4.esm';
|
||||||
import {fomanticQuery} from '../modules/fomantic/base.ts';
|
import {fomanticQuery} from '../modules/fomantic/base.ts';
|
||||||
|
import type {Entries} from 'type-fest';
|
||||||
|
|
||||||
const customEventListener = {
|
const customEventListener: Plugin = {
|
||||||
id: 'customEventListener',
|
id: 'customEventListener',
|
||||||
afterEvent: (chart, args, opts) => {
|
afterEvent: (chart, args, opts) => {
|
||||||
// event will be replayed from chart.update when reset zoom,
|
// event will be replayed from chart.update when reset zoom,
|
||||||
@ -65,10 +69,10 @@ export default {
|
|||||||
data: () => ({
|
data: () => ({
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
errorText: '',
|
errorText: '',
|
||||||
totalStats: {},
|
totalStats: {} as Record<string, any>,
|
||||||
sortedContributors: {},
|
sortedContributors: {} as Record<string, any>,
|
||||||
type: 'commits',
|
type: 'commits',
|
||||||
contributorsStats: [],
|
contributorsStats: {} as Record<string, any>,
|
||||||
xAxisStart: null,
|
xAxisStart: null,
|
||||||
xAxisEnd: null,
|
xAxisEnd: null,
|
||||||
xAxisMin: null,
|
xAxisMin: null,
|
||||||
@ -99,7 +103,7 @@ export default {
|
|||||||
async fetchGraphData() {
|
async fetchGraphData() {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
try {
|
try {
|
||||||
let response;
|
let response: Response;
|
||||||
do {
|
do {
|
||||||
response = await GET(`${this.repoLink}/activity/contributors/data`);
|
response = await GET(`${this.repoLink}/activity/contributors/data`);
|
||||||
if (response.status === 202) {
|
if (response.status === 202) {
|
||||||
@ -112,7 +116,7 @@ export default {
|
|||||||
// below line might be deleted if we are sure go produces map always sorted by keys
|
// below line might be deleted if we are sure go produces map always sorted by keys
|
||||||
total.weeks = Object.fromEntries(Object.entries(total.weeks).sort());
|
total.weeks = Object.fromEntries(Object.entries(total.weeks).sort());
|
||||||
|
|
||||||
const weekValues = Object.values(total.weeks);
|
const weekValues = Object.values(total.weeks) as any;
|
||||||
this.xAxisStart = weekValues[0].week;
|
this.xAxisStart = weekValues[0].week;
|
||||||
this.xAxisEnd = firstStartDateAfterDate(new Date());
|
this.xAxisEnd = firstStartDateAfterDate(new Date());
|
||||||
const startDays = startDaysBetween(this.xAxisStart, this.xAxisEnd);
|
const startDays = startDaysBetween(this.xAxisStart, this.xAxisEnd);
|
||||||
@ -120,7 +124,7 @@ export default {
|
|||||||
this.xAxisMin = this.xAxisStart;
|
this.xAxisMin = this.xAxisStart;
|
||||||
this.xAxisMax = this.xAxisEnd;
|
this.xAxisMax = this.xAxisEnd;
|
||||||
this.contributorsStats = {};
|
this.contributorsStats = {};
|
||||||
for (const [email, user] of Object.entries(rest)) {
|
for (const [email, user] of Object.entries(rest) as Entries<Record<string, Record<string, any>>>) {
|
||||||
user.weeks = fillEmptyStartDaysWithZeroes(startDays, user.weeks);
|
user.weeks = fillEmptyStartDaysWithZeroes(startDays, user.weeks);
|
||||||
this.contributorsStats[email] = user;
|
this.contributorsStats[email] = user;
|
||||||
}
|
}
|
||||||
@ -146,7 +150,7 @@ export default {
|
|||||||
user.total_additions = 0;
|
user.total_additions = 0;
|
||||||
user.total_deletions = 0;
|
user.total_deletions = 0;
|
||||||
user.max_contribution_type = 0;
|
user.max_contribution_type = 0;
|
||||||
const filteredWeeks = user.weeks.filter((week) => {
|
const filteredWeeks = user.weeks.filter((week: Record<string, number>) => {
|
||||||
const oneWeek = 7 * 24 * 60 * 60 * 1000;
|
const oneWeek = 7 * 24 * 60 * 60 * 1000;
|
||||||
if (week.week >= this.xAxisMin - oneWeek && week.week <= this.xAxisMax + oneWeek) {
|
if (week.week >= this.xAxisMin - oneWeek && week.week <= this.xAxisMax + oneWeek) {
|
||||||
user.total_commits += week.commits;
|
user.total_commits += week.commits;
|
||||||
@ -195,7 +199,7 @@ export default {
|
|||||||
return (1 - (coefficient % 1)) * 10 ** exp + maxValue;
|
return (1 - (coefficient % 1)) * 10 ** exp + maxValue;
|
||||||
},
|
},
|
||||||
|
|
||||||
toGraphData(data) {
|
toGraphData(data: Array<Record<string, any>>): ChartData<'line'> {
|
||||||
return {
|
return {
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
@ -211,9 +215,9 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
updateOtherCharts(event, reset) {
|
updateOtherCharts({chart}: {chart: Chart}, reset?: boolean = false) {
|
||||||
const minVal = event.chart.options.scales.x.min;
|
const minVal = chart.options.scales.x.min;
|
||||||
const maxVal = event.chart.options.scales.x.max;
|
const maxVal = chart.options.scales.x.max;
|
||||||
if (reset) {
|
if (reset) {
|
||||||
this.xAxisMin = this.xAxisStart;
|
this.xAxisMin = this.xAxisStart;
|
||||||
this.xAxisMax = this.xAxisEnd;
|
this.xAxisMax = this.xAxisEnd;
|
||||||
@ -225,7 +229,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getOptions(type) {
|
getOptions(type: string): ChartOptions<'line'> {
|
||||||
return {
|
return {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
maintainAspectRatio: false,
|
maintainAspectRatio: false,
|
||||||
@ -238,6 +242,7 @@ export default {
|
|||||||
position: 'top',
|
position: 'top',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
|
// @ts-expect-error: bug in chart.js types
|
||||||
customEventListener: {
|
customEventListener: {
|
||||||
chartType: type,
|
chartType: type,
|
||||||
instance: this,
|
instance: this,
|
||||||
|
@ -7,6 +7,7 @@ import {
|
|||||||
LinearScale,
|
LinearScale,
|
||||||
TimeScale,
|
TimeScale,
|
||||||
type ChartOptions,
|
type ChartOptions,
|
||||||
|
type ChartData,
|
||||||
} from 'chart.js';
|
} from 'chart.js';
|
||||||
import {GET} from '../modules/fetch.ts';
|
import {GET} from '../modules/fetch.ts';
|
||||||
import {Bar} from 'vue-chartjs';
|
import {Bar} from 'vue-chartjs';
|
||||||
@ -15,6 +16,7 @@ import {
|
|||||||
firstStartDateAfterDate,
|
firstStartDateAfterDate,
|
||||||
fillEmptyStartDaysWithZeroes,
|
fillEmptyStartDaysWithZeroes,
|
||||||
type DayData,
|
type DayData,
|
||||||
|
type DayDataObject,
|
||||||
} from '../utils/time.ts';
|
} from '../utils/time.ts';
|
||||||
import {chartJsColors} from '../utils/color.ts';
|
import {chartJsColors} from '../utils/color.ts';
|
||||||
import {sleep} from '../utils.ts';
|
import {sleep} from '../utils.ts';
|
||||||
@ -61,11 +63,11 @@ async function fetchGraphData() {
|
|||||||
}
|
}
|
||||||
} while (response.status === 202);
|
} while (response.status === 202);
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const data = await response.json();
|
const dayDataObj: DayDataObject = await response.json();
|
||||||
const start = Object.values(data)[0].week;
|
const start = Object.values(dayDataObj)[0].week;
|
||||||
const end = firstStartDateAfterDate(new Date());
|
const end = firstStartDateAfterDate(new Date());
|
||||||
const startDays = startDaysBetween(start, end);
|
const startDays = startDaysBetween(start, end);
|
||||||
data.value = fillEmptyStartDaysWithZeroes(startDays, data).slice(-52);
|
data.value = fillEmptyStartDaysWithZeroes(startDays, dayDataObj).slice(-52);
|
||||||
errorText.value = '';
|
errorText.value = '';
|
||||||
} else {
|
} else {
|
||||||
errorText.value = response.statusText;
|
errorText.value = response.statusText;
|
||||||
@ -77,10 +79,11 @@ async function fetchGraphData() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toGraphData(data) {
|
function toGraphData(data: DayData[]): ChartData<'bar'> {
|
||||||
return {
|
return {
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
|
// @ts-expect-error -- bar chart expects one-dimensional data, but apparently x/y still works
|
||||||
data: data.map((i) => ({x: i.week, y: i.commits})),
|
data: data.map((i) => ({x: i.week, y: i.commits})),
|
||||||
label: 'Commits',
|
label: 'Commits',
|
||||||
backgroundColor: chartJsColors['commits'],
|
backgroundColor: chartJsColors['commits'],
|
||||||
@ -91,10 +94,9 @@ function toGraphData(data) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = {
|
const options: ChartOptions<'bar'> = {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
maintainAspectRatio: false,
|
maintainAspectRatio: false,
|
||||||
animation: true,
|
|
||||||
scales: {
|
scales: {
|
||||||
x: {
|
x: {
|
||||||
type: 'time',
|
type: 'time',
|
||||||
|
@ -49,7 +49,11 @@ export type DayData = {
|
|||||||
commits: number,
|
commits: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fillEmptyStartDaysWithZeroes(startDays: number[], data: DayData[]): DayData[] {
|
export type DayDataObject = {
|
||||||
|
[timestamp: string]: DayData,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fillEmptyStartDaysWithZeroes(startDays: number[], data: DayDataObject): DayData[] {
|
||||||
const result = {};
|
const result = {};
|
||||||
|
|
||||||
for (const startDay of startDays) {
|
for (const startDay of startDays) {
|
||||||
|
Loading…
Reference in New Issue
Block a user