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>Travis CI Status</title> 9 <meta name="description" content="Welcome to Travis CI'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="1790915139"> 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/27/favicon-3a4bd34c-f8d3-468e-ab94-50c3bef48ddc.png" /> 46 47 <link rel="shortcut icon" href='//dka575ofm4ao0.cloudfront.net/pages-favicon_logos/original/27/favicon-3a4bd34c-f8d3-468e-ab94-50c3bef48ddc.png'> 48 49 <link rel="alternate" type="application/atom+xml" href="https://www.traviscistatus.com/history.atom" title="Travis CI Status History - Atom Feed"> 50 <link rel="alternate" type="application/rss+xml" href="https://www.traviscistatus.com/history.rss" title="Travis CI 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.traviscistatus.com"> 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.traviscistatus.com/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":"#0068FF","border":"#CCE1FF","body_background":"#fff","font":"#333333","graph":"#0068FF","green":"#05c47a","light_font":"#8794A0","link":"#0068FF","orange":"#FF8C3E","red":"#FF5050","yellow":"#efcc00","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:#fff; 80 } 81 82 #uptime-tooltip .pointer-container .pointer-smaller { 83 border-bottom-color:#fff; 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:#8794A0; 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:#CCE1FF; 138 } 139 140 div[id^="subscribe-modal"] .modal-footer, 141 .markdown-display table td { 142 border-top-color:#CCE1FF; 143 } 144 145 .markdown-display table td + td, .markdown-display table th + th { 146 border-left-color:#CCE1FF; 147 } 148 149 div[id^="subscribe-modal"] .modal-header, 150 #uptime-tooltip .pointer-container .pointer-larger { 151 border-bottom-color:#CCE1FF; 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(204,225,255,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(204,225,255,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:#FF5050; 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:#FF5050; 193 } 194 195 .layout-content.status.status-index .unresolved-incident.impact-critical .updates { 196 border-color:#FF5050; 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:#FF8C3E; 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:#FF8C3E; 219 } 220 221 .layout-content.status.status-index .unresolved-incident.impact-major .updates { 222 border-color:#FF8C3E; 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:#efcc00; 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:#efcc00; 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:#efcc00; 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:#0068FF; 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:#0068FF; 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:#0068FF; 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:#05c47a; 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:#05c47a; 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:#0068FF; 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:#0068FF; 312 } 313 314 315 316 317 /* CUSTOM COLOR OVERRIDES FOR UPTIME SHOWCASE */ 318 .components-section .components-uptime-link { 319 color: #8794a0; 320 } 321 322 .layout-content.status .shared-partial.uptime-90-days-wrapper .legend .legend-item { 323 color: #8794a0; 324 opacity: 1; 325 } 326 .layout-content.status .shared-partial.uptime-90-days-wrapper .legend .legend-item.light { 327 color: #8794a0; 328 opacity: 1; 329 } 330 .layout-content.status .shared-partial.uptime-90-days-wrapper .legend .spacer { 331 background: #8794a0; 332 opacity: 1; 333 } 334</style> 335 336 337 <!-- custom css --> 338 339 <!-- polyfills --> 340
340<script crossorigin="anonymous" src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.js"></script>
340 341 342 <!-- Le HTML5 shim --> 343 <!--[if lt IE 9]> 344
344<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
344 345 <![endif]--> 346 347 <!-- injection for static --> 348 349 350 351 </head> 352 353 354 <body class="status index status-none sp-a11y-status-focus-visibility a11y-focus-indicators"> 355 356 357 358 359 360 <div class="layout-content status status-index premium"> 361 <div class="masthead-container premium"> 362 <div class="masthead"> 363 <div class="images-container" id="cover-image-container" data-js-hook="images-container"></div> 364 <style> 365 #cover-image-container { 366 background-image:url("//dka575ofm4ao0.cloudfront.net/pages-hero_covers/normal/27/tci-logo_w1700h630-e25efd0e-8bda-4e6f-b5ca-e6ba7eb2ab65.png"); 367 } 368 369 @media only screen and (-webkit-min-device-pixel-ratio: 2), 370 only screen and (min-resolution: 192dpi) { 371 #cover-image-container { 372 background-image:url("//dka575ofm4ao0.cloudfront.net/pages-hero_covers/retina/27/tci-logo_w1700h630-e25efd0e-8bda-4e6f-b5ca-e6ba7eb2ab65.png") !important; 373 } 374 } 375 </style> 376 377 <div class="text-container"> 378 <span class="page-name font-largest"> 379 <a href="https://travis-ci.com">Travis CI</a> 380 </span> 381 382 <div class="updates-dropdown-container" data-js-hook="updates-dropdown-container"> 383 <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"> 384 <span class="subscribe-text-full">Subscribe to Updates</span><span class="subscribe-text-short">Subscribe</span> 385 </a> 386 387<!-- Accessibility guidelines for tabs: https://www.w3.org/TR/wai-aria-practices-1.1/examples/tabs/tabs-1/tabs.html --> 388 <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"> 389 <div class="updates-dropdown-nav nav-items-5" role="tablist" aria-label="Subscribe to updates"> 390 <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"> 391 <span class="icon-container email"> 392 </a> 393 <a href="#updates-dropdown-slack" aria-controls="updates-dropdown-slack" aria-label="Subscribe via slack" role="tab" id="updates-dropdown-slack-btn"> 394 <span class="icon-container slack"> 395 </a> 396 <a href="#updates-dropdown-webhook" aria-controls="updates-dropdown-webhook" aria-label="Subscribe via webhook" role="tab" id="updates-dropdown-webhook-btn"> 397 <span class="icon-container webhook"> 398 </a> 399 <a href="#updates-dropdown-atom" aria-controls="updates-dropdown-atom" aria-label="Subscribe via RSS" role="tab" id="updates-dropdown-atom-btn"> 400 <span class="icon-container rss"> 401 </a> 402 <button data-js-hook="updates-dropdown-close" aria-label="Close subscribe form" id="updates-dropdown-close-btn"> 403 x 404 </button> 405 </div> 406 <div class="updates-dropdown-sections-container"> 407 <div class="updates-dropdown-section email" id="updates-dropdown-email" style="display:none" role="tabpanel" aria-labelledby="updates-dropdown-email-btn"> 408 <div class="directions"> 409 Get email notifications whenever Travis CI <strong>creates</strong>, <strong>updates</strong> or <strong>resolves</strong> an incident. 410 </div> 411 <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="KIFt4sQMO2UFlo2YiTGxgG1pEvNxGH1ZNCXufVIXNrSFUZ4xKG_PkIhB4OFpVe5sOaH02c4rdUVMpweU1L29yQ" autocomplete="off" /> 412 <input type="hidden" name="email_otp_verify_flow" id="email_otp_verify_flow" value="false" autocomplete="off" /> 413 <!-- make sure not to put cookie values in here since this gets cached --> 414 <label for="email">Email address:</label> 415 <input name="email" id="email" type="text" class="full-width" data-js-hook="email-notification-field" autocomplete="email"> 416 <input name="email_otp_auth_token" type='hidden' id="email-
416otp-token-field"> 417 <div class="opt-container-section" id="email-otp-container", style="display:none" > 418 <label for="email-otp">Enter OTP:</label> 419 <input name="otp" id="email-otp" type="text" value="" class="prepend full-width"> 420 <p id="email-otp-timer">Resend OTP in: <span id="email-otp-countdown"></span> seconds </p> 421 <p id="resend-email-otp"> 422 Didn't receive the OTP? 423 <a href="#" id="resend-email-otp-btn" >Resend OTP </a> 424 </p> 425 </div> 426 <input type="hidden" name="captcha_error" id="captcha_error" value="false" autocomplete="off" /> 427 <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" > 428 <div class="terms_and_privacy_information bottom small"><div class="privacy_policy_information small">By subscribing you agree to our <a target="_blank" rel="noopener" class="accessible-link" href="https://www.ideracorp.com/Legal/PrivacyPolicy">Privacy Policy</a>.</div> 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> 429</form> </div> 430 431 432 <div class="updates-dropdown-section slack" id="updates-dropdown-slack" style="display:none" role="tabpanel" aria-labelledby="updates-dropdown-slack-btn"> 433 <div class="directions"> 434 Get incident updates and maintenance status messages in Slack. 435 </div> 436 <a value="Subscribe via Slack" class="flat-button full-width" id="subscribe-btn-slack" data-disabled-text="Subscribing..." data-revert-on-success="true" style="margin-top:.75rem" href="https://subscriptions.statuspage.io/slack_authentication/kickoff?page_code=pnpcptp8xh9k">Subscribe via Slack</a> 437 <div class="terms_and_privacy_information bottom small">By subscribing you acknowledge our <a target="_blank" rel="noopener" class="accessible-link" href="https://www.ideracorp.com/Legal/PrivacyPolicy">Privacy Policy</a>. In addition, you agree to the Atlassian <a target="_blank" rel="noopener" class="accessible-link" href="https://www.atlassian.com/legal/cloud-terms-of-service">Cloud Terms of Service</a> and acknowledge Atlassian's <a target="_blank" rel="noopener" class="accessible-link" href="https://www.atlassian.com/legal/privacy-policy">Privacy Policy</a>.</div> 438 </div> 439 440 441 <div class="updates-dropdown-section webhook" id="updates-dropdown-webhook" style="display:none" role="tabpanel" aria-labelledby="updates-dropdown-webhook-btn"> 442 <div class="directions"> 443 Get webhook notifications whenever Travis CI <strong>creates</strong> an incident, <strong>updates</strong> an incident, <strong>resolves</strong> an incident or <strong>changes</strong> a component status. 444 </div> 445 <form id="subscribe-form-webhook" action="/subscriptions/webhook.json" accept-charset="UTF-8" data-remote="true" method="post"><input type="hidden" name="authenticity_token" value="y_FQIFPdzXjt4mFyTyqWsjgXDvIJ_SHF0G088Jzq5bFmIaPzv745jWA1DAuvTslebN_o2LbOKdmo79UZGkBuzA" autocomplete="off" /> 446 <div class="control-group"> 447 <div class="controls"> 448 <label for="endpoint-webhooks">Webhook URL:</label> 449 <input type="text" name="endpoint" id="endpoint-webhooks" data-js-hook="endpoint" class="full-width" aria-describedby="url-help-block" /> 450 <p class="help-block" id="url-help-block">The URL we should send the webhooks to</p> 451 </div> 452 </div> 453 454 <div class="control-group"> 455 <div class="controls"> 456 <label for="email-webhooks">Email address:</label> 457 <input type="text" name="email" id="email-webhooks" data-js-hook="email" class="full-width" aria-describedby="email-help-block" /> 458 <p class="help-block" id="email-help-block">We'll send you email if your endpoint fails</p> 459 </div> 460 </div> 461 462 <input type="hidden" name="captcha_error" id="captcha_error" value="false" autocomplete="off" /> 463 <input type="submit" value=Subscribe To Notifications class="flat-button full-width g-recaptcha" id="subscribe-btn-webhook" data-disabled-text="Subscribing..." data-sitekey=6LcQ-b0UAAAAAJjfdwO_-ozGC-CzWDj4Pm1kJ2Ah data-callback="submitNewWebhookSubscriber" data-error-callback="webhookSubscriberCaptchaError"> 464 <div class="terms_and_privacy_information bottom small"><div class="privacy_policy_information small">By subscribing you agree to our <a target="_blank" rel="noopener" class="accessible-link" href="https://www.ideracorp.com/Legal/PrivacyPolicy">Privacy Policy</a>.</div> 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> 465 466</form> </div> 467 468 469 470 <div class="updates-dropdown-section atom" id="updates-dropdown-atom" role="tabpanel" aria-labelledby="updates-dropdown-atom-btn"> 471 Get the <a href="https://www.traviscistatus.com/history.atom" target="_blank">Atom Feed</a> or <a href="https://www.traviscistatus.com/history.rss" target="_blank">RSS Feed</a>. 472 </div> 473 </div> 474 </div> 475 </div> 476
477<script> 478 $(function () { 479 const phoneNumberInput = $('#phone-number'); 480 const errorDiv = $('#sms-atl-error') 481 if(errorDiv.length){ 482 function checkSelectedCountry() { 483 const selectedCountry = $('#phone-country').val(); 484 const isOtpEnabled = $('#phone-number-country-code').attr('data-otp-enabled') === 'true'; 485 const form = document.getElementById('subscribe-form-sms'); 486 form.action = '/subscriptions/new-sms'; 487 const isOtpFlow = document.getElementById('otp_verify_flow'); 488 document.getElementById('otp-container').style.display = "none"; 489 if(false && selectedCountry === 'sg') { // Replace 'SG' with the actual value representing Singapore in your select tag 490 phoneNumberInput.prop('disabled', true); 491 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.`); 492 } else { 493 phoneNumberInput.prop('readonly', false); 494 errorDiv.html(''); 495 if(false){ 496 if(isOtpEnabled){ 497 document.getElementById('subscribe-btn-sms').value = "Send OTP"; 498 } 499 else { 500 isOtpFlow.value = false; 501 document.getElementById('subscribe-btn-sms').value = "Subscribe via Text Message"; 502 } 503 } 504 } 505 } 506 507 $('#phone-country').on('change', checkSelectedCountry); 508 checkSelectedCountry(); 509 } 510 }); 511 512 document.addEventListener('DOMContentLoaded', function() { 513 const dropdown = document.querySelector('#phone-number-country-code .phone-country'); 514 if (dropdown){ 515 const wrapperDiv = document.getElementById('phone-number-country-code'); 516 const selectedOption = dropdown.options[dropdown.selectedIndex]; 517 const otpEnabled = selectedOption.getAttribute('data-otp-enabled'); 518 519 wrapperDiv.setAttribute('data-otp-enabled', otpEnabled); 520 521 dropdown.addEventListener('change', function() { 522 const selectedOption = dropdown.options[dropdown.selectedIndex]; 523 const otpEnabled = selectedOption.getAttribute('data-otp-enabled'); 524 525 wrapperDiv.setAttribute('data-otp-enabled', otpEnabled); 526 }); 527 } 528 }); 529 530 var countdownTimer; 531 var resendBtn = document.getElementById('resend'); 532 var timer = document.getElementById('timer'); 533 var form = document.getElementById('subscribe-form-sms'); 534 var RESEND_TIMER = 30; 535 $(function() { 536 $('#subscribe-form-sms').on('ajax:success', function(e, data, status, xhr){ 537 const form = this; 538 const action = form.getAttribute('action'); 539 if (data.type === 'success' && data.otp_flow === true) { 540 document.getElementById('subscriber_code').value = data.subscriber_code 541 document.getElementById('otp-container').style.display = "block"; 542 $('#phone-number').prop('readonly', true); 543 var display = document.getElementById('countdown'); 544 disableResend(); 545 startTimer(RESEND_TIMER, display) 546 document.getElementById('subscribe-btn-sms').value = "Verify OTP and Subscribe"; 547 document.getElementById('otp_verify_flow').value = true; 548 form.action = '/subscriptions/verify-otp'; 549 } else if (data.type === 'success' && action.includes('verify')){ 550 document.getElementById('otp-container').style.display = "none"; 551 $('#phone-number').val('').prop('readonly', false); 552 $('#otp').val(''); 553 document.getElementById('subscribe-btn-sms').value = "Send OTP"; 554 document.getElementById('otp_verify_flow').value = false; 555 form.action = '/subscriptions/new-sms'; 556 SP.currentPage.updatesDropdown.hide(); 557 } 558 }); 559 $("#btn-subcriber-change-number").on('click', () => { 560 document.getElementById('otp-container').style.display = "none"; 561 $('#phone-number').prop('readonly', false); 562 document.getElementById('subscribe-btn-sms').value = "Send OTP"; 563 form.action = '/subscriptions/new-sms'; 564 return false 565 }) 566 $('#resend-otp-btn').on('click', function(e) { 567 e.preventDefault(); 568 let phoneNumber = $('#phone-number').val(); 569 let countryCode = $('.phone-country').val(); 570 $.ajax({ 571 type: 'POST', 572 url: "/subscriptions/new-sms", 573 data: { 574 phone_number: phoneNumber, 575 phone_country: countryCode, 576 type: 'resend' 577 }, 578 }).done(function(data) { 579 var messageOptions = (data.type !== undefined && data.type !== null) ? { cssClass: data.type } : {}; 580 HRB.utils.notify(data.text, messageOptions); 581 var display = document.getElementById('countdown'); 582 disableResend(); 583 timer.style.display = "none" 584 if (data.type === 'success') { 585 startTimer(RESEND_TIMER, display); 586 } 587 }) 588 }); 589 }) 590 591 function startTimer(duration, display){ 592 var timer = duration, seconds; 593 clearInterval(countdownTimer); 594 countdownTimer = setInterval(function () { 595 seconds = parseInt(timer % 60, 10); 596 display.textContent = seconds; 597 if(--timer < 0){ 598 enableResend(); 599 clearInterval(countdownTimer); 600 } 601 }, 1000); 602 disableResend(); 603 } 604 function enableResend(){ 605 resendBtn.style.display = "block"; 606 timer.style.display = "none" 607 } 608 function disableResend(){ 609 resendBtn.style.display = "none"; 610 timer.style.display = "block" 611 } 612 613 $(function() { 614 $('#subscribe-form-email').on('submit', function() {
615 var tokenField = document.getElementById('email-otp-token-field'); 616 if (!tokenField) { 617 return; 618 } 619 let page_code = "pnpcptp8xh9k" 620 let key = keyForEmailOtpToken($('#email').val(), page_code); 621 tokenField.value = localStorage.getItem(key); 622 }); 623 }); 624 625 var emailOtpCountdownTimer; 626 var emailOtpResendBtn = document.getElementById('resend-email-otp'); 627 var emailOtpTimer = document.getElementById('email-otp-timer'); 628 var emailOtpForm = document.getElementById('subscribe-form-email'); 629 var EMAIL_OTP_RESEND_TIMER = 600; 630 $(function() { 631 $('#subscribe-form-email').on('ajax:success', function(e, data, status, xhr){ 632 const form = this; 633 const action = form.getAttribute('action'); 634 if (data.type === 'success' && data.email_otp_verify_flow === true) { 635 document.getElementById('email-otp-container').style.display = "block"; 636 var display = document.getElementById('email-otp-countdown'); 637 display.textContent = EMAIL_OTP_RESEND_TIMER; 638 disableEmailOtpResend(); 639 startEmailOtpTimer(EMAIL_OTP_RESEND_TIMER, display) 640 document.getElementById('subscribe-btn-email').value = "Verify OTP and Subscribe"; 641 document.getElementById('email_otp_verify_flow').value = true; 642 form.action = '/subscriptions/verify-email-otp'; 643 } else if (data.type === 'success' && action.includes('verify')){ 644 let email = $('#email') 645 let page_code = "pnpcptp8xh9k" 646 let key = keyForEmailOtpToken(email.val(), page_code); 647 localStorage.setItem(key, data.email_otp_auth_token); 648 649 document.getElementById('email-otp-container').style.display = "none"; 650 email.val('').prop('readonly', false); 651 $('#email-otp').val(''); 652 document.getElementById('subscribe-btn-email').value = "Send OTP"; 653 document.getElementById('email_otp_verify_flow').value = false; 654 form.action = '/subscriptions/new-email'; 655 SP.currentPage.updatesDropdown.hide(); 656 } 657 }); 658 $('#resend-email-otp-btn').on('click', function(e) { 659 e.preventDefault(); 660 let email = $('#email').val(); 661 $.ajax({ 662 type: 'POST', 663 url: "/subscriptions/new-email", 664 data: { 665 email: email 666 }, 667 }).done(function(data) { 668 var messageOptions = (data.type !== undefined && data.type !== null) ? { cssClass: data.type } : {}; 669 HRB.utils.notify(data.text, messageOptions); 670 if (data.type === 'success') { 671 var display = document.getElementById('email-otp-countdown'); 672 display.textContent = EMAIL_OTP_RESEND_TIMER; 673 disableEmailOtpResend(); 674 emailOtpTimer.style.display = "none" 675 startEmailOtpTimer(EMAIL_OTP_RESEND_TIMER, display); 676 } 677 }) 678 }); 679 }) 680 681 function startEmailOtpTimer(duration, display){ 682 var timer = duration, seconds; 683 clearInterval(emailOtpCountdownTimer); 684 emailOtpCountdownTimer = setInterval(function () { 685 seconds = parseInt(timer, 10); 686 display.textContent = seconds; 687 if(--timer < 0){ 688 enableEmailOtpResend(); 689 clearInterval(emailOtpCountdownTimer); 690 } 691 }, 1000); 692 disableEmailOtpResend(); 693 } 694 695 function enableEmailOtpResend(){ 696 emailOtpResendBtn.style.display = "block"; 697 emailOtpTimer.style.display = "none" 698 } 699 function disableEmailOtpResend(){ 700 emailOtpResendBtn.style.display = "none"; 701 emailOtpTimer.style.display = "block" 702 } 703 function keyForEmailOtpToken(email, pageCode) { 704 return email + '|' + pageCode+ '|SUBSCRIBE_VIA_EMAIL'; 705 } 706</script>
706 707 708 </div> 709 </div> 710 711</div> 712 <!-- this is outside of the .container so that the cover photo can go full width on mobile --> 713 714 <div class="container" role="main"> 715 <div class="page-status status-none"> 716 <h2 class="status font-large"> 717 All Systems Operational 718 </h2> 719 <span class="last-updated-stamp font-small"></span> 720 </div> 721 722 723 724 <div class="components-section font-regular"> 725 <i class="component-status hidden major_outage"></i> 726 <div class="components-uptime-link history-footer-link"> 727 Uptime over the past <var data-var="num" data-pluralize="90">90</var> days. <a href="/uptime">View historical uptime.</a> 728 </div> 729 <div class="components-container one-column"> 730 <div class="component-container border-color"> 731 732<div data-component-id="v3pv505czcvn" 733 class="component-inner-container status-green showcased" 734 data-component-status="operational" 735 data-js-hook=""> 736 737 <span class="name" role="heading" aria-level="2"> 738 API 739 </span> 740 741 742 <span 743 class="component-status " 744 745 title="" 746 > 747 748 Operational 749 750 </span> 751 752 <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> 753 754 <div class="uptime-lazy-placeholder" data-uptime-lazy="v3pv505czcvn" aria-hidden="true"></div> 755</div> 756 757 </div> 758 <div class="component-container border-color"> 759 760<div data-component-id="x0lpb7qzw919" 761 class="component-inner-container status-green showcased" 762 data-component-status="operational" 763 data-js-hook=""> 764 765 <span class="name" role="heading" aria-level="2"> 766 Web App 767 </span> 768 769 770 <span 771 class="component-status " 772 773 title="" 774 > 775 776 Operational 777 778 </span> 779 780 <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> 781 782 <div class="uptime-lazy-placeholder" data-uptime-lazy="x0lpb7qzw919" aria-hidden="true"></div> 783</div> 784 785 </div> 786 <div class="component-container border-color is-group "> 787 788<div data-component-id="zd1jfc33yt1p" 789 class="component-inner-container status-green showcased" 790 data-component-status="operational" 791 data-js-hook="component-group-opener"> 792 793 <span class="name" role="heading" aria-level="2"> 794 <span class="fa group-parent-indicator color-secondary font-small fa-plus-square-o" role="button" aria-expanded="false" aria-label="Toggle Builds Processing" tabindex="0"></span> 795 <span> 796 Builds Processing 797 </span> 798 </span> 799 800 801 <span 802 class="component-status " 803 role="button" tabindex="0" data-js-hook="tooltip" 804 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." 805 > 806 807 Operational 808 809 </span> 810 811 <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> 812 813 <div class="uptime-lazy-placeholder" data-uptime-lazy="zd1jfc33yt1p" aria-hidden="true"></div> 814</div> 815 816 817 <!-- children components --> 818 <div class="child-components-container mix-match-showcase"> 819 820<div data-component-id="fv408yjjqhv6" 821 class="component-inner-container status-green showcased" 822 data-component-status="operational" 823 data-js-hook=""> 824 825 <span class="name" role="heading" aria-level="2"> 826 Linux and Windows Builds 827 </span> 828 829 <button 830 type="button" 831 class="tooltip-base tool" 832 data-js-hook="tooltip" 833 tabindex="0" 834 aria-label="More information about Linux and Windows Builds" 835 aria-describedby="tooltip-fv408yjjqhv6" 836 data-original-title="VM builds running in GCE. This includes both Linux (all distributions) and Windows builds." 837 >?</button> 838 839 <span 840 class="component-status " 841 842 title="" 843 > 844 845 Operational 846 847 </span> 848 849 <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> 850 851 <div class="uptime-lazy-placeholder" data-uptime-lazy="fv408yjjqhv6" aria-hidden="true"></div> 852</div> 853 854 855<div data-component-id="5wvsvvr8b7j4" 856 class="component-inner-container status-green " 857 data-component-status="operational" 858 data-js-hook=""> 859 860 <span class="name" role="heading" aria-level="2"> 861 IBM Z Builds 862 </span> 863 864 <button 865 type="button" 866 class="tooltip-base tool" 867 data-js-hook="tooltip" 868 tabindex="0" 869 aria-label="More information about IBM Z Builds" 870 aria-describedby="tooltip-5wvsvvr8b7j4" 871 data-original-title="Scheduling and running of builds on the IBM s390x architecture." 872 >?</button> 873 874 <span 875 class="component-status " 876 877 title="" 878 > 879 880 Operational 881 882 </span> 883 884 <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> 885 886</div> 887 888 </div> 889</div> 890 891 <div class="component-container border-color is-group "> 892 893<div data-component-id="43255b952p01" 894 class="component-inner-container status-green showcased" 895 data-component-status="operational" 896 data-js-hook="component-group-opener"> 897 898 <span class="name" role="heading" aria-level="2">
899 <span class="fa group-parent-indicator color-secondary font-small fa-plus-square-o" role="button" aria-expanded="false" aria-label="Toggle Background Processing" tabindex="0"></span> 900 <span> 901 Background Processing 902 </span> 903 </span> 904 905 906 <span 907 class="component-status " 908 role="button" tabindex="0" data-js-hook="tooltip" 909 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." 910 > 911 912 Operational 913 914 </span> 915 916 <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> 917 918 <div class="uptime-lazy-placeholder" data-uptime-lazy="43255b952p01" aria-hidden="true"></div> 919</div> 920 921 922 <!-- children components --> 923 <div class="child-components-container "> 924 925<div data-component-id="pw8ss5jcjb45" 926 class="component-inner-container status-green showcased" 927 data-component-status="operational" 928 data-js-hook=""> 929 930 <span class="name" role="heading" aria-level="2"> 931 Log Processing 932 </span> 933 934 935 <span 936 class="component-status " 937 938 title="" 939 > 940 941 Operational 942 943 </span> 944 945 <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> 946 947 <div class="uptime-lazy-placeholder" data-uptime-lazy="pw8ss5jcjb45" aria-hidden="true"></div> 948</div> 949 950 951<div data-component-id="vmgk8phkxfdf" 952 class="component-inner-container status-green showcased" 953 data-component-status="operational" 954 data-js-hook=""> 955 956 <span class="name" role="heading" aria-level="2"> 957 User Sync 958 </span> 959 960 <button 961 type="button" 962 class="tooltip-base tool" 963 data-js-hook="tooltip" 964 tabindex="0" 965 aria-label="More information about User Sync" 966 aria-describedby="tooltip-vmgk8phkxfdf" 967 data-original-title="Synchronization with GitHub / Assembla / GitLab / BitBucket via their API" 968 >?</button> 969 970 <span 971 class="component-status " 972 973 title="" 974 > 975 976 Operational 977 978 </span> 979 980 <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> 981 982 <div class="uptime-lazy-placeholder" data-uptime-lazy="vmgk8phkxfdf" aria-hidden="true"></div> 983</div> 984 985 986<div data-component-id="y0v5kvk1msqy" 987 class="component-inner-container status-green showcased" 988 data-component-status="operational" 989 data-js-hook=""> 990 991 <span class="name" role="heading" aria-level="2"> 992 Notifications 993 </span> 994 995 <button 996 type="button" 997 class="tooltip-base tool" 998 data-js-hook="tooltip" 999 tabindex="0" 1000 aria-label="More information about Notifications" 1001 aria-describedby="tooltip-y0v5kvk1msqy" 1002 data-original-title="Build notifications like email, Campfire, Slack, HipChat, IRC" 1003 >?</button> 1004 1005 <span 1006 class="component-status " 1007 1008 title="" 1009 > 1010 1011 Operational 1012 1013 </span> 1014 1015 <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> 1016 1017 <div class="uptime-lazy-placeholder" data-uptime-lazy="y0v5kvk1msqy" aria-hidden="true"></div> 1018</div> 1019 1020 </div> 1021</div> 1022 1023 <div class="component-container border-color is-group "> 1024 1025<div data-component-id="ygwn6k3272yn" 1026 class="component-inner-container status-green " 1027 data-component-status="operational" 1028 data-js-hook="component-group-opener"> 1029 1030 <span class="name" role="heading" aria-level="2"> 1031 <span class="fa group-parent-indicator color-secondary font-small fa-plus-square-o" role="button" aria-expanded="false" aria-label="Toggle Third Party Services" tabindex="0"></span> 1032 <span> 1033 Third Party Services 1034 </span> 1035 </span> 1036 1037 1038 <span 1039 class="component-status " 1040 role="button" tabindex="0" data-js-hook="tooltip" 1041 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." 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 <!-- children components --> 1054 <div class="child-components-container "> 1055 1056<div data-component-id="kgbljfbx7598" 1057 class="component-inner-container status-green " 1058 data-component-status="operational" 1059 data-js-hook=""> 1060 1061 <span class="name" role="heading" aria-level="2"> 1062 GitHub 1063 </span> 1064 1065 1066 <span 1067 class="component-status " 1068 1069 title="" 1070 > 1071 1072 Operational 1073 1074 </span> 1075 1076 <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> 1077 1078</div> 1079 1080 1081<div data-component-id="xgcz8vf731tx" 1082 class="component-inner-container status-green " 1083 data-component-status="operational" 1084 data-js-hook=""> 1085 1086 <span class="name" role="heading" aria-level="2"> 1087 DNSimple Name Servers 1088 </span> 1089 1090 1091 <span 1092 class="component-status " 1093 1094 title="" 1095 > 1096 1097 Operational 1098 1099 </span> 1100 1101 <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> 1102 1103</div> 1104 1105 1106<div data-component-id="032hr7t0bg9b" 1107 class="component-inner-container status-green " 1108 data-component-status="operational" 1109 data-js-hook=""> 1110 1111 <span class="name" role="heading" aria-level="2"> 1112 Pusher Pusher REST API 1113 </span> 1114 1115 1116 <span 1117 class="component-status " 1118 1119 title="" 1120 > 1121 1122 Operational 1123 1124 </span> 1125 1126 <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> 1127 1128</div> 1129 1130 1131<div data-component-id="t3ncs9kc9w2x" 1132 class="component-inner-container status-green " 1133 data-component-status="operational" 1134 data-js-hook=""> 1135 1136 <span class="name" role="heading" aria-level="2"> 1137 Pusher WebSocket client API 1138 </span> 1139 1140 1141 <span 1142 class="component-status " 1143 1144 title="" 1145 > 1146 1147 Operational 1148 1149 </span> 1150 1151 <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> 1152 1153</div> 1154 1155 1156<div data-component-id="qblbn1tf2q02" 1157 class="component-inner-container status-green " 1158 data-component-status="operational" 1159 data-js-hook=""> 1160 1161 <span class="name" role="heading" aria-level="2"> 1162 Pusher Presence channels 1163 </span> 1164 1165 1166 <span 1167 class="component-status " 1168 1169 title="" 1170 > 1171 1172 Operational 1173 1174 </span> 1175 1176 <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> 1177 1178</div> 1179 1180 1181<div data-component-id="lxczb8x45gmm" 1182 class="component-inner-container status-green " 1183 data-component-status="operational" 1184 data-js-hook=""> 1185 1186 <span class="name" role="heading" aria-level="2"> 1187 Pusher Webhooks 1188 </span> 1189 1190 1191 <span 1192 class="component-status " 1193 1194 title="" 1195 > 1196 1197 Operational 1198 1199 </span> 1200 1201 <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> 1202 1203</div> 1204 1205 1206<div data-component-id="5vr9p1qt86l6" 1207 class="component-inner-container status-green " 1208 data-component-status="operational" 1209 data-js-hook=""> 1210 1211 <span class="name" role="heading" aria-level="2"> 1212 AWS ec2-us-east-1 1213 </span> 1214 1215 1216 <span 1217 class="component-status " 1218 1219 title="" 1220 > 1221 1222 Operational 1223 1224 </span> 1225 1226 <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> 1227 1228</div> 1229 1230 1231<div data-component-id="wrxql47n0svb" 1232 class="component-inner-container status-green " 1233 data-component-status="operational" 1234 data-js-hook=""> 1235 1236 <span class="name" role="heading" aria-level="2"> 1237 PagerDuty Notification Delivery 1238 </span> 1239 1240 1241 <span 1242 class="component-status " 1243 1244 title="" 1245 > 1246 1247 Operational 1248 1249 </span> 1250 1251 <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> 1252 1253</div> 1254 1255 1256<div data-component-id="k17399181mfn" 1257 class="component-inner-container status-green " 1258 data-component-status="operational" 1259 data-js-hook=""> 1260 1261 <span class="name" role="heading" aria-level="2"> 1262 npm, Inc. Registry Reads 1263 </span> 1264 1265 <button 1266 type="button" 1267 class="tooltip-base tool" 1268 data-js-hook="tooltip" 1269 tabindex="0" 1270 aria-label="More information about npm, Inc. Registry Reads" 1271 aria-describedby="tooltip-k17399181mfn" 1272 data-original-title="GETs to registry.npmjs.org" 1273 >?</button> 1274 1275 <span 1276 class="component-status " 1277 1278 title="" 1279 > 1280 1281 Operational 1282 1283 </span> 1284 1285 <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> 1286 1287</div> 1288 1289 1290<div data-component-id="6p07pwzcl4wb" 1291 class="component-inner-container status-green " 1292 data-component-status="operational" 1293 data-js-hook=""> 1294 1295 <span class="name" role="heading" aria-level="2"> 1296 Assembla 1297 </span> 1298 1299 <button 1300 type="button" 1301 class="tooltip-base tool" 1302 data-js-hook="tooltip" 1303 tabindex="0" 1304 aria-label="More information about Assembla" 1305 aria-describedby="tooltip-6p07pwzcl4wb" 1306 data-original-title="Assembla.com Git, SVN and P4 repository and project management tool." 1307 >?</button> 1308 1309 <span 1310 class="component-status " 1311 1312 title="" 1313 > 1314 1315 Operational 1316 1317 </span> 1318 1319 <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> 1320 1321</div> 1322 1323 </div> 1324</div> 1325 1326 <div class="component-container border-color"> 1327 1328<div data-component-id="q4xyt8yypthv" 1329 class="component-inner-container status-green " 1330 data-component-status="operational" 1331 data-js-hook=""> 1332 1333 <span class="name" role="heading" aria-level="2"> 1334 Google Cloud Platform Google Compute Engine 1335 </span> 1336 1337 1338 <span 1339 class="component-status " 1340 1341 title="" 1342 > 1343 1344 Operational 1345 1346 </span> 1347 1348 <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> 1349 1350</div> 1351 1352 </div> 1353 <div class="component-container border-color"> 1354 1355<div data-component-id="xhp6ymqqyg3h" 1356 class="component-inner-container status-green " 1357 data-component-status="operational" 1358 data-js-hook=""> 1359 1360 <span class="name" role="heading" aria-level="2"> 1361 GitHub API Requests 1362 </span> 1363 1364 1365 <span 1366 class="component-status " 1367 1368 title="" 1369 > 1370 1371 Operational 1372 1373 </span> 1374 1375 <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> 1376 1377</div> 1378 1379 </div> 1380 <div class="component-container border-color"> 1381 1382<div data-component-id="c75kxzjv80rv" 1383 class="component-inner-container status-green " 1384 data-component-status="operational" 1385 data-js-hook=""> 1386 1387 <span class="name" role="heading" aria-level="2"> 1388 GitHub Issues, PRs, Dashboard, Projects 1389 </span> 1390 1391 1392 <span 1393 class="component-status " 1394 1395 title="" 1396 > 1397 1398 Operational 1399 1400 </span> 1401 1402 <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> 1403 1404</div> 1405 1406 </div> 1407 <div class="component-container border-color"> 1408 1409<div data-component-id="cs2n4vkyfmtk" 1410 class="component-inner-container status-green " 1411 data-component-status="operational" 1412 data-js-hook=""> 1413 1414 <span class="name" role="heading" aria-level="2"> 1415 Assembla API and Merge Requests 1416 </span> 1417 1418 1419 <span 1420 class="component-status " 1421 1422 title="" 1423 > 1424 1425 Operational 1426 1427 </span> 1428 1429 <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> 1430 1431</div> 1432 1433 </div> 1434 <div class="component-container border-color"> 1435 1436<div data-component-id="fhqxrfxvc50z" 1437 class="component-inner-container status-green " 1438 data-component-status="operational" 1439 data-js-hook=""> 1440 1441 <span class="name" role="heading" aria-level="2"> 1442 GitLab API and Pull Requests 1443 </span> 1444 1445 1446 <span 1447 class="component-status " 1448 1449 title="" 1450 > 1451 1452 Operational 1453 1454 </span> 1455 1456 <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> 1457 1458</div> 1459 1460 </div> 1461 </div> 1462 <div class="component-statuses-legend font-small"> 1463 <div class="legend-item status-green"> 1464 <span class="icon-indicator fa fa-check"></span> 1465 Operational 1466 </div> 1467 <div class="legend-item status-yellow"> 1468 <span class="icon-indicator fa fa-minus-square"></span> 1469 Degraded Performance 1470 </div> 1471 <div class="legend-item status-orange"> 1472 <span class="icon-indicator fa fa-exclamation-triangle"></span>
1473 Partial Outage 1474 </div> 1475 <div class="breaker"></div> 1476 <div class="legend-item status-red"> 1477 <span class="icon-indicator fa fa-times"></span> 1478 Major Outage 1479 </div> 1480 <div class="legend-item status-blue"> 1481 <span class="icon-indicator fa fa-wrench"></span> 1482 Maintenance 1483 </div> 1484</div> 1485 1486 </div> 1487 1488 <div id="uptime-tooltip"> 1489 <div class="pointer-container"> 1490 <div class="pointer-larger"></div> 1491 <div class="pointer-smaller"></div> 1492 </div> 1493 <div class="tooltip-box"> 1494 <div class="tooltip-content"> 1495 <div class="tooltip-close"> 1496 <i class="fa fa-times"></i> 1497 </div> 1498 <div class="date"></div> 1499 <div class="outages"> 1500 <div class="outage-field major"> 1501 <span class="label"> 1502 <i class="component-status page-colors text-color major_outage"></i> 1503 Major outage 1504 </span> 1505 <span class="value-hrs"></span> 1506 <span class="value-mins"></span> 1507 </div> 1508 <div class="outage-field partial"> 1509 <span class="label"> 1510 <i class="component-status page-colors text-color partial_outage"></i> 1511 Partial outage 1512 </span> 1513 <span class="value-hrs"></span> 1514 <span class="value-mins"></span> 1515 </div> 1516 <div class="no-outages-msg"> 1517 No downtime recorded on this day. 1518 </div> 1519 <div class="no-data-msg"> 1520 No data exists for this day. 1521 </div> 1522 <div id="major-outage-group-count" class="outage-count"> 1523 <i class="component-status page-colors text-color major_outage"></i> 1524 <span class="count"></span> 1525 had a major outage. 1526 </div> 1527 <div id="partial-outage-group-count" class="outage-count"> 1528 <i class="component-status page-colors text-color partial_outage"></i> 1529 <span class="count"></span> 1530 had a partial outage. 1531 </div> 1532 </div> 1533 <div class="related-events"> 1534 <h3 id="related-event-header">Related</h3> 1535 <ul id="related-events-list"></ul> 1536 </div> 1537 <div class="no-related-msg"> 1538 <p>No incidents or maintenance related to this downtime.</p> 1539 </div> 1540 </div> 1541 </div> 1542</div> 1543
1544<script src="https://dka575ofm4ao0.cloudfront.net/assets/vendor/bowser-1643ca34a6d589b2d4d42163a891e4512d5d7657125e09bb5f3d44288114e6bd.js"></script>
vendor: 1 bytes, line 1544
1544
1545<script type="text/javascript"> 1546 /** 1547 This file contains the code needed to handle display of the uptime tooltips on status. 1548 Note: because it's in ERB, only ES5 syntax is allowed. 1549 */ 1550 1551 window.uptimeData = window.uptimeData || {}; 1552 var uptimeData = window.uptimeData; 1553 var timeoutId; 1554 var monthStrings = [ 1555 'Jan', 'Feb', 'Mar', 1556 'Apr', 'May', 'Jun', 1557 'Jul', 'Aug', 'Sep', 1558 'Oct', 'Nov', 'Dec' 1559 ]; 1560 var EVENT_MAX_LENGTH = 90; 1561 1562 // Detect device (desktop vs. touch device) 1563 function touchDevice() { 1564 var browser = bowser.getParser(window.navigator.userAgent); 1565 // if type is either mobile or tablet, return true 1566 return browser.parse().parsedResult.platform.type !== 'desktop'; 1567 } 1568 1569 // Class is in format day-<number>. Convert to just number 1570 function dayNumberFromClass(className) { 1571 return parseInt(className.split('-')[1]); 1572 } 1573 1574 // Class is in format component-<code>. Convert to just code 1575 function componentCodeFromClass(className) { 1576 return className.split('-')[1]; 1577 } 1578 1579 // Convert number to string pixel measurement 1580 function intToPixels(number) { 1581 return number.toString() + 'px'; 1582 } 1583 1584 function truncate(str) { 1585 return str.substring(0, EVENT_MAX_LENGTH) + 1586 (str.length > EVENT_MAX_LENGTH ? '...' : ''); 1587 } 1588 1589 // Tooltip Handling class constructor 1590 function UptimeTooltipHandler(frameWidth) { 1591 this.visible = false; 1592 this.activeDay = { 1593 hovered: false 1594 }; 1595 this.tooltip = document.getElementById('uptime-tooltip'); 1596 this.frameWidth = frameWidth === undefined ? window.innerWidth : frameWidth; 1597 this.scrolling = false; 1598 1599 window.addEventListener('mousemove', this.tooltipListener.bind(this)); 1600 window.addEventListener('orientationchange', this.orientationListener.bind(this)); 1601 1602 // on tooltip creation, determine whether to display touch-specific controls 1603 var tooltipCloseButton = document.querySelector('.tooltip-close'); 1604 1605 if (touchDevice()) { 1606 var componentsContainer = document.querySelector('.components-container'); 1607 componentsContainer.addEventListener('touchstart', this.handleTouch.bind(this)); 1608 1609 tooltipCloseButton.addEventListener('touchstart', this.unhoverTooltip.bind(this)); 1610 } else { 1611 window.addEventListener('resize', this.resizeListener.bind(this)); 1612 // classList not supported by IE < 9 1613 tooltipCloseButton.className += ' hidden'; 1614 } 1615 1616 // Handle toggle of group elements 1617 var groupComponents = document.querySelectorAll('[data-js-hook=component-group-opener]'); 1618 for (var i = 0; i < groupComponents.length; i++) { 1619 groupComponents[i].addEventListener('click', this.hideTooltip.bind(this)); 1620 } 1621 1622 var tooltipBox = document.querySelector('#uptime-tooltip .tooltip-box'); 1623 tooltipBox.addEventListener('mouseenter', this.mouseEnteredTooltip.bind(this)); 1624 tooltipBox.addEventListener('mouseleave', this.unhoverTooltip.bind(this)); 1625 } 1626 1627 // STATUS-801: extracted so the lazy loader (_uptime_showcase_lazy_js) can bind 1628 // focus/blur/keydown handlers on rects that are injected AFTER initial paint. 1629 // Pass a root element to bind only that subtree's rects (avoids re-binding 1630 // existing ones); defaults to the whole document for the inline render path. 1631 function bindUptimeDayRects(root) { 1632 (root || document).querySelectorAll('.uptime-day').forEach(function (rect) { 1633 rect.addEventListener('focus', function (event) { 1634 var tooltipHandler = new UptimeTooltipHandler(); 1635 tooltipHandler.updateHoveredDay(event); 1636 tooltipHandler.updateTooltip(event); 1637 }); 1638 1639 rect.addEventListener('blur', function () { 1640 var tooltipHandler = new UptimeTooltipHandler(); 1641 tooltipHandler.unhoverTooltip(); 1642 }); 1643 1644 rect.addEventListener('keydown', function (event) { 1645 if (event.key === 'Escape' || event.keyCode === 27) { 1646 var tooltipHandler = new UptimeTooltipHandler(); 1647 tooltipHandler.unhoverTooltip(); 1648 } 1649 }); 1650 }); 1651 } 1652 window.bindUptimeDayRects = bindUptimeDayRects; 1653 bindUptimeDayRects(document); 1654 1655 UptimeTooltipHandler.prototype.tooltipListener = function(event) { 1656 if (!this.tooltipHovered) { 1657 this.updateHoveredDay(event); 1658 this.updateTooltip(event); 1659 } 1660 } 1661 1662 // this handler will accommodate for mobile orientation change 1663 UptimeTooltipHandler.prototype.orientationListener = function(event) { 1664 // just close the tooltip 1665 this.unhoverTooltip(); 1666 } 1667 1668 UptimeTooltipHandler.prototype.resizeListener = function(event) { 1669 this.frameWidth = window.innerWidth; 1670 } 1671 1672 UptimeTooltipHandler.prototype.handleTouch = function (event) { 1673 if (event.target.classList.contains('uptime-day')) { 1674 event.stopPropagation(); 1675 this.bladeTouched(event); 1676 } 1677 } 1678 1679 UptimeTooltipHandler.prototype.mouseEnteredTooltip = function() { 1680 // Necessary to clear the timeout set for closing the tooltip when the mouse 1681 // moves off the blade or timeline, so the tooltip isnt closed on hover 1682 clearTimeout(timeoutId); 1683 // Sets it to null so the timeout can be set later, as clearTimeout only 1684 // cancels the timer, and we need to allow it to be reset in the mouse 1685 // move handler below 1686 timeoutId = null; 1687 this.tooltipHovered = true; 1688 } 1689 1690 UptimeTooltipHandler.prototype.unhoverTooltip = function() { 1691 this.tooltipHovered = false;
1692 this.activeDay.hovered = false; 1693 this.hideTooltip(); 1694 } 1695 1696 UptimeTooltipHandler.prototype.bladeTouched = function (event) { 1697 event.preventDefault(); 1698 var classes = event.target.getAttribute('class').split(' '); 1699 var componentCode = componentCodeFromClass(classes[1]) 1700 var index = dayNumberFromClass(classes[2]); 1701 1702 // If open and tapped on same component and day, close tooltip 1703 if (this.visible && this.activeDay.component === componentCode && this.activeDay.index === index) { 1704 this.hideTooltip(); 1705 } else { 1706 this.updateHoveredDay(event); 1707 this.updateTooltip(event); 1708 } 1709 } 1710 1711 UptimeTooltipHandler.prototype.updateHoveredDay = function(event) { 1712 var classes = event.target.getAttribute('class'); // classList doesn't work in IE 1713 var onDay = classes != null && classes.split(' ').indexOf('uptime-day') !== -1; 1714 1715 if (onDay) { 1716 classes = classes.split(' '); 1717 1718 var componentCode = componentCodeFromClass(classes[1]); 1719 1720 this.activeDay = { 1721 index: dayNumberFromClass(classes[2]), 1722 component: componentCode, 1723 bounds: event.target.getBoundingClientRect(), 1724 isGroup: uptimeData[componentCode].component.isGroup, 1725 hovered: true 1726 } 1727 } else { 1728 this.activeDay.hovered = false; 1729 } 1730 } 1731 1732 UptimeTooltipHandler.prototype.updateTooltip = function(event) { 1733 var classes = event.target.getAttribute('class'); // classList doesn't work in IE 1734 var hoveredOnGraphic = classes != null && classes.split(' ').indexOf('availability-time-line-graphic') !== -1; 1735 1736 if (this.activeDay.hovered) { 1737 this.updateTooltipData(); 1738 this.positionTooltip(); 1739 } else if (this.visible && !this.activeDay.hovered && !hoveredOnGraphic) { 1740 // Important: since this is on mouse move it will be called multiple times 1741 // which will clear timeoutId and reset it to the new value, meaning 1742 // it is a race condition to cancel it 1743 if (!timeoutId) { 1744 var _this = this; 1745 timeoutId = setTimeout(function() { 1746 _this.hideTooltip(); 1747 timeoutId = null; 1748 }, 250); 1749 } 1750 } 1751 } 1752 1753 UptimeTooltipHandler.prototype.updateTooltipData = function() { 1754 // Get the data for the day we're hovered on 1755 var day = uptimeData[this.activeDay.component].days[this.activeDay.index]; 1756 1757 // Update the date for the tooltip 1758 var date = new Date(day.date); 1759 1760 // Get the component's start date. Note that it will be undefined here unless it is populated in our database 1761 var startDay = uptimeData[this.activeDay.component].component.startDate; 1762 var startDate = startDay ? new Date(startDay) : null; 1763 1764 // Determine whether current date falls before component's start date. 1765 var beforeStartDate = startDate ? date.getTime() < startDate.getTime() : false; 1766 1767 // UTC necessary since days are passed yyyy-mm-dd, and new Date uses midnight UTC, so local times 1768 // are presented as the day before 1769 var dateString = date.getUTCDate() + " " + monthStrings[date.getUTCMonth()] + " " + date.getUTCFullYear(); 1770 document.querySelector('#uptime-tooltip .date').innerHTML = dateString; 1771 1772 // Update the outage fields 1773 if (this.activeDay.isGroup) { 1774 this.updateGroupOutageFields() 1775 } else { 1776 this.updateOutageFields(day.outages.p, day.outages.m, day.related_events, beforeStartDate); 1777 } 1778 } 1779 1780 UptimeTooltipHandler.prototype.hoursFromSeconds = function(s) { 1781 return Math.floor(s / 3600); 1782 } 1783 1784 UptimeTooltipHandler.prototype.minutesFromSeconds = function(s) { 1785 // If less than a minute, round up to 1 minute to show that some outage existed 1786 if (s > 0 && s < 60) { 1787 return 1; 1788 } 1789 1790 // Otherwise use floor 1791 return Math.floor((s % 3600) / 60); 1792 } 1793 1794 UptimeTooltipHandler.prototype.updateGroupOutageFields = function() { 1795 // Hide time info 1796 document.querySelector('#uptime-tooltip .outage-field.major').style.display = 'none'; 1797 document.querySelector('#uptime-tooltip .outage-field.partial').style.display = 'none'; 1798 document.querySelector(".related-events h3").style.display = 'none'; 1799 document.querySelector('.no-related-msg').style.display = 'none'; 1800 1801 var eventList = document.getElementById("related-events-list") 1802 var cloneList = eventList.cloneNode(false); 1803 eventList.parentNode.replaceChild(cloneList, eventList); 1804 1805 var partialCount = 0; 1806 var majorCount = 0; 1807 1808 /** 1809 We were originally using the operationalCount as part of the no outage copy for group components, 1810 but ultimately decided not to use it. I opted to leave the variable in place in case we ever 1811 decide to use it in the future. 1812 */ 1813 var operationalCount = 0;
1814 var noDataCount = 0; 1815 var showcasedComponentsCount = 0; 1816 1817 var components = uptimeData[this.activeDay.component].component.group 1818 1819 for (var i = 0; i < components.length; i++) { 1820 if (!uptimeData[components[i]]) continue; 1821 1822 showcasedComponentsCount++; 1823 1824 var outages = uptimeData[components[i]].days[this.activeDay.index].outages; 1825 1826 var currentDay = uptimeData[components[i]].days[this.activeDay.index]; 1827 var currentDate = new Date(currentDay.date); 1828 1829 // Get the component's start date. Note that it will be undefined here unless it is populated in our database 1830 var startDay = uptimeData[components[i]].component.startDate; 1831 var startDate = startDay ? new Date(startDay) : null; 1832 1833 if (outages.p) { 1834 partialCount += 1; 1835 } 1836 1837 if (outages.m) { 1838 majorCount += 1; 1839 } 1840 1841 // Only increase operational count if component has data for this day 1842 if (!outages.p && !outages.m) { 1843 if (startDate && currentDate.getTime() < startDate.getTime()) { 1844 noDataCount +=1; 1845 } 1846 else { 1847 operationalCount +=1; 1848 } 1849 } 1850 } 1851 1852 document.querySelector('#major-outage-group-count').style.display = majorCount ? 'block' : 'none'; 1853 document.querySelector('#partial-outage-group-count').style.display = partialCount ? 'block' : 'none'; 1854 1855 document.querySelector('#major-outage-group-count .count').innerText = majorCount + (majorCount === 1 ? " component" : " components"); 1856 document.querySelector('#partial-outage-group-count .count').innerText = partialCount + (partialCount === 1 ? " component" : " components "); 1857 1858 // Show no data message only if we do not have data for any showcased components in the group 1859 var showNoDataMessage = noDataCount === showcasedComponentsCount; 1860 1861 // Show no outages message if we have data for the components and no outages in that data 1862 document.querySelector('#uptime-tooltip .no-outages-msg').style.display = (majorCount || partialCount || showNoDataMessage) ? 'none' : 'block'; 1863 document.querySelector('#uptime-tooltip .no-data-msg').style.display = showNoDataMessage ? 'block' : 'none'; 1864 } 1865 1866 UptimeTooltipHandler.prototype.updateOutageFields = function(partial, major, relatedEvents, beforeStartDate) { 1867 // Hide group info 1868 document.querySelector('#major-outage-group-count').style.display = 'none'; 1869 document.querySelector('#partial-outage-group-count').style.display = 'none'; 1870 1871 // Show the message that no outage present, if none is present 1872 if (partial || major || beforeStartDate) { 1873 document.querySelector('#uptime-tooltip .no-outages-msg').style.display = 'none'; 1874 } else { 1875 document.querySelector('#uptime-tooltip .no-outages-msg').style.display = 'block'; 1876 } 1877 1878 if (beforeStartDate) { 1879 document.querySelector('#uptime-tooltip .no-data-msg').style.display = 'block'; 1880 } 1881 else { 1882 document.querySelector('#uptime-tooltip .no-data-msg').style.display = 'none'; 1883 } 1884 1885 // Update partial outage field if an outage exists, otherwise hide it 1886 if (partial) { 1887 var hrs = this.hoursFromSeconds(partial); 1888 var mins = this.minutesFromSeconds(partial); 1889 document.querySelector('#uptime-tooltip .outage-field.partial .value-hrs').innerHTML = hrs.toString() + ' hrs'; 1890 document.querySelector('#uptime-tooltip .outage-field.partial .value-mins').innerHTML = mins.toString() + ' mins'; 1891 document.querySelector('#uptime-tooltip .outage-field.partial').style.display = 'flex'; 1892 } else { 1893 document.querySelector('#uptime-tooltip .outage-field.partial').style.display = 'none'; 1894 } 1895 1896 // Update major outage field if an outage exists, otherwise hide it 1897 if (major) { 1898 var hrs = this.hoursFromSeconds(major); 1899 var mins = this.minutesFromSeconds(major); 1900 document.querySelector('#uptime-tooltip .outage-field.major .value-hrs').innerHTML = hrs.toString() + ' hrs'; 1901 document.querySelector('#uptime-tooltip .outage-field.major .value-mins').innerHTML = mins.toString() + ' mins'; 1902 document.querySelector('#uptime-tooltip .outage-field.major').style.display = 'flex'; 1903 } else { 1904 document.querySelector('#uptime-tooltip .outage-field.major').style.display = 'none'; 1905 } 1906 1907 var eventList = document.getElementById("related-events-list") 1908 var cloneList = eventList.cloneNode(false); 1909 document.querySelector(".related-events h3").style.display = (relatedEvents.length ? 'block' : 'none'); 1910 1911 for (var i = 0; i < relatedEvents.length; i++) { 1912 var listItem = document.createElement("li"); 1913 listItem.className = "related-event"; 1914 var anchor = document.createElement("a"); 1915 anchor.className = "related-event-link"; 1916 anchor.target = "_blank"; 1917 anchor.href = window.Routes.incident_path(relatedEvents[i].code); 1918 1919 1920 var text = document.createTextNode(truncate(relatedEvents[i].name)); 1921 anchor.appendChild(text); 1922 listItem.appendChild(anchor); 1923 cloneList.appendChild(listItem); 1924 } 1925 1926 const displayNoRelatedMsg = ((major || partial) && !relatedEvents.length); 1927 document.querySelector('.no-related-msg').style.display = (displayNoRelatedMsg ? 'block' : 'none'); 1928 1929 eventList.parentNode.replaceChild(cloneList, eventList); 1930 } 1931 1932 UptimeTooltipHandler.prototype.positionTooltip = function() { 1933 this.calculatePointerCenter(); 1934 this.calculateBoxPosition(); 1935 1936 // show tooltip 1937 this.tooltip.style.display = 'block'; 1938 1939 // position pointer 1940 var pointer = this.tooltip.getElementsByClassName('pointer-container')[0]; 1941 pointer.style.left = intToPixels(this.pointerCenter.x - 8); 1942 pointer.style.top = intToPixels(this.pointerCenter.y - 5); 1943 1944 // position display box 1945 var box = this.tooltip.getElementsByClassName('tooltip-box')[0]; 1946 box.style.left = intToPixels(this.boxLeft); 1947 box.style.top = intToPixels(this.pointerCenter.y + 5); 1948 1949 this.visible = true; 1950 } 1951 1952 UptimeTooltipHandler.prototype.calculatePointerCenter = function() { 1953 var bounds = this.activeDay.bounds; 1954 var rectLeft = bounds.left + window.pageXOffset; 1955 var rectBottom = bounds.bottom + window.pageYOffset; 1956 var rectWidth = bounds.right - bounds.left; 1957 1958 this.pointerCenter = { 1959 x: rectLeft + Math.floor(rectWidth / 2), 1960 y: rectBottom + 5 1961 } 1962 } 1963 1964 UptimeTooltipHandler.prototype.calculateBoxPosition = function() { 1965 var sideWidth = 162.5; 1966 if (this.pointerCenter.x - sideWidth < 0) { 1967 this.boxLeft = 0; 1968 } else if (this.pointerCenter.x + sideWidth > this.frameWidth) { 1969 this.boxLeft = this.frameWidth - sideWidth * 2; 1970 } else { 1971 this.boxLeft = this.pointerCenter.x - sideWidth; 1972 } 1973 } 1974 1975 UptimeTooltipHandler.prototype.hideTooltip = function() { 1976 this.tooltip.style.display = 'none'; 1977 this.visible = false;
1978 } 1979 1980 new UptimeTooltipHandler(); 1981 1982</script>
1982 1983 1984 1985
1985<script type="text/javascript"> 1986 /** 1987 * STATUS-801: viewport-triggered loader for the 90-day uptime showcase. 1988 * 1989 * When LAZY_UPTIME_SHOWCASE is enabled the status document ships WITHOUT the 1990 * per-component SVG bars and the multi-MB inline `uptimeData` blob (that inline 1991 * payload is what caused `200 OK` + `ERR_HTTP2_PROTOCOL_ERROR` truncation on 1992 * large pages). Each showcase-eligible component instead renders a small 1993 * placeholder (`[data-uptime-lazy="<code>"]`). This script watches those 1994 * placeholders and, as they scroll into view, fetches their bars in small 1995 * batches from `status#uptime_showcase`, replaces the placeholder with the 1996 * returned markup, merges the tooltip data into `window.uptimeData`, and wires 1997 * up hover/keyboard tooltips + responsive (30/60/90-day) resizing. 1998 * 1999 * ES5 only (matches the rest of the status inline scripts). No hard dependency 2000 * on fetch/IntersectionObserver: falls back gracefully when unavailable. 2001 */ 2002 (function () { 2003 var ENDPOINT = "/uptime_showcase"; 2004 var BATCH_LIMIT = 60; // must stay <= SHOWCASE_BATCH_LIMIT server-side 2005 var FLUSH_DELAY_MS = 60; // coalesce rapidly-observed placeholders 2006 var MAX_WIDTH_30_DAYS = 600; 2007 var MAX_WIDTH_60_DAYS = 1024; 2008 var PRELOAD_MARGIN = '250px 0px'; // start fetching just before they scroll in 2009 2010 // code -> {ninety, sixty, thirty} for responsive legend updates. 2011 var uptimeValues = {}; 2012 // code -> true while queued/in-flight, to avoid duplicate requests. 2013 var inFlight = {}; 2014 var queue = []; 2015 var flushTimer = null; 2016 var observer = null; 2017 2018 function init() { 2019 var placeholders = document.querySelectorAll('[data-uptime-lazy]'); 2020 if (!placeholders.length) return; 2021 2022 window.uptimeData = window.uptimeData || {}; 2023 2024 if ('IntersectionObserver' in window) { 2025 observer = new IntersectionObserver(onIntersect, { rootMargin: PRELOAD_MARGIN }); 2026 for (var i = 0; i < placeholders.length; i++) { 2027 observer.observe(placeholders[i]); 2028 } 2029 } else { 2030 // Older browsers: no lazy behaviour, just load everything in batches. 2031 for (var j = 0; j < placeholders.length; j++) { 2032 enqueue(placeholders[j].getAttribute('data-uptime-lazy')); 2033 } 2034 } 2035 2036 var resizeTimer; 2037 window.addEventListener('resize', function () { 2038 clearTimeout(resizeTimer); 2039 resizeTimer = setTimeout(resizeSvgViewBoxes, 150); 2040 }); 2041 } 2042 2043 function onIntersect(entries) { 2044 for (var i = 0; i < entries.length; i++) { 2045 if (entries[i].isIntersecting) { 2046 enqueue(entries[i].target.getAttribute('data-uptime-lazy')); 2047 } 2048 } 2049 } 2050 2051 function enqueue(code) { 2052 if (!code || inFlight[code]) return; 2053 inFlight[code] = true; 2054 queue.push(code); 2055 if (!flushTimer) flushTimer = setTimeout(flush, FLUSH_DELAY_MS); 2056 } 2057 2058 function flush() { 2059 flushTimer = null; 2060 if (!queue.length) return; 2061 var batch = queue.splice(0, BATCH_LIMIT); 2062 fetchBatch(batch); 2063 if (queue.length && !flushTimer) flushTimer = setTimeout(flush, FLUSH_DELAY_MS); 2064 } 2065 2066 function fetchBatch(codes) { 2067 var xhr = new XMLHttpRequest(); 2068 xhr.open('GET', ENDPOINT + '?components=' + encodeURIComponent(codes.join(',')), true); 2069 xhr.setRequestHeader('Accept', 'application/json'); 2070 xhr.onreadystatechange = function () { 2071 if (xhr.readyState !== 4) return; 2072 if (xhr.status >= 200 && xhr.status < 300) { 2073 var data; 2074 try { data = JSON.parse(xhr.responseText); } 2075 catch (e) { release(codes); return; } 2076 applyBatch(data, codes); 2077 } else { 2078 // Transient failure: allow these codes to be retried if re-observed. 2079 release(codes); 2080 } 2081 }; 2082 xhr.send(); 2083 } 2084 2085 // Free codes so a future intersection can retry them (e.g. after a 5xx). 2086 function release(codes) { 2087 for (var i = 0; i < codes.length; i++) inFlight[codes[i]] = false; 2088 } 2089 2090 function applyBatch(data, codes) { 2091 var timelines = data.timelines || {}; 2092 for (var key in timelines) { 2093 if (timelines.hasOwnProperty(key)) window.uptimeData[key] = timelines[key]; 2094 } 2095 2096 var values = data.values || []; 2097 for (var v = 0; v < values.length; v++) { 2098 uptimeValues[values[v].component] = values[v]; 2099 } 2100 2101 var components = data.components || {}; 2102 for (var c = 0; c < codes.length; c++) { 2103 var code = codes[c]; 2104 var placeholder = document.querySelector('[data-uptime-lazy="' + code + '"]'); 2105 if (!placeholder) continue; 2106 if (observer) observer.unobserve(placeholder); 2107 2108 var html = components[code]; 2109 if (!html) { 2110 // Server returned no markup for this code (not actually showcased): 2111 // drop the placeholder and stop retrying. 2112 if (placeholder.parentNode) placeholder.parentNode.removeChild(placeholder); 2113 continue; 2114 } 2115 2116 // Replace the neutral placeholder with the fetched `.uptime-90-days-wrapper` 2117 // so the resulting DOM matches the inline (non-lazy) render exactly. 2118 var holder = document.createElement('div'); 2119 holder.innerHTML = html; 2120 var node = holder.firstElementChild; 2121 if (node && placeholder.parentNode) { 2122 placeholder.parentNode.replaceChild(node, placeholder); 2123 if (window.bindUptimeDayRects) window.bindUptimeDayRects(node); 2124 } 2125 } 2126 2127 resizeSvgViewBoxes(); 2128 } 2129 2130 /* ----- responsive resize (adapted from components_js) ----------------- */ 2131 2132 function calculateViewbox(dayCount, rectWidth, rectPadding) { 2133 var viewBox = []; 2134 if (dayCount === 90) {
2135 viewBox.push(0); 2136 } else { 2137 var offset = 90 - dayCount; 2138 viewBox.push((offset * rectWidth) + (rectPadding * offset)); 2139 } 2140 viewBox.push(0); 2141 viewBox.push((rectWidth * dayCount) + (rectPadding * (dayCount - 1))); 2142 viewBox.push(34); 2143 return viewBox.join(' '); 2144 } 2145 2146 function getKeyAndCount(width) { 2147 if (width <= MAX_WIDTH_30_DAYS) return { dayCount: 30, uptimeKey: 'thirty' }; 2148 if (width <= MAX_WIDTH_60_DAYS) return { dayCount: 60, uptimeKey: 'sixty' }; 2149 return { dayCount: 90, uptimeKey: 'ninety' }; 2150 } 2151 2152 function setUptimeValue(values, uptimeKey) { 2153 var current = document.querySelector('.legend-item-' + values.component); 2154 if (!current) return; 2155 var clone = current.cloneNode(false); 2156 var uptimeSpan = document.createElement('span'); 2157 uptimeSpan.id = 'uptime-percent-' + values.component; 2158 uptimeSpan.innerText = values[uptimeKey]; 2159 clone.appendChild(uptimeSpan); 2160 clone.appendChild(document.createTextNode(' % uptime')); 2161 current.parentNode.replaceChild(clone, current); 2162 } 2163 2164 function setDayCount(el, dayCount) { 2165 var clone = el.cloneNode(false); 2166 var dateSpan = document.createElement('span'); 2167 dateSpan.className = 'availability-time-line-legend-day-count'; 2168 dateSpan.innerText = dayCount; 2169 clone.appendChild(dateSpan); 2170 clone.appendChild(document.createTextNode(' days ago')); 2171 el.parentNode.replaceChild(clone, el); 2172 } 2173 2174 function resizeSvgViewBoxes() { 2175 var svgs = document.getElementsByClassName('availability-time-line-graphic'); 2176 if (!svgs.length) return; 2177 2178 var rects = svgs[0].getElementsByTagName('rect'); 2179 if (rects.length < 2) return; 2180 2181 var rectWidth = parseInt(rects[0].getAttribute('width')); 2182 var rectPadding = parseInt(rects[1].getAttribute('x')) - parseInt(rects[0].getAttribute('x')) - rectWidth; 2183 var info = getKeyAndCount(window.innerWidth); 2184 var newViewbox = calculateViewbox(info.dayCount, rectWidth, rectPadding); 2185 2186 for (var i = 0; i < svgs.length; i++) { 2187 if (svgs[i].getAttribute('viewBox') !== newViewbox) { 2188 svgs[i].setAttribute('viewBox', newViewbox); 2189 } 2190 } 2191 2192 var dayCountElements = document.querySelectorAll('.legend-item-date-range:first-of-type'); 2193 for (var d = 0; d < dayCountElements.length; d++) { 2194 setDayCount(dayCountElements[d], info.dayCount); 2195 } 2196 2197 for (var code in uptimeValues) { 2198 if (uptimeValues.hasOwnProperty(code)) setUptimeValue(uptimeValues[code], info.uptimeKey); 2199 } 2200 2201 var uptimeLinkVar = document.querySelector('.components-uptime-link > var'); 2202 if (uptimeLinkVar) uptimeLinkVar.innerHTML = info.dayCount; 2203 } 2204 2205 if (document.readyState === 'loading') { 2206 document.addEventListener('DOMContentLoaded', init); 2207 } else { 2208 init(); 2209 } 2210 })(); 2211</script>
2211 2212 2213 2214 2215 2216 <div class="custom-metrics-container" id="custom-metrics-container"> 2217 <div class="timeframes-container"> 2218 <a class="font-largest no-link" id="system-metrics" href="#system-metrics">System Metrics</a> 2219 <a href="#" class="timeframe color-secondary font-regular border-color" data-js-hook="data-time-period-toggle" data-time-period="month">Month</a> 2220 <a href="#" class="timeframe color-secondary font-regular border-color" data-js-hook="data-time-period-toggle" data-time-period="week"><span class="translation_missing" title="translation missing: en.week">Week</span></a> 2221 <a href="#" class="timeframe active color-secondary font-regular border-color" data-js-hook="data-time-period-toggle" data-time-period="day">Day</a> 2222 </div> 2223 <div class="metrics-container"> 2224 <div class="metric border-color"> 2225 <div class="metric-meta font-large"> 2226 <div class="metric-name color-primary"> 2227 Active Linux Builds for Open Source projects 2228 </div> 2229 2230 <div data-js-hook="metrics-display-current-f9xnl1j783xl" class="metric-average color-secondary"><span class="translation_missing" title="translation missing: en.fetching">Fetching</span></div> 2231 </div> 2232 <div class="metrics-display-graph"> 2233 <div class="graph-container" id="metrics-display-graph-container-f9xnl1j783xl" data-js-hook= "metrics-display-graph-container-f9xnl1j783xl"></div> 2234 </div> 2235 </div> 2236 <div class="metric border-color"> 2237 <div class="metric-meta font-large"> 2238 <div class="metric-name color-primary"> 2239 Backlog Linux Builds for Open Source projects 2240 </div> 2241 2242 <div data-js-hook="metrics-display-current-td6nbzppbz2j" class="metric-average color-secondary"><span class="translation_missing" title="translation missing: en.fetching">Fetching</span></div> 2243 </div> 2244 <div class="metrics-display-graph"> 2245 <div class="graph-container" id="metrics-display-graph-container-td6nbzppbz2j" data-js-hook= "metrics-display-graph-container-td6nbzppbz2j"></div> 2246 </div> 2247 </div> 2248 </div> 2249 </div> 2250 2251 2252 <div class="incidents-list format-expanded"> 2253 <h2 class="font-largest no-link" id="past-incidents">Past Incidents</h2> 2254 2255 <div class="status-day font-regular no-incidents"> 2256 <h3 class="date border-color font-large">Oct <var data-var="date"> 2</var>, <var data-var="year">2026</var></h3> 2257 <p class="color-secondary">No incidents reported today.</p> 2258 </div> 2259 2260 2261 <div class="status-day font-regular no-incidents"> 2262 <h3 class="date border-color font-large">Oct <var data-var="date"> 1</var>, <var data-var="year">2026</var></h3> 2263 <p class="color-secondary">No incidents reported.</p> 2264 </div> 2265 2266 2267 <div class="status-day font-regular no-incidents"> 2268 <h3 class="date border-color font-large">Sep <var data-var="date">30</var>, <var data-var="year">2026</var></h3> 2269 <p class="color-secondary">No incidents reported.</p> 2270 </div> 2271 2272 2273 <div class="status-day font-regular no-incidents"> 2274 <h3 class="date border-color font-large">Sep <var data-var="date">29</var>, <var data-var="year">2026</var></h3> 2275 <p class="color-secondary">No incidents reported.</p> 2276 </div> 2277 2278 2279 <div class="status-day font-regular no-incidents"> 2280 <h3 class="date border-color font-large">Sep <var data-var="date">28</var>, <var data-var="year">2026</var></h3> 2281 <p class="color-secondary">No incidents reported.</p> 2282 </div> 2283 2284 2285 <div class="status-day font-regular no-incidents"> 2286 <h3 class="date border-color font-large">Sep <var data-var="date">27</var>, <var data-var="year">2026</var></h3> 2287 <p class="color-secondary">No incidents reported.</p> 2288 </div> 2289 2290 2291 <div class="status-day font-regular no-incidents"> 2292 <h3 class="date border-color font-large">Sep <var data-var="date">26</var>, <var data-var="year">2026</var></h3> 2293 <p class="color-secondary">No incidents reported.</p> 2294 </div> 2295 2296 2297 <div class="status-day font-regular no-incidents"> 2298 <h3 class="date border-color font-large">Sep <var data-var="date">25</var>, <var data-var="year">2026</var></h3> 2299 <p class="color-secondary">No incidents reported.</p> 2300 </div> 2301 2302 2303 <div class="status-day font-regular no-incidents"> 2304 <h3 class="date border-color font-large">Sep <var data-var="date">24</var>, <var data-var="year">2026</var></h3> 2305 <p class="color-secondary">No incidents reported.</p> 2306 </div> 2307 2308 2309 <div class="status-day font-regular no-incidents"> 2310 <h3 class="date border-color font-large">Sep <var data-var="date">23</var>, <var data-var="year">2026</var></h3> 2311 <p class="color-secondary">No incidents reported.</p> 2312 </div> 2313 2314 2315 <div class="status-day font-regular no-incidents"> 2316 <h3 class="date border-color font-large">Sep <var data-var="date">22</var>, <var data-var="year">2026</var></h3> 2317 <p class="color-secondary">No incidents reported.</p> 2318 </div> 2319 2320 2321 <div class="status-day font-regular no-incidents"> 2322 <h3 class="date border-color font-large">Sep <var data-var="date">21</var>, <var data-var="year">2026</var></h3> 2323 <p class="color-secondary">No incidents reported.</p> 2324 </div> 2325 2326 2327 <div class="status-day font-regular no-incidents"> 2328 <h3 class="date border-color font-large">Sep <var data-var="date">20</var>, <var data-var="year">2026</var></h3> 2329 <p class="color-secondary">No incidents reported.</p> 2330 </div> 2331 2332 2333 <div class="status-day font-regular no-incidents"> 2334 <h3 class="date border-color font-large">Sep <var data-var="date">19</var>, <var data-var="year">2026</var></h3> 2335 <p class="color-secondary">No incidents reported.</p> 2336 </div> 2337 2338 2339 <div class="status-day font-regular no-incidents"> 2340 <h3 class="date border-color font-large">Sep <var data-var="date">18</var>, <var data-var="year">2026</var></h3> 2341 <p class="color-secondary">No incidents reported.</p> 2342 </div> 2343 2344 </div> 2345 2346 2347 <div class="page-footer border-color font-small"> 2348 <a href="/history" class="history-footer-link"><span style="font-family:arial" aria-hidden="true">←</span> Incident History</a> 2349
2350 <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.traviscistatus.com&utm_content=SP-notifications&utm_medium=powered-by&utm_source=inapp">Powered by Atlassian Statuspage</a></span> 2351 </div> 2352 </div> 2353 2354 2355 2356 </div> 2357 2358 2359 2360 <!-- custom metrics stuff --> 2361 2362 2363 2364 2365 2366
2366<script src="https://dka575ofm4ao0.cloudfront.net/assets/status_manifest-b790849ccb41192b3f7d9c14d5a4a6d5142add81fc8522649ca5c82f6a1fbb0e.js"></script>
2366 2367 <div id="cpt-notification-container" role="status" aria-live="polite" aria-atomic="true"></div> 2368 2369 2370 2371 2372 2373 <!-- all of the content_for stuff --> 2374
2374<script src="https://dka575ofm4ao0.cloudfront.net/assets/register_subscription_form-589b657fec607087fc5c740c568270907310bc4f6aaa20256e70f01b103025ca.js"></script>
2374 2375 2376
2376<script type="text/javascript"> 2377 $(function() { 2378 SP.currentPage.registerSubscriptionForm('email'); 2379 2380 2381 SP.currentPage.registerSubscriptionForm('webhook'); 2382 2383 }); 2384 2385 2386 2387 2388 2389 </script>
2389 2390
2390<script src="https://dka575ofm4ao0.cloudfront.net/assets/status_common-a7b1e9f22a2c94a83d347ec517cabf21494ca11867ebf891f46f89c9b4101811.js"></script>
2390 2391
2391<script> 2392 SP.pollForChanges('/api/v2/status.json'); 2393 </script>
2393 2394 2395
2395<script> 2396 $(function() { 2397 $('.tool').tooltipster({ 2398 animationDuration: 100, 2399 contentAsHTML: true, 2400 delay: 100, 2401 theme: 'tooltipster-borderless', 2402 functionInit: function (instance, helper) { 2403 var $origin = $(helper.origin), 2404 dataOptions = $origin.attr('data-tooltip-config'); 2405 if (dataOptions){ 2406 dataOptions = JSON.parse(dataOptions); 2407 $.each(dataOptions, function(name, option){ 2408 instance.option(name, option); 2409 }); 2410 } 2411 } 2412 }); 2413 // clicks on first tab in subscribe popout since we won't know which is first 2414 // upon construction in the ruby code 2415 $('.updates-dropdown-nav > a').eq(0).click(); 2416 2417 // twitter follow button needs some margin 2418 $('.twitter-follow-button').css('margin-right', '6px'); 2419 }); 2420 2421 $(function() { 2422 // open/close component groups 2423 HRB.utils.djshook('component-group-opener').on('click', function() { 2424 var groupParentIndicator = $(this).find('.group-parent-indicator'); 2425 groupParentIndicator.toggleClass('fa-plus-square-o').toggleClass('fa-minus-square-o').end().parent().toggleClass('open'); 2426 toggleGroup(groupParentIndicator) 2427 }); 2428 }); 2429 2430 $(function() { 2431 HRB.utils.djshook('component-group-opener').on('keydown', function(event) { 2432 if (event.key !== "Enter" && event.key !== " ") { 2433 return; 2434 } 2435 event.preventDefault() 2436 var groupParentIndicator = $(this).find('.group-parent-indicator'); 2437 groupParentIndicator.toggleClass('fa-plus-square-o').toggleClass('fa-minus-square-o').end().parent().toggleClass('open'); 2438 toggleGroup(groupParentIndicator) 2439 }); 2440 }); 2441 2442 function toggleGroup(groupParentIndicator) { 2443 var isOpen = groupParentIndicator.attr('aria-expanded') 2444 if (isOpen == 'false') { 2445 groupParentIndicator.attr('aria-expanded', 'true'); 2446 } else { 2447 groupParentIndicator.attr('aria-expanded', 'false'); 2448 } 2449 } 2450 2451 $(function() { 2452 $(document).on('ajax:complete', '.modal.in', function(e) { 2453 // Close the active modal. 2454 $('.modal.in').modal('hide'); 2455 }); 2456 }); 2457 2458 </script>
2458 2459
2459<script src="https://dka575ofm4ao0.cloudfront.net/assets/vendor/highstock.min-a7181c8f093438143dae37524f8463a97e2503789bc322732d3141f2c00c1c1a.js"></script>
2459 2460 2461
2461<script> 2462 //<![CDATA[ 2463 String.prototype.commafy = function () { 2464 return this.replace(/(^|[^\w.])(\d{4,})/g, function($0, $1, $2) { 2465 return $1 + $2.replace(/\d(?=(?:\d\d\d)+(?!\d))/g, "$&,"); 2466 }); 2467 } 2468 2469 Number.prototype.commafy = function () { 2470 return String(this).commafy(); 2471 } 2472 2473 $(function() { 2474 SP.currentPage.numberToDecimalPlaces = function(num, dec) { 2475 if (dec == 0) { 2476 return Math.round(num).commafy(); 2477 } 2478 2479 newnum = num.toFixed(dec) 2480 var finalValue; 2481 2482 // this gets rid of the 100.000% thing 2483 if (num == parseInt(newnum)) 2484 finalValue = Math.round(num); 2485 else 2486 finalValue = newnum; 2487 2488 return finalValue.commafy(); 2489 } 2490 2491 SP.currentPage.getDataForTimePeriod = function(period) { 2492 $.ajax({ 2493 type: "GET", 2494 // this line must be end up with "//status.*" type of URLs (no protocol, just leading slashes). customers use SSL through us or by offloading with 2495 // cloudflare or something like it and the request.protocol the server sees is different than what the browser sees 2496 url: "//www.traviscistatus.com/metrics-display/f9xnl1j783xl/_.json".replace('_', period) 2497 }).done(function(metricsDisplay, textStatus, xhr) { 2498 var summary = metricsDisplay.summary 2499 , $metricSummaryLabel = HRB.utils.djshook('metrics-display-current-f9xnl1j783xl') 2500 , $graphContainer = HRB.utils.djshook('metrics-display-graph-container-f9xnl1j783xl'); 2501 var errorMsg = null; 2502 2503 if(summary === "unavailable") { 2504 errorMsg = 'We\'re having issues retrieving data for <strong>Active Linux Builds for Open Source projects</strong>.</div>'; 2505 } else if(summary) { 2506 // we need to do a basic check to make sure we have any data at all 2507 var hasDataRollupsAvailable = false; 2508 for(var h = 0; h < metricsDisplay.metrics.length; h++) { 2509 if(metricsDisplay.metrics[h].data.length > 0) { 2510 hasDataRollupsAvailable = true; 2511 break; 2512 } 2513 } 2514 if(!hasDataRollupsAvailable) { 2515 errorMsg = "Oops! No data has been indexed for <strong>Active Linux Builds for Open Source projects</strong> for this time period yet."; 2516 } 2517 } else { 2518 errorMsg = "Failed to load. <strong>Active Linux Builds for Open Source projects</strong>"; 2519 } 2520 2521 if(errorMsg !== null) { 2522 $metricSummaryLabel.text("--"); // display -- instead of number 2523 $graphContainer.html('<div class="small" style="text-align:center;">' + errorMsg + '</div>'); // removed .parent().find('.metric-meta').remove() so name still shows 2524 $graphContainer.removeAttr("style"); 2525 return; 2526 } 2527 2528 $graphContainer.show(); 2529 $graphContainer.attr("style", "height: 120px"); // set style after error message removed it 2530 // proceed since we have data 2531 $metricSummaryLabel.text(SP.currentPage.numberToDecimalPlaces(summary['mean'], 0 ) + ' jobs'); 2532 2533 var metricDataPoints = {} 2534 , intervalMsec = metricsDisplay.period.interval * 1000; 2535 2536 var startingBucketMsec = parseInt((new Date()).getTime() / intervalMsec) * intervalMsec; 2537 2538 for(var h = 0; h < metricsDisplay.metrics.length; h++) { 2539 metricDataPoints[metricsDisplay.metrics[h].metric.id] = [] 2540 var data = metricsDisplay.metrics[h].data 2541 , currentBucketMsec = startingBucketMsec; 2542 2543 for(var i = metricsDisplay.period.count; i > 0; i--) { 2544 // loop over the data and pull out the data point with the following characteristics 2545 // -> closest to currentBucketMsec 2546 // -> without being greater than currentMsecBucket 2547 // -> without being more than 1 intervalMsec bucket away 2548 var valueToUse = null; 2549 for(var j = data.length - 1; j >= 0; j--) { 2550 var currentTimestampMsec = data[j].timestamp * 1000; 2551 if(currentTimestampMsec <= currentBucketMsec && currentTimestampMsec > (currentBucketMsec - intervalMsec)) { 2552 valueToUse = data[j].value; 2553 // console.log("Using ts:" + currentTimestampMsec + " with value:" + valueToUse + " for bucket:" + currentBucketMsec); 2554 break; 2555 } 2556 } 2557 2558 // local time 2559 var offset = -1 * (new Date()).getTimezoneOffset() * 60 * 1000; 2560 2561 metricDataPoints[metricsDisplay.metrics[h].metric.id].push([currentBucketMsec + offset, valueToUse]) 2562 currentBucketMsec -= intervalMsec; 2563 } 2564 2565 metricDataPoints[metricsDisplay.metrics[h].metric.id].reverse(); 2566 } 2567 // set Global options 2568 Highcharts.setOptions({ 2569 lang: { 2570 thousandsSep: ',' 2571 } 2572 }); 2573 2574 $('#metrics-display-graph-container-f9xnl1j783xl').highcharts('StockChart', { 2575 plotOptions : { 2576 series : { 2577 animation : false, 2578 color : '#0068FF', 2579 connectNulls: false 2580 }, 2581 }, 2582 2583 chart : { 2584 backgroundColor: '#fff' 2585 }, 2586 2587 title : { 2588 text: '', 2589 style: { 2590 display: 'none', 2591 } 2592 }, 2593 2594 credits : { 2595 enabled : false 2596 }, 2597 2598 exporting : { 2599 enabled : false 2600 }, 2601 2602 rangeSelector : { 2603 enabled : false 2604 }, 2605 2606 scrollbar : { 2607 enabled : false 2608 }, 2609 2610 navigator : { 2611 enabled : false 2612 }, 2613 2614 xAxis: { 2615 gridLineColor : 'rgba(204,225,255,.8)', 2616 labels: { 2617 style : { 2618 color: '#8794A0' 2619 } 2620 }, 2621 lineColor: '#CCE1FF', 2622 }, 2623 2624 yAxis: { 2625 gridLineColor : 'rgba(204,225,255,.5)', 2626 labels: { 2627 align: 'left', 2628 x: 5, 2629 y: 3, 2630 style : { 2631 color: '#8794A0' 2632 }, 2633 enabled : true 2634 }, 2635 showLastLabel: true, 2636 tickPixelInterval: 40, 2637 2638 }, 2639 2640 series : [ 2641 { 2642 name : 'Active Linux Builds for Open Source projects', 2643 data : metricDataPoints['8r2tgpgjfcmf'], 2644 tooltip: { 2645 valueSuffix: ' jobs' 2646 }, 2647 enableMouseTracking : ($(window).outerWidth() > 480) && true 2648 } 2649 2650 ], 2651 2652 tooltip: { 2653 borderWidth: 0, 2654 enabled: ($(window).outerWidth() > 480) && true, 2655 headerFormat: "<span style='font-size: 10px'>{point.key} </span>", 2656 hideDelay: 300, 2657 pointFormat: "<span style='color:{point.color}'>â</span> <b>{point.y}</b><br/>", 2658 positioner: function() { return {x: 0, y: 0 }; }, 2659 shadow: false, 2660 shape: "square", 2661 split: false 2662 } 2663 }); 2664 2665 }); 2666 $.ajax({ 2667 type: "GET", 2668 // this line must be end up with "//status.*" type of URLs (no protocol, just leading slashes). customers use SSL through us or by offloading with 2669 // cloudflare or something like it and the request.protocol the server sees is different than what the browser sees 2670 url: "//www.traviscistatus.com/metrics-display/td6nbzppbz2
2670j/_.json".replace('_', period) 2671 }).done(function(metricsDisplay, textStatus, xhr) { 2672 var summary = metricsDisplay.summary 2673 , $metricSummaryLabel = HRB.utils.djshook('metrics-display-current-td6nbzppbz2j') 2674 , $graphContainer = HRB.utils.djshook('metrics-display-graph-container-td6nbzppbz2j'); 2675 var errorMsg = null; 2676 2677 if(summary === "unavailable") { 2678 errorMsg = 'We\'re having issues retrieving data for <strong>Backlog Linux Builds for Open Source projects</strong>.</div>'; 2679 } else if(summary) { 2680 // we need to do a basic check to make sure we have any data at all 2681 var hasDataRollupsAvailable = false; 2682 for(var h = 0; h < metricsDisplay.metrics.length; h++) { 2683 if(metricsDisplay.metrics[h].data.length > 0) { 2684 hasDataRollupsAvailable = true; 2685 break; 2686 } 2687 } 2688 if(!hasDataRollupsAvailable) { 2689 errorMsg = "Oops! No data has been indexed for <strong>Backlog Linux Builds for Open Source projects</strong> for this time period yet."; 2690 } 2691 } else { 2692 errorMsg = "Failed to load. <strong>Backlog Linux Builds for Open Source projects</strong>"; 2693 } 2694 2695 if(errorMsg !== null) { 2696 $metricSummaryLabel.text("--"); // display -- instead of number 2697 $graphContainer.html('<div class="small" style="text-align:center;">' + errorMsg + '</div>'); // removed .parent().find('.metric-meta').remove() so name still shows 2698 $graphContainer.removeAttr("style"); 2699 return; 2700 } 2701 2702 $graphContainer.show(); 2703 $graphContainer.attr("style", "height: 120px"); // set style after error message removed it 2704 // proceed since we have data 2705 $metricSummaryLabel.text(SP.currentPage.numberToDecimalPlaces(summary['mean'], 0 ) + ' jobs'); 2706 2707 var metricDataPoints = {} 2708 , intervalMsec = metricsDisplay.period.interval * 1000; 2709 2710 var startingBucketMsec = parseInt((new Date()).getTime() / intervalMsec) * intervalMsec; 2711 2712 for(var h = 0; h < metricsDisplay.metrics.length; h++) { 2713 metricDataPoints[metricsDisplay.metrics[h].metric.id] = [] 2714 var data = metricsDisplay.metrics[h].data 2715 , currentBucketMsec = startingBucketMsec; 2716 2717 for(var i = metricsDisplay.period.count; i > 0; i--) { 2718 // loop over the data and pull out the data point with the following characteristics 2719 // -> closest to currentBucketMsec 2720 // -> without being greater than currentMsecBucket 2721 // -> without being more than 1 intervalMsec bucket away 2722 var valueToUse = null; 2723 for(var j = data.length - 1; j >= 0; j--) { 2724 var currentTimestampMsec = data[j].timestamp * 1000; 2725 if(currentTimestampMsec <= currentBucketMsec && currentTimestampMsec > (currentBucketMsec - intervalMsec)) { 2726 valueToUse = data[j].value; 2727 // console.log("Using ts:" + currentTimestampMsec + " with value:" + valueToUse + " for bucket:" + currentBucketMsec); 2728 break; 2729 } 2730 } 2731 2732 // local time 2733 var offset = -1 * (new Date()).getTimezoneOffset() * 60 * 1000; 2734 2735 metricDataPoints[metricsDisplay.metrics[h].metric.id].push([currentBucketMsec + offset, valueToUse]) 2736 currentBucketMsec -= intervalMsec; 2737 } 2738 2739 metricDataPoints[metricsDisplay.metrics[h].metric.id].reverse(); 2740 } 2741 // set Global options 2742 Highcharts.setOptions({ 2743 lang: { 2744 thousandsSep: ',' 2745 } 2746 }); 2747 2748 $('#metrics-display-graph-container-td6nbzppbz2j').highcharts('StockChart', { 2749 plotOptions : { 2750 series : { 2751 animation : false, 2752 color : '#0068FF', 2753 connectNulls: false 2754 }, 2755 }, 2756 2757 chart : { 2758 backgroundColor: '#fff' 2759 }, 2760 2761 title : { 2762 text: '', 2763 style: { 2764 display: 'none', 2765 } 2766 }, 2767 2768 credits : { 2769 enabled : false 2770 }, 2771 2772 exporting : { 2773 enabled : false 2774 }, 2775 2776 rangeSelector : { 2777 enabled : false 2778 }, 2779 2780 scrollbar : { 2781 enabled : false 2782 }, 2783 2784 navigator : { 2785 enabled : false 2786 }, 2787 2788 xAxis: { 2789 gridLineColor : 'rgba(204,225,255,.8)', 2790 labels: { 2791 style : { 2792 color: '#8794A0' 2793 } 2794 }, 2795 lineColor: '#CCE1FF', 2796 }, 2797 2798 yAxis: { 2799 gridLineColor : 'rgba(204,225,255,.5)', 2800 labels: { 2801 align: 'left', 2802 x: 5, 2803 y: 3, 2804 style : { 2805 color: '#8794A0' 2806 }, 2807 enabled : true 2808 }, 2809 showLastLabel: true, 2810 tickPixelInterval: 40, 2811 2812 }, 2813 2814 series : [ 2815 { 2816 name : 'Backlog Linux Builds for Open Source projects', 2817 data : metricDataPoints['5t9vf2rrkm79'], 2818 tooltip: { 2819 valueSuffix: ' jobs' 2820 }, 2821 enableMouseTracking : ($(window).outerWidth() > 480) && true 2822 } 2823 2824 ], 2825 2826 tooltip: { 2827 borderWidth: 0, 2828 enabled: ($(window).outerWidth() > 480) && true, 2829 headerFormat: "<span style='font-size: 10px'>{point.key} </span>", 2830 hideDelay: 300, 2831 pointFormat: "<span style='color:{point.color}'>â</span> <b>{point.y}</b><br/>", 2832 positioner: function() { return {x: 0, y: 0 }; }, 2833 shadow: false, 2834 shape: "square", 2835 split: false 2836 } 2837 }); 2838 2839 }); 2840 } 2841 2842 var $timePeriodToggles = HRB.utils.djshook('data-time-period-toggle'); 2843 2844 SP.currentPage.activeTimePeriodToggle = function(period) { 2845 $timePeriodToggles.removeClass('active'); 2846 $timePeriodToggles.filter('[data-time-period="' + period + '"]').addClass('active'); 2847 } 2848 2849 SP.currentPage.getAndDisplayInitialChartData = function() { 2850 if (window.location.hash == '#week') { 2851 SP.currentPage.getDataForTimePeriod('week'); 2852 SP.currentPage.activeTimePeriodToggle('week'); 2853 } 2854 else if (window.location.hash == '#month') { 2855 SP.currentPage.getDataForTimePeriod('month'); 2856 SP.currentPage.activeTimePeriodToggle('month'); 2857 } 2858 else { 2859 SP.currentPage.getDataForTimePeriod('day'); 2860 SP.currentPage.activeTimePeriodToggle('day'); 2861 } 2862 } 2863 2864 $timePeriodToggles.on('click', function() { 2865 var newPeriod = $(this).attr('data-time-period'); 2866 2867 SP.currentPage.activeTimePeriodToggle(newPeriod); 2868 SP.currentPage.getDataForTimePeriod(newPeriod); 2869 window.location.hash = newPeriod; 2870 2871 return false;
2872 }); 2873 2874 SP.currentPage.getAndDisplayInitialChartData(); 2875 }) 2876 //]]> 2877 </script>
2877 2878 2879 2880 2881
2881<script> 2882 /** INITIALIZATION **/ 2883 var recaptchaIds = {} 2884 2885 // Unfortunately there's no unique selectors on the parent divs that recaptcha adds. The first unique selector 2886 // is the iframe rendered 2 levels deep. So this waits until the iframes are added to the page, then finds 2887 // the parent div and sets the z index so that it'll render above our modals & dropdowns from the start. 2888 function setZIndex(captchaCount, startTime) { 2889 // bail after 10s just in case so we don't do this forever if something whaky happens 2890 if (new Date() - startTime > 10000) { 2891 return; 2892 } 2893 2894 var iframes = document.querySelectorAll('iframe[title="recaptcha challenge"]'); 2895 if (iframes.length != captchaCount) { 2896 setTimeout(function() { 2897 setZIndex(captchaCount, startTime); 2898 }, 500); 2899 } 2900 2901 for (var i = 0; i < iframes.length; i++) { 2902 // incident subscribe modal is 1050, so this has to be above that 2903 iframes[i].parentElement.parentElement.style.zIndex = "1100"; 2904 } 2905 } 2906 2907 function updateCaptchaIframeTitle(captchaCount, startTime, updates=0) { 2908 2909 if (new Date() - startTime > 10000 || captchaCount === updates) { 2910 return; 2911 } 2912 var iframesWithTitle = document.querySelectorAll('iframe[title="recaptcha challenge expires in two minutes"]'); 2913 2914 if (iframesWithTitle.length != captchaCount) { 2915 setTimeout(function() { 2916 updateCaptchaIframeTitle(captchaCount, startTime, iframesWithTitle.length + updates); 2917 }, 500); 2918 } 2919 2920 for (var i = 0; i < iframesWithTitle.length; i++) { 2921 iframesWithTitle[i].title = "recaptcha"; 2922 } 2923 } 2924 2925 function addIncidentCaptcha() { 2926 var incidentCaptcha = document.createElement('div'); 2927 incidentCaptcha.setAttribute('id', 'subscribe-incident-recaptcha'); 2928 incidentCaptcha.setAttribute('class', 'g-recaptcha'); 2929 incidentCaptcha.setAttribute('data-sitekey', '6LcZ-b0UAAAAAENi956aWzynTT2ZJ80dGU3F80Op'); 2930 incidentCaptcha.setAttribute('data-callback', 'submitIncidentSubscriberSuccess'); 2931 incidentCaptcha.setAttribute('data-error-callback', 'submitIncidentSubscriberError'); 2932 incidentCaptcha.setAttribute('data-size', 'invisible'); 2933 document.body.appendChild(incidentCaptcha); 2934 var incidentCode = document.createElement('input'); 2935 incidentCode.setAttribute('type', 'hidden'); 2936 incidentCode.setAttribute('id', 'submit_incident_code'); 2937 document.body.appendChild(incidentCode); 2938 } 2939 2940 var onloadCallback = function() { 2941 // if there is an incident, then add incident captcha element 2942 if (document.getElementsByClassName('modal-open-incident-subscribe').length > 0) { 2943 addIncidentCaptcha(); 2944 } 2945 2946 var captchas = document.getElementsByClassName("g-recaptcha"); 2947 2948 for(var i = 0; i < captchas.length; i++) { 2949 var elId = captchas[i].id; 2950 recaptchaIds[elId] = grecaptcha.enterprise.render(elId); 2951 } 2952 2953 setZIndex(captchas.length, new Date()); 2954 updateCaptchaIframeTitle(captchas.length, new Date()); 2955 } 2956 2957 2958 /** SUBSCRIBE DROPDOWN */ 2959 2960 // callbacks for captcha success 2961 function submitNewSubscriber(type, error) { 2962 if (error) document.querySelector('#subscribe-form-' + type + ' #captcha_error').value = 'true'; 2963 2964 document.getElementById('subscribe-form-' + type).dispatchEvent(new Event('submit', {bubbles: true, cancelable: true})); 2965 grecaptcha.enterprise.reset(recaptchaIds['subscribe-btn-' + type]); 2966 } 2967 function submitNewEmailSubscriber(token) { 2968 submitNewSubscriber('email'); 2969 } 2970 function submitNewSmsSubscriber(token) { 2971 submitNewSubscriber('sms'); 2972 } 2973 function submitNewWebhookSubscriber(token) { 2974 submitNewSubscriber('webhook'); 2975 } 2976 function submitIncidentSubscriber(token, error, incidentCodeOverride) { 2977 var incidentCode = incidentCodeOverride; 2978 if (!incidentCode) { 2979 var incidentCodeEl = document.getElementById('submit_incident_code'); 2980 incidentCode = incidentCodeEl && incidentCodeEl.value; 2981 } 2982 var incidentForm = incidentCode && document.getElementById('subscribe-form-' + incidentCode); 2983 if (!incidentForm) { 2984 return; 2985 } 2986 2987 var captchaError = incidentForm.querySelector('input[name="captcha_error"]'); 2988 var recaptchaResponse = incidentForm.querySelector('input[name="g-recaptcha-response"]'); 2989 if (captchaError) { 2990 captchaError.value = error; 2991 } 2992 if (recaptchaResponse) { 2993 recaptchaResponse.value = token; 2994 } 2995 incidentForm.dispatchEvent(new Event('submit', {bubbles: true, cancelable: true})); 2996 if (window.grecaptcha && grecaptcha.enterprise && recaptchaIds['subscribe-incident-recaptcha'] != null) { 2997 grecaptcha.enterprise.reset(recaptchaIds['subscribe-incident-recaptcha']); 2998 } 2999 } 3000 function submitIncidentSubscriberSuccess(token) { 3001 submitIncidentSubscriber(token, 'false'); 3002 } 3003 3004 // callbacks if we get captcha network errors 3005 function emailSubscriberCaptchaError(token) { 3006 submitNewSubscriber('email', true); 3007 } 3008 function smsSubscriberCaptchaError(token) { 3009 submitNewSubscriber('sms', true); 3010 } 3011 function webhookSubscriberCaptchaError(token) { 3012 submitNewSubscriber('webhook', true); 3013 } 3014 function submitIncidentSubscriberError(token) { 3015 submitIncidentSubscriber(token, 'true'); 3016 } 3017 3018 // tracking clicks 3019 ['email', 'sms', 'webhook'].forEach(function(type) { 3020 var el = document.getElementById('subscribe-btn-' + type); 3021 el && el.addEventListener("click", function() { 3022 $.ajax({ 3023 type: "POST", 3024 url: "/subscriptions/track_attempt", 3025 data: { 3026 type: type 3027 } 3028 }) 3029 }) 3030 }) 3031 3032 // form submission success callbacks 3033 $('#subscribe-form-email').on('ajax:success', function(e, data, status, xhr){ 3034 if (data.type === 'success') { 3035 SP.currentPage.updatesDropdown.hide(); 3036 var emailField = document.getElementById('email'); 3037 if (emailField) { 3038 emailField.value = ''; 3039 } 3040 } 3041 }); 3042 $('#subscribe-form-sms').on('ajax:success', function(e, data, status, xhr){ 3043 if (data.type === 'success' && data.otp_flow !== true) { 3044 SP.currentPage.updatesDropdown.hide(); 3045 var phoneField = document.getElementById('phone-number'); 3046 if (phoneField) { 3047 phoneField.value = ''; 3048 } 3049 } 3050 }); 3051 $('#subscribe-form-webhook').on('ajax:success', function(e, data, status, xhr){ 3052 if (data.type === 'success') { 3053 SP.currentPage.updatesDropdown.hide(); 3054 document.getElementById('endpoint-webhooks').value = ''; 3055 document.getElementById('email-webhooks').value = ''; 3056 } 3057 }); 3058 3059 $('a.subscribe').on('click', function() { 3060 document.body.style.overflow = "hidden"; 3061 document.body.style.height = "100vh"; 3062 }); 3063 3064 $('div.modal-open-incident-subscribe').on('hidden', function(){ 3065 document.body.style.overflow = ""; 3066 document.body.style.height = ""; 3067 }); 3068 3069 function submitCaptchaIncidentSubscribe(event) { 3070 var incidentCode = event.target.id.split('-')[2]; 3071 event.preventDefault(); 3072 3073 $.ajax({ 3074 type: "POST", 3075 url: "/subscriptions/track_attempt", 3076 data: { 3077 type: 'incident' 3078 } 3079 }) 3080 3081 var incidentCodeField = document.getElementById('submit_incident_code'); 3082 if (incidentCodeField) { 3083 incidentCodeField.value = incidentCode; 3084 } 3085 3086 // Recaptcha's onloadCallback is what creates #submit_incident_code and the 3087 // widget id. If the enterprise.js script is blocked (ad blockers, CI url 3088 // blacklist), execute() and .value on a null node throw and the subscribe 3089 // click never reaches the server. 3090 var recaptchaId = recaptchaIds['subscribe-incident-recaptcha']; 3091 if (window.grecaptcha && grecaptcha.enterprise && typeof grecaptcha.enterprise.execute === 'function' && recaptchaId != null) { 3092 grecaptcha.enterprise.execute(recaptchaId); 3093 } else { 3094 submitIncidentSubscriber('', 'true', incidentCode); 3095 } 3096 } 3097</script>
vendor: 135 bytes, lines 3097-3103
3097 3098 3099<script src='https://www.recaptcha.net/recaptcha/enterprise.js?onload=onloadCallback&render=explicit' async defer></script> 3100 3101 3102 3103
3103<script src="https://dka575ofm4ao0.cloudfront.net/packs/common-b57e85f6a60348cdd566.chunk.js"></script>
3103 3104
3104<script src="https://dka575ofm4ao0.cloudfront.net/packs/globals-79d49f8cfe179f020629.chunk.js"></script>
3104 3105 3106
3106<script src="https://dka575ofm4ao0.cloudfront.net/packs/runtime-e9fe27ac357824763c7d.js"></script>
3106 3107 3108 3109 3110 3111
3111<script> 3112 window.addEventListener('load', function () { 3113 const urlParams = new URLSearchParams(window.location.search); 3114 const messageToken = urlParams.get('slack_message_token'); 3115 const channelName = escape(urlParams.get('channel_name')); 3116 3117 if(!!messageToken) { 3118 switch(messageToken) { 3119 case 'slack_auth_error': 3120 HRB.utils.notify('The Slack authorization attempt was unsuccessful. Try again.', {cssClass:'error'}); 3121 break; 3122 case 'subscribers_disabled_error': 3123 HRB.utils.notify('Slack subscriptions are not enabled on this page.', {cssClass:'error'}); 3124 break; 3125 case 'direct_message_channel_error': 3126 HRB.utils.notify('Subscriptions arenât supported in direct messages. Try subscribing again and choose a channel instead.', {cssClass:'error'}); 3127 break 3128 case 'duplicate_error': 3129 HRB.utils.notify("You're already subscribed to get Slack notifications in that channel.", {cssClass:'error'}); 3130 break; 3131 case 'duplicate_private_channel_error': 3132 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'}); 3133 break; 3134 case 'default_success': 3135 HRB.utils.notify("You're now subscribed to get Statuspage updates in Slack!", {cssClass:'success'}); 3136 break; 3137 case 'private_channel_success': 3138 HRB.utils.notify(`IMPORTANT: Invite the @Statuspage app to your Slack channel #${channelName} to start getting status updates.`, {cssClass:'success'}); 3139 break; 3140 } 3141 } 3142 }); 3143</script>
3143 3144 3145 3146<!-- FOR FLASH NOTICES --> 3147 3148<!-- FOR ERROR --> 3149 3150 3151
3151<script> 3152 $(function() { 3153 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.traviscistatus.com&utm_content=SP-notifications&utm_medium=powered-by&utm_source=inapp">Powered by Atlassian Statuspage</a></span>'); 3154 3155 var setPoweredByStyles = function() { 3156 if (!$('.powered-by').length) { 3157 $link.appendTo($('.page-footer')) 3158 } 3159 $('.powered-by').attr('style', 'display: inline !important; visibility:visible !important; opacity: 1 !important; position:static !important; text-indent:0px !important; transform:scale(1) !important'); 3160 } 3161 3162 setInterval(setPoweredByStyles, 1000); 3163 }); 3164</script>
3164 3165 3166 3167 3168 3169 3170 </body> 3171</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.