22 <Panel
33 class =" bg-transparent border-none"
44 header =" Lychee Pull Requests"
5- :pt:header:class =" 'justify-center text-4xl font-bold mb-8 '"
5+ :pt:header:class =" 'justify-center text-4xl font-bold'"
66 >
77 <div class =" flex flex-col max-w-4xl mx-auto gap-4 text-left" >
8+ <div class =" group mb-4 text-muted-color text-center cursor-pointer" @click =" refresh" >
9+ <span class =" group-hover:hidden" >Last update: {{ formattedUpdated }}</span >
10+ <span class =" hidden group-hover:inline text-primary-emphasis" >Click to clear cache.</span >
11+ </div >
812 <template v-if =" pullRequests " >
913 <template v-if =" pullRequests .length === 1 " >
1014 <PrList v-if =" pullRequests" :pull-requests =" pullRequests[0].data" />
3337
3438<script setup lang="ts">
3539import { Octokit } from ' octokit' ;
36- import { ref } from ' vue' ;
3740import { onMounted } from ' vue' ;
3841import { Panel } from ' primevue' ;
39- import {
40- type PullRequest ,
41- type PullRequestReview ,
42- type ReviewStatus ,
43- type User ,
44- APPROVED ,
45- CHANGES_REQUESTED ,
46- CONTRIBUTOR ,
47- } from ' ./ResponsesTypes.ts' ;
42+ import { type PullRequest } from ' ./ResponsesTypes.ts' ;
4843import { useSplitter } from ' ./composables/splitter' ;
4944import { computed } from ' vue' ;
5045import PrList from ' ./components/PrList.vue' ;
46+ import { useQueryStore } from ' ./stores/queryStore' ;
47+ import { useOctokitWrapper } from ' ./composables/octokitWrapper' ;
48+ import { useGetData } from ' ./composables/getData' ;
49+ import { storeToRefs } from ' pinia' ;
50+
51+ const queryStore = useQueryStore ();
52+ const { updated } = storeToRefs (queryStore );
53+ const octokit = new Octokit ();
54+
55+ const { fetchPullRequests, fetchPullRequestReviews } = useOctokitWrapper (octokit , queryStore );
56+ const { pullRequestsData, getPrs, getStatuses } = useGetData (fetchPullRequests , fetchPullRequestReviews );
5157
5258const { spliter } = useSplitter ();
53- const pullRequestsData = ref <(PullRequest & ReviewStatus )[] | undefined >(undefined );
5459const pullRequests = computed (() => {
5560 if (! pullRequestsData .value ) return undefined ;
5661 return spliter (pullRequestsData .value , prToGroup , prToGroup );
5762});
58- const octokit = new Octokit ();
59-
6063function prToGroup(pr : PullRequest ): string {
6164 if (! pr .head .ref .includes (' /' )) {
6265 return ' standalone' ;
@@ -65,91 +68,31 @@ function prToGroup(pr: PullRequest): string {
6568 return pr .head .ref .split (' /' )[0 ] || ' standalone' ;
6669}
6770
68- async function getPrs(): Promise <void > {
69- return octokit .rest .pulls
70- .list ({
71- owner: ' LycheeOrg' ,
72- repo: ' Lychee' ,
73- })
74- .then ((response ) => {
75- pullRequestsData .value = response .data as unknown as PullRequest [];
76- })
77- .catch ((error ) => {
78- console .error (' Error fetching pull requests:' , error );
79- });
80- }
81-
82- async function getStatuses() {
83- if (! pullRequestsData .value || pullRequestsData .value .length === 0 ) {
84- console .warn (' No pull requests available to fetch statuses for.' );
85- return ;
86- }
87-
88- pullRequestsData .value .forEach (async (pr , idx ) => {
89- await octokit .rest .pulls
90- .listReviews ({
91- owner: ' LycheeOrg' ,
92- repo: ' Lychee' ,
93- pull_number: pr .number , // Use the pull request number from the fetched PRs
94- })
95- .then ((response ) => {
96- console .log (
97- ` Pull request reviews for PR #${pr .number } fetched successfully: ` ,
98- response .data ,
99- );
100- if (! pullRequestsData .value ) {
101- console .warn (
102- ' pullRequestsData.value is undefined, cannot update review status.' ,
103- );
104- return ;
105- }
106-
107- pullRequestsData .value [idx ].review = extractStatusForPr (
108- response .data as PullRequestReview [],
109- ).review ;
110- })
111- .catch ((error ) => {
112- console .error (` Error fetching pull request reviews for PR #${pr .number }: ` , error );
113- });
114- });
115- }
116-
11771function allDrafts(prs : PullRequest []): boolean {
11872 return prs .every ((pr ) => pr .draft );
11973}
12074
121- function extractStatusForPr(reviews : PullRequestReview []): ReviewStatus {
122- // Loop through the reviews.
123- // Ignore all the reviews that are not from the contributors.
124- const statuses = reviews .reduce (
125- (acc , review ) => {
126- if (
127- (review .state === APPROVED || review .state === CHANGES_REQUESTED ) &&
128- review .author_association === CONTRIBUTOR
129- ) {
130- acc [review .user .login ] = { status: review .state , user: review .user };
131- }
132- return acc ;
133- },
134- {} as Record <string , { status: string ; user: User }>,
75+ const formattedUpdated = computed (() => {
76+ if (! updated .value ) return ' ' ;
77+ const date = new Date (updated .value );
78+ return (
79+ date .getDate () +
80+ ' /' +
81+ (date .getMonth () + 1 ) +
82+ ' /' +
83+ date .getFullYear () +
84+ ' ' +
85+ date .getHours () +
86+ ' :' +
87+ date .getMinutes ()
13588 );
89+ });
13690
137- const result: ReviewStatus = {
138- review: {
139- approved: false ,
140- changes_requested: false ,
141- by: [],
142- },
143- };
144- Object .entries (statuses ).forEach (([_no , review ]) => {
145- if (review .status === APPROVED ) {
146- result .review ! .approved = true ;
147- } else if (status === CHANGES_REQUESTED ) {
148- result .review ! .changes_requested = true ;
149- }
150- result .review ! .by .push (review .user );
151- });
152- return result ;
91+ async function refresh() {
92+ queryStore .reset ();
93+ pullRequestsData .value = undefined ;
94+ await getPrs ();
95+ getStatuses ();
15396}
15497
15598onMounted (async () => {
0 commit comments