1
1
<template >
2
2
<div class =" timetable" >
3
3
<div v-if =" !this.loaded" class =" lds-dual-ring" ></div >
4
- <div v-else class =' container' >
5
- <div class =' info' >{{ this.groupInfo.number }} группа</div >
6
- <div class =" no-events" v-if =" !this.timetable.length" >пары отсутствуют</div >
4
+ <div v-else class =" container" >
5
+ <div class =" info" >{{ this.groupInfo.number }} группа</div >
6
+ <div class =" no-events" v-if =" !this.timetable.length" >
7
+ пары отсутствуют
8
+ </div >
7
9
<ul v-else >
8
- <EventRow v-for =" lesson of this.timetable" :key =' lesson.id' :lesson =" lesson" />
10
+ <EventRow
11
+ v-for =" lesson of this.timetable"
12
+ :key =" lesson.id"
13
+ :lesson =" lesson"
14
+ />
9
15
</ul >
10
-
11
16
</div >
12
17
</div >
13
18
</template >
14
19
15
20
<script >
16
- import EventRow from ' @/components/EventRow.vue'
21
+ import EventRow from " @/components/EventRow.vue" ;
22
+ import retry from " @/utils/Retrying.js" ;
23
+ import { fetchTimetable } from " @/utils/FetchTimetable.js" ;
24
+ import { getMonday , getMidnight , isToday } from " @/utils/Dates.js" ;
25
+
17
26
export default {
18
27
name: " Timetable" ,
19
28
data () {
@@ -22,78 +31,132 @@ export default {
22
31
pageId: 1 ,
23
32
date: new Date (),
24
33
groupId: null ,
25
- groupInfo: { number: ' ' },
26
- timetable: []
34
+ groupInfo: { number: " " },
35
+ timetable: [],
27
36
};
28
37
},
29
38
components: {
30
39
EventRow: EventRow,
31
40
},
32
41
methods: {
33
42
loadGroupInfo () {
34
- var url = new URL (` ${ process .env .VUE_APP_API_TIMETABLE } /timetable/group/${ this .groupId } ` );
35
- fetch (url).then (response => response .json ())
36
- .then (json => {
37
- this .groupInfo = json;
38
- })
43
+ // Loading from cache if exists
44
+ try {
45
+ this .groupInfo = JSON .parse (
46
+ localStorage .getItem (" timetable-group-info" ) || ' {"number": ""}'
47
+ );
48
+ } catch (err) {
49
+ console .log (" Can not take group info from cache" , err);
50
+ }
51
+
52
+ // Loading from internet else
53
+ try {
54
+ fetch (
55
+ ` ${ process .env .VUE_APP_API_TIMETABLE } /timetable/group/${ this .groupId } `
56
+ )
57
+ .then ((response ) => response .json ())
58
+ .then ((json ) => {
59
+ this .groupInfo = json;
60
+ localStorage .setItem (" timetable-group-info" , JSON .stringify (json));
61
+ });
62
+ } catch (error) {
63
+ console .error (" Failed to load group info" );
64
+ }
39
65
},
40
66
loadTimetableOnDate (date ) {
41
- var time_start = new Date (date);
42
- time_start .setHours (time_start .getHours () - date .getTimezoneOffset () / 60 )
67
+ var time_start = getMidnight (date);
43
68
var time_end = new Date (time_start);
44
- time_end .setDate (time_start .getDate () + 1 )
45
- var url = new URL (` ${ process .env .VUE_APP_API_TIMETABLE } /timetable/event/` ),
46
- params = {
47
- start: time_start .toISOString ().slice (0 , 10 ),
48
- end: time_end .toISOString ().slice (0 , 10 ),
49
- limit: 0 ,
50
- offset: 0 ,
51
- group_id: this .groupId
52
- }
53
- Object .keys (params).forEach (key => url .searchParams .append (key, params[key]))
54
- this .loaded = false ;
55
- fetch (url).then (response => response .json ())
56
- .then (json => {
57
- this .timetable = json .items ;
58
- this .loaded = true ;
59
- })
69
+ time_end .setDate (time_start .getDate () + 1 );
70
+
71
+ // Quering events from internet, trying 5 times with 1sec between
72
+ try {
73
+ retry (
74
+ () =>
75
+ fetchTimetable (time_start, time_end, this .groupId ).then ((json ) => {
76
+ this .timetable = json .items ;
77
+ this .loaded = true ;
78
+ console .log (" Loaded from internet" );
79
+ }),
80
+ 5 ,
81
+ 1000
82
+ );
83
+ } catch (error) {
84
+ console .log (" Can not load from internet" , error);
85
+ }
60
86
87
+ // Loading from cache if exists
88
+ let cached = JSON .parse (localStorage .getItem (" timetable-cache" ) || " []" );
89
+ cached = cached .filter ((value ) =>
90
+ isToday (Date .parse (value .start_ts ), date)
91
+ );
92
+ console .log (cached);
93
+ if (! this .loaded && cached .length > 0 ) {
94
+ this .timetable = cached;
95
+ this .loaded = true ;
96
+ console .log (` Loaded ${ cached .length } events from cache` );
97
+ }
98
+ },
99
+ loadTimetableCache () {
100
+ console .log (" Caching timetable" );
101
+ // Загружает текущую неделю + следующую в кэш
102
+ var time_start = getMonday (new Date ());
103
+ var time_end = new Date (time_start);
104
+ time_end .setDate (time_start .getDate () + 14 );
105
+ retry (
106
+ // Повтори загрузку недели трижды с интервалом 10 секунд
107
+ () =>
108
+ fetchTimetable (time_start, time_end, this .groupId ).then ((json ) => {
109
+ localStorage .setItem (" timetable-cache" , JSON .stringify (json .items ));
110
+ console .log (` Cached ${ json .items .length } items` );
111
+ }),
112
+ 3 ,
113
+ 10000
114
+ );
61
115
},
62
116
swipeEventHandler (e ) {
63
- var nextDate = new Date (this .date )
64
- if (e .detail .dir == ' left' )
65
- nextDate .setDate (this .date .getDate () + 1 );
66
- if (e .detail .dir == ' right' )
67
- nextDate .setDate (this .date .getDate () - 1 );
68
- document .dispatchEvent (new CustomEvent (' change-main-date' , { detail: { date: nextDate } }));
69
- }
70
-
117
+ var nextDate = new Date (this .date );
118
+ if (e .detail .dir == " left" ) nextDate .setDate (this .date .getDate () + 1 );
119
+ if (e .detail .dir == " right" ) nextDate .setDate (this .date .getDate () - 1 );
120
+ document .dispatchEvent (
121
+ new CustomEvent (" change-main-date" , { detail: { date: nextDate } })
122
+ );
123
+ },
124
+ },
125
+ watch: {
126
+ date (newDate ) {
127
+ this .loaded = false ;
128
+ // 5 раз с интервалом в 1 секунду попробуй скачать расписание
129
+ this .loadTimetableOnDate (newDate);
130
+ },
71
131
},
72
132
beforeMount () {
73
- document .dispatchEvent (new CustomEvent (" change-page" , { detail: this .pageId }));
74
- document .addEventListener (' change-date' , (e ) => {
75
- this .date = e .detail .date ;
76
- this .loadTimetableOnDate (this .date );
77
- });
78
-
133
+ document .dispatchEvent (
134
+ new CustomEvent (" change-page" , { detail: this .pageId })
135
+ );
136
+ document .addEventListener (
137
+ " change-date" ,
138
+ (e ) => (this .date = e .detail .date )
139
+ );
79
140
},
80
- updated (){
81
- document .dispatchEvent (new CustomEvent (" change-page" , { detail: this .pageId }));
141
+ updated () {
142
+ document .dispatchEvent (
143
+ new CustomEvent (" change-page" , { detail: this .pageId })
144
+ );
82
145
},
83
146
mounted () {
84
- this .groupId = localStorage .getItem (' timetable-group-id' );
147
+ this .groupId = localStorage .getItem (" timetable-group-id" );
85
148
this .loadGroupInfo ();
86
- document .dispatchEvent (new CustomEvent (' sync-date' ))
149
+ document .dispatchEvent (new CustomEvent (" sync-date" ));
87
150
// обработка свайпов
88
151
document .addEventListener (" swipe" , this .swipeEventHandler );
152
+
153
+ // Загружаем кэш в память
154
+ this .loadTimetableCache ();
89
155
},
90
- beforeUnmount (){
156
+ beforeUnmount () {
91
157
document .removeEventListener (" swipe" , this .swipeEventHandler );
92
- console .log (' removed' );
93
- }
94
-
158
+ },
95
159
};
96
-
97
160
</script >
98
161
99
162
<style scoped>
116
179
font-weight : 700 ;
117
180
color : lightgray ;
118
181
text-transform : uppercase ;
119
-
120
182
}
121
183
122
184
.container {
141
203
142
204
.info {
143
205
height : 20px ;
144
- font-family : ' Roboto' ;
206
+ font-family : " Roboto" ;
145
207
font-style : normal ;
146
208
font-weight : 700 ;
147
209
font-size : 16px ;
0 commit comments