mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-29 10:57:44 +09:00 
			
		
		
		
	This PR improves some `.vue` components by using `shallowRef instead of ref`, which `should improve performance`. It's probably not significant, but it's an improvement because Vue no longer deep watches the ref (shallowRef). Also i used `useTemplateRef` instead of `ref`. --------- Signed-off-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
		
			
				
	
	
		
			151 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <script lang="ts" setup>
 | |
| import {SvgIcon} from '../svg.ts';
 | |
| import {
 | |
|   Chart,
 | |
|   Tooltip,
 | |
|   BarElement,
 | |
|   LinearScale,
 | |
|   TimeScale,
 | |
|   type ChartOptions,
 | |
|   type ChartData,
 | |
| } from 'chart.js';
 | |
| import {GET} from '../modules/fetch.ts';
 | |
| import {Bar} from 'vue-chartjs';
 | |
| import {
 | |
|   startDaysBetween,
 | |
|   firstStartDateAfterDate,
 | |
|   fillEmptyStartDaysWithZeroes,
 | |
|   type DayData,
 | |
|   type DayDataObject,
 | |
| } from '../utils/time.ts';
 | |
| import {chartJsColors} from '../utils/color.ts';
 | |
| import {sleep} from '../utils.ts';
 | |
| import 'chartjs-adapter-dayjs-4/dist/chartjs-adapter-dayjs-4.esm';
 | |
| import {onMounted, ref, shallowRef} from 'vue';
 | |
| 
 | |
| const {pageData} = window.config;
 | |
| 
 | |
| Chart.defaults.color = chartJsColors.text;
 | |
| Chart.defaults.borderColor = chartJsColors.border;
 | |
| 
 | |
| Chart.register(
 | |
|   TimeScale,
 | |
|   LinearScale,
 | |
|   BarElement,
 | |
|   Tooltip,
 | |
| );
 | |
| 
 | |
| defineProps<{
 | |
|   locale: {
 | |
|     loadingTitle: string;
 | |
|     loadingTitleFailed: string;
 | |
|     loadingInfo: string;
 | |
|   };
 | |
| }>();
 | |
| 
 | |
| const isLoading = shallowRef(false);
 | |
| const errorText = shallowRef('');
 | |
| const repoLink = pageData.repoLink;
 | |
| const data = ref<DayData[]>([]);
 | |
| 
 | |
| onMounted(() => {
 | |
|   fetchGraphData();
 | |
| });
 | |
| 
 | |
| async function fetchGraphData() {
 | |
|   isLoading.value = true;
 | |
|   try {
 | |
|     let response: Response;
 | |
|     do {
 | |
|       response = await GET(`${repoLink}/activity/recent-commits/data`);
 | |
|       if (response.status === 202) {
 | |
|         await sleep(1000); // wait for 1 second before retrying
 | |
|       }
 | |
|     } while (response.status === 202);
 | |
|     if (response.ok) {
 | |
|       const dayDataObj: DayDataObject = await response.json();
 | |
|       const start = Object.values(dayDataObj)[0].week;
 | |
|       const end = firstStartDateAfterDate(new Date());
 | |
|       const startDays = startDaysBetween(start, end);
 | |
|       data.value = fillEmptyStartDaysWithZeroes(startDays, dayDataObj).slice(-52);
 | |
|       errorText.value = '';
 | |
|     } else {
 | |
|       errorText.value = response.statusText;
 | |
|     }
 | |
|   } catch (err) {
 | |
|     errorText.value = err.message;
 | |
|   } finally {
 | |
|     isLoading.value = false;
 | |
|   }
 | |
| }
 | |
| 
 | |
| function toGraphData(data: DayData[]): ChartData<'bar'> {
 | |
|   return {
 | |
|     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})),
 | |
|         label: 'Commits',
 | |
|         backgroundColor: chartJsColors['commits'],
 | |
|         borderWidth: 0,
 | |
|         tension: 0.3,
 | |
|       },
 | |
|     ],
 | |
|   };
 | |
| }
 | |
| 
 | |
| const options: ChartOptions<'bar'> = {
 | |
|   responsive: true,
 | |
|   maintainAspectRatio: false,
 | |
|   scales: {
 | |
|     x: {
 | |
|       type: 'time',
 | |
|       grid: {
 | |
|         display: false,
 | |
|       },
 | |
|       time: {
 | |
|         minUnit: 'week',
 | |
|       },
 | |
|       ticks: {
 | |
|         maxRotation: 0,
 | |
|         maxTicksLimit: 52,
 | |
|       },
 | |
|     },
 | |
|     y: {
 | |
|       ticks: {
 | |
|         maxTicksLimit: 6,
 | |
|       },
 | |
|     },
 | |
|   },
 | |
| } satisfies ChartOptions;
 | |
| </script>
 | |
| 
 | |
| <template>
 | |
|   <div>
 | |
|     <div class="ui header tw-flex tw-items-center tw-justify-between">
 | |
|       {{ isLoading ? locale.loadingTitle : errorText ? locale.loadingTitleFailed: "Number of commits in the past year" }}
 | |
|     </div>
 | |
|     <div class="tw-flex ui segment main-graph">
 | |
|       <div v-if="isLoading || errorText !== ''" class="gt-tc tw-m-auto">
 | |
|         <div v-if="isLoading">
 | |
|           <SvgIcon name="octicon-sync" class="tw-mr-2 circular-spin"/>
 | |
|           {{ locale.loadingInfo }}
 | |
|         </div>
 | |
|         <div v-else class="text red">
 | |
|           <SvgIcon name="octicon-x-circle-fill"/>
 | |
|           {{ errorText }}
 | |
|         </div>
 | |
|       </div>
 | |
|       <Bar
 | |
|         v-memo="data" v-if="data.length !== 0"
 | |
|         :data="toGraphData(data)" :options="options"
 | |
|       />
 | |
|     </div>
 | |
|   </div>
 | |
| </template>
 | |
| <style scoped>
 | |
| .main-graph {
 | |
|   height: 250px;
 | |
| }
 | |
| </style>
 |