-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathfullCalendar.ur
176 lines (155 loc) · 5.81 KB
/
fullCalendar.ur
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
open FullCalendarFfi
type event = source (option event)
type t = {Show : xbody,
Calendar : source (option FullCalendarFfi.t),
QueuedEvents : source (list (event * event_data))}
type settings = {
DefaultDate : option time,
AllDaySlot : bool,
SlotDuration : option string,
SnapDuration : option string,
Content : option (t -> event -> {Header : xbody, Body : xbody}),
OnSelect : option (t -> time -> time -> transaction unit),
OnDrop : option (t -> event -> event -> transaction unit)
}
fun create settings =
id <- fresh;
cal <- source None;
evs <- source [];
t' <- return {Show = <xml></xml>,
Calendar = cal,
QueuedEvents = evs};
return {Calendar = cal,
QueuedEvents = evs,
Show = <xml>
<div id={id}/>
<active code={calV <- FullCalendarFfi.replace id
(settings --- [Content = _, OnSelect = _, OnDrop = _]
++ {Content = Option.mp (fn f ev =>
ev <- source (Some ev);
return (f t' ev)) settings.Content,
OnSelect = Option.mp (fn f => f t') settings.OnSelect,
OnDrop = Option.mp (fn f ev1 ev2 =>
ev1 <- source (Some ev1);
ev2 <- source (Some ev2);
f t' ev1 ev2) settings.OnDrop});
evsV <- get evs;
List.app (fn (s, ev) =>
ev <- FullCalendarFfi.addEvent calV ev;
set s (Some ev)) evsV;
set evs [];
set cal (Some calV);
FullCalendarFfi.refresh calV;
return <xml></xml>}/>
</xml>}
fun render self = self.Show
fun events self =
cal <- get self.Calendar;
case cal of
None =>
evs <- get self.QueuedEvents;
return (List.mp (fn (ev, _) => ev) evs)
| Some cal =>
evs <- FullCalendarFfi.events cal;
List.mapM (fn ev => source (Some ev)) evs
fun addEvent self ev =
cal <- get self.Calendar;
case cal of
None =>
evs <- get self.QueuedEvents;
s <- source None;
set self.QueuedEvents ((s, ev) :: evs);
return s
| Some cal =>
ev <- FullCalendarFfi.addEvent cal ev;
FullCalendarFfi.refresh cal;
source (Some ev)
fun addEvents self evl =
cal <- get self.Calendar;
case cal of
None =>
evs <- get self.QueuedEvents;
evl <- List.mapM (fn ev => s <- source None; return (s, ev)) evl;
set self.QueuedEvents (List.append evl evs)
| Some cal =>
FullCalendarFfi.addEvents cal evl;
FullCalendarFfi.refresh cal
fun clear cal =
calv <- get cal.Calendar;
case calv of
None => set cal.QueuedEvents []
| Some cal =>
evs <- FullCalendarFfi.events cal;
List.app FullCalendarFfi.removeEvent evs
fun unselect cal =
calv <- get cal.Calendar;
case calv of
None => return ()
| Some cal => FullCalendarFfi.unselect cal
fun removeEvent ev =
ev <- get ev;
case ev of
None => error <xml>Trying to remove event that wasn't created yet</xml>
| Some ev => FullCalendarFfi.removeEvent ev
fun eventStart ev =
ev <- get ev;
case ev of
None => error <xml>Trying to examine event that wasn't created yet</xml>
| Some ev => FullCalendarFfi.eventStart ev
fun eventTitle ev =
ev <- get ev;
case ev of
None => error <xml>Trying to examine event that wasn't created yet</xml>
| Some ev => FullCalendarFfi.eventTitle ev
fun eventRendering ev =
ev <- get ev;
case ev of
None => error <xml>Trying to examine event that wasn't created yet</xml>
| Some ev => FullCalendarFfi.eventRendering ev
fun eventId ev =
ev <- get ev;
case ev of
None => error <xml>Trying to examine event that wasn't created yet</xml>
| Some ev => FullCalendarFfi.eventId ev
fun getEventById cal id =
calv <- get cal.Calendar;
case calv of
None =>
evs <- get cal.QueuedEvents;
return (List.search (fn (ev, evd) => if evd.Id = Some id then Some ev else None) evs)
| Some cal =>
evo <- FullCalendarFfi.getEventById cal id;
case evo of
None => return None
| Some ev =>
ev <- source (Some ev);
return (Some ev)
fun durationToSeconds s =
case String.split s #":" of
None => error <xml>Bad duration format: {[s]}</xml>
| Some (h, m) =>
case (read h, read m) of
(Some h, Some m) => 60 * (60 * h + m)
| _ => error <xml>Bad duration format: {[s]}</xml>
fun pad n s =
if String.length s >= n then
s
else
"0" ^ pad (n - 1) s
fun secondsToDuration n =
let
val n = n / 60
in
pad 2 (show (n / 60)) ^ ":" ^ pad 2 (show (n % 60))
end
fun halveDuration s =
let
val n = durationToSeconds s
fun divider i =
if n / i % 60 = 0 then
n / i
else
divider (i + 1)
in
secondsToDuration (divider 2)
end