PageSourceSearch

https://www.voipfonestatus.co.uk/

html voipfonestatus.co.uk collected 2026-10-05 08:16:05 UTC 113,069 bytes, 2,872 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en">
3  <head>
4    <meta http-equiv="X-UA-Compatible" content="IE=edge">
5    <!-- force IE browsers in compatibility mode to use their most aggressive rendering engine -->
6
7    <meta charset="utf-8">
8    <title>Voipfone Status</title>
9    <meta name="description" content="Welcome to Voipfone&#39;s home for real-time and historical data on system performance.">
10
11    <!-- Mobile viewport optimization -->
12    <meta name="HandheldFriendly" content="True">
13    <meta name="MobileOptimized" content="320">
14    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0">
15
16    <!-- Time this page was rendered - http://purl.org/dc/terms/issued -->
17    <meta name="issued" content="1791188164">
18
19    <!-- Mobile IE allows us to activate ClearType technology for smoothing fonts for easy reading -->
20    <meta http-equiv="cleartype" content="on">
21
22      <!-- Atlassian Sans & Mono Fonts -->
23<link
24  rel="preconnect"
25  href="https://ds-cdn.prod-east.frontend.public.atl-paas.net" />
26<link
27  rel="preload"
28  href="https://ds-cdn.prod-east.frontend.public.atl-paas.net/assets/fonts/atlassian-sans/v3/AtlassianSans-latin.woff2"
29  as="font" type="font/woff2" crossorigin />
30<link
31  rel="preload"
32  href="https://ds-cdn.prod-east.frontend.public.atl-paas.net/assets/font-rules/v5/atlassian-fonts.css"
33  as="style" crossorigin />
34
35    <style>
36  /* Dynamic Font Stack based on Feature Flag */
37    /* Using Atlassian Sans & Mono */
38    :root {
39      --font-stack-a: "Atlassian Sans", "Helvetica Neue", Helvetica, Arial, Sans-Serif;
40      --font-stack-b: "Atlassian Mono", "SFMono-Medium", "SF Mono", "Segoe UI Mono", "Roboto Mono", "Ubuntu Mono", Menlo, Consolas, Courier, monospace;
41    }
42</style>
43
44
45      <link rel="icon" type="image/x-icon" href="//dka575ofm4ao0.cloudfront.net/pages-favicon_logos/original/16003/uFVlAwiSTaskFLgaj06A" />
46
47    <link rel="shortcut icon" href='//dka575ofm4ao0.cloudfront.net/pages-favicon_logos/original/16003/uFVlAwiSTaskFLgaj06A'>
48
49    <link rel="alternate" type="application/atom+xml" href="https://www.voipfonestatus.co.uk/history.atom" title="Voipfone Status History - Atom Feed">
50    <link rel="alternate" type="application/rss+xml" href="https://www.voipfonestatus.co.uk/history.rss" title="Voipfone Status History - RSS Feed">
51
52      <!-- Canonical Link to ensure that only the custom domain is indexed when present -->
53      <link rel="canonical" href="https://www.voipfonestatus.co.uk">
54
55    <meta name="_globalsign-domain-verification" content="y_VzfckMy4iePo5oDJNivyYIjh8LffYa4jzUndm_bZ"/>
56
57
58    <link rel="alternate" type="application/atom+xml" title="ATOM" href="https://www.voipfonestatus.co.uk/history.atom" />
59
60    <!-- Le styles -->
61    <link rel="stylesheet" href="https://dka575ofm4ao0.cloudfront.net/packs/0.a7d86fc6a129fa9540bc.css" media="screen" />
62    <link rel="stylesheet" href="https://dka575ofm4ao0.cloudfront.net/assets/status/status_manifest-e7416fcfeedbe261454d619d119599335f4c7b18c9e245c13722dbb0998dc023.css" media="all" />
63
64    
64<script src="https://dka575ofm4ao0.cloudfront.net/assets/jquery-3.5.1.min-729e416557a365062a8a20f0562f18aa171da57298005d392312670c706c68de.js"></script>
64
65
66    
66<script>
67      window.pageColorData = {"blue":"#3498DB","border":"#E0E0E0","body_background":"#ffffff","font":"#333333","graph":"#3498db","green":"#2fcc66","light_font":"#AAAAAA","link":"#3498db","orange":"#e67e22","red":"#e74c3c","yellow":"#f1c40f","no_data":"#b3bac5"};
68    </script>
68
69    <style>
70  /* BODY BACKGROUND */ /* BODY BACKGROUND */ /* BODY BACKGROUND */ /* BODY BACKGROUND */ /* BODY BACKGROUND */
71  body,
72  .layout-content.status.status-api .section .example-container .example-opener .color-secondary,
73  .grouped-items-selector,
74  .layout-content.status.status-full-history .history-nav a.current,
75  div[id^="subscribe-modal"] .modal-footer,
76  div[id^="subscribe-modal"],
77  div[id^="updates-dropdown"] .updates-dropdown-section,
78  #uptime-tooltip .tooltip-box {
79    background-color:#ffffff;
80  }
81
82  #uptime-tooltip .pointer-container .pointer-smaller {
83    border-bottom-color:#ffffff;
84  }
85
86
87
88
89  /* PRIMARY FONT COLOR */ /* PRIMARY FONT COLOR */ /* PRIMARY FONT COLOR */ /* PRIMARY FONT COLOR */
90  body.status,
91  .color-primary,
92  .color-primary:hover,
93  .layout-content.status-index .status-day .update-title.impact-none a,
94  .layout-content.status-index .status-day .update-title.impact-none a:hover,
95  .layout-content.status-index .timeframes-container .timeframe.active,
96  .layout-content.status-full-history .month .incident-container .impact-none,
97  .layout-content.status.status-index .incidents-list .incident-title.impact-none a,
98  .incident-history .impact-none,
99  .layout-content.status .grouped-items-selector.inline .grouped-item.active,
100  .layout-content.status.status-full-history .history-nav a.current,
101  .layout-content.status.status-full-history .history-nav a:not(.current):hover,
102  div[id^="subscribe-modal"] .modal-header .close,
103  .grouped-item-label,
104  #uptime-tooltip .tooltip-box .tooltip-content .related-events .related-event a.related-event-link {
105    color:#333333;
106  }
107
108  .layout-content.status.status-index .components-statuses .component-container .name {
109    color:#333333;
110    color:rgba(51,51,51,.8);
111  }
112
113
114
115
116  /* SECONDARY FONT COLOR */ /* SECONDARY FONT COLOR */ /* SECONDARY FONT COLOR */ /* SECONDARY FONT COLOR */
117  small,
118  .layout-content.status .table-row .date,
119  .color-secondary,
120  .layout-content.status .grouped-items-selector.inline .grouped-item,
121  .layout-content.status.status-full-history .history-footer .pagination a.disabled,
122  .layout-content.status.status-full-history .history-nav a,
123  #uptime-tooltip .tooltip-box .tooltip-content .related-events #related-event-header {
124    color:#AAAAAA;
125  }
126
127
128
129
130  /* BORDER COLOR */  /* BORDER COLOR */  /* BORDER COLOR */  /* BORDER COLOR */  /* BORDER COLOR */  /* BORDER COLOR */
131  body.status .layout-content.status .border-color,
132  hr,
133  .tooltip-base,
134  .markdown-display table,
135  div[id^="subscribe-modal"],
136  #uptime-tooltip .tooltip-box {
137    border-color:#E0E0E0;
138  }
139
140  div[id^="subscribe-modal"] .modal-footer,
141  .markdown-display table td {
142    border-top-color:#E0E0E0;
143  }
144
145  .markdown-display table td + td, .markdown-display table th + th {
146    border-left-color:#E0E0E0;
147  }
148
149  div[id^="subscribe-modal"] .modal-header,
150  #uptime-tooltip .pointer-container .pointer-larger {
151    border-bottom-color:#E0E0E0;
152  }
153
154  #uptime-tooltip .tooltip-box .outage-field {
155    /*
156      Generate the background-color for the outage-field from the css_body_background_color and css_border_color.
157
158      For the default background (#ffffff) and default css_border_color (#e0e0e0), use the luminosity of the default background with a magic number to arrive at
159      the original outage-field background color (#f4f5f7). I used the formula Target Color = Color * alpha + Background * (1 - alpha) to find the magic number of ~0.08.
160
161      For darker css_body_background_color, luminosity values are lower so alpha trends toward becoming transparent (thus outage-field background becomes same as css_body_background_color).
162    */
163    background-color: rgba(224,224,224,0.31);
164
165    /*
166      outage-field border-color alpha is inverse to the luminosity of css_body_background_color.
167      That is to say, with a default white background this border is transparent, but on a black background, it's opaque css_border_color.
168    */
169    border-color: rgba(224,224,224,0.0);
170  }
171
172
173
174
175  /* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */ /* CSS REDS */
176  .layout-content.status.status-index .status-day .update-title.impact-critical a,
177  .layout-content.status.status-index .status-day .update-title.impact-critical a:hover,
178  .layout-content.status.status-index .page-status.status-critical,
179  .layout-content.status.status-index .unresolved-incident.impact-critical .incident-title,
180  .flat-button.background-red {
181    background-color:#e74c3c;
182  }
183
184  .layout-content.status-index .components-statuses .component-container.status-red:after,
185  .layout-content.status-full-history .month .incident-container .impact-critical,
186  .layout-content.status-incident .incident-name.impact-critical,
187  .layout-content.status.status-index .incidents-list .incident-title.impact-critical a,
188  .status-red .icon-indicator,
189  .incident-history .impact-critical,
190  .components-container .component-inner-container.status-red .component-status,
191  .components-container .component-inner-container.status-red .icon-indicator {
192    color:#e74c3c;
193  }
194
195  .layout-content.status.status-index .unresolved-incident.impact-critical .updates {
196    border-color:#e74c3c;
197  }
198
199
200
201
202  /* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */ /* CSS ORANGES */
203  .layout-content.status.status-index .status-day .update-title.impact-major a,
204  .layout-content.status.status-index .status-day .update-title.impact-major a:hover,
205  .layout-content.status.status-index .page-status.status-major,
206  .layout-content.status.status-index .unresolved-incident.impact-major .incident-title {
207    background-color:#e67e22;
208  }
209
210  .layout-content.status-index .components-statuses .component-container.status-orange:after,
211  .layout-content.status-full-history .month .incident-container .impact-major,
212  .layout-content.status-incident .incident-name.impact-major,
213  .layout-content.status.status-index .incidents-list .incident-title.impact-major a,
214  .status-orange .icon-indicator,
215  .incident-history .impact-major,
216  .components-container .component-inner-container.status-orange .component-status,
217  .components-container .component-inner-container.status-orange .icon-indicator {
218    color:#e67e22;
219  }
220
221  .layout-content.status.status-index .unresolved-incident.impact-major .updates {
222    border-color:#e67e22;
223  }
224
225
226
227
228  /* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */ /* CSS YELLOWS */
229  .layout-content.status.status-index .status-day .update-title.impact-minor a,
230  .layout-content.status.status-index .status-day .update-title.impact-minor a:hover,
231  .layout-content.status.status-index .page-status.status-minor,
232  .layout-content.status.status-index .unresolved-incident.impact-minor .incident-title,
233  .layout-content.status.status-index .scheduled-incidents-container .tab {
234    background-color:#f1c40f;
235  }
236
237  .layout-content.status-index .components-statuses .component-container.status-yellow:after,
238  .layout-content.status-full-history .month .incident-container .impact-minor,
239  .layout-content.status-incident .incident-name.impact-minor,
240  .layout-content.status.status-index .incidents-list .incident-title.impact-minor a,
241  .status-yellow .icon-indicator,
242  .incident-history .impact-minor,
243  .components-container .component-inner-container.status-yellow .component-status,
244  .components-container .component-inner-container.status-yellow .icon-indicator,
245  .layout-content.status.manage-subscriptions .confirmation-infobox .fa {
246    color:#f1c40f;
247  }
248
249  .layout-content.status.status-index .unresolved-incident.impact-minor .updates,
250  .layout-content.status.status-index .scheduled-incidents-container {
251    border-color:#f1c40f;
252  }
253
254
255
256
257  /* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */ /* CSS BLUES */
258  .layout-content.status.status-index .status-day .update-title.impact-maintenance a,
259  .layout-content.status.status-index .status-day .update-title.impact-maintenance a:hover,
260  .layout-content.status.status-index .page-status.status-maintenance,
261  .layout-content.status.status-index .unresolved-incident.impact-maintenance .incident-title,
262  .layout-content.status.status-index .scheduled-incidents-container .tab {
263    background-color:#3498DB;
264  }
265
266  .layout-content.status-index .components-statuses .component-container.status-blue:after,
267  .layout-content.status-full-history .month .incident-container .impact-maintenance,
268  .layout-content.status-incident .incident-name.impact-maintenance,
269  .layout-content.status.status-index .incidents-list .incident-title.impact-maintenance a,
270  .status-blue .icon-indicator,
271  .incident-history .impact-maintenance,
272  .components-container .component-inner-container.status-blue .component-status,
273  .components-container .component-inner-container.status-blue .icon-indicator {
274    color:#3498DB;
275  }
276
277  .layout-content.status.status-index .unresolved-incident.impact-maintenance .updates,
278  .layout-content.status.status-index .scheduled-incidents-container {
279    border-color:#3498DB;
280  }
281
282
283
284
285  /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */ /* CSS GREENS */
286  .layout-content.status.status-index .page-status.status-none {
287    background-color:#2fcc66;
288  }
289  .layout-content.status-index .components-statuses .component-container.status-green:after,
290  .status-green .icon-indicator,
291  .components-container .component-inner-container.status-green .component-status,
292  .components-container .component-inner-container.status-green .icon-indicator {
293    color:#2fcc66;
294  }
295
296
297
298
299  /* CSS LINK COLOR */  /* CSS LINK COLOR */  /* CSS LINK COLOR */  /* CSS LINK COLOR */  /* CSS LINK COLOR */  /* CSS LINK COLOR */
300  a,
301  a:hover,
302  .layout-content.status-index .page-footer span a:hover,
303  .layout-content.status-index .timeframes-container .timeframe:not(.active):hover,
304  .layout-content.status-incident .subheader a:hover {
305    color:#3498db;
306  }
307
308  .flat-button,
309  .masthead .updates-dropdown-container .show-updates-dropdown,
310  .layout-content.status-full-history .show-filter.open  {
311    background-color:#3498db;
312  }
313
314
315
316
317  /* CUSTOM COLOR OVERRIDES FOR UPTIME SHOWCASE */
318  .components-section .components-uptime-link {
319    color: #aaaaaa;
320  }
321
322  .layout-content.status .shared-partial.uptime-90-days-wrapper .legend .legend-item {
323    color: #aaaaaa;
324    opacity: 1;
325  }
326  .layout-content.status .shared-partial.uptime-90-days-wrapper .legend .legend-item.light {
327    color: #aaaaaa;
328    opacity: 1;
329  }
330  .layout-content.status .shared-partial.uptime-90-days-wrapper .legend .spacer {
331    background: #aaaaaa;
332    opacity: 1;
333  }
334</style>
335
336
337    <!-- custom css -->
338        <link rel="stylesheet" type="text/css" href="//dka575ofm4ao0.cloudfront.net/page_display_customizations-custom_css_externals/15953/external20151019-19655-1pkdy7p.css">
339
340      <!-- polyfills -->
341        
341<script crossorigin="anonymous" src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.js"></script>
341
342
343    <!-- Le HTML5 shim -->
344    <!--[if lt IE 9]>
345      
345<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
345
346    <![endif]-->
347
348    <!-- injection for static -->
349
350
351    
352  </head>
353
354
355  <body class="status index status-none sp-a11y-status-focus-visibility a11y-focus-indicators">
356
357    
358
359
360
361  <div class="layout-content status status-index premium">
362      <div class="masthead-container premium">
363    <div class="masthead">
364      <div class="images-container" id="cover-image-container" data-js-hook="images-container"></div>
365      <style>
366          #cover-image-container {
367            background-image:url("//dka575ofm4ao0.cloudfront.net/pages-hero_covers/normal/16003/G2c4voyqSRa37wPXSOry");
368          }
369
370          @media only screen and (-webkit-min-device-pixel-ratio: 2),
371                 only screen and (min-resolution: 192dpi) {
372            #cover-image-container {
373              background-image:url("//dka575ofm4ao0.cloudfront.net/pages-hero_covers/retina/16003/G2c4voyqSRa37wPXSOry") !important;
374            }
375          }
376      </style>
377
378      <div class="text-container">
379        <span class="page-name font-largest">
380            <a href="http://www.voipfone.co.uk">Voipfone</a>
381        </span>
382          
383  <div class="updates-dropdown-container" data-js-hook="updates-dropdown-container">
384    <a href="#" data-js-hook="show-updates-dropdown" id="show-updates-dropdown" class="show-updates-dropdown" aria-label="Subscribe to updates" aria-expanded="false" aria-haspopup="dialog" role="button">
385      <span class="subscribe-text-full">Subscribe to Updates</span><span class="subscribe-text-short">Subscribe</span>
386    </a>
387
388<!--    Accessibility guidelines for tabs: https://www.w3.org/TR/wai-aria-practices-1.1/examples/tabs/tabs-1/tabs.html -->
389    <div class="updates-dropdown" data-js-hook="updates-dropdown" id="updates-dropdown" style="display:none" role="dialog" aria-modal="false" aria-label="Subscribe to updates">
390      <div class="updates-dropdown-nav nav-items-5" role="tablist" aria-label="Subscribe to updates">
391          <a href="#updates-dropdown-email" aria-controls="updates-dropdown-email" aria-label="Subscribe via email" role="tab" aria-selected="true" id="updates-dropdown-email-btn">
392            <span class="icon-container email">
393          </a>
394          <a href="#updates-dropdown-sms" aria-controls="updates-dropdown-sms" aria-label="Subscribe via SMS" role="tab" id="updates-dropdown-sms-btn">
395            <span class="icon-container sms">
396          </a>
397          <a href="#updates-dropdown-twitter" aria-controls="updates-dropdown-twitter" aria-label="Subscribe via twitter" role="tab" id="updates-dropdown-twitter-btn">
398            <span class="icon-container twitter">
399          </a>
400          <a href="#updates-dropdown-atom" aria-controls="updates-dropdown-atom" aria-label="Subscribe via RSS" role="tab" id="updates-dropdown-atom-btn">
401            <span class="icon-container rss">
402          </a>
403        <button data-js-hook="updates-dropdown-close" aria-label="Close subscribe form" id="updates-dropdown-close-btn">
404          x
405        </button>
406      </div>
407      <div class="updates-dropdown-sections-container">
408          <div class="updates-dropdown-section email" id="updates-dropdown-email" style="display:none" role="tabpanel" aria-labelledby="updates-dropdown-email-btn">
409            <div class="directions">
410              Get email notifications whenever Voipfone <strong>creates</strong>,  <strong>updates</strong> or <strong>resolves</strong> an incident.
411            </div>
412            <form id="subscribe-form-email" action="/subscriptions/new-email" accept-charset="UTF-8" data-remote="true" method="post"><input type="hidden" name="authenticity_token" value="ifgJO8Rt4q-7wbkNFn2OntQO6cieQeqlrlSO1uVU9jI-MsAcbfa_5ucY0VxgMPhNI4311wvVkiyMNP_ueOap5Q" autocomplete="off" />
413              <input type="hidden" name="email_otp_verify_flow" id="email_otp_verify_flow" value="false" autocomplete="off" />
414                <!-- make sure not to put cookie values in here since this gets cached -->
415                <label for="email">Email address:</label>
416                <input name="email" id="email" type="text" class="full-width" data-js-hook="email-notification-field" autocomplete="email">
417                <input name="email_otp_auth_token" type='hidden' id="email-
417otp-token-field">
418                <div class="opt-container-section" id="email-otp-container", style="display:none" >
419                  <label for="email-otp">Enter OTP:</label>
420                  <input name="otp" id="email-otp" type="text" value="" class="prepend full-width">
421                  <p id="email-otp-timer">Resend OTP in: <span id="email-otp-countdown"></span> seconds </p>
422                  <p id="resend-email-otp">
423                    Didn't receive the OTP?
424                    <a href="#" id="resend-email-otp-btn" >Resend OTP </a>
425                  </p>
426                </div>
427                  <input type="hidden" name="captcha_error" id="captcha_error" value="false" autocomplete="off" />
428                  <input type="submit" value="Subscribe via Email" class="flat-button full-width g-recaptcha" id="subscribe-btn-email" data-disabled-text="Subscribing..." data-sitekey=6LdTS8AUAAAAAOIbCKoCAP4LQku1olYGrywPTaZz data-callback="submitNewEmailSubscriber" data-error-callback="emailSubscriberCaptchaError" >
429                  <div class="terms_and_privacy_information bottom small"> This site is protected by reCAPTCHA and the Google <a target="_blank" rel="noopener" class="accessible-link" href="https://policies.google.com/privacy">Privacy Policy</a> and <a target="_blank" rel="noopener" class="accessible-link" data-js-hook="captcha-terms-of-service-link" href="https://policies.google.com/terms">Terms of Service</a> apply.</div>
430</form>          </div>
431
432          <div class="updates-dropdown-section phone" id="updates-dropdown-sms" style="display:none" role="tabpanel" aria-labelledby="updates-dropdown-sms-btn">
433            <div class="directions">
434                Get text message notifications whenever Voipfone <strong>creates</strong> or <strong>resolves</strong> an incident.
435            </div>
436            <form id="subscribe-form-sms" action="/subscriptions/new-sms" accept-charset="UTF-8" data-remote="true" method="post"><input type="hidden" name="authenticity_token" value="sckwI8zj9V8gE-_YERrVnq1i7sxcaqCsdp3DGSPHJroGA_kEZXioFnzKh4lnV6NNWuHy08n-2CVU_bIhvnV5bQ" autocomplete="off" />
437              <input type="hidden" name="otp_verify_flow" id="otp_verify_flow" value="false" autocomplete="off" />
438              <input type="hidden" name="subscriber_code" id="subscriber_code" value="" autocomplete="off" />
439              <div class="control-group">
440                <div class="controls externalities-sms-container">
441                  <!-- make sure not to put cookie values in here since this gets cached -->
442                  <label for="phone-country">Country code:</label>
443                  <div id="phone-number-country-code" class="phone-country-wrapper"
444                      data-otp-enabled="false">
445                      <select name="phone_country" id="phone-country" data-js-hook="phone-country" class="phone-country"><option value="af" data-otp-enabled="false" >Afghanistan (+93)</option>
446<option value="al" data-otp-enabled="false" >Albania (+355)</option>
447<option value="dz" data-otp-enabled="false" >Algeria (+213)</option>
448<option value="as" data-otp-enabled="false" >American Samoa (+1)</option>
449<option value="ad" data-otp-enabled="false" >Andorra (+376)</option>
450<option value="ao" data-otp-enabled="false" >Angola (+244)</option>
451<option value="ai" data-otp-enabled="false" >Anguilla (+1)</option>
452<option value="ag" data-otp-enabled="false" >Antigua and Barbuda (+1)</option>
453<option value="ar" data-otp-enabled="false" >Argentina (+54)</option>
454<option value="am" data-otp-enabled="false" >Armenia (+374)</option>
455<option value="aw" data-otp-enabled="false" >Aruba (+297)</option>
456<option value="au" data-otp-enabled="false" >Australia/Cocos/Christmas Island (+61)</option>
457<option value="at" data-otp-enabled="false" >Austria (+43)</option>
458<option value="az" data-otp-enabled="false" >Azerbaijan (+994)</option>
459<option value="bs" data-otp-enabled="false" >Bahamas (+1)</option>
460<option value="bh" data-otp-enabled="false" >Bahrain (+973)</option>
461<option value="bd" data-otp-enabled="false" >Bangladesh (+880)</option>
462<option value="bb" data-otp-enabled="false" >Barbados (+1)</option>
463<option value="by" data-otp-enabled="false" >Belarus (+375)</option>
464<option value="be" data-otp-enabled="false" >Belgium (+32)</option>
465<option value="bz" data-otp-enabled="false" >Belize (+501)</option>
466<option value="bj" data-otp-enabled="false" >Benin (+229)</option>
467<option value="bm" data-otp-enabled="false" >Bermuda (+1)</option>
468<option value="bo" data-otp-enabled="false" >Bolivia (+591)</option>
469<option value="ba" data-otp-enabled="false" >Bosnia and Herzegovina (+387)</option>
470<option value="bw" data-otp-enabled="false" >Botswana (+267)</option>
471<option value="br" data-otp-enabled="false" >Brazil (+55)</option>
472<option value="bn" data-otp-enabled="false" >Brunei (+673)</option>
473<option value="bg" data-otp-enabled="false" >Bulgaria (+359)</option>
474<option value="bf" data-otp-enabled="false" >Burkina Faso (+226)</option>
475<option value="bi" data-otp-enabled="false" >Burundi (+257)</option>
476<option value="kh" data-otp-enabled="false" >Cambodia (+855)</option>
477<option value="cm" data-otp-enabled="false" >Cameroon (+237)</option>
478<option value="ca" data-otp-enabled="false" >Canada (+1)</option>
479<option value="cv" data-otp-enabled="false" >Cape Verde (+238)</option>
480<option value="ky" data-otp-enabled="false" >Cayman Islands (+1)</option>
481<option value="cf" data-otp-enabled="false" >Central Africa (+236)</option>
482<option value="td" data-otp-enabled="false" >Chad (+235)</option>
483<option value="cl" data-otp-enabled="false" >Chile (+56)</option>
484<option value="cn" data-otp-enabled="false" >China (+86)</option>
485<option value="co" data-otp-enabled="false" >Colombia (+57)</option>
486<option value="km" data-otp-enabled="false" >Comoros (+269)</option>
487<option value="cg" data-otp-enabled="false" >Congo (+242)</option>
488<option value="cd" data-otp-enabled="false" >Congo, Dem Rep (+243)</option>
489<option value="cr" data-otp-enabled="false" >Costa Rica (+506)</option>
490<option value="hr" data-otp-enabled="false" >Croatia (+385)</option>
491<option value="cy" data-otp-enabled="false" >Cyprus (+357)</option>
492<option value="cz" data-otp-enabled="false" >Czech Republic (+420)</option>
493<option value="dk" data-otp-enabled="false" >Denmark (+45)</option>
494<option value="dj" data-otp-enabled="false" >Djibouti (+253)</option>
495<option value="dm" data-otp-enabled="false" >Dominica (+1)</option>
496<option value="do" data-otp-enabled="false" >Dominican Republic (+1)</option>
497<option value="eg" data-otp-enabled="false" >Egypt (+20)</option>
498<option value="sv" data-otp-enabled="false" >El Salvador (+503)</option>
499<option value="gq" data-otp-enabled="false" >Equatorial Guinea (+240)</option>
500<option value="ee" data-otp-enabled="false" >Estonia (+372)</option>
501<option value="et" data-otp-enabled="false" >Ethiopia (+251)</option>
502<option value="fo" data-otp-enabled="false" >Faroe Islands (+298)</option>
503<option value="fj" data-otp-enabled="false" >Fiji (+679)</option>
504<option value="fi" data-otp-enabled="false" >Finland/Aland Islands (+358)</option>
505<option value="fr" data-otp-enabled="false" >France (+33)</option>
506<option value="gf" data-otp-enabled="false" >French Guiana (+594)</option>
507<option value="pf" data-otp-enabled="false" >French Polynesia (+689)</option>
508<option value="ga" data-otp-enabled="false" >Gabon (+241)</option>
509<option value="gm" data-otp-enabled="false" >Gambia (+220)</option>
510<option value="ge" data-otp-enabled="false" >Georgia (+995)</option>
511<option value="de" data-otp-enabled="false" >Germany (+49)</option>
512<option value="gh" data-otp-enabled="false" >Ghana (+233)</option>
513<option value="gi" data-otp-enabled="false" >Gibraltar (+350)</option>
514<option value="gr" data-otp-enabled="false" >Greece (+30)</option>
515<option value="gl" data-otp-enabled="false" >Greenland (+299)</option>
516<option value="gd" data-otp-enabled="false" >Grenada (+1)</option>
517<option value="gp" data-otp-enabled="false" >Guadeloupe (+590)</option>
518<option value="gu" data-otp-enabled="false" >
518Guam (+1)</option>
519<option value="gt" data-otp-enabled="false" >Guatemala (+502)</option>
520<option value="gn" data-otp-enabled="false" >Guinea (+224)</option>
521<option value="gy" data-otp-enabled="false" >Guyana (+592)</option>
522<option value="ht" data-otp-enabled="false" >Haiti (+509)</option>
523<option value="hn" data-otp-enabled="false" >Honduras (+504)</option>
524<option value="hk" data-otp-enabled="false" >Hong Kong (+852)</option>
525<option value="hu" data-otp-enabled="false" >Hungary (+36)</option>
526<option value="is" data-otp-enabled="false" >Iceland (+354)</option>
527<option value="in" data-otp-enabled="false" >India (+91)</option>
528<option value="id" data-otp-enabled="false" >Indonesia (+62)</option>
529<option value="iq" data-otp-enabled="false" >Iraq (+964)</option>
530<option value="ie" data-otp-enabled="false" >Ireland (+353)</option>
531<option value="il" data-otp-enabled="false" >Israel (+972)</option>
532<option value="it" data-otp-enabled="false" >Italy (+39)</option>
533<option value="jm" data-otp-enabled="false" >Jamaica (+1)</option>
534<option value="jp" data-otp-enabled="false" >Japan (+81)</option>
535<option value="jo" data-otp-enabled="false" >Jordan (+962)</option>
536<option value="ke" data-otp-enabled="false" >Kenya (+254)</option>
537<option value="kr" data-otp-enabled="false" >Korea, Republic of (+82)</option>
538<option value="xk" data-otp-enabled="false" >Kosovo (+383)</option>
539<option value="kw" data-otp-enabled="false" >Kuwait (+965)</option>
540<option value="kg" data-otp-enabled="false" >Kyrgyzstan (+996)</option>
541<option value="la" data-otp-enabled="false" >Laos (+856)</option>
542<option value="lv" data-otp-enabled="false" >Latvia (+371)</option>
543<option value="lb" data-otp-enabled="false" >Lebanon (+961)</option>
544<option value="ls" data-otp-enabled="false" >Lesotho (+266)</option>
545<option value="lr" data-otp-enabled="false" >Liberia (+231)</option>
546<option value="ly" data-otp-enabled="false" >Libya (+218)</option>
547<option value="li" data-otp-enabled="false" >Liechtenstein (+423)</option>
548<option value="lt" data-otp-enabled="false" >Lithuania (+370)</option>
549<option value="lu" data-otp-enabled="false" >Luxembourg (+352)</option>
550<option value="mo" data-otp-enabled="false" >Macao (+853)</option>
551<option value="mk" data-otp-enabled="false" >Macedonia (+389)</option>
552<option value="mg" data-otp-enabled="false" >Madagascar (+261)</option>
553<option value="mw" data-otp-enabled="false" >Malawi (+265)</option>
554<option value="my" data-otp-enabled="false" >Malaysia (+60)</option>
555<option value="mv" data-otp-enabled="false" >Maldives (+960)</option>
556<option value="ml" data-otp-enabled="false" >Mali (+223)</option>
557<option value="mt" data-otp-enabled="false" >Malta (+356)</option>
558<option value="mq" data-otp-enabled="false" >Martinique (+596)</option>
559<option value="mr" data-otp-enabled="false" >Mauritania (+222)</option>
560<option value="mu" data-otp-enabled="false" >Mauritius (+230)</option>
561<option value="mx" data-otp-enabled="false" >Mexico (+52)</option>
562<option value="mc" data-otp-enabled="false" >Monaco (+377)</option>
563<option value="mn" data-otp-enabled="false" >Mongolia (+976)</option>
564<option value="me" data-otp-enabled="false" >Montenegro (+382)</option>
565<option value="ms" data-otp-enabled="false" >Montserrat (+1)</option>
566<option value="ma" data-otp-enabled="false" >Morocco/Western Sahara (+212)</option>
567<option value="mz" data-otp-enabled="false" >Mozambique (+258)</option>
568<option value="na" data-otp-enabled="false" >Namibia (+264)</option>
569<option value="np" data-otp-enabled="false" >Nepal (+977)</option>
570<option value="nl" data-otp-enabled="false" >Netherlands (+31)</option>
571<option value="nz" data-otp-enabled="false" >New Zealand (+64)</option>
572<option value="ni" data-otp-enabled="false" >Nicaragua (+505)</option>
573<option value="ne" data-otp-enabled="false" >Niger (+227)</option>
574<option value="ng" data-otp-enabled="false" >Nigeria (+234)</option>
575<option value="no" data-otp-enabled="false" >Norway (+47)</option>
576<option value="om" data-otp-enabled="false" >Oman (+968)</option>
577<option value="pk" data-otp-enabled="false" >Pakistan (+92)</option>
578<option value="ps" data-otp-enabled="false" >Palestinian Territory (+970)</option>
579<option value="pa" data-otp-enabled="false" >Panama (+507)</option>
580<option value="py" data-otp-enabled="false" >Paraguay (+595)</option>
581<option value="pe" data-otp-enabled="false" >Peru (+51)</option>
582<option value="ph" data-otp-enabled="false" >Philippines (+63)</option>
583<option value="pl" data-otp-enabled="false" >Poland (+48)</option>
584<option value="pt" data-otp-enabled="false" >Portugal (+351)</option>
585<option value="pr" data-otp-enabled="false" >Puerto Rico (+1)</option>
586<option value="qa" data-otp-enabled="false" >Qatar (+974)</option>
587<option value="re" data-otp-enabled="false" >Reunion/Mayotte (+262)</option>
588<option value="ro" data-otp-enabled="false" >Romania (+40)</option>
589<option value="ru" data-otp-enabled="false" >Russia/Kazakhstan (+7)</option>
590<option value="rw" data-otp-enabled="false" >Rwanda (+250)</option>
591<option value="ws" data-otp-enabled="false" >Samoa (+685)</option>
592<option value="sm" data-otp-enabled="false" >San Marino (+378)</option>
593<option value="sa" data-otp-enabled="false" >Saudi Arabia (+966)</option>
594<option value="sn" data-otp-enabled="false" >Senegal (+221)</option>
595<option value="rs" data-otp-enabled="false" >Serbia (+381)</option>
596<option value="sc" data-otp-enabled="false" >Seychelles (+248)</option>
597<option value="sl" data-otp-enabled="false" >Sierra Leone (+232)</option>
598<option value="sg" data-otp-enabled="false" >Singapore (+65)</option>
599<option value="sk" data-otp-enabled="false" >Slovakia (+421)</option>
600<option value="si" data-otp-enabled="false" >Slovenia (+386)</option>
601<option value="za" data-otp-enabled="false" >South Africa (+27)</option>
602<option value="es" data-otp-enabled="false" >Spain (+34)</option>
603<option value="lk" data-otp-enabled="false" >Sri Lanka (+94)</option>
604<option value="kn" data-otp-enabled="false" >St Kitts and Nevis (+1)</option>
605<option value="lc" data-otp-enabled="false" >St Lucia (+1)</option>
606<option value="vc" data-otp-enabled="false" >St Vincent Grenadines (+1)</option>
607<option value="sd" data-otp-enabled="false" >Sudan (+249)</option>
608<option value="sr" data-otp-enabled="false" >Suriname (+597)</option>
609<option value="sz" data-otp-enabled="false" >Swaziland (+268)</option>
610<option value="se" data-otp-enabled="false" >Sweden (+46)</option>
611<option value="ch" data-otp-enabled="false" >Switzerland (+41)</option>
612<option value="tw" data-otp-enabled="false" >Taiwan (+886)</option>
613<option value="tj" data-otp-enabled="false" >Tajikistan (+992)</option>
614<option value="tz" data-otp-enabled="false" >Tanzania (+255)</option>
615<option value="th" data-otp-enabled="false" >Thailand (+66)</option>
616<option value="tg" data-otp-enabled="false" >Togo (+228)</option>
617<option value="to" data-otp-enabled="false" >Tonga (+676)</option>
618<option value="tt" data-otp-enabled="false" >Trinidad and Tobago (+1)</option>
619<option value="tn" data-otp-enabled="false" >Tunisia (+216)</option>
620<option value="tr" data-otp-enabled="false" >Turkey (+90)</option>
621<option value="tc" data-otp-enabled="false" >Turks and Caicos Islands (+1)</option>
622<option value="ug" data-otp-enabled="false" >Uganda (+256)</option>
623<option value="ua" data-otp-enabled="false" >Ukraine (+380)</option>
624<option value="ae" data-otp-enabled="false" >United Arab Emirates (+971)</option>
625<option value="gb" data-otp-enabled="false" selected>United Kingdom (+44)</option>
626<option value="us" data-otp-enabled="false" >United States (+1)</option>
627<option value="uy" data-otp-enabled="false" >Uruguay (+598)</option>
628<option value="uz" data-otp-enabled="false" >Uzbekistan (+998)</option>
629<option value="ve" data-otp-enabled="false" >Venezuela (+58)</option>
630<option value="vn" data-otp-enabled="false" >Vietnam (+84)</option>
631<option value="vg" data-otp-enabled="false" >Virgin Islands, British (+1)</option>
632<option value="vi" data-otp-enabled="false" >Virgin Islands, U.S. (+1)</option>
633<option value="ye" data-otp-enabled="false" >Yemen (+967)</option>
634<option value="zm" data-otp-enabled="false" >Zambia (+260)</option>
635<option value="zw" data-otp-enabled="false" >Zimbabwe (+263)</option></select>
636                  </div>
637                  <label for="phone-number">Phone number:</label>
638                  <input name="phone_number" id="phone-number" type="text" class="prepend full-width" data-js-hook="sms-notification-field">
639                  <div class="sms-atl-error" id="sms-atl-error"></div>
640                  <div class="clearfix"></div>
641                  <div class="opt-container-section" id="otp-container" style="display:none">
642                    <a href="#" id="btn-subcriber-change-number">Change number</a>
643                    <label for="otp">Enter OTP:</label>
644                    <input name="otp" id="otp" type="text" class="prepend full-width">
645                    <p id="timer">Resend OTP in: <span id="countdown">30</span> seconds </p>
646                    <p id="resend">
647                      Didn't receive the OTP?
648                      <a href="#" id="resend-otp-btn" >Resend OTP </a>
649                    </p>
650                    </div>
651                </div>
652              </div>
653
654                <input type="hidden" name="captcha_error" id="captcha_error" value="false" autocomplete="off" />
655                <input type="submit" value="Subscribe via Text Message" class="flat-button full-width g-recaptcha" id="subscribe-btn-sms" data-disabled-text="Subscribing..." data-sitekey=6LcH-b0UAAAAACVQtMb14LBhflMA9y0Nmu7l_W6d data-callback="submitNewSmsSubscriber" data-error-callback="smsSubscriberCaptchaError">
656              <div class="terms_and_privacy_information bottom small">Message and data rates may apply. By subscribing you agree to the Atlassian <a target="_blank" rel="noopener" class="accessible-link" href="https://www.atlassian.com/legal/product-specific-terms#statuspage-specific-terms">Terms of Service</a>, and the Atlassian <a target="_blank" rel="noopener" class="accessible-link" href="https://www.atlassian.com/legal/privacy-policy">Privacy Policy</a>. This site is protected by reCAPTCHA and the Google <a target="_blank" rel="noopener" class="accessible-link" href="https://policies.google.com/privacy">Privacy Policy</a> and <a target="_blank" rel="noopener" class="accessible-link" data-js-hook="captcha-terms-of-service-link" href="https://policies.google.com/terms">Terms of Service</a> apply.</div>
657</form>          </div>
658
659
660
661
662          <div class="updates-dropdown-section twitter" id="updates-dropdown-twitter" style="display:none" role="tabpanel" aria-labelledby="updates-dropdown-twitter-btn">
663            <a href="https://twitter.com/Voipfonestatus" class="twitter-follow-button" data-show-count="false" data-show-screen-name="true" data-width="59px">Follow @Voipfonestatus</a>
664            or&nbsp;
665            <a href="https://twitter.com/Voipfonestatus" target="_blank">view our profile</a>.
666            <style>
667              .twitter-follow-button {
668                margin-bottom: -6px;
669              }
670            </style>
671
672              
672<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
672
673          </div>
674
675
676          <div class="updates-dropdown-section atom" id="updates-dropdown-atom" role="tabpanel" aria-labelledby="updates-dropdown-atom-btn">
677            Get the <a href="https://www.voipfonestatus.co.uk/history.atom" target="_blank">Atom Feed</a> or <a href="https://www.voipfonestatus.co.uk/history.rss" target="_blank">RSS Feed</a>.
678          </div>
679      </div>
680    </div>
681  </div>
682
683<script>
684  $(function () {
685    const phoneNumberInput = $('#phone-number');
686    const errorDiv = $('#sms-atl-error')
687    if(errorDiv.length){
688      function checkSelectedCountry() {
689        const selectedCountry = $('#phone-country').val();
690        const isOtpEnabled = $('#phone-number-country-code').attr('data-otp-enabled') === 'true';
691        const form = document.getElementById('subscribe-form-sms');
692        form.action = '/subscriptions/new-sms';
693        const isOtpFlow = document.getElementById('otp_verify_flow');
694        document.getElementById('otp-container').style.display = "none";
695        if(false && selectedCountry === 'sg') { // Replace 'SG' with the actual value representing Singapore in your select tag
696          phoneNumberInput.prop('disabled', true);
697          errorDiv.html(`Due to new Singapore government regulations, we're currently not supporting text subscriptions in Singapore.<a href="https://community.atlassian.com/t5/Statuspage-articles/Attention-SMS-notifications-will-be-disabled-on-August-1st-2023/ba-p/2424398" target="_blank"> Learn more.</a> <br> Select another method to subscribe.`);
698        } else {
699          phoneNumberInput.prop('readonly', false);
700          errorDiv.html('');
701          if(false){
702            if(isOtpEnabled){
703              document.getElementById('subscribe-btn-sms').value = "Send OTP";
704            }
705            else {
706              isOtpFlow.value = false;
707              document.getElementById('subscribe-btn-sms').value = "Subscribe via Text Message";
708            }
709          }
710        }
711      }
712
713      $('#phone-country').on('change', checkSelectedCountry);
714      checkSelectedCountry();
715    }
716  });
717
718  document.addEventListener('DOMContentLoaded', function() {
719    const dropdown = document.querySelector('#phone-number-country-code .phone-country');
720    if (dropdown){
721      const wrapperDiv = document.getElementById('phone-number-country-code');
722      const selectedOption = dropdown.options[dropdown.selectedIndex];
723      const otpEnabled = selectedOption.getAttribute('data-otp-enabled');
724
725      wrapperDiv.setAttribute('data-otp-enabled', otpEnabled);
726
727      dropdown.addEventListener('change', function() {
728        const selectedOption = dropdown.options[dropdown.selectedIndex];
729        const otpEnabled = selectedOption.getAttribute('data-otp-enabled');
730
731        wrapperDiv.setAttribute('data-otp-enabled', otpEnabled);
732      });
733    }
734  });
735
736  var countdownTimer;
737  var resendBtn = document.getElementById('resend');
738  var timer = document.getElementById('timer');
739  var form = document.getElementById('subscribe-form-sms');
740  var RESEND_TIMER = 30;
741  $(function() {
742    $('#subscribe-form-sms').on('ajax:success', function(e, data, status, xhr){
743      const form = this;
744      const action = form.getAttribute('action');
745      if (data.type === 'success' && data.otp_flow === true) {
746        document.getElementById('subscriber_code').value = data.subscriber_code
747        document.getElementById('otp-container').style.display = "block";
748        $('#phone-number').prop('readonly', true);
749        var display = document.getElementById('countdown');
750        disableResend();
751        startTimer(RESEND_TIMER, display)
752        document.getElementById('subscribe-btn-sms').value = "Verify OTP and Subscribe";
753        document.getElementById('otp_verify_flow').value = true;
754        form.action = '/subscriptions/verify-otp';
755      } else if (data.type === 'success' && action.includes('verify')){
756        document.getElementById('otp-container').style.display = "none";
757        $('#phone-number').val('').prop('readonly', false);
758        $('#otp').val('');
759        document.getElementById('subscribe-btn-sms').value = "Send OTP";
760        document.getElementById('otp_verify_flow').value = false;
761        form.action = '/subscriptions/new-sms';
762        SP.currentPage.updatesDropdown.hide();
763      }
764    });
765    $("#btn-subcriber-change-number").on('click', () => {
766      document.getElementById('otp-container').style.display = "none";
767      $('#phone-number').prop('readonly', false);
768      document.getElementById('subscribe-btn-sms').value = "Send OTP";
769      form.action = '/subscriptions/new-sms';
770      return false
771    })
772    $('#resend-otp-btn').on('click', function(e) {
773      e.preventDefault();
774      let phoneNumber = $('#phone-number').val();
775      let countryCode = $('.phone-country').val();
776      $.ajax({
777        type: 'POST',
778        url: "/subscriptions/new-sms",
779        data: {
780          phone_number: phoneNumber,
781          phone_country: countryCode,
782          type: 'resend'
783        },
784      }).done(function(data) {
785        var messageOptions = (data.type !== undefined && data.type !== null) ? { cssClass: data.type } : {};
786        HRB.utils.notify(data.text, messageOptions);
787        var display = document.getElementById('countdown');
788        disableResend();
789        timer.style.display = "none"
790        if (data.type === 'success') {
791          startTimer(RESEND_TIMER, display);
792        }
793      })
794    });
795  })
796
797  function startTimer(duration, display){
798    var timer = duration, seconds;
799    clearInterval(countdownTimer);
800    countdownTimer = setInterval(function () {
801      seconds = parseInt(timer % 60, 10);
802      display.textContent = seconds;
803      if(--timer < 0){
804        enableResend();
805        clearInterval(countdownTimer);
806      }
807    }, 1000);
808    disableResend();
809  }
810  function enableResend(){
811    resendBtn.style.display = "block";
812    timer.style.display = "none"
813  }
814  function disableResend(){
815    resendBtn.style.display = "none";
816    timer.style.display = "block"
817  }
818
819  $(function() {
820    $('#subscribe-form-email').on('submit', function() {
821      var tokenField = document.getElementById('email-otp-token-field');
822      if (!tokenField) {
823        return;
824      }
825      let page_code = "g1j7mrrz279t"
826      let key = keyForEmailOtpToken($('#email').val(), page_code);
827      tokenField.value = localStorage.getItem(key);
828    });
829  });
830
831  var emailOtpCountdownTimer;
832  var emailOtpResendBtn = document.getElementById('resend-email-otp');
833  var emailOtpTimer = document.getElementById('email-otp-timer');
834  var emailOtpForm = document.getElementById('subscribe-form-email');
835  var EMAIL_OTP_RESEND_TIMER = 600;
836  $(function() {
837    $('#subscribe-form-email').on('ajax:success', function(e, data, status, xhr){
838      const form = this;
839      const action = form.getAttribute('action');
840      if (data.type === 'success' && data.email_otp_verify_flow === true) {
841        document.getElementById('email-otp-container').style.display = "block";
842        var display = document.getElementById('email-otp-countdown');
843        display.textContent = EMAIL_OTP_RESEND_TIMER;
844        disableEmailOtpResend();
845        startEmailOtpTimer(EMAIL_OTP_RESEND_TIMER, display)
846        document.getElementById('subscribe-btn-email').value = "Verify OTP and Subscribe";
847        document.getElementById('email_otp_verify_flow').value = true;
848        form.action = '/subscriptions/verify-email-otp';
849      } else if (data.type === 'success' && action.includes('verify')){
850        let email =  $('#email')
851        let page_code = "g1j7mrrz279t"
852        let key = keyForEmailOtpToken(email.val(), page_code);
853        localStorage.setItem(key, data.email_otp_auth_token);
854
855        document.getElementById('email-otp-container').style.display = "none";
856        email.val('').prop('readonly', false);
857        $('#email-otp').val('');
858        document.getElementById('subscribe-btn-email').value = "Send OTP";
859        document.getElementById('email_otp_verify_flow').value = false;
860        form.action = '/subscriptions/new-email';
861        SP.currentPage.updatesDropdown.hide();
862      }
863    });
864    $('#resend-email-otp-btn').on('click', function(e) {
865      e.preventDefault();
866      let email = $('#email').val();
867      $.ajax({
868        type: 'POST',
869        url: "/subscriptions/new-email",
870        data: {
871          email: email
872        },
873      }).done(function(data) {
874        var messageOptions = (data.type !== undefined && data.type !== null) ? { cssClass: data.type } : {};
875        HRB.utils.notify(data.text, messageOptions);
876        if (data.type === 'success') {
877          var display = document.getElementById('email-otp-countdown');
878          display.textContent = EMAIL_OTP_RESEND_TIMER;
879          disableEmailOtpResend();
880          emailOtpTimer.style.display = "none"
881          startEmailOtpTimer(EMAIL_OTP_RESEND_TIMER, display);
882        }
883      })
884    });
885  })
886
887  function startEmailOtpTimer(duration, display){
888    var timer = duration, seconds;
889    clearInterval(emailOtpCountdownTimer);
890    emailOtpCountdownTimer = setInterval(function () {
891      seconds = parseInt(timer, 10);
892      display.textContent = seconds;
893      if(--timer < 0){
894        enableEmailOtpResend();
895        clearInterval(emailOtpCountdownTimer);
896      }
897    }, 1000);
898    disableEmailOtpResend();
899  }
900
901  function enableEmailOtpResend(){
902    emailOtpResendBtn.style.display = "block";
903    emailOtpTimer.style.display = "none"
904  }
905  function disableEmailOtpResend(){
906    emailOtpResendBtn.style.display = "none";
907    emailOtpTimer.style.display = "block"
908  }
909  function keyForEmailOtpToken(email, pageCode) {
910    return email + '|' + pageCode+ '|SUBSCRIBE_VIA_EMAIL';
911  }
912</script>
912
913
914      </div>
915    </div>
916
917</div>
918 <!-- this is outside of the .container so that the cover photo can go full width on mobile -->
919
920    <div class="container" role="main">
921        <div class="page-status status-none">
922          <h2 class="status font-large">
923            All Systems Operational
924          </h2>
925          <span class="last-updated-stamp  font-small"></span>
926        </div>
927
928
929        <div class="text-section">
930          <h2 class="font-largest">
931            <a id="about-this-site" href="#about-this-site" class="no-link">About This Site</a>
932          </h2>
933          <p class="color-secondary font-regular">
934            Welcome to <a href="http://www.voipfone.co.uk" title="Visit our website!">Voipfone</a>'s status page. As an award-winning Internet Telephony Service Provider, we are proud to offer a reliable service to our customers. However, from time to time, we may experience issues – rest assured, our engineers will always be on top of the problem to restore functionality as quickly as possible. We are continuously improving our platform and, in order to do that, we schedule our maintenance windows outside business hours. Follow us on <a href="https://x.com/voipfonestatus" title="See our Voipfone Status X page">X</a> or subscribe to updates on this page to receive notifications of any works carried out or incidents involving our network.
935          </p>
936        </div>
937
938        <div class="components-section font-regular">
939      <i class="component-status hidden major_outage"></i>
940      <div class="components-uptime-link history-footer-link">
941        Uptime over the past <var data-var="num" data-pluralize="90">90</var> days. <a href="/uptime">View historical uptime.</a>
942      </div>
943    <div class="components-container one-column">
944          <div class="component-container border-color is-group ">
945  
946<div data-component-id="qkvw844ykqgj"
947     class="component-inner-container status-green showcased"
948     data-component-status="operational"
949     data-js-hook="component-group-opener">
950
951   <span class="name" role="heading" aria-level="2">
952       <span class="fa group-parent-indicator color-secondary font-small fa-plus-square-o" role="button" aria-expanded="false" aria-label="Toggle Voice Services" tabindex="0"></span>
953       <span>
954         Voice Services
955       </span>
956   </span>
957
958
959  <span
960    class="component-status "
961    role="button" tabindex="0" data-js-hook="tooltip"
962    data-original-title="Groups take on the status of their most degraded child component or service. Click to see the status of the individual children."
963  >
964
965    Operational
966
967  </span>
968
969  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
970
971    <div class="uptime-lazy-placeholder" data-uptime-lazy="qkvw844ykqgj" aria-hidden="true"></div>
972</div>
973
974
975  <!-- children components -->
976  <div class="child-components-container mix-match-showcase">
977      
978<div data-component-id="czxfbk7fwcv5"
979     class="component-inner-container status-green "
980     data-component-status="operational"
981     data-js-hook="">
982
983   <span class="name" role="heading" aria-level="2">
984      Outbound UK Landline Calls
985   </span>
986
987
988  <span
989    class="component-status "
990    
991    title=""
992  >
993
994    Operational
995
996  </span>
997
998  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
999
1000</div>
1001
1002      
1003<div data-component-id="ppmwxspps50q"
1004     class="component-inner-container status-green "
1005     data-component-status="operational"
1006     data-js-hook="">
1007
1008   <span class="name" role="heading" aria-level="2">
1009      Outbound UK Mobile Calls
1010   </span>
1011
1012
1013  <span
1014    class="component-status "
1015    
1016    title=""
1017  >
1018
1019    Operational
1020
1021  </span>
1022
1023  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1024
1025</div>
1026
1027      
1028<div data-component-id="rx2tvhdt861z"
1029     class="component-inner-container status-green "
1030     data-component-status="operational"
1031     data-js-hook="">
1032
1033   <span class="name" role="heading" aria-level="2">
1034      Outbound UK Non-Geographic Calls
1035   </span>
1036
1037
1038  <span
1039    class="component-status "
1040    
1041    title=""
1042  >
1043
1044    Operational
1045
1046  </span>
1047
1048  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1049
1050</div>
1051
1052      
1053<div data-component-id="fy3g9w17y2rm"
1054     class="component-inner-container status-green "
1055     data-component-status="operational"
1056     data-js-hook="">
1057
1058   <span class="name" role="heading" aria-level="2">
1059      Outbound International Calls
1060   </span>
1061
1062
1063  <span
1064    class="component-status "
1065    
1066    title=""
1067  >
1068
1069    Operational
1070
1071  </span>
1072
1073  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1074
1075</div>
1076
1077      
1078<div data-component-id="3rhs3t75tfrw"
1079     class="component-inner-container status-green "
1080     data-component-status="operational"
1081     data-js-hook="">
1082
1083   <span class="name" role="heading" aria-level="2">
1084      Inbound Calls to UK Landline Numbers
1085   </span>
1086
1087
1088  <span
1089    class="component-status "
1090    
1091    title=""
1092  >
1093
1094    Operational
1095
1096  </span>
1097
1098  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1099
1100</div>
1101
1102      
1103<div data-component-id="hgkjp5zymh33"
1104     class="component-inner-container status-green "
1105     data-component-status="operational"
1106     data-js-hook="">
1107
1108   <span class="name" role="heading" aria-level="2">
1109      Inbound Calls to UK Non-Geographic Numbers
1110   </span>
1111
1112
1113  <span
1114    class="component-status "
1115    
1116    title=""
1117  >
1118
1119    Operational
1120
1121  </span>
1122
1123  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1124
1125</div>
1126
1127      
1128<div data-component-id="3rtvhclm17qf"
1129     class="component-inner-container status-green "
1130     data-component-status="operational"
1131     data-js-hook="">
1132
1133   <span class="name" role="heading" aria-level="2">
1134      Inbound Calls to International Numbers
1135   </span>
1136
1137
1138  <span
1139    class="component-status "
1140    
1141    title=""
1142  >
1143
1144    Operational
1145
1146  </span>
1147
1148  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1149
1150</div>
1151
1152      
1153<div data-component-id="8cpdrlz3ln4y"
1154     class="component-inner-container status-green "
1155     data-component-status="operational"
1156     data-js-hook="">
1157
1158   <span class="name" role="heading" aria-level="2">
1159      CPS
1160   </span>
1161
1162
1163  <span
1164    class="component-status "
1165    
1166    title=""
1167  >
1168
1169    Operational
1170
1171  </span>
1172
1173  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1174
1175</div>
1176
1177      
1178<div data-component-id="mk3s9jmmw263"
1179     class="component-inner-container status-green showcased"
1180     data-component-status="operational"
1181     data-js-hook="">
1182
1183   <span class="name" role="heading" aria-level="2">
1184      Voipfone Softphone
1185   </span>
1186
1187
1188  <span
1189    class="component-status "
1190    
1191    title=""
1192  >
1193
1194    Operational
1195
1196  </span>
1197
1198  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1199
1200    <div class="uptime-lazy-placeholder" data-uptime-lazy="mk3s9jmmw263" aria-hidden="true"></div>
1201</div>
1202
1203      
1204<div data-component-id="vx9f49ltyhw8"
1205     class="component-inner-container status-green showcased"
1206     data-component-status="operational"
1207     data-js-hook="">
1208
1209   <span class="name" role="heading" aria-level="2">
1210      Voicemail
1211   </span>
1212
1213
1214  <span
1215    class="component-status "
1216    
1217    title=""
1218  >
1219
1220    Operational
1221
1222  </span>
1223
1224  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1225
1226    <div class="uptime-lazy-placeholder" data-uptime-lazy="vx9f49ltyhw8" aria-hidden="true"></div>
1227</div>
1228
1229      
1230<div data-component-id="9xfgc7lq662h"
1231     class="component-inner-container status-green showcased"
1232     data-component-status="operational"
1233     data-js-hook="">
1234
1235   <span class="name" role="heading" aria-level="2">
1236      Conference Call
1237   </span>
1238
1239
1240  <span
1241    class="component-status "
1242    
1243    title=""
1244  >
1245
1246    Operational
1247
1248  </span>
1249
1250  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1251
1252    <div class="uptime-lazy-placeholder" data-uptime-lazy="9xfgc7lq662h" aria-hidden="true"></div>
1253</div>
1254
1255  </div>
1256</div>
1257
1258          <div class="component-container border-color is-group ">
1259  
1260<div data-component-id="dh524gth3dp0"
1261     class="component-inner-container status-green "
1262     data-component-status="operational"
1263     data-js-hook="component-group-opener">
1264
1265   <span class="name" role="heading" aria-level="2">
1266       <span class="fa group-parent-indicator color-secondary font-small fa-plus-square-o" role="button" aria-expanded="false" aria-label="Toggle Fax Services" tabindex="0"></span>
1267       <span>
1268         Fax Services
1269       </span>
1270   </span>
1271
1272
1273  <span
1274    class="component-status "
1275    role="button" tabindex="0" data-js-hook="tooltip"
1276    data-original-title="Groups take on the status of their most degraded child component or service. Click to see the status of the individual children."
1277  >
1278
1279    Operational
1280
1281  </span>
1282
1283  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1284
1285</div>
1286
1287
1288  <!-- children components -->
1289  <div class="child-components-container ">
1290      
1291<div data-component-id="73gcnvfhdq0l"
1292     class="component-inner-container status-green "
1293     data-component-status="operational"
1294     data-js-hook="">
1295
1296   <span class="name" role="heading" aria-level="2">
1297      Outbound Faxes
1298   </span>
1299
1300
1301  <span
1302    class="component-status "
1303    
1304    title=""
1305  >
1306
1307    Operational
1308
1309  </span>
1310
1311  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1312
1313</div>
1314
1315      
1316<div data-component-id="zpfls7j8gyng"
1317     class="component-inner-container status-green "
1318     data-component-status="operational"
1319     data-js-hook="">
1320
1321   <span class="name" role="heading" aria-level="2">
1322      Inbound Faxes
1323   </span>
1324
1325
1326  <span
1327    class="component-status "
1328    
1329    title=""
1330  >
1331
1332    Operational
1333
1334  </span>
1335
1336  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1337
1338</div>
1339
1340  </div>
1341</div>
1342
1343          <div class="component-container border-color is-group ">
1344  
1345<div data-component-id="ts5dl12ykdt7"
1346     class="component-inner-container status-green "
1347     data-component-status="operational"
1348     data-js-hook="component-group-opener">
1349
1350   <span class="name" role="heading" aria-level="2">
1351       <span class="fa group-parent-indicator color-secondary font-small fa-plus-square-o" role="button" aria-expanded="false" aria-label="Toggle SMS Services" tabindex="0"></span>
1352       <span>
1353         SMS Services
1354       </span>
1355   </span>
1356
1357
1358  <span
1359    class="component-status "
1360    role="button" tabindex="0" data-js-hook="tooltip"
1361    data-original-title="Groups take on the status of their most degraded child component or service. Click to see the status of the individual children."
1362  >
1363
1364    Operational
1365
1366  </span>
1367
1368  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1369
1370</div>
1371
1372
1373  <!-- children components -->
1374  <div class="child-components-container ">
1375      
1376<div data-component-id="2695qbg7gwcw"
1377     class="component-inner-container status-green "
1378     data-component-status="operational"
1379     data-js-hook="">
1380
1381   <span class="name" role="heading" aria-level="2">
1382      Outbound SMS
1383   </span>
1384
1385
1386  <span
1387    class="component-status "
1388    
1389    title=""
1390  >
1391
1392    Operational
1393
1394  </span>
1395
1396  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1397
1398</div>
1399
1400      
1401<div data-component-id="z3p3nlgglc9r"
1402     class="component-inner-container status-green "
1403     data-component-status="operational"
1404     data-js-hook="">
1405
1406   <span class="name" role="heading" aria-level="2">
1407      Inbound SMS
1408   </span>
1409
1410
1411  <span
1412    class="component-status "
1413    
1414    title=""
1415  >
1416
1417    Operational
1418
1419  </span>
1420
1421  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1422
1423</div>
1424
1425  </div>
1426</div>
1427
1428          <div class="component-container border-color">
1429            
1430<div data-component-id="tp7y6ygl3124"
1431     class="component-inner-container status-green "
1432     data-component-status="operational"
1433     data-js-hook="">
1434
1435   <span class="name" role="heading" aria-level="2">
1436      Line Rental
1437   </span>
1438
1439
1440  <span
1441    class="component-status "
1442    
1443    title=""
1444  >
1445
1446    Operational
1447
1448  </span>
1449
1450  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1451
1452</div>
1453
1454          </div>
1455          <div class="component-container border-color">
1456            
1457<div data-component-id="j59vkz4f8fn5"
1458     class="component-inner-container status-green "
1459     data-component-status="operational"
1460     data-js-hook="">
1461
1462   <span class="name" role="heading" aria-level="2">
1463      Broadband
1464   </span>
1465
1466
1467  <span
1468    class="component-status "
1469    
1470    title=""
1471  >
1472
1473    Operational
1474
1475  </span>
1476
1477  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1478
1479</div>
1480
1481          </div>
1482          <div class="component-container border-color">
1483            
1484<div data-component-id="wljm4jccbtb4"
1485     class="component-inner-container status-green "
1486     data-component-status="operational"
1487     data-js-hook="">
1488
1489   <span class="name" role="heading" aria-level="2">
1490      Billing and Payments
1491   </span>
1492
1493    <button
1494      type="button"
1495      class="tooltip-base tool"
1496      data-js-hook="tooltip"
1497      tabindex="0"
1498      aria-label="More information about Billing and Payments"
1499      aria-describedby="tooltip-wljm4jccbtb4"
1500      data-original-title="Card Payment processing, general invoicing and credit transactions etc."
1501    >?</button>
1502
1503  <span
1504    class="component-status "
1505    
1506    title=""
1507  >
1508
1509    Operational
1510
1511  </span>
1512
1513  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1514
1515</div>
1516
1517          </div>
1518          <div class="component-container border-color">
1519            
1520<div data-component-id="d8sffd95b24c"
1521     class="component-inner-container status-green "
1522     data-component-status="operational"
1523     data-js-hook="">
1524
1525   <span class="name" role="heading" aria-level="2">
1526      Control Panel
1527   </span>
1528
1529    <button
1530      type="button"
1531      class="tooltip-base tool"
1532      data-js-hook="tooltip"
1533      tabindex="0"
1534      aria-label="More information about Control Panel"
1535      aria-describedby="tooltip-d8sffd95b24c"
1536      data-original-title="my.voipfone.co.uk website"
1537    >?</button>
1538
1539  <span
1540    class="component-status "
1541    
1542    title=""
1543  >
1544
1545    Operational
1546
1547  </span>
1548
1549  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1550
1551</div>
1552
1553          </div>
1554          <div class="component-container border-color">
1555            
1556<div data-component-id="j9p5m0396clb"
1557     class="component-inner-container status-green "
1558     data-component-status="operational"
1559     data-js-hook="">
1560
1561   <span class="name" role="heading" aria-level="2">
1562      Website
1563   </span>
1564
1565    <button
1566      type="button"
1567      class="tooltip-base tool"
1568      data-js-hook="tooltip"
1569      tabindex="0"
1570      aria-label="More information about Website"
1571      aria-describedby="tooltip-j9p5m0396clb"
1572      data-original-title="www.voipfone.co.uk website"
1573    >?</button>
1574
1575  <span
1576    class="component-status "
1577    
1578    title=""
1579  >
1580
1581    Operational
1582
1583  </span>
1584
1585  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1586
1587</div>
1588
1589          </div>
1590          <div class="component-container border-color">
1591            
1592<div data-component-id="562qvych6ft8"
1593     class="component-inner-container status-green showcased"
1594     data-component-status="operational"
1595     data-js-hook="">
1596
1597   <span class="name" role="heading" aria-level="2">
1598      Virtual PA
1599   </span>
1600
1601
1602  <span
1603    class="component-status "
1604    
1605    title=""
1606  >
1607
1608    Operational
1609
1610  </span>
1611
1612  <button type="button" class="tool icon-indicator fa fa-check status-icon-button" aria-label="Operational" data-js-hook="tooltip" data-original-title="Operational"></button>
1613
1614    <div class="uptime-lazy-placeholder" data-uptime-lazy="562qvych6ft8" aria-hidden="true"></div>
1615</div>
1616
1617          </div>
1618    </div>
1619    <div class="component-statuses-legend font-small">
1620  <div class="legend-item status-green">
1621    <span class="icon-indicator fa fa-check"></span>
1622    Operational
1623  </div>
1624  <div class="legend-item status-yellow">
1625    <span class="icon-indicator fa fa-minus-square"></span>
1626    Degraded Performance
1627  </div>
1628  <div class="legend-item status-orange">
1629    <span class="icon-indicator fa fa-exclamation-triangle"></span>
1630    Partial Outage
1631  </div>
1632  <div class="breaker"></div>
1633  <div class="legend-item status-red">
1634    <span class="icon-indicator fa fa-times"></span>
1635    Major Outage
1636  </div>
1637  <div class="legend-item status-blue">
1638    <span class="icon-indicator fa fa-wrench"></span>
1639    Maintenance
1640  </div>
1641</div>
1642
1643  </div>
1644
1645    <div id="uptime-tooltip">
1646  <div class="pointer-container">
1647    <div class="pointer-larger"></div>
1648    <div class="pointer-smaller"></div>
1649  </div>
1650  <div class="tooltip-box">
1651    <div class="tooltip-content">
1652      <div class="tooltip-close">
1653        <i class="fa fa-times"></i>
1654      </div>
1655      <div class="date"></div>
1656      <div class="outages">
1657        <div class="outage-field major">
1658          <span class="label">
1659            <i class="component-status page-colors text-color major_outage"></i>
1660            Major outage
1661          </span>
1662          <span class="value-hrs"></span>
1663          <span class="value-mins"></span>
1664        </div>
1665        <div class="outage-field partial">
1666          <span class="label">
1667            <i class="component-status page-colors text-color partial_outage"></i>
1668            Partial outage
1669          </span>
1670          <span class="value-hrs"></span>
1671          <span class="value-mins"></span>
1672        </div>
1673        <div class="no-outages-msg">
1674          No downtime recorded on this day.
1675        </div>
1676        <div class="no-data-msg">
1677          No data exists for this day.
1678        </div>
1679        <div id="major-outage-group-count" class="outage-count">
1680          <i class="component-status page-colors text-color major_outage"></i>
1681          <span class="count"></span>
1682          had a major outage.
1683        </div>
1684        <div id="partial-outage-group-count" class="outage-count">
1685          <i class="component-status page-colors text-color partial_outage"></i>
1686          <span class="count"></span>
1687          had a partial outage.
1688        </div>
1689      </div>
1690      <div class="related-events">
1691        <h3 id="related-event-header">Related</h3>
1692        <ul id="related-events-list"></ul>
1693      </div>
1694      <div class="no-related-msg">
1695        <p>No incidents or maintenance related to this downtime.</p>
1696      </div>
1697    </div>
1698  </div>
1699</div>
1700
1701<script src="https://dka575ofm4ao0.cloudfront.net/assets/vendor/bowser-1643ca34a6d589b2d4d42163a891e4512d5d7657125e09bb5f3d44288114e6bd.js"></script>
vendor: 1 bytes, line 1701
1701
1702<script type="text/javascript">
1703  /**
1704    This file contains the code needed to handle display of the uptime tooltips on status.
1705    Note: because it's in ERB, only ES5 syntax is allowed.
1706  */
1707
1708  window.uptimeData = window.uptimeData || {};
1709  var uptimeData = window.uptimeData;
1710  var timeoutId;
1711  var monthStrings = [
1712    'Jan', 'Feb', 'Mar',
1713    'Apr', 'May', 'Jun',
1714    'Jul', 'Aug', 'Sep',
1715    'Oct', 'Nov', 'Dec'
1716  ];
1717  var EVENT_MAX_LENGTH = 90;
1718
1719  // Detect device (desktop vs. touch device)
1720  function touchDevice() {
1721    var browser = bowser.getParser(window.navigator.userAgent);
1722    // if type is either mobile or tablet, return true
1723    return browser.parse().parsedResult.platform.type !== 'desktop';
1724  }
1725
1726  // Class is in format day-<number>. Convert to just number
1727  function dayNumberFromClass(className) {
1728    return parseInt(className.split('-')[1]);
1729  }
1730
1731  // Class is in format component-<code>. Convert to just code
1732  function componentCodeFromClass(className) {
1733    return className.split('-')[1];
1734  }
1735
1736  // Convert number to string pixel measurement
1737  function intToPixels(number) {
1738    return number.toString() + 'px';
1739  }
1740
1741  function truncate(str) {
1742    return str.substring(0, EVENT_MAX_LENGTH) +
1743      (str.length > EVENT_MAX_LENGTH ? '...' : '');
1744  }
1745
1746  // Tooltip Handling class constructor
1747  function UptimeTooltipHandler(frameWidth) {
1748    this.visible = false;
1749    this.activeDay = {
1750      hovered: false
1751    };
1752    this.tooltip = document.getElementById('uptime-tooltip');
1753    this.frameWidth = frameWidth === undefined ? window.innerWidth : frameWidth;
1754    this.scrolling = false;
1755
1756    window.addEventListener('mousemove', this.tooltipListener.bind(this));
1757    window.addEventListener('orientationchange', this.orientationListener.bind(this));
1758
1759    // on tooltip creation, determine whether to display touch-specific controls
1760    var tooltipCloseButton = document.querySelector('.tooltip-close');
1761
1762    if (touchDevice()) {
1763      var componentsContainer = document.querySelector('.components-container');
1764      componentsContainer.addEventListener('touchstart', this.handleTouch.bind(this));
1765
1766      tooltipCloseButton.addEventListener('touchstart', this.unhoverTooltip.bind(this));
1767    } else {
1768      window.addEventListener('resize', this.resizeListener.bind(this));
1769      // classList not supported by IE < 9
1770      tooltipCloseButton.className += ' hidden';
1771    }
1772
1773    // Handle toggle of group elements
1774    var groupComponents = document.querySelectorAll('[data-js-hook=component-group-opener]');
1775    for (var i = 0; i < groupComponents.length; i++) {
1776      groupComponents[i].addEventListener('click', this.hideTooltip.bind(this));
1777    }
1778
1779    var tooltipBox = document.querySelector('#uptime-tooltip .tooltip-box');
1780    tooltipBox.addEventListener('mouseenter', this.mouseEnteredTooltip.bind(this));
1781    tooltipBox.addEventListener('mouseleave', this.unhoverTooltip.bind(this));
1782  }
1783
1784  // STATUS-801: extracted so the lazy loader (_uptime_showcase_lazy_js) can bind
1785  // focus/blur/keydown handlers on rects that are injected AFTER initial paint.
1786  // Pass a root element to bind only that subtree's rects (avoids re-binding
1787  // existing ones); defaults to the whole document for the inline render path.
1788  function bindUptimeDayRects(root) {
1789    (root || document).querySelectorAll('.uptime-day').forEach(function (rect) {
1790      rect.addEventListener('focus', function (event) {
1791        var tooltipHandler = new UptimeTooltipHandler();
1792        tooltipHandler.updateHoveredDay(event);
1793        tooltipHandler.updateTooltip(event);
1794      });
1795
1796      rect.addEventListener('blur', function () {
1797        var tooltipHandler = new UptimeTooltipHandler();
1798        tooltipHandler.unhoverTooltip();
1799      });
1800
1801      rect.addEventListener('keydown', function (event) {
1802        if (event.key === 'Escape' || event.keyCode === 27) {
1803          var tooltipHandler = new UptimeTooltipHandler();
1804          tooltipHandler.unhoverTooltip();
1805        }
1806      });
1807    });
1808  }
1809  window.bindUptimeDayRects = bindUptimeDayRects;
1810  bindUptimeDayRects(document);
1811
1812  UptimeTooltipHandler.prototype.tooltipListener = function(event) {
1813    if (!this.tooltipHovered) {
1814      this.updateHoveredDay(event);
1815      this.updateTooltip(event);
1816    }
1817  }
1818
1819  // this handler will accommodate for mobile orientation change
1820  UptimeTooltipHandler.prototype.orientationListener = function(event) {
1821    // just close the tooltip
1822    this.unhoverTooltip();
1823  }
1824
1825  UptimeTooltipHandler.prototype.resizeListener = function(event) {
1826    this.frameWidth = window.innerWidth;
1827  }
1828
1829  UptimeTooltipHandler.prototype.handleTouch = function (event) {
1830    if (event.target.classList.contains('uptime-day')) {
1831      event.stopPropagation();
1832      this.bladeTouched(event);
1833    }
1834  }
1835
1836  UptimeTooltipHandler.prototype.mouseEnteredTooltip = function() {
1837    // Necessary to clear the timeout set for closing the tooltip when the mouse
1838    // moves off the blade or timeline, so the tooltip isnt closed on hover
1839    clearTimeout(timeoutId);
1840    // Sets it to null so the timeout can be set later, as clearTimeout only
1841    // cancels the timer, and we need to allow it to be reset in the mouse
1842    // move handler below
1843    timeoutId = null;
1844    this.tooltipHovered = true;
1845  }
1846
1847  UptimeTooltipHandler.prototype.unhoverTooltip = function() {
1848    this.tooltipHovered = false;
1849    this.activeDay.hovered = false;
1850    this.hideTooltip();
1851  }
1852
1853  UptimeTooltipHandler.prototype.bladeTouched = function (event) {
1854    event.preventDefault();
1855    var classes = event.target.getAttribute('class').split(' ');
1856    var componentCode = componentCodeFromClass(classes[1])
1857    var index = dayNumberFromClass(classes[2]);
1858
1859    // If open and tapped on same component and day, close tooltip
1860    if (this.visible && this.activeDay.component === componentCode && this.activeDay.index === index) {
1861      this.hideTooltip();
1862    } else {
1863      this.updateHoveredDay(event);
1864      this.updateTooltip(event);
1865    }
1866  }
1867
1868  UptimeTooltipHandler.prototype.updateHoveredDay = function(event) {
1869    var classes = event.target.getAttribute('class'); // classList doesn't work in IE
1870    var onDay = classes != null && classes.split(' ').indexOf('uptime-day') !== -1;
1871
1872    if (onDay) {
1873      classes = classes.split(' ');
1874
1875      var componentCode = componentCodeFromClass(classes[1]);
1876
1877      this.activeDay = {
1878        index: dayNumberFromClass(classes[2]),
1879        component: componentCode,
1880        bounds: event.target.getBoundingClientRect(),
1881        isGroup: uptimeData[componentCode].component.isGroup,
1882        hovered: true
1883      }
1884    } else {
1885      this.activeDay.hovered = false;
1886    }
1887  }
1888
1889  UptimeTooltipHandler.prototype.updateTooltip = function(event) {
1890    var classes = event.target.getAttribute('class'); // classList doesn't work in IE
1891    var hoveredOnGraphic = classes != null && classes.split(' ').indexOf('availability-time-line-graphic') !== -1;
1892
1893    if (this.activeDay.hovered) {
1894      this.updateTooltipData();
1895      this.positionTooltip();
1896    } else if (this.visible && !this.activeDay.hovered && !hoveredOnGraphic) {
1897      // Important: since this is on mouse move it will be called multiple times
1898      // which will clear timeoutId and reset it to the new value, meaning
1899      // it is a race condition to cancel it
1900      if (!timeoutId) {
1901        var _this = this;
1902        timeoutId = setTimeout(function() {
1903          _this.hideTooltip();
1904          timeoutId = null;
1905        }, 250);
1906      }
1907    }
1908  }
1909
1910  UptimeTooltipHandler.prototype.updateTooltipData = function() {
1911    // Get the data for the day we're hovered on
1912    var day = uptimeData[this.activeDay.component].days[this.activeDay.index];
1913
1914    // Update the date for the tooltip
1915    var date = new Date(day.date);
1916
1917    // Get the component's start date.  Note that it will be undefined here unless it is populated in our database
1918    var startDay = uptimeData[this.activeDay.component].component.startDate;
1919    var startDate = startDay ? new Date(startDay) : null;
1920
1921    // Determine whether current date falls before component's start date.
1922    var beforeStartDate = startDate ? date.getTime() < startDate.getTime() : false;
1923
1924    // UTC necessary since days are passed yyyy-mm-dd, and new Date uses midnight UTC, so local times
1925    // are presented as the day before
1926    var dateString = date.getUTCDate() + " " + monthStrings[date.getUTCMonth()] + " " + date.getUTCFullYear();
1927    document.querySelector('#uptime-tooltip .date').innerHTML = dateString;
1928
1929    // Update the outage fields
1930    if (this.activeDay.isGroup) {
1931      this.updateGroupOutageFields()
1932    } else {
1933      this.updateOutageFields(day.outages.p, day.outages.m, day.related_events, beforeStartDate);
1934    }
1935  }
1936
1937  UptimeTooltipHandler.prototype.hoursFromSeconds = function(s) {
1938    return Math.floor(s / 3600);
1939  }
1940
1941  UptimeTooltipHandler.prototype.minutesFromSeconds = function(s) {
1942    // If less than a minute, round up to 1 minute to show that some outage existed
1943    if (s > 0 && s < 60) {
1944      return 1;
1945    }
1946
1947    // Otherwise use floor
1948    return Math.floor((s % 3600) / 60);
1949  }
1950
1951  UptimeTooltipHandler.prototype.updateGroupOutageFields = function() {
1952    // Hide time info
1953    document.querySelector('#uptime-tooltip .outage-field.major').style.display = 'none';
1954    document.querySelector('#uptime-tooltip .outage-field.partial').style.display = 'none';
1955    document.querySelector(".related-events h3").style.display = 'none';
1956    document.querySelector('.no-related-msg').style.display = 'none';
1957
1958    var eventList = document.getElementById("related-events-list")
1959    var cloneList = eventList.cloneNode(false);
1960    eventList.parentNode.replaceChild(cloneList, eventList);
1961
1962    var partialCount = 0;
1963    var majorCount = 0;
1964
1965    /**
1966       We were originally using the operationalCount as part of the no outage copy for group components,
1967       but ultimately decided not to use it. I opted to leave the variable in place in case we ever
1968       decide to use it in the future.
1969     */
1970    var operationalCount = 0;
1971    var noDataCount = 0;
1972    var showcasedComponentsCount = 0;
1973
1974    var components = uptimeData[this.activeDay.component].component.group
1975
1976    for (var i = 0; i < components.length; i++) {
1977      if (!uptimeData[components[i]]) continue;
1978
1979      showcasedComponentsCount++;
1980
1981      var outages = uptimeData[components[i]].days[this.activeDay.index].outages;
1982
1983      var currentDay = uptimeData[components[i]].days[this.activeDay.index];
1984      var currentDate = new Date(currentDay.date);
1985
1986      // Get the component's start date.  Note that it will be undefined here unless it is populated in our database
1987      var startDay = uptimeData[components[i]].component.startDate;
1988      var startDate = startDay ? new Date(startDay) : null;
1989
1990      if (outages.p) {
1991        partialCount += 1;
1992      }
1993
1994      if (outages.m) {
1995        majorCount += 1;
1996      }
1997
1998      // Only increase operational count if component has data for this day
1999      if (!outages.p && !outages.m) {
2000        if (startDate && currentDate.getTime() < startDate.getTime()) {
2001          noDataCount +=1;
2002        }
2003        else {
2004          operationalCount +=1;
2005        }
2006      }
2007    }
2008
2009    document.querySelector('#major-outage-group-count').style.display = majorCount ? 'block' : 'none';
2010    document.querySelector('#partial-outage-group-count').style.display = partialCount ? 'block' : 'none';
2011
2012    document.querySelector('#major-outage-group-count .count').innerText = majorCount + (majorCount === 1 ? " component" : " components");
2013    document.querySelector('#partial-outage-group-count .count').innerText = partialCount + (partialCount === 1 ? " component" : " components ");
2014
2015    // Show no data message only if we do not have data for any showcased components in the group
2016    var showNoDataMessage = noDataCount === showcasedComponentsCount;
2017
2018    // Show no outages message if we have data for the components and no outages in that data
2019    document.querySelector('#uptime-tooltip .no-outages-msg').style.display = (majorCount || partialCount || showNoDataMessage) ? 'none' : 'block';
2020    document.querySelector('#uptime-tooltip .no-data-msg').style.display = showNoDataMessage ? 'block' : 'none';
2021  }
2022
2023  UptimeTooltipHandler.prototype.updateOutageFields = function(partial, major, relatedEvents, beforeStartDate) {
2024    // Hide group info
2025    document.querySelector('#major-outage-group-count').style.display = 'none';
2026    document.querySelector('#partial-outage-group-count').style.display = 'none';
2027
2028    // Show the message that no outage present, if none is present
2029    if (partial || major || beforeStartDate) {
2030      document.querySelector('#uptime-tooltip .no-outages-msg').style.display = 'none';
2031    } else {
2032      document.querySelector('#uptime-tooltip .no-outages-msg').style.display = 'block';
2033    }
2034
2035    if (beforeStartDate) {
2036      document.querySelector('#uptime-tooltip .no-data-msg').style.display = 'block';
2037    }
2038    else {
2039      document.querySelector('#uptime-tooltip .no-data-msg').style.display = 'none';
2040    }
2041
2042    // Update partial outage field if an outage exists, otherwise hide it
2043    if (partial) {
2044      var hrs = this.hoursFromSeconds(partial);
2045      var mins = this.minutesFromSeconds(partial);
2046      document.querySelector('#uptime-tooltip .outage-field.partial .value-hrs').innerHTML = hrs.toString() + ' hrs';
2047      document.querySelector('#uptime-tooltip .outage-field.partial .value-mins').innerHTML = mins.toString() + ' mins';
2048      document.querySelector('#uptime-tooltip .outage-field.partial').style.display = 'flex';
2049    } else {
2050       document.querySelector('#uptime-tooltip .outage-field.partial').style.display = 'none';
2051    }
2052
2053    // Update major outage field if an outage exists, otherwise hide it
2054    if (major) {
2055      var hrs = this.hoursFromSeconds(major);
2056      var mins = this.minutesFromSeconds(major);
2057      document.querySelector('#uptime-tooltip .outage-field.major .value-hrs').innerHTML = hrs.toString() + ' hrs';
2058      document.querySelector('#uptime-tooltip .outage-field.major .value-mins').innerHTML = mins.toString() + ' mins';
2059      document.querySelector('#uptime-tooltip .outage-field.major').style.display = 'flex';
2060    } else {
2061      document.querySelector('#uptime-tooltip .outage-field.major').style.display = 'none';
2062    }
2063
2064    var eventList = document.getElementById("related-events-list")
2065    var cloneList = eventList.cloneNode(false);
2066    document.querySelector(".related-events h3").style.display = (relatedEvents.length ? 'block' : 'none');
2067
2068    for (var i = 0; i < relatedEvents.length; i++) {
2069      var listItem = document.createElement("li");
2070      listItem.className = "related-event";
2071      var anchor = document.createElement("a");
2072      anchor.className = "related-event-link";
2073      anchor.target = "_blank";
2074      anchor.href = window.Routes.incident_path(relatedEvents[i].code);
2075
2076
2077      var text = document.createTextNode(truncate(relatedEvents[i].name));
2078      anchor.appendChild(text);
2079      listItem.appendChild(anchor);
2080      cloneList.appendChild(listItem);
2081    }
2082
2083    const displayNoRelatedMsg = ((major || partial) && !relatedEvents.length);
2084    document.querySelector('.no-related-msg').style.display = (displayNoRelatedMsg ? 'block' : 'none');
2085
2086    eventList.parentNode.replaceChild(cloneList, eventList);
2087  }
2088
2089  UptimeTooltipHandler.prototype.positionTooltip = function() {
2090    this.calculatePointerCenter();
2091    this.calculateBoxPosition();
2092
2093    // show tooltip
2094    this.tooltip.style.display = 'block';
2095
2096    // position pointer
2097    var pointer = this.tooltip.getElementsByClassName('pointer-container')[0];
2098    pointer.style.left = intToPixels(this.pointerCenter.x - 8);
2099    pointer.style.top = intToPixels(this.pointerCenter.y - 5);
2100
2101    // position display box
2102    var box = this.tooltip.getElementsByClassName('tooltip-box')[0];
2103    box.style.left = intToPixels(this.boxLeft);
2104    box.style.top = intToPixels(this.pointerCenter.y + 5);
2105
2106    this.visible = true;
2107  }
2108
2109  UptimeTooltipHandler.prototype.calculatePointerCenter = function() {
2110    var bounds = this.activeDay.bounds;
2111    var rectLeft = bounds.left + window.pageXOffset;
2112    var rectBottom = bounds.bottom + window.pageYOffset;
2113    var rectWidth = bounds.right - bounds.left;
2114
2115    this.pointerCenter = {
2116      x: rectLeft + Math.floor(rectWidth / 2),
2117      y: rectBottom + 5
2118    }
2119  }
2120
2121  UptimeTooltipHandler.prototype.calculateBoxPosition = function() {
2122    var sideWidth = 162.5;
2123    if (this.pointerCenter.x - sideWidth < 0) {
2124      this.boxLeft = 0;
2125    } else if (this.pointerCenter.x + sideWidth > this.frameWidth) {
2126      this.boxLeft = this.frameWidth - sideWidth * 2;
2127    } else {
2128      this.boxLeft = this.pointerCenter.x - sideWidth;
2129    }
2130  }
2131
2132  UptimeTooltipHandler.prototype.hideTooltip = function() {
2133    this.tooltip.style.display = 'none';
2134    this.visible = false;
2135  }
2136
2137  new UptimeTooltipHandler();
2138
2139</script>
2139
2140
2141
2142    
2142<script type="text/javascript">
2143  /**
2144   * STATUS-801: viewport-triggered loader for the 90-day uptime showcase.
2145   *
2146   * When LAZY_UPTIME_SHOWCASE is enabled the status document ships WITHOUT the
2147   * per-component SVG bars and the multi-MB inline `uptimeData` blob (that inline
2148   * payload is what caused `200 OK` + `ERR_HTTP2_PROTOCOL_ERROR` truncation on
2149   * large pages). Each showcase-eligible component instead renders a small
2150   * placeholder (`[data-uptime-lazy="<code>"]`). This script watches those
2151   * placeholders and, as they scroll into view, fetches their bars in small
2152   * batches from `status#uptime_showcase`, replaces the placeholder with the
2153   * returned markup, merges the tooltip data into `window.uptimeData`, and wires
2154   * up hover/keyboard tooltips + responsive (30/60/90-day) resizing.
2155   *
2156   * ES5 only (matches the rest of the status inline scripts). No hard dependency
2157   * on fetch/IntersectionObserver: falls back gracefully when unavailable.
2158   */
2159  (function () {
2160    var ENDPOINT = "/uptime_showcase";
2161    var BATCH_LIMIT = 60;              // must stay <= SHOWCASE_BATCH_LIMIT server-side
2162    var FLUSH_DELAY_MS = 60;           // coalesce rapidly-observed placeholders
2163    var MAX_WIDTH_30_DAYS = 600;
2164    var MAX_WIDTH_60_DAYS = 1024;
2165    var PRELOAD_MARGIN = '250px 0px';  // start fetching just before they scroll in
2166
2167    // code -> {ninety, sixty, thirty} for responsive legend updates.
2168    var uptimeValues = {};
2169    // code -> true while queued/in-flight, to avoid duplicate requests.
2170    var inFlight = {};
2171    var queue = [];
2172    var flushTimer = null;
2173    var observer = null;
2174
2175    function init() {
2176      var placeholders = document.querySelectorAll('[data-uptime-lazy]');
2177      if (!placeholders.length) return;
2178
2179      window.uptimeData = window.uptimeData || {};
2180
2181      if ('IntersectionObserver' in window) {
2182        observer = new IntersectionObserver(onIntersect, { rootMargin: PRELOAD_MARGIN });
2183        for (var i = 0; i < placeholders.length; i++) {
2184          observer.observe(placeholders[i]);
2185        }
2186      } else {
2187        // Older browsers: no lazy behaviour, just load everything in batches.
2188        for (var j = 0; j < placeholders.length; j++) {
2189          enqueue(placeholders[j].getAttribute('data-uptime-lazy'));
2190        }
2191      }
2192
2193      var resizeTimer;
2194      window.addEventListener('resize', function () {
2195        clearTimeout(resizeTimer);
2196        resizeTimer = setTimeout(resizeSvgViewBoxes, 150);
2197      });
2198    }
2199
2200    function onIntersect(entries) {
2201      for (var i = 0; i < entries.length; i++) {
2202        if (entries[i].isIntersecting) {
2203          enqueue(entries[i].target.getAttribute('data-uptime-lazy'));
2204        }
2205      }
2206    }
2207
2208    function enqueue(code) {
2209      if (!code || inFlight[code]) return;
2210      inFlight[code] = true;
2211      queue.push(code);
2212      if (!flushTimer) flushTimer = setTimeout(flush, FLUSH_DELAY_MS);
2213    }
2214
2215    function flush() {
2216      flushTimer = null;
2217      if (!queue.length) return;
2218      var batch = queue.splice(0, BATCH_LIMIT);
2219      fetchBatch(batch);
2220      if (queue.length && !flushTimer) flushTimer = setTimeout(flush, FLUSH_DELAY_MS);
2221    }
2222
2223    function fetchBatch(codes) {
2224      var xhr = new XMLHttpRequest();
2225      xhr.open('GET', ENDPOINT + '?components=' + encodeURIComponent(codes.join(',')), true);
2226      xhr.setRequestHeader('Accept', 'application/json');
2227      xhr.onreadystatechange = function () {
2228        if (xhr.readyState !== 4) return;
2229        if (xhr.status >= 200 && xhr.status < 300) {
2230          var data;
2231          try { data = JSON.parse(xhr.responseText); }
2232          catch (e) { release(codes); return; }
2233          applyBatch(data, codes);
2234        } else {
2235          // Transient failure: allow these codes to be retried if re-observed.
2236          release(codes);
2237        }
2238      };
2239      xhr.send();
2240    }
2241
2242    // Free codes so a future intersection can retry them (e.g. after a 5xx).
2243    function release(codes) {
2244      for (var i = 0; i < codes.length; i++) inFlight[codes[i]] = false;
2245    }
2246
2247    function applyBatch(data, codes) {
2248      var timelines = data.timelines || {};
2249      for (var key in timelines) {
2250        if (timelines.hasOwnProperty(key)) window.uptimeData[key] = timelines[key];
2251      }
2252
2253      var values = data.values || [];
2254      for (var v = 0; v < values.length; v++) {
2255        uptimeValues[values[v].component] = values[v];
2256      }
2257
2258      var components = data.components || {};
2259      for (var c = 0; c < codes.length; c++) {
2260        var code = codes[c];
2261        var placeholder = document.querySelector('[data-uptime-lazy="' + code + '"]');
2262        if (!placeholder) continue;
2263        if (observer) observer.unobserve(placeholder);
2264
2265        var html = components[code];
2266        if (!html) {
2267          // Server returned no markup for this code (not actually showcased):
2268          // drop the placeholder and stop retrying.
2269          if (placeholder.parentNode) placeholder.parentNode.removeChild(placeholder);
2270          continue;
2271        }
2272
2273        // Replace the neutral placeholder with the fetched `.uptime-90-days-wrapper`
2274        // so the resulting DOM matches the inline (non-lazy) render exactly.
2275        var holder = document.createElement('div');
2276        holder.innerHTML = html;
2277        var node = holder.firstElementChild;
2278        if (node && placeholder.parentNode) {
2279          placeholder.parentNode.replaceChild(node, placeholder);
2280          if (window.bindUptimeDayRects) window.bindUptimeDayRects(node);
2281        }
2282      }
2283
2284      resizeSvgViewBoxes();
2285    }
2286
2287    /* ----- responsive resize (adapted from components_js) ----------------- */
2288
2289    function calculateViewbox(dayCount, rectWidth, rectPadding) {
2290      var viewBox = [];
2291      if (dayCount === 90) {
2292        viewBox.push(0);
2293      } else {
2294        var offset = 90 - dayCount;
2295        viewBox.push((offset * rectWidth) + (rectPadding * offset));
2296      }
2297      viewBox.push(0);
2298      viewBox.push((rectWidth * dayCount) + (rectPadding * (dayCount - 1)));
2299      viewBox.push(34);
2300      return viewBox.join(' ');
2301    }
2302
2303    function getKeyAndCount(width) {
2304      if (width <= MAX_WIDTH_30_DAYS) return { dayCount: 30, uptimeKey: 'thirty' };
2305      if (width <= MAX_WIDTH_60_DAYS) return { dayCount: 60, uptimeKey: 'sixty' };
2306      return { dayCount: 90, uptimeKey: 'ninety' };
2307    }
2308
2309    function setUptimeValue(values, uptimeKey) {
2310      var current = document.querySelector('.legend-item-' + values.component);
2311      if (!current) return;
2312      var clone = current.cloneNode(false);
2313      var uptimeSpan = document.createElement('span');
2314      uptimeSpan.id = 'uptime-percent-' + values.component;
2315      uptimeSpan.innerText = values[uptimeKey];
2316      clone.appendChild(uptimeSpan);
2317      clone.appendChild(document.createTextNode(' % uptime'));
2318      current.parentNode.replaceChild(clone, current);
2319    }
2320
2321    function setDayCount(el, dayCount) {
2322      var clone = el.cloneNode(false);
2323      var dateSpan = document.createElement('span');
2324      dateSpan.className = 'availability-time-line-legend-day-count';
2325      dateSpan.innerText = dayCount;
2326      clone.appendChild(dateSpan);
2327      clone.appendChild(document.createTextNode(' days ago'));
2328      el.parentNode.replaceChild(clone, el);
2329    }
2330
2331    function resizeSvgViewBoxes() {
2332      var svgs = document.getElementsByClassName('availability-time-line-graphic');
2333      if (!svgs.length) return;
2334
2335      var rects = svgs[0].getElementsByTagName('rect');
2336      if (rects.length < 2) return;
2337
2338      var rectWidth = parseInt(rects[0].getAttribute('width'));
2339      var rectPadding = parseInt(rects[1].getAttribute('x')) - parseInt(rects[0].getAttribute('x')) - rectWidth;
2340      var info = getKeyAndCount(window.innerWidth);
2341      var newViewbox = calculateViewbox(info.dayCount, rectWidth, rectPadding);
2342
2343      for (var i = 0; i < svgs.length; i++) {
2344        if (svgs[i].getAttribute('viewBox') !== newViewbox) {
2345          svgs[i].setAttribute('viewBox', newViewbox);
2346        }
2347      }
2348
2349      var dayCountElements = document.querySelectorAll('.legend-item-date-range:first-of-type');
2350      for (var d = 0; d < dayCountElements.length; d++) {
2351        setDayCount(dayCountElements[d], info.dayCount);
2352      }
2353
2354      for (var code in uptimeValues) {
2355        if (uptimeValues.hasOwnProperty(code)) setUptimeValue(uptimeValues[code], info.uptimeKey);
2356      }
2357
2358      var uptimeLinkVar = document.querySelector('.components-uptime-link > var');
2359      if (uptimeLinkVar) uptimeLinkVar.innerHTML = info.dayCount;
2360    }
2361
2362    if (document.readyState === 'loading') {
2363      document.addEventListener('DOMContentLoaded', init);
2364    } else {
2365      init();
2366    }
2367  })();
2368</script>
2368
2369
2370
2371
2372
2373
2374
2375      <div class="incidents-list format-expanded">
2376        <h2 class="font-largest no-link" id="past-incidents">Past Incidents</h2>
2377          
2378  <div class="status-day font-regular no-incidents">
2379    <h3 class="date border-color font-large">Oct <var data-var="date"> 5</var>, <var data-var="year">2026</var></h3>
2380        <p class="color-secondary">No incidents reported today.</p>
2381  </div>
2382
2383          
2384  <div class="status-day font-regular no-incidents">
2385    <h3 class="date border-color font-large">Oct <var data-var="date"> 4</var>, <var data-var="year">2026</var></h3>
2386        <p class="color-secondary">No incidents reported.</p>
2387  </div>
2388
2389          
2390  <div class="status-day font-regular no-incidents">
2391    <h3 class="date border-color font-large">Oct <var data-var="date"> 3</var>, <var data-var="year">2026</var></h3>
2392        <p class="color-secondary">No incidents reported.</p>
2393  </div>
2394
2395          
2396  <div class="status-day font-regular no-incidents">
2397    <h3 class="date border-color font-large">Oct <var data-var="date"> 2</var>, <var data-var="year">2026</var></h3>
2398        <p class="color-secondary">No incidents reported.</p>
2399  </div>
2400
2401          
2402  <div class="status-day font-regular no-incidents">
2403    <h3 class="date border-color font-large">Oct <var data-var="date"> 1</var>, <var data-var="year">2026</var></h3>
2404        <p class="color-secondary">No incidents reported.</p>
2405  </div>
2406
2407          
2408  <div class="status-day font-regular no-incidents">
2409    <h3 class="date border-color font-large">Sep <var data-var="date">30</var>, <var data-var="year">2026</var></h3>
2410        <p class="color-secondary">No incidents reported.</p>
2411  </div>
2412
2413          
2414  <div class="status-day font-regular no-incidents">
2415    <h3 class="date border-color font-large">Sep <var data-var="date">29</var>, <var data-var="year">2026</var></h3>
2416        <p class="color-secondary">No incidents reported.</p>
2417  </div>
2418
2419          
2420  <div class="status-day font-regular no-incidents">
2421    <h3 class="date border-color font-large">Sep <var data-var="date">28</var>, <var data-var="year">2026</var></h3>
2422        <p class="color-secondary">No incidents reported.</p>
2423  </div>
2424
2425          
2426  <div class="status-day font-regular no-incidents">
2427    <h3 class="date border-color font-large">Sep <var data-var="date">27</var>, <var data-var="year">2026</var></h3>
2428        <p class="color-secondary">No incidents reported.</p>
2429  </div>
2430
2431          
2432  <div class="status-day font-regular no-incidents">
2433    <h3 class="date border-color font-large">Sep <var data-var="date">26</var>, <var data-var="year">2026</var></h3>
2434        <p class="color-secondary">No incidents reported.</p>
2435  </div>
2436
2437          
2438  <div class="status-day font-regular no-incidents">
2439    <h3 class="date border-color font-large">Sep <var data-var="date">25</var>, <var data-var="year">2026</var></h3>
2440        <p class="color-secondary">No incidents reported.</p>
2441  </div>
2442
2443          
2444  <div class="status-day font-regular no-incidents">
2445    <h3 class="date border-color font-large">Sep <var data-var="date">24</var>, <var data-var="year">2026</var></h3>
2446        <p class="color-secondary">No incidents reported.</p>
2447  </div>
2448
2449          
2450  <div class="status-day font-regular no-incidents">
2451    <h3 class="date border-color font-large">Sep <var data-var="date">23</var>, <var data-var="year">2026</var></h3>
2452        <p class="color-secondary">No incidents reported.</p>
2453  </div>
2454
2455          
2456  <div class="status-day font-regular no-incidents">
2457    <h3 class="date border-color font-large">Sep <var data-var="date">22</var>, <var data-var="year">2026</var></h3>
2458        <p class="color-secondary">No incidents reported.</p>
2459  </div>
2460
2461          
2462  <div class="status-day font-regular no-incidents">
2463    <h3 class="date border-color font-large">Sep <var data-var="date">21</var>, <var data-var="year">2026</var></h3>
2464        <p class="color-secondary">No incidents reported.</p>
2465  </div>
2466
2467      </div>
2468
2469
2470      <div class="page-footer border-color font-small">
2471          <a href="/history" class="history-footer-link"><span style="font-family:arial" aria-hidden="true">&larr;</span> Incident History</a>
2472
2473        <span class="color-secondary powered-by"><a class="color-secondary" target="_blank" rel="noopener noreferrer nofollow" href="https://www.atlassian.com/software/statuspage?utm_campaign=www.voipfonestatus.co.uk&amp;utm_content=SP-notifications&amp;utm_medium=powered-by&amp;utm_source=inapp">Powered by Atlassian Statuspage</a></span>
2474      </div>
2475    </div>
2476
2477    
2478
2479  </div>
2480
2481
2482
2483
2484
2485
2486
2487    
2487<script src="https://dka575ofm4ao0.cloudfront.net/assets/status_manifest-b790849ccb41192b3f7d9c14d5a4a6d5142add81fc8522649ca5c82f6a1fbb0e.js"></script>
2487
2488    <div id="cpt-notification-container" role="status" aria-live="polite" aria-atomic="true"></div>
2489    
2490
2491
2492
2493
2494    <!-- all of the content_for stuff -->
2495      
2495<script src="https://dka575ofm4ao0.cloudfront.net/assets/register_subscription_form-589b657fec607087fc5c740c568270907310bc4f6aaa20256e70f01b103025ca.js"></script>
2495
2496
2497  
2497<script type="text/javascript">
2498      $(function() {
2499          SP.currentPage.registerSubscriptionForm('email');
2500
2501          SP.currentPage.registerSubscriptionForm('sms');
2502
2503
2504      });
2505
2506
2507
2508
2509
2510  </script>
2510
2511  
2511<script src="https://dka575ofm4ao0.cloudfront.net/assets/status_common-a7b1e9f22a2c94a83d347ec517cabf21494ca11867ebf891f46f89c9b4101811.js"></script>
2511
2512    
2512<script>
2513      SP.pollForChanges('/api/v2/status.json');
2514    </script>
2514
2515
2516  
2516<script>
2517    $(function() {
2518      $('.tool').tooltipster({
2519        animationDuration: 100,
2520        contentAsHTML: true,
2521        delay: 100,
2522        theme: 'tooltipster-borderless',
2523        functionInit: function (instance, helper) {
2524          var $origin = $(helper.origin),
2525              dataOptions = $origin.attr('data-tooltip-config');
2526          if (dataOptions){
2527            dataOptions = JSON.parse(dataOptions);
2528            $.each(dataOptions, function(name, option){
2529                instance.option(name, option);
2530            });
2531          }
2532        }
2533      });
2534      // clicks on first tab in subscribe popout since we won't know which is first
2535      // upon construction in the ruby code
2536      $('.updates-dropdown-nav > a').eq(0).click();
2537
2538      // twitter follow button needs some margin
2539      $('.twitter-follow-button').css('margin-right', '6px');
2540    });
2541
2542    $(function() {
2543      // open/close component groups
2544      HRB.utils.djshook('component-group-opener').on('click', function() {
2545        var groupParentIndicator = $(this).find('.group-parent-indicator');
2546        groupParentIndicator.toggleClass('fa-plus-square-o').toggleClass('fa-minus-square-o').end().parent().toggleClass('open');
2547        toggleGroup(groupParentIndicator)
2548      });
2549    });
2550
2551    $(function() {
2552      HRB.utils.djshook('component-group-opener').on('keydown', function(event) {
2553        if (event.key !== "Enter" && event.key !== " ") {
2554          return;
2555        }
2556        event.preventDefault()
2557        var groupParentIndicator = $(this).find('.group-parent-indicator');
2558        groupParentIndicator.toggleClass('fa-plus-square-o').toggleClass('fa-minus-square-o').end().parent().toggleClass('open');
2559        toggleGroup(groupParentIndicator)
2560      });
2561    });
2562
2563    function toggleGroup(groupParentIndicator) {
2564      var isOpen = groupParentIndicator.attr('aria-expanded')
2565      if (isOpen == 'false') {
2566          groupParentIndicator.attr('aria-expanded', 'true');
2567        } else {
2568          groupParentIndicator.attr('aria-expanded', 'false');
2569        }
2570    }
2571
2572    $(function() {
2573      $(document).on('ajax:complete', '.modal.in', function(e) {
2574        // Close the active modal.
2575        $('.modal.in').modal('hide');
2576      });
2577    });
2578
2579  </script>
2579
2580
2581
2582      
2582<script>
2583  /** INITIALIZATION **/
2584  var recaptchaIds = {}
2585
2586  // Unfortunately there's no unique selectors on the parent divs that recaptcha adds. The first unique selector
2587  // is the iframe rendered 2 levels deep. So this waits until the iframes are added to the page, then finds
2588  // the parent div and sets the z index so that it'll render above our modals & dropdowns from the start.
2589  function setZIndex(captchaCount, startTime) {
2590    // bail after 10s just in case so we don't do this forever if something whaky happens
2591    if (new Date() - startTime > 10000) {
2592      return;
2593    }
2594
2595    var iframes = document.querySelectorAll('iframe[title="recaptcha challenge"]');
2596    if (iframes.length != captchaCount) {
2597      setTimeout(function() {
2598        setZIndex(captchaCount, startTime);
2599      }, 500);
2600    }
2601
2602    for (var i = 0; i < iframes.length; i++) {
2603      // incident subscribe modal is 1050, so this has to be above that
2604      iframes[i].parentElement.parentElement.style.zIndex = "1100";
2605    }
2606  }
2607
2608  function updateCaptchaIframeTitle(captchaCount, startTime, updates=0) {
2609
2610    if (new Date() - startTime > 10000 || captchaCount === updates) {
2611      return;
2612    }
2613    var iframesWithTitle = document.querySelectorAll('iframe[title="recaptcha challenge expires in two minutes"]');
2614
2615    if (iframesWithTitle.length != captchaCount) {
2616      setTimeout(function() {
2617        updateCaptchaIframeTitle(captchaCount, startTime, iframesWithTitle.length + updates);
2618      }, 500);
2619    }
2620
2621    for (var i = 0; i < iframesWithTitle.length; i++) {
2622      iframesWithTitle[i].title = "recaptcha";
2623    }
2624  }
2625
2626  function addIncidentCaptcha() {
2627    var incidentCaptcha = document.createElement('div');
2628    incidentCaptcha.setAttribute('id', 'subscribe-incident-recaptcha');
2629    incidentCaptcha.setAttribute('class', 'g-recaptcha');
2630    incidentCaptcha.setAttribute('data-sitekey', '6LcZ-b0UAAAAAENi956aWzynTT2ZJ80dGU3F80Op');
2631    incidentCaptcha.setAttribute('data-callback', 'submitIncidentSubscriberSuccess');
2632    incidentCaptcha.setAttribute('data-error-callback', 'submitIncidentSubscriberError');
2633    incidentCaptcha.setAttribute('data-size', 'invisible');
2634    document.body.appendChild(incidentCaptcha);
2635    var incidentCode = document.createElement('input');
2636    incidentCode.setAttribute('type', 'hidden');
2637    incidentCode.setAttribute('id', 'submit_incident_code');
2638    document.body.appendChild(incidentCode);
2639  }
2640
2641  var onloadCallback = function() {
2642    // if there is an incident, then add incident captcha element
2643    if (document.getElementsByClassName('modal-open-incident-subscribe').length > 0) {
2644      addIncidentCaptcha();
2645    }
2646
2647    var captchas = document.getElementsByClassName("g-recaptcha");
2648
2649    for(var i = 0; i < captchas.length; i++) {
2650      var elId = captchas[i].id;
2651      recaptchaIds[elId] = grecaptcha.enterprise.render(elId);
2652    }
2653
2654    setZIndex(captchas.length, new Date());
2655    updateCaptchaIframeTitle(captchas.length, new Date());
2656  }
2657
2658
2659  /** SUBSCRIBE DROPDOWN */
2660
2661  // callbacks for captcha success
2662  function submitNewSubscriber(type, error) {
2663    if (error) document.querySelector('#subscribe-form-' + type + ' #captcha_error').value = 'true';
2664
2665    document.getElementById('subscribe-form-' + type).dispatchEvent(new Event('submit', {bubbles: true, cancelable: true}));
2666    grecaptcha.enterprise.reset(recaptchaIds['subscribe-btn-' + type]);
2667  }
2668  function submitNewEmailSubscriber(token) {
2669    submitNewSubscriber('email');
2670  }
2671  function submitNewSmsSubscriber(token) {
2672    submitNewSubscriber('sms');
2673  }
2674  function submitNewWebhookSubscriber(token) {
2675    submitNewSubscriber('webhook');
2676  }
2677  function submitIncidentSubscriber(token, error, incidentCodeOverride) {
2678    var incidentCode = incidentCodeOverride;
2679    if (!incidentCode) {
2680      var incidentCodeEl = document.getElementById('submit_incident_code');
2681      incidentCode = incidentCodeEl && incidentCodeEl.value;
2682    }
2683    var incidentForm = incidentCode && document.getElementById('subscribe-form-' + incidentCode);
2684    if (!incidentForm) {
2685      return;
2686    }
2687
2688    var captchaError = incidentForm.querySelector('input[name="captcha_error"]');
2689    var recaptchaResponse = incidentForm.querySelector('input[name="g-recaptcha-response"]');
2690    if (captchaError) {
2691      captchaError.value = error;
2692    }
2693    if (recaptchaResponse) {
2694      recaptchaResponse.value = token;
2695    }
2696    incidentForm.dispatchEvent(new Event('submit', {bubbles: true, cancelable: true}));
2697    if (window.grecaptcha && grecaptcha.enterprise && recaptchaIds['subscribe-incident-recaptcha'] != null) {
2698      grecaptcha.enterprise.reset(recaptchaIds['subscribe-incident-recaptcha']);
2699    }
2700  }
2701  function submitIncidentSubscriberSuccess(token) {
2702    submitIncidentSubscriber(token, 'false');
2703  }
2704
2705  // callbacks if we get captcha network errors
2706  function emailSubscriberCaptchaError(token) {
2707    submitNewSubscriber('email', true);
2708  }
2709  function smsSubscriberCaptchaError(token) {
2710    submitNewSubscriber('sms', true);
2711  }
2712  function webhookSubscriberCaptchaError(token) {
2713    submitNewSubscriber('webhook', true);
2714  }
2715  function submitIncidentSubscriberError(token) {
2716    submitIncidentSubscriber(token, 'true');
2717  }
2718
2719  // tracking clicks
2720  ['email', 'sms', 'webhook'].forEach(function(type) {
2721    var el = document.getElementById('subscribe-btn-' + type);
2722    el && el.addEventListener("click", function() {
2723      $.ajax({
2724        type: "POST",
2725        url: "/subscriptions/track_attempt",
2726        data: {
2727          type: type
2728        }
2729      })
2730    })
2731  })
2732
2733  // form submission success callbacks
2734  $('#subscribe-form-email').on('ajax:success', function(e, data, status, xhr){
2735    if (data.type === 'success') {
2736      SP.currentPage.updatesDropdown.hide();
2737      var emailField = document.getElementById('email');
2738      if (emailField) {
2739        emailField.value = '';
2740      }
2741    }
2742  });
2743  $('#subscribe-form-sms').on('ajax:success', function(e, data, status, xhr){
2744    if (data.type === 'success' && data.otp_flow !== true) {
2745      SP.currentPage.updatesDropdown.hide();
2746      var phoneField = document.getElementById('phone-number');
2747      if (phoneField) {
2748        phoneField.value = '';
2749      }
2750    }
2751  });
2752  $('#subscribe-form-webhook').on('ajax:success', function(e, data, status, xhr){
2753    if (data.type === 'success') {
2754      SP.currentPage.updatesDropdown.hide();
2755      document.getElementById('endpoint-webhooks').value = '';
2756      document.getElementById('email-webhooks').value = '';
2757    }
2758  });
2759
2760  $('a.subscribe').on('click', function() {
2761    document.body.style.overflow = "hidden";
2762    document.body.style.height = "100vh";
2763  });
2764
2765  $('div.modal-open-incident-subscribe').on('hidden', function(){
2766    document.body.style.overflow = "";
2767    document.body.style.height = "";
2768  });
2769
2770  function submitCaptchaIncidentSubscribe(event) {
2771    var incidentCode = event.target.id.split('-')[2];
2772    event.preventDefault();
2773
2774    $.ajax({
2775      type: "POST",
2776      url: "/subscriptions/track_attempt",
2777      data: {
2778        type: 'incident'
2779      }
2780    })
2781
2782    var incidentCodeField = document.getElementById('submit_incident_code');
2783    if (incidentCodeField) {
2784      incidentCodeField.value = incidentCode;
2785    }
2786
2787    // Recaptcha's onloadCallback is what creates #submit_incident_code and the
2788    // widget id. If the enterprise.js script is blocked (ad blockers, CI url
2789    // blacklist), execute() and .value on a null node throw and the subscribe
2790    // click never reaches the server.
2791    var recaptchaId = recaptchaIds['subscribe-incident-recaptcha'];
2792    if (window.grecaptcha && grecaptcha.enterprise && typeof grecaptcha.enterprise.execute === 'function' && recaptchaId != null) {
2793      grecaptcha.enterprise.execute(recaptchaId);
2794    } else {
2795      submitIncidentSubscriber('', 'true', incidentCode);
2796    }
2797  }
2798</script>
vendor: 135 bytes, lines 2798-2804
2798
2799
2800<script src='https://www.recaptcha.net/recaptcha/enterprise.js?onload=onloadCallback&render=explicit' async defer></script>
2801
2802
2803    
2804  
2804<script src="https://dka575ofm4ao0.cloudfront.net/packs/common-b57e85f6a60348cdd566.chunk.js"></script>
2804
2805  
2805<script src="https://dka575ofm4ao0.cloudfront.net/packs/globals-79d49f8cfe179f020629.chunk.js"></script>
2805
2806
2807    
2807<script src="https://dka575ofm4ao0.cloudfront.net/packs/runtime-e9fe27ac357824763c7d.js"></script>
2807
2808    
2809    
2810
2811
2812    
2812<script>
2813  window.addEventListener('load', function () {
2814    const urlParams = new URLSearchParams(window.location.search);
2815    const messageToken = urlParams.get('slack_message_token');
2816    const channelName = escape(urlParams.get('channel_name'));
2817
2818    if(!!messageToken) {
2819      switch(messageToken) {
2820        case 'slack_auth_error':
2821          HRB.utils.notify('The Slack authorization attempt was unsuccessful. Try again.', {cssClass:'error'});
2822          break;
2823        case 'subscribers_disabled_error':
2824          HRB.utils.notify('Slack subscriptions are not enabled on this page.', {cssClass:'error'});
2825          break;
2826        case 'direct_message_channel_error':
2827          HRB.utils.notify('Subscriptions aren’t supported in direct messages. Try subscribing again and choose a channel instead.', {cssClass:'error'});
2828          break
2829        case 'duplicate_error':
2830          HRB.utils.notify("You're already subscribed to get Slack notifications in that channel.", {cssClass:'error'});
2831          break;
2832        case 'duplicate_private_channel_error':
2833          HRB.utils.notify(`You're already subscribed to get Slack notifications in #${channelName}. Invite the @Statuspage app to that channel to start getting status updates.`, {cssClass: 'error'});
2834          break;
2835        case 'default_success':
2836          HRB.utils.notify("You're now subscribed to get Statuspage updates in Slack!", {cssClass:'success'});
2837          break;
2838        case 'private_channel_success':
2839          HRB.utils.notify(`IMPORTANT: Invite the @Statuspage app to your Slack channel #${channelName} to start getting status updates.`, {cssClass:'success'});
2840          break;
2841      }
2842    }
2843  });
2844</script>
2844
2845
2846    
2847<!-- FOR FLASH NOTICES -->
2848
2849<!-- FOR ERROR -->
2850
2851
2852    
2852<script>
2853  $(function() {
2854    var $link = $('<span class="color-secondary powered-by"><a class="color-secondary" target="_blank" rel="noopener noreferrer nofollow" href="https://www.atlassian.com/software/statuspage?utm_campaign=www.voipfonestatus.co.uk&amp;utm_content=SP-notifications&amp;utm_medium=powered-by&amp;utm_source=inapp">Powered by Atlassian Statuspage</a></span>');
2855
2856  	var setPoweredByStyles = function() {
2857  		if (!$('.powered-by').length) {
2858  			$link.appendTo($('.page-footer'))
2859  		}
2860  		$('.powered-by').attr('style', 'display: inline !important; visibility:visible !important; opacity: 1 !important; position:static !important; text-indent:0px !important; transform:scale(1) !important');
2861  	}
2862
2863  	setInterval(setPoweredByStyles, 1000);
2864  });
2865</script>
2865
2866
2867
2868
2869
2870
2871  </body>
2872</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.