Scheduled for Tuesday, 23 April 2024 at 7:00 PM

An error occurred while processing the template.
The following has evaluated to null or missing:
==> video_id  [in template "12768602#20123#258052" at line 61, column 76]

----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
	- Failed at: #assign VOID = http_options.setLocati...  [in template "12768602#20123#258052" at line 61, column 3]
----
1<#function formatFileSize bytes> 
2  <#assign units = ["B", "KB", "MB", "GB", "TB", "PB"] /> 
3  <#assign size = bytes?number /> 
4  <#assign unitIndex = 0 /> 
5   
6  <#list 1..10 as i> 
7    <#if size gte 1024 && unitIndex lt units?size - 1> 
8      <#assign size = size / 1024 /> 
9      <#assign unitIndex = unitIndex + 1 /> 
10    <#else> 
11      <#break> 
12    </#if> 
13  </#list> 
14   
15  <#return size?string("0.#") + " " + units[unitIndex]> 
16</#function> 
17 
18 
19 
20<#assign UserLocalService = serviceLocator.findService("com.liferay.portal.kernel.service.UserLocalService")/> 
21 
22<#if UserLocalService.hasRoleUser(1751340, user.getUserId())> 
23<div class="shadow" style="position: fixed; top: 4.5rem; right: 1.5rem; background-color: red; color: white; font-weight: bold; padding: 0.75rem 1rem; z-index: 500; border: 2px solid white; text-align: center; border-radius: 0.375rem; max-width: 12rem;"><span class="d-block">You are viewing this as a logged in user</span></div> 
24</#if> 
25 
26<#if (agenda.getData())?has_content || (minutes.getData())?has_content> 
27<h3 class="lccc-summary-list__header">Documents available for this meeting:</h3> 
28<ul class="list-unstyled spaced-2 mb-5"> 
29<#if (agenda.getData())?has_content> 
30<li><a href="${agenda.getData()}">Agenda <#if getterUtil.getBoolean(reportsIncluded.getData())>and Reports </#if>(PDF)</a></li> 
31</#if> 
32<#if (minutes.getData())?has_content> 
33<li><a href="${minutes.getData()}">Minutes (PDF)</a></li> 
34</#if> 
35</ul> 
36</#if> 
37 
38 
39<#assign dateInMilliseconds = date.getData()?datetime("yyyy-MM-dd")?long > 
40<#assign timeInMilliseconds = (timeHours.getData()?number * 3600000 + timeMinutes.getData()?number * 60000) > 
41<#assign dateAndTimeInMilliseconds = dateInMilliseconds + timeInMilliseconds > 
42 
43<div class="meeting"> 
44 
45<#if audioVideoURL.getData()?? && (getterUtil.getBoolean(showAudioVideo.getData()) || UserLocalService.hasRoleUser(1751340, user.getUserId())) && audioVideoURL.getData()?contains("vimeo.com")> 
46  <#assign videoURL = audioVideoURL.getData()> 
47	<#if videoURL?contains("iframe")> 
48	  <#assign videoURL = videoURL?keep_after("src=\"")?keep_before("\"")> 
49		<#assign video_id = videoURL?keep_after("vimeo.com/video/")?keep_before("?")> 
50	</#if> 
51  <h3 class="lccc-summary-list__header">Watch this meeting:</h3> 
52	<#if !getterUtil.getBoolean(showAudioVideo.getData())><span style="display: inline-block; padding: 0.25rem 0.5rem; background-color: red; color: white; font-weight: bold; border-radius: 0.25rem; margin-bottom: 1rem;">NOT CURRENTLY VISIBLE TO THE PUBLIC</span></#if> 
53  <div style="padding:56.25% 0 0 0;position:relative;"><iframe src="${videoURL}" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="Video of meeting"></iframe></div> 
54  <script src="https://player.vimeo.com/api/player.js"></script> 
55	 
56 
57  <#assign httpServletRequest = digitalplace_serviceContext.getRequest()/> 
58  <#assign httpSession = httpServletRequest.getSession() /> 
59	<#assign http_options = staticUtil["com.liferay.portal.kernel.util.InstanceFactory"].newInstance("com.liferay.portal.kernel.util.Http$Options")/> 
60  <#assign VOID = http_options.addHeader("Authorization", "Bearer 1577416bbc0e511d47e6e871fc80f065")/> 
61  <#assign VOID = http_options.setLocation("https://api.vimeo.com/videos/${video_id}?fields=download")/> 
62	 
63	<#if (httpSession.getAttribute("vimeo.video.download")?has_content) && ((httpSession.getAttribute("vimeo.video.download.expires")!0 - .now?long!0) > 3600000) && ((httpSession.getAttribute("vimeo.video.id")!"") == video_id) > 
64 
65    <#assign download = httpSession.getAttribute("vimeo.video.download")/> 
66		 
67  <#else> 
68			 
69    <#assign download = jsonFactoryUtil.looseDeserialize(httpUtil.URLtoString(http_options))/> 
70	 
71  </#if> 
72 
73  <#if download?has_content && download?size gt 0> 
74 
75<script>console.log("download has content");</script> 
76 
77  	<#list download.download?filter(x -> x.rendition == "720p") as x> 
78      <#assign link = x.link /> 
79      <#assign expires = x.expires?datetime.iso?long /> 
80			<#assign size = x.size!0 /> 
81    </#list> 
82 
83    <#if link?has_content> 
84	    <div class="download-container"><a href="${link}" class="btn btn-primary my-3">Download video <span class="small">(${formatFileSize(size)})</span></a></div> 
85    <#else> 
86			<div class="download-container"></div> 
87		</#if> 
88		 
89	  <#assign VOID = httpSession.setAttribute("vimeo.video.download", download)/> 
90    <#assign VOID = httpSession.setAttribute("vimeo.video.download.expires", expires)/> 
91    <#assign VOID = httpSession.setAttribute("vimeo.video.id", video_id)/> 
92		 
93  </#if> 
94 
95 
96 
97</#if> 
98 
99<#if audioVideoURL.getData()?? && (getterUtil.getBoolean(showAudioVideo.getData()) || UserLocalService.hasRoleUser(1751340, user.getUserId())) && audioVideoURL.getData()?contains("soundcloud.com")> 
100  <#assign audioURL = audioVideoURL.getData()> 
101	<#if audioURL?contains("iframe")> 
102	  <#assign audioURL = audioURL?keep_after("?url=")?keep_before("&color")> 
103	</#if> 
104  <h3 class="lccc-summary-list__header">Listen to this meeting:</h3> 
105	<#if !getterUtil.getBoolean(showAudioVideo.getData())><span style="display: inline-block; padding: 0.25rem 0.5rem; background-color: red; color: white; font-weight: bold; border-radius: 0.25rem; margin-bottom: 1rem;">NOT CURRENTLY VISIBLE TO THE PUBLIC</span></#if> 
106  <script src="https://w.soundcloud.com/player/api.js"></script> 
107  <iframe allow="autoplay" title="audio player" id="audio" src="https://w.soundcloud.com/player/?url=${audioURL}&amp;color=53c3e9&amp;auto_play=false&amp;hide_related=true&amp;show_artwork=false&amp;show_comments=false&amp;show_user=false&amp;show_reposts=false&amp;download=true&amp;liking=false" width="100%" style="border: 0; max-width: 48rem; border: 1px solid var(--primary);"></iframe> 
108</#if> 
109 
110<#if (getterUtil.getBoolean(showChapters.getData()) || UserLocalService.hasRoleUser(1751340, user.getUserId())) && chapters.getSiblings()?has_content> 
111    <div class="mt-4 mb-4" style="max-width: 48rem;"> 
112      <h4 class="inline-block mt-4 mb-4">Contents:</h4> 
113      <p>Use the links below to skip to a specific part of the recording.</p> 
114      <#if !getterUtil.getBoolean(showChapters.getData())><span style="display: inline-block; padding: 0.25rem 0.5rem; background-color: red; color: white; font-weight: bold; border-radius: 0.25rem; margin-bottom: 1rem;">NOT CURRENTLY VISIBLE TO THE PUBLIC</span></#if> 
115	    <table> 
116			  <thead> 
117				  <tr style="line-height: 1.1;"> 
118					  <th style="width: 12%">Item number</th> 
119						<th>Item title</th> 
120						<th>Time</th> 
121          </tr> 
122				</thead> 
123			  <tbody> 
124				  <#list chapters.getSiblings() as item> 
125				 
126          <tr> 
127            <#if !getterUtil.getBoolean(item.confidential.getData())> 
128						  <td>${item.itemNumber.getData()}</td> 
129              <td><a href="#" class="track-link align-top" data-timestamp="${item.timestamp.getData()}">${item.itemTitle.getData()}</a></td> 
130              <td>${item.timestamp.getData()}</td> 
131            <#else> 
132              <td class="confidential">${item.itemNumber.getData()}</td> 
133							<td colspan="2" class="confidential"><span>${item.itemTitle.getData()}</span><span class="badge badge-dark float-right mr-0">Confidential</span></td> 
134            </#if> 
135          </tr> 
136															 
137				  </#list> 
138				</tbody> 
139			</table> 
140		</div> 
141</#if> 
142 
143<script> 
144 
145function convertTimeToMs(time) { 
146  var timeSplit = time.split(':'); 
147  var hours = 0; 
148  var minutes = 0; 
149  var seconds = 0; 
150  var s = 0; 
151  var ms = 0; 
152    hours = parseInt(timeSplit[0]); 
153    minutes = parseInt(timeSplit[1]); 
154    seconds = parseInt(timeSplit[2]); 
155  ms = hours*(3600000) + minutes*(60000) + seconds*(1000); 
156   
157  return ms; 
158
159 
160function convertTimeToSeconds(time) { 
161  var timeSplit = time.split(':'); 
162  var hours = 0; 
163  var minutes = 0; 
164  var seconds = 0; 
165  var s = 0; 
166    hours = parseInt(timeSplit[0]); 
167    minutes = parseInt(timeSplit[1]); 
168    seconds = parseInt(timeSplit[2]); 
169  s = hours*(3600) + minutes*(60) + seconds; 
170   
171  return s; 
172
173 
174</script> 
175 
176 
177<#if audioVideoURL.getData()?contains("soundcloud.com")> 
178<!-- BEGIN - code for audio playback --> 
179<script> 
180 
181var widget = SC.Widget(document.getElementById('audio')); 
182 
183widget.bind(SC.Widget.Events.READY, function() { 
184 
185    var trackLinks = document.querySelectorAll('.track-link'); 
186 
187    for (var i=0; i<trackLinks.length; i++) { 
188        trackLinks[i].addEventListener('click', function(e) { 
189            e.preventDefault(); 
190 
191            // Note: there seems to be a weird unexpected behavior in that 
192            // the first click doesn't actually seek if the widget isn't 
193            // playing. I confirmed this in Soundcloud's API playground 
194            // so if we detect we are paused, we want to trigger a play first 
195            // before we seekTo otherwise it doesn't work at all 
196 
197            widget.isPaused(function(e) { 
198                if (e) { 
199                    widget.play(); 
200
201            }); 
202 
203            widget.seekTo(convertTimeToMs(this.dataset.timestamp)); 
204        }); 
205
206 
207}); 
208 
209</script> 
210 
211</#if> 
212 
213 
214 
215 
216<#if audioVideoURL.getData()?contains("vimeo.com")> 
217<!-- BEGIN - code for video playback --> 
218<script> 
219 
220    var iframe = document.querySelector('iframe'); 
221    var player = new Vimeo.Player(iframe); 
222    var trackLinks = document.querySelectorAll('.track-link'); 
223 
224    for (var i=0; i<trackLinks.length; i++) { 
225        trackLinks[i].addEventListener('click', function(e) { 
226            e.preventDefault(); 
227			 
228			player.setCurrentTime(convertTimeToSeconds(this.dataset.timestamp)).then(function(seconds) { 
229			    player.play(); 
230			    }).catch(function(error) { 
231			        switch (error.name) { 
232			           case 'RangeError': 
233			           // The time is less than 0 or greater than the video's duration 
234			           break; 
235			           default: 
236			           // Some other error occurred 
237			           break; 
238
239                }); 
240        }); 
241
242 
243</script> 
244<!-- END - code for video playback --> 
245</#if> 
246 
247</div>