Fix format type mismatch
[sitka/overdrive-evergreen-opac.git] / src / od_data.coffee
CommitLineData
9669700c
SC
1define [
2 'lodash'
3 'moment'
4], (
5 _
6 M
7) ->
8
9 # A base class defining utilitarian methods
10 class U
11 constructor: (x) ->
12 return unless x
13 t = @
14 t extends x
15 return
16
17 # Mutate an ISO 8601 date string into a Moment object. If the argument is
18 # just a date value, then it specifies an absolute date in ISO 8601 format.
19 # If the argument is a pair, then it specifies a date relative to now. For
20 # an ISO 8601 date, we correct for what seems to be an error in time zone,
21 # Zulu time is really East Coast time.
22 momentize: (date, unit) ->
23 switch arguments.length
24 when 1
25 if date then M(date.replace /Z$/, '-0400') else M()
26 when 2
27 if date then M().add date, unit else M()
28 else M()
29
508513a1
SC
30 # The URL endpoint is converted to its reverse proxy version,
31 # because we are using the Evergreen server as a reverse proxy to
32 # the Overdrive server.
33 proxy: (x) ->
34 return unless x
35 y = x
36 y = y.replace 'https://', '//'
37 y = y.replace 'http://' , '//'
38 y = y.replace '//oauth-patron.overdrive.com', '/od/oauth-patron'
39 y = y.replace '//oauth.overdrive.com', '/od/oauth'
40 y = y.replace '//patron.api.overdrive.com', '/od/api-patron'
41 y = y.replace '//api.overdrive.com', '/od/api'
42 y = y.replace '//images.contentreserve.com', '/od/images'
43 y = y.replace '//fulfill.contentreserve.com', '/od/fulfill'
44 #log "proxy #{x} -> #{y}"
45 y
46 proxies: (x) ->
47 (v.href = @proxy l) for n, v of x when l = v.href
48 return x
49
9669700c
SC
50
51 class Metadata extends U
52 constructor: (x) ->
53 super x
54
55 # Convert ID to upper case to match same case found in EG catalogue
56 @id = @id.toUpperCase()
57 # Provide a simplified notion of author: first name in creators
58 # list having a role of author
59 @author = (v.name for v in @creators when v.role is 'Author')[0] or ''
508513a1
SC
60 # Convert image links to use reverse proxy
61 @proxies @images
9669700c
SC
62
63 return
64
65
66 class Availability extends U
67 constructor: (x, email_address) ->
68 super x
69
70 @zero()
71 @hold email_address if @actions?.hold
fe5e191d 72 @proxies @actions if @actions?
e07737bf 73 @action_formats()
9669700c
SC
74
75 return @
76
77 # Add zero values
78 zero: ->
79 @copiesOwned = 0 unless @copiesOwned
80 @copiesAvailable = 0 unless @copiesAvailable
81 @numberOfHolds = 0 unless @numberOfHolds
82 return @
83
84 hold: (email_address) ->
85 # The reserve ID is empty in the actions.hold.fields; we have to fill it ourselves.
86 _.where(@actions.hold.fields, name: 'reserveId')[0].value = @id
87 # We jam the email address from the prefs page into the fields object from the server
88 # so that the new form will display it.
89 if email_address
90 _.where(@actions.hold.fields, name: 'emailAddress')[0].value = email_address
91 return @
92
e07737bf
SC
93 # Surface the format options list that might be buried in an actions object
94 action_formats: ->
95 xs = @actions?.checkout?.fields
96 return @ unless xs?.length > 0
97 break for x in xs when x.name is 'formatType'
98 return @ unless x.options.length > 0
99 @formats = ( { id: v, name: '' } for v in x.options )
100 return @
101
9669700c
SC
102
103 class Holds extends U
104 constructor: (x) ->
105 super x
106
107 @add()
108 .remove()
508513a1 109 .proxy_urls()
9669700c
SC
110 .moments()
111 .count()
112 .sort()
113
114 return
115
116 # Ensure there is always a holds list, even if it's empty
117 add: ->
118 @holds = [] if @holds is undefined
119 return @
120
121 # Delete action to release a suspension if a hold is not
122 # suspended, because such actions are redundant
123 remove: ->
124 delete x.actions.releaseSuspension for x in @holds when not x.holdSuspension
125 return @
126
508513a1
SC
127 proxy_urls: ->
128 (@proxies v.actions) for v, n in @holds
129 return @
130
9669700c
SC
131 # For each hold, convert any ISO 8601 date strings into a
132 # Moment object (at local time zone)
133 moments: ->
134 for x in @holds
135 x.holdPlacedDate = @momentize x.holdPlacedDate
136 x.holdExpires = @momentize x.holdExpires
137 if x.holdSuspension
138 x.holdSuspension.numberOfDays = @momentize x.holdSuspension.numberOfDays, 'days'
139 return @
140
141 # Count the number of holds that can be checked out now
142 count: ->
143 @ready = _.countBy @holds, (x) -> if x.actions.checkout then 'forCheckout' else 'other'
144 @ready.forCheckout = 0 unless @ready.forCheckout
145 return @
146
147 # Sort the holds list by position and placed date
148 # and sort ready holds first
149 sort: ->
150 @holds = _(@holds)
151 .sortBy ['holdListPosition', 'holdPlacedDate']
152 .sortBy (x) -> x.actions.checkout
153 .value()
154 return @
155
156
157 class Checkouts extends U
158 constructor: (x) ->
159 super x
160
161 @add()
508513a1 162 .proxy_urls()
9669700c
SC
163 .moments()
164 .sort()
165
166 return
167
168 # Ensure there is always a checkouts list, even if it's empty
169 add: ->
170 @checkouts = [] if @checkouts is undefined
171 return @
172
508513a1
SC
173 proxy_urls:->
174 (@proxies v.actions) for v, n in @checkouts
175 return @
176
9669700c
SC
177 # For each checkout, convert any ISO 8601 date strings into a
178 # Moment object (at local time zone)
179 moments: ->
180 for x in @checkouts
181 x.expires = @momentize x.expires
182 return @
183
184 # Sort the checkout list by expiration date
185 sort: ->
186 @checkouts = _.sortBy @checkouts, 'expires'
187 return @
188
189
190 class Interests
191 constructor: (h, c) ->
192 return {
193 nHolds: h.totalItems
194 nHoldsReady: h.ready.forCheckout
195 nCheckouts: c.totalItems
196 nCheckoutsReady: c.totalCheckouts
197 ofHolds: h.holds
198 ofCheckouts: c.checkouts
199 # The following property is a map from product ID to a hold or
200 # a checkout object, eg, interests.byID(124)
201 byID: do (hs = h.holds, cs = c.checkouts) ->
202 byID = {}
203 for v, n in hs
204 v.type = 'hold'
205 byID[v.reserveId] = v
206 for v, n in cs
207 v.type = 'checkout'
208 byID[v.reserveId] = v
209 return byID
210 }
211
212 return {
213 Metadata: Metadata
214 Availability: Availability
215 Holds: Holds
216 Checkouts: Checkouts
217 Interests: Interests
218 }