1
+ <script lang="ts" setup>
2
+ import { NAlert , NSpace , NTable , NInput , NButton , NSelect , NThead , NTbody , NTh , NTd , NTr } from ' naive-ui' ;
3
+ import { ref , reactive } from ' vue' ;
4
+
5
+ const url = new URL (window .location .href );
6
+
7
+ const data = reactive ({
8
+ client_id: " " ,
9
+ client_secret: " " ,
10
+ access_token: url .searchParams .get (" access_token" ) || " " ,
11
+ refresh_token: " " ,
12
+ })
13
+
14
+ const way = ref <" access_token" | " refresh_token" >(" access_token" )
15
+
16
+ interface Token {
17
+ access_token: string ;
18
+ expires_in: number ;
19
+ refresh_token: string ;
20
+ scope: string ;
21
+ error: string ;
22
+ error_description: string ;
23
+ }
24
+
25
+ interface Album {
26
+ albums: {
27
+ id: string ,
28
+ title: string ,
29
+ productUrl: string ,
30
+ coverPhotoBaseUrl: string ,
31
+ coverPhotoMediaItemId: string ,
32
+ isWriteable: string ,
33
+ mediaItemsCount: string
34
+ }[];
35
+ nextPageToken: string ;
36
+ error: {
37
+ code: number ,
38
+ message: string ,
39
+ status: string ,
40
+ };
41
+ }
42
+
43
+ const token = ref <Token >();
44
+ const album = ref <Album >();
45
+ let albums = ref <Album [' albums' ]>([]);
46
+
47
+ const getToken = async () => {
48
+ const params = new URLSearchParams ();
49
+ params .append (" client_id" , data .client_id );
50
+ params .append (" client_secret" , data .client_secret );
51
+ params .append (" grant_type" , " refresh_token" );
52
+ params .append (" refresh_token" , data .refresh_token );
53
+
54
+ fetch (" https://www.googleapis.com/oauth2/v4/token" , {
55
+ method: " POST" ,
56
+ headers: {
57
+ " Content-Type" : " application/x-www-form-urlencoded" ,
58
+ },
59
+ body: params ,
60
+ })
61
+ .then ((resp ) => resp .json ())
62
+ .then ((res ) => {
63
+ console .log (res );
64
+ token .value = res
65
+ if (typeof (res .error ) == ' undefined' || ! res .error ) {
66
+ data .access_token = res .access_token
67
+ if (typeof (res .access_token ) != ' undefined' && res .access_token )
68
+ getAlbum (null )
69
+ }
70
+ });
71
+ };
72
+
73
+ const getAlbum = async (nextPageToken ) => {
74
+ if (nextPageToken == null )
75
+ nextPageToken = " "
76
+
77
+ fetch (` https://photoslibrary.googleapis.com/v1/albums?pageToken=${nextPageToken }&pageSize=50 ` , {
78
+ method: " GET" ,
79
+ headers: {
80
+ " Authorization" : ` Bearer ${data .access_token } ` ,
81
+ },
82
+ })
83
+ .then ((resp ) => resp .json ())
84
+ .then ((res ) => {
85
+ console .log (res );
86
+ album .value = res ;
87
+ if (typeof (res .error ) == ' undefined' || ! res .error ) {
88
+ albums .value = albums .value .concat (res .albums )
89
+ console .log (albums );
90
+ if (typeof (res .nextPageToken ) != ' undefined' && res .nextPageToken ) {
91
+ getAlbum (res .nextPageToken )
92
+ }
93
+ }
94
+ });
95
+ };
96
+
97
+ // auto get
98
+ if (data .access_token ) {
99
+ getAlbum (null )
100
+ }
101
+
102
+ function fetchAlbum() {
103
+ albums .value = []
104
+ if (way .value == ' refresh_token' )
105
+ getToken ()
106
+ else
107
+ getAlbum (null )
108
+ }
109
+
110
+ </script >
111
+
112
+ <template >
113
+ <NSpace vertical size =" large" >
114
+ <NSelect v-model:value =" way" size =" large" :options =" [
115
+ { label: 'Access token', value: 'access_token' },
116
+ { label: 'Client & Refresh token', value: 'refresh_token' }
117
+ ]" />
118
+ <NSpace v-if =" way == 'refresh_token'" vertical size =" large" >
119
+ <h4 >client_id</h4 >
120
+ <NInput size =" large" v-model:value =" data.client_id" />
121
+ <h4 >client_secret</h4 >
122
+ <NInput size =" large" v-model:value =" data.client_secret" />
123
+ <h4 >refresh_token</h4 >
124
+ <NInput size =" large" v-model:value =" data.refresh_token" />
125
+ </NSpace >
126
+ <NSpace v-else vertical size =" large" >
127
+ <h4 >access_token</h4 >
128
+ <NInput size =" large" v-model:value =" data.access_token" />
129
+ </NSpace >
130
+
131
+ <NButton size =" large" type =" primary" block @click =" fetchAlbum" >Fetch Album</NButton >
132
+ <NAlert :title =" token?.error" v-if =" token?.error || token?.error_description" type =" error" >
133
+ {{ token?.error_description }}
134
+ </NAlert >
135
+ <NAlert :title =" album?.error.status" v-if =" album?.error" type =" error" >
136
+ {{ album?.error.message }}
137
+ </NAlert >
138
+ <h4 >Albums</h4 >
139
+ <NTable size =" large" >
140
+ <NThead >
141
+ <NTr >
142
+ <NTh >Album Title</NTh >
143
+ <NTh >Album ID</NTh >
144
+ </NTr >
145
+ </NThead >
146
+ <NTbody >
147
+ <NTr v-for =" (item, _) in albums" >
148
+ <NTd >{{ item.title }}</NTd >
149
+ <NTd >{{ item.id }}</NTd >
150
+ </NTr >
151
+ </NTbody >
152
+ </NTable >
153
+ </NSpace >
154
+ </template >
155
+
156
+ <style scoped>
157
+ h4 ,
158
+ h3 {
159
+ margin : 0 ;
160
+ }
161
+
162
+ td {
163
+ word-break : break-all ;
164
+ word-wrap : break-word ;
165
+ }
166
+ </style >
0 commit comments