mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-11-04 08:21:11 +00:00 
			
		
		
		
	This will conclude the refactor of 1:1 class replacements to tailwind,
except `gt-hidden`. Commands ran:
```bash
perl -p -i -e 's#gt-(p|m)([lrtbxy])?-0#tw-$1$2-0#g'   {web_src/js,templates,routers,services}/**/*
perl -p -i -e 's#gt-(p|m)([lrtbxy])?-1#tw-$1$2-0.5#g' {web_src/js,templates,routers,services}/**/*
perl -p -i -e 's#gt-(p|m)([lrtbxy])?-2#tw-$1$2-1#g'   {web_src/js,templates,routers,services}/**/*
perl -p -i -e 's#gt-(p|m)([lrtbxy])?-3#tw-$1$2-2#g'   {web_src/js,templates,routers,services}/**/*
perl -p -i -e 's#gt-(p|m)([lrtbxy])?-4#tw-$1$2-4#g'   {web_src/js,templates,routers,services}/**/*
perl -p -i -e 's#gt-(p|m)([lrtbxy])?-5#tw-$1$2-8#g'   {web_src/js,templates,routers,services}/**/*
```
(cherry picked from commit 68ec9b48592fe88765bcc3a73093d43c98b315de)
Conflicts:
	routers/web/repo/view.go
	templates/base/head_navbar.tmpl
	templates/repo/code/recently_pushed_new_branches.tmpl
	templates/repo/diff/box.tmpl
	templates/repo/diff/compare.tmpl
	templates/repo/diff/conversation.tmpl
	templates/repo/header.tmpl
	templates/repo/issue/filter_list.tmpl
	templates/repo/issue/view_content/conversation.tmpl
	templates/repo/issue/view_content/sidebar.tmpl
	templates/repo/settings/options.tmpl
	templates/repo/view_file.tmpl
	templates/shared/user/blocked_users.tmpl
	templates/status/500.tmpl
	web_src/js/components/DashboardRepoList.vue
	resolved by prefering Forgejo version and applying the
	commands to all files
		
	
			
		
			
				
	
	
		
			172 lines
		
	
	
	
		
			4.2 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
	
		
			4.2 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
<script>
 | 
						|
import {SvgIcon} from '../svg.js';
 | 
						|
import {
 | 
						|
  Chart,
 | 
						|
  Legend,
 | 
						|
  LinearScale,
 | 
						|
  TimeScale,
 | 
						|
  PointElement,
 | 
						|
  LineElement,
 | 
						|
  Filler,
 | 
						|
} from 'chart.js';
 | 
						|
import {GET} from '../modules/fetch.js';
 | 
						|
import {Line as ChartLine} 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,
 | 
						|
  Legend,
 | 
						|
  PointElement,
 | 
						|
  LineElement,
 | 
						|
  Filler,
 | 
						|
);
 | 
						|
 | 
						|
export default {
 | 
						|
  components: {ChartLine, 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/code-frequency/data`);
 | 
						|
          if (response.status === 202) {
 | 
						|
            await sleep(1000); // wait for 1 second before retrying
 | 
						|
          }
 | 
						|
        } while (response.status === 202);
 | 
						|
        if (response.ok) {
 | 
						|
          this.data = await response.json();
 | 
						|
          const weekValues = Object.values(this.data);
 | 
						|
          const start = weekValues[0].week;
 | 
						|
          const end = firstStartDateAfterDate(new Date());
 | 
						|
          const startDays = startDaysBetween(new Date(start), new Date(end));
 | 
						|
          this.data = fillEmptyStartDaysWithZeroes(startDays, this.data);
 | 
						|
          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.additions})),
 | 
						|
            pointRadius: 0,
 | 
						|
            pointHitRadius: 0,
 | 
						|
            fill: true,
 | 
						|
            label: 'Additions',
 | 
						|
            backgroundColor: chartJsColors['additions'],
 | 
						|
            borderWidth: 0,
 | 
						|
            tension: 0.3,
 | 
						|
          },
 | 
						|
          {
 | 
						|
            data: data.map((i) => ({x: i.week, y: -i.deletions})),
 | 
						|
            pointRadius: 0,
 | 
						|
            pointHitRadius: 0,
 | 
						|
            fill: true,
 | 
						|
            label: 'Deletions',
 | 
						|
            backgroundColor: chartJsColors['deletions'],
 | 
						|
            borderWidth: 0,
 | 
						|
            tension: 0.3,
 | 
						|
          },
 | 
						|
        ],
 | 
						|
      };
 | 
						|
    },
 | 
						|
 | 
						|
    getOptions() {
 | 
						|
      return {
 | 
						|
        responsive: true,
 | 
						|
        maintainAspectRatio: false,
 | 
						|
        animation: true,
 | 
						|
        plugins: {
 | 
						|
          legend: {
 | 
						|
            display: true,
 | 
						|
          },
 | 
						|
        },
 | 
						|
        scales: {
 | 
						|
          x: {
 | 
						|
            type: 'time',
 | 
						|
            grid: {
 | 
						|
              display: false,
 | 
						|
            },
 | 
						|
            time: {
 | 
						|
              minUnit: 'month',
 | 
						|
            },
 | 
						|
            ticks: {
 | 
						|
              maxRotation: 0,
 | 
						|
              maxTicksLimit: 12,
 | 
						|
            },
 | 
						|
          },
 | 
						|
          y: {
 | 
						|
            ticks: {
 | 
						|
              maxTicksLimit: 6,
 | 
						|
            },
 | 
						|
          },
 | 
						|
        },
 | 
						|
      };
 | 
						|
    },
 | 
						|
  },
 | 
						|
};
 | 
						|
</script>
 | 
						|
<template>
 | 
						|
  <div>
 | 
						|
    <div class="ui header tw-flex tw-items-center tw-justify-between">
 | 
						|
      {{ isLoading ? locale.loadingTitle : errorText ? locale.loadingTitleFailed: `Code frequency over the history of ${repoLink.slice(1)}` }}
 | 
						|
    </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 job-status-rotate"/>
 | 
						|
          {{ locale.loadingInfo }}
 | 
						|
        </div>
 | 
						|
        <div v-else class="text red">
 | 
						|
          <SvgIcon name="octicon-x-circle-fill"/>
 | 
						|
          {{ errorText }}
 | 
						|
        </div>
 | 
						|
      </div>
 | 
						|
      <ChartLine
 | 
						|
        v-memo="data" v-if="data.length !== 0"
 | 
						|
        :data="toGraphData(data)" :options="getOptions()"
 | 
						|
      />
 | 
						|
    </div>
 | 
						|
  </div>
 | 
						|
</template>
 | 
						|
<style scoped>
 | 
						|
.main-graph {
 | 
						|
  height: 440px;
 | 
						|
}
 | 
						|
</style>
 |