mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 10:27:29 -04:00 
			
		
		
		
	This is the implementation of Recent Commits page. This feature was mentioned on #18262. It adds another tab to Activity page called Recent Commits. Recent Commits tab shows number of commits since last year for the repository.
		
			
				
	
	
		
			150 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <script>
 | |
| import {SvgIcon} from '../svg.js';
 | |
| import {
 | |
|   Chart,
 | |
|   Tooltip,
 | |
|   BarElement,
 | |
|   LinearScale,
 | |
|   TimeScale,
 | |
| } from 'chart.js';
 | |
| import {GET} from '../modules/fetch.js';
 | |
| import {Bar} from 'vue-chartjs';
 | |
| import {
 | |
|   startDaysBetween,
 | |
|   firstStartDateAfterDate,
 | |
|   fillEmptyStartDaysWithZeroes,
 | |
| } from '../utils/time.js';
 | |
| import {chartJsColors} from '../utils/color.js';
 | |
| import {sleep} from '../utils.js';
 | |
| import 'chartjs-adapter-dayjs-4/dist/chartjs-adapter-dayjs-4.esm';
 | |
| 
 | |
| const {pageData} = window.config;
 | |
| 
 | |
| Chart.defaults.color = chartJsColors.text;
 | |
| Chart.defaults.borderColor = chartJsColors.border;
 | |
| 
 | |
| Chart.register(
 | |
|   TimeScale,
 | |
|   LinearScale,
 | |
|   BarElement,
 | |
|   Tooltip,
 | |
| );
 | |
| 
 | |
| export default {
 | |
|   components: {Bar, SvgIcon},
 | |
|   props: {
 | |
|     locale: {
 | |
|       type: Object,
 | |
|       required: true
 | |
|     },
 | |
|   },
 | |
|   data: () => ({
 | |
|     isLoading: false,
 | |
|     errorText: '',
 | |
|     repoLink: pageData.repoLink || [],
 | |
|     data: [],
 | |
|   }),
 | |
|   mounted() {
 | |
|     this.fetchGraphData();
 | |
|   },
 | |
|   methods: {
 | |
|     async fetchGraphData() {
 | |
|       this.isLoading = true;
 | |
|       try {
 | |
|         let response;
 | |
|         do {
 | |
|           response = await GET(`${this.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 data = await response.json();
 | |
|           const start = Object.values(data)[0].week;
 | |
|           const end = firstStartDateAfterDate(new Date());
 | |
|           const startDays = startDaysBetween(new Date(start), new Date(end));
 | |
|           this.data = fillEmptyStartDaysWithZeroes(startDays, data).slice(-52);
 | |
|           this.errorText = '';
 | |
|         } else {
 | |
|           this.errorText = response.statusText;
 | |
|         }
 | |
|       } catch (err) {
 | |
|         this.errorText = err.message;
 | |
|       } finally {
 | |
|         this.isLoading = false;
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     toGraphData(data) {
 | |
|       return {
 | |
|         datasets: [
 | |
|           {
 | |
|             data: data.map((i) => ({x: i.week, y: i.commits})),
 | |
|             label: 'Commits',
 | |
|             backgroundColor: chartJsColors['commits'],
 | |
|             borderWidth: 0,
 | |
|             tension: 0.3,
 | |
|           },
 | |
|         ],
 | |
|       };
 | |
|     },
 | |
| 
 | |
|     getOptions() {
 | |
|       return {
 | |
|         responsive: true,
 | |
|         maintainAspectRatio: false,
 | |
|         animation: true,
 | |
|         scales: {
 | |
|           x: {
 | |
|             type: 'time',
 | |
|             grid: {
 | |
|               display: false,
 | |
|             },
 | |
|             time: {
 | |
|               minUnit: 'week',
 | |
|             },
 | |
|             ticks: {
 | |
|               maxRotation: 0,
 | |
|               maxTicksLimit: 52
 | |
|             },
 | |
|           },
 | |
|           y: {
 | |
|             ticks: {
 | |
|               maxTicksLimit: 6
 | |
|             },
 | |
|           },
 | |
|         },
 | |
|       };
 | |
|     },
 | |
|   },
 | |
| };
 | |
| </script>
 | |
| <template>
 | |
|   <div>
 | |
|     <div class="ui header gt-df gt-ac gt-sb">
 | |
|       {{ isLoading ? locale.loadingTitle : errorText ? locale.loadingTitleFailed: "Number of commits in the past year" }}
 | |
|     </div>
 | |
|     <div class="gt-df ui segment main-graph">
 | |
|       <div v-if="isLoading || errorText !== ''" class="gt-tc gt-m-auto">
 | |
|         <div v-if="isLoading">
 | |
|           <SvgIcon name="octicon-sync" class="gt-mr-3 job-status-rotate"/>
 | |
|           {{ 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="getOptions()"
 | |
|       />
 | |
|     </div>
 | |
|   </div>
 | |
| </template>
 | |
| <style scoped>
 | |
| .main-graph {
 | |
|   height: 250px;
 | |
| }
 | |
| </style>
 |