From 3d7cd4f99ef66a829926eef815b12b76b20e3a59 Mon Sep 17 00:00:00 2001 From: David Mason Date: Fri, 12 Jun 2015 12:13:29 +1000 Subject: [PATCH] Update zanata-spa to commit 7d6c54600db4d8b747f8a919b1aa2fd89b1f6824 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes: - Add 100% height to editor wrapper so background is 100% in firefox - Fix dropdown/transunit overflow problems - Applying difference properties to the right elements… again. --- zanata-war/src/main/webapp/app/css/app.css | 2 +- zanata-war/src/main/webapp/app/js/app.js | 4 ++-- zanata-war/src/main/webapp/app/js/templates.js | 4 ++-- zanata-war/src/main/webapp/app/maps/app.js.map | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/zanata-war/src/main/webapp/app/css/app.css b/zanata-war/src/main/webapp/app/css/app.css index 542bd686ad..42877fae53 100644 --- a/zanata-war/src/main/webapp/app/css/app.css +++ b/zanata-war/src/main/webapp/app/css/app.css @@ -1 +1 @@ -.u-cf:before,.u-cf:after{content:" ";display:table}.u-cf:after{clear:both}.u-nbfc{overflow:hidden!important}.u-nbfcAlt{display:table-cell!important;width:10000px!important}.u-floatLeft{float:left!important}.u-floatRight{float:right!important}@media (min-width:0) and (max-width:740px){.u-sm-floatNone{clear:both;float:none!important}}.u-bgFaint{opacity:.9}.u-bgHigh{background-color:#f5f6f7}.u-bgHigher{background-color:#fbfcfc}.u-bgHighest{background-color:#fff}.u-bgLow{background-color:#e5e8e9}.u-bgLower{background-color:#dee1e2}.u-bgLowest{background-color:#d7d9da}.u-bgPop{border:1px solid rgba(32,113,138,.12);border-bottom-width:2px}.u-bgNeutral{background-color:#ECEFF0}.u-bgPrimary{background-color:#03A6D7}.u-bgSecondary{background-color:#20718A}.u-bgDanger{background-color:#ffd8d8}.u-bgWarning{background-color:#fec}.u-bgUnsure{background-color:#fdfce8}.u-bgSuccess{background-color:#def4e5}.u-bgHighlight{background-color:#cdedf7}.u-block{display:block!important}.u-hidden{display:none!important}.u-hiddenVisually{position:absolute!important;overflow:hidden!important;width:1px!important;height:1px!important;padding:0!important;border:0!important;clip:rect(1px,1px,1px,1px)!important}.u-inline{display:inline!important}.u-inlineBlock{display:inline-block!important;max-width:100%}.u-table{display:table!important}.u-tableCell{display:table-cell!important}.u-tableRow{display:table-row!important}.u-round{border-radius:1000px!important}.u-round,.u-roundish{overflow:hidden!important}.u-roundish{border-radius:.5625rem!important}.u-rounded{border-radius:1.125rem!important;overflow:hidden!important}@media (min-width:0) and (max-width:740px){.u-sm-hidden{display:none!important}}@media (min-width:741px) and (max-width:960px){.u-md-hidden{display:none!important}}@media (max-width:960px){.u-ltemd-hidden{display:none!important}}@media (min-width:741px){.u-gtemd-hidden{display:none!important}}@media (min-width:961px) and (max-width:1270px){.u-lg-hidden{display:none!important}}@media (min-width:961px){.u-gtelg-hidden{display:none!important}}.u-dlUnstyled>dd{margin-left:0}.u-dlInline dt,.u-dlInline dd{display:inline-block;margin-right:.1875rem;margin-left:0}.u-listUnstyled{margin-bottom:0;padding-left:0;list-style:none}.u-listUnstyled>li{margin-left:0;list-style:none}.u-listInline{margin-left:-.1875rem;padding-left:0;list-style:none}.u-listInline>li{display:inline-block;padding-right:.1875rem;padding-left:.1875rem}.u-listHorizontal{font-size:0;list-style:none}.u-listHorizontal>li{font-size:1rem;display:inline-block;vertical-align:top}.u-posAbsolute,.u-posAbsoluteCenter{position:absolute!important}.u-posAbsoluteCenter{bottom:0!important;left:0!important;margin:auto!important;right:0!important;top:0!important}.u-posFixed{position:fixed!important;-webkit-backface-visibility:hidden;backface-visibility:hidden}.u-posRelative{position:relative!important}.u-posStatic{position:static!important}.u-posAbsoluteLeft{left:0!important}.u-posAbsoluteLeft,.u-posAbsoluteRight{bottom:0!important;position:absolute!important;top:0!important}.u-posAbsoluteRight{right:0!important}.u-posCenterCenter{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.u-sizeFit{display:block!important;float:left!important;width:auto!important}.u-sizeFitAlt{float:right!important}.u-sizeFitAlt,.u-sizeFill{display:block!important;width:auto!important}.u-sizeFill{overflow:hidden!important}.u-sizeFillAlt{display:table-cell!important;max-width:100%!important;width:10000px!important}.u-sizeFull{box-sizing:border-box!important;display:block!important;width:100%!important}.u-size1of12{width:8.333333333333332%!important}.u-size1of10{width:10%!important}.u-size1of8{width:12.5%!important}.u-size1of6,.u-size2of12{width:16.666666666666664%!important}.u-size1of5,.u-size2of10{width:20%!important}.u-size1of4,.u-size2of8,.u-size3of12{width:25%!important}.u-size3of10{width:30%!important}.u-size1of3,.u-size2of6,.u-size4of12{width:33.33333333333333%!important}.u-size3of8{width:37.5%!important}.u-size2of5,.u-size4of10{width:40%!important}.u-size5of12{width:41.66666666666667%!important}.u-size1of2,.u-size2of4,.u-size3of6,.u-size4of8,.u-size5of10,.u-size6of12{width:50%!important}.u-size7of12{width:58.333333333333336%!important}.u-size3of5,.u-size6of10{width:60%!important}.u-size5of8{width:62.5%!important}.u-size2of3,.u-size4of6,.u-size8of12{width:66.66666666666666%!important}.u-size7of10{width:70%!important}.u-size3of4,.u-size6of8,.u-size9of12{width:75%!important}.u-size4of5,.u-size8of10{width:80%!important}.u-size5of6,.u-size10of12{width:83.33333333333334%!important}.u-size7of8{width:87.5%!important}.u-size9of10{width:90%!important}.u-size11of12{width:91.66666666666666%!important}@media (min-width:0) and (max-width:740px){.u-sm-sizeFit{display:block!important;float:left!important;width:auto!important}.u-sm-sizeFitAlt{float:right!important}.u-sm-sizeFitAlt,.u-sm-sizeFill{display:block!important;width:auto!important}.u-sm-sizeFill{overflow:hidden!important}.u-sm-sizeFillAlt{display:table-cell!important;max-width:100%!important;width:10000px!important}.u-sm-sizeFull{box-sizing:border-box!important;display:block!important;width:100%!important}.u-sm-size1of12{width:8.333333333333332%!important}.u-sm-size1of10{width:10%!important}.u-sm-size1of8{width:12.5%!important}.u-sm-size1of6,.u-sm-size2of12{width:16.666666666666664%!important}.u-sm-size1of5,.u-sm-size2of10{width:20%!important}.u-sm-size1of4,.u-sm-size2of8,.u-sm-size3of12{width:25%!important}.u-sm-size3of10{width:30%!important}.u-sm-size1of3,.u-sm-size2of6,.u-sm-size4of12{width:33.33333333333333%!important}.u-sm-size3of8{width:37.5%!important}.u-sm-size2of5,.u-sm-size4of10{width:40%!important}.u-sm-size5of12{width:41.66666666666667%!important}.u-sm-size1of2,.u-sm-size2of4,.u-sm-size3of6,.u-sm-size4of8,.u-sm-size5of10,.u-sm-size6of12{width:50%!important}.u-sm-size7of12{width:58.333333333333336%!important}.u-sm-size3of5,.u-sm-size6of10{width:60%!important}.u-sm-size5of8{width:62.5%!important}.u-sm-size2of3,.u-sm-size4of6,.u-sm-size8of12{width:66.66666666666666%!important}.u-sm-size7of10{width:70%!important}.u-sm-size3of4,.u-sm-size6of8,.u-sm-size9of12{width:75%!important}.u-sm-size4of5,.u-sm-size8of10{width:80%!important}.u-sm-size5of6,.u-sm-size10of12{width:83.33333333333334%!important}.u-sm-size7of8{width:87.5%!important}.u-sm-size9of10{width:90%!important}.u-sm-size11of12{width:91.66666666666666%!important}}@media (min-width:741px) and (max-width:960px){.u-md-sizeFit{display:block!important;float:left!important;width:auto!important}.u-md-sizeFitAlt{float:right!important}.u-md-sizeFitAlt,.u-md-sizeFill{display:block!important;width:auto!important}.u-md-sizeFill{overflow:hidden!important}.u-md-sizeFillAlt{display:table-cell!important;max-width:100%!important;width:10000px!important}.u-md-sizeFull{box-sizing:border-box!important;display:block!important;width:100%!important}.u-md-size1of12{width:8.333333333333332%!important}.u-md-size1of10{width:10%!important}.u-md-size1of8{width:12.5%!important}.u-md-size1of6,.u-md-size2of12{width:16.666666666666664%!important}.u-md-size1of5,.u-md-size2of10{width:20%!important}.u-md-size1of4,.u-md-size2of8,.u-md-size3of12{width:25%!important}.u-md-size3of10{width:30%!important}.u-md-size1of3,.u-md-size2of6,.u-md-size4of12{width:33.33333333333333%!important}.u-md-size3of8{width:37.5%!important}.u-md-size2of5,.u-md-size4of10{width:40%!important}.u-md-size5of12{width:41.66666666666667%!important}.u-md-size1of2,.u-md-size2of4,.u-md-size3of6,.u-md-size4of8,.u-md-size5of10,.u-md-size6of12{width:50%!important}.u-md-size7of12{width:58.333333333333336%!important}.u-md-size3of5,.u-md-size6of10{width:60%!important}.u-md-size5of8{width:62.5%!important}.u-md-size2of3,.u-md-size4of6,.u-md-size8of12{width:66.66666666666666%!important}.u-md-size7of10{width:70%!important}.u-md-size3of4,.u-md-size6of8,.u-md-size9of12{width:75%!important}.u-md-size4of5,.u-md-size8of10{width:80%!important}.u-md-size5of6,.u-md-size10of12{width:83.33333333333334%!important}.u-md-size7of8{width:87.5%!important}.u-md-size9of10{width:90%!important}.u-md-size11of12{width:91.66666666666666%!important}}@media (min-width:961px) and (max-width:1270px){.u-lg-sizeFit{display:block!important;float:left!important;width:auto!important}.u-lg-sizeFitAlt{float:right!important}.u-lg-sizeFitAlt,.u-lg-sizeFill{display:block!important;width:auto!important}.u-lg-sizeFill{overflow:hidden!important}.u-lg-sizeFillAlt{display:table-cell!important;max-width:100%!important;width:10000px!important}.u-lg-sizeFull{box-sizing:border-box!important;display:block!important;width:100%!important}.u-lg-size1of12{width:8.333333333333332%!important}.u-lg-size1of10{width:10%!important}.u-lg-size1of8{width:12.5%!important}.u-lg-size1of6,.u-lg-size2of12{width:16.666666666666664%!important}.u-lg-size1of5,.u-lg-size2of10{width:20%!important}.u-lg-size1of4,.u-lg-size2of8,.u-lg-size3of12{width:25%!important}.u-lg-size3of10{width:30%!important}.u-lg-size1of3,.u-lg-size2of6,.u-lg-size4of12{width:33.33333333333333%!important}.u-lg-size3of8{width:37.5%!important}.u-lg-size2of5,.u-lg-size4of10{width:40%!important}.u-lg-size5of12{width:41.66666666666667%!important}.u-lg-size1of2,.u-lg-size2of4,.u-lg-size3of6,.u-lg-size4of8,.u-lg-size5of10,.u-lg-size6of12{width:50%!important}.u-lg-size7of12{width:58.333333333333336%!important}.u-lg-size3of5,.u-lg-size6of10{width:60%!important}.u-lg-size5of8{width:62.5%!important}.u-lg-size2of3,.u-lg-size4of6,.u-lg-size8of12{width:66.66666666666666%!important}.u-lg-size7of10{width:70%!important}.u-lg-size3of4,.u-lg-size6of8,.u-lg-size9of12{width:75%!important}.u-lg-size4of5,.u-lg-size8of10{width:80%!important}.u-lg-size5of6,.u-lg-size10of12{width:83.33333333333334%!important}.u-lg-size7of8{width:87.5%!important}.u-lg-size9of10{width:90%!important}.u-lg-size11of12{width:91.66666666666666%!important}}.u-sizeWidth-1-4{width:.375rem!important}.u-sizeWidth-1-2{width:.75rem!important}.u-sizeWidth-3-4{width:1.125rem!important}.u-sizeWidth-1{width:1.5rem!important}.u-sizeWidth-1_1-2{width:2.25rem!important}.u-sizeWidth-2{width:3rem!important}.u-sizeWidth-6{width:9rem!important}.u-sizeHeight-1-4{height:.375rem!important}.u-sizeHeight-1-2{height:.75rem!important}.u-sizeHeight-3-4{height:1.125rem!important}.u-sizeHeight-1{height:1.5rem!important}.u-sizeHeight-1_1-4{height:1.875rem!important}.u-sizeHeight-1_1-2{height:2.25rem!important}.u-sizeHeight-2{height:3rem!important}.u-sizeLineHeight-1-4{line-height:.375rem!important}.u-sizeLineHeight-1-2{line-height:.75rem!important}.u-sizeLineHeight-3-4{line-height:1.125rem!important}.u-sizeLineHeight-1{line-height:1.5rem!important}.u-sizeLineHeight-1_1-4{line-height:1.875rem!important}.u-sizeLineHeight-1_1-2{line-height:2.25rem!important}.u-sizeLineHeight-2{line-height:3rem!important}.u-sM-1-8{margin:.1875rem!important}.u-sM-1-4{margin:.375rem!important}.u-sM-1-2{margin:.75rem!important}.u-sM-3-4{margin:1.125rem!important}.u-sM-1{margin:1.5rem!important}.u-sM-1_1-2{margin:2.25rem!important}.u-sM-2{margin:3rem!important}.u-sMT-1-8{margin-top:.1875rem!important}.u-sMT-1-4{margin-top:.375rem!important}.u-sMT-1-2{margin-top:.75rem!important}.u-sMT-3-4{margin-top:1.125rem!important}.u-sMT-1{margin-top:1.5rem!important}.u-sMT-1_1-2{margin-top:2.25rem!important}.u-sMT-2{margin-top:3rem!important}.u-sMR-1-4{margin-right:.375rem!important}.u-sMR-1-2{margin-right:.75rem!important}.u-sMR-3-4{margin-right:1.125rem!important}.u-sMR-1{margin-right:1.5rem!important}.u-sMR-1_1-2{margin-right:2.25rem!important}.u-sMR-2{margin-right:3rem!important}.u-sMB-1-4{margin-bottom:.375rem!important}.u-sMB-1-2{margin-bottom:.75rem!important}.u-sMB-3-4{margin-bottom:1.125rem!important}.u-sMB-1{margin-bottom:1.5rem!important}.u-sMB-1_1-2{margin-bottom:2.25rem!important}.u-sMB-2{margin-bottom:3rem!important}.u-sML-1-4{margin-left:.375rem!important}.u-sML-1-2{margin-left:.75rem!important}.u-sML-3-4{margin-left:1.125rem!important}.u-sML-1{margin-left:1.5rem!important}.u-sML-1_1-2{margin-left:2.25rem!important}.u-sML-2{margin-left:3rem!important}.u-sMV-1-4{margin-top:.375rem!important;margin-bottom:.375rem!important}.u-sMV-1-2{margin-top:.75rem!important;margin-bottom:.75rem!important}.u-sMV-3-4{margin-top:1.125rem!important;margin-bottom:1.125rem!important}.u-sMV-1{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.u-sMV-1_1-2{margin-top:2.25rem!important;margin-bottom:2.25rem!important}.u-sMV-2{margin-top:3rem!important;margin-bottom:3rem!important}.u-sMH-1-4{margin-left:.375rem!important;margin-right:.375rem!important}.u-sMH-1-2{margin-left:.75rem!important;margin-right:.75rem!important}.u-sMH-3-4{margin-left:1.125rem!important;margin-right:1.125rem!important}.u-sMH-1{margin-left:1.5rem!important;margin-right:1.5rem!important}.u-sMH-1_1-2{margin-left:2.25rem!important;margin-right:2.25rem!important}.u-sMH-2{margin-left:3rem!important;margin-right:3rem!important}.u-sP-1-4{padding:.375rem!important}.u-sP-1-2{padding:.75rem!important}.u-sP-3-4{padding:1.125rem!important}.u-sP-1{padding:1.5rem!important}.u-sP-1_1-2{padding:2.25rem!important}.u-sP-2{padding:3rem!important}.u-sPT-1-4{padding-top:.375rem!important}.u-sPT-1-2{padding-top:.75rem!important}.u-sPT-3-4{padding-top:1.125rem!important}.u-sPT-1{padding-top:1.5rem!important}.u-sPT-1_1-2{padding-top:2.25rem!important}.u-sPT-2{padding-top:3rem!important}.u-sPR-1-4{padding-right:.375rem!important}.u-sPR-1-2{padding-right:.75rem!important}.u-sPR-3-4{padding-right:1.125rem!important}.u-sPR-1{padding-right:1.5rem!important}.u-sPR-1_1-2{padding-right:2.25rem!important}.u-sPR-2{padding-right:3rem!important}.u-sPB-1-4{padding-bottom:.375rem!important}.u-sPB-1-2{padding-bottom:.75rem!important}.u-sPB-3-4{padding-bottom:1.125rem!important}.u-sPB-1{padding-bottom:1.5rem!important}.u-sPB-1_1-2{padding-bottom:2.25rem!important}.u-sPB-2{padding-bottom:3rem!important}.u-sPL-1-4{padding-left:.375rem!important}.u-sPL-1-2{padding-left:.75rem!important}.u-sPL-3-4{padding-left:1.125rem!important}.u-sPL-1{padding-left:1.5rem!important}.u-sPL-1_1-2{padding-left:2.25rem!important}.u-sPL-2{padding-left:3rem!important}.u-sPV-1-4{padding-top:.375rem!important;padding-bottom:.375rem!important}.u-sPV-1-2{padding-top:.75rem!important;padding-bottom:.75rem!important}.u-sPV-3-4{padding-top:1.125rem!important;padding-bottom:1.125rem!important}.u-sPV-1{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.u-sPV-1_1-2{padding-top:2.25rem!important;padding-bottom:2.25rem!important}.u-sPV-2{padding-top:3rem!important;padding-bottom:3rem!important}.u-sPH-1-4{padding-left:.375rem!important;padding-right:.375rem!important}.u-sPH-1-2{padding-left:.75rem!important;padding-right:.75rem!important}.u-sPH-3-4{padding-left:1.125rem!important;padding-right:1.125rem!important}.u-sPH-1{padding-left:1.5rem!important;padding-right:1.5rem!important}.u-sPH-1_1-2{padding-left:2.25rem!important;padding-right:2.25rem!important}.u-sPH-2{padding-left:3rem!important;padding-right:3rem!important}.u-textBreak{word-wrap:break-word!important}.u-textCenter{text-align:center!important}.u-textLeft{text-align:left!important}.u-textRight{text-align:right!important}.u-textInheritColor{color:inherit!important}.u-textKern{text-rendering:optimizeLegibility;-webkit-font-feature-settings:"kern" 1;-moz-font-feature-settings:"kern" 1;font-feature-settings:"kern" 1;-webkit-font-kerning:normal;-moz-font-kerning:normal;font-kerning:normal}.u-textNoWrap,.u-textTruncate{white-space:nowrap!important}.u-textTruncate{max-width:100%;overflow:hidden!important;text-overflow:ellipsis!important;word-wrap:normal!important}.u-textUpper{text-transform:uppercase}.u-textLower{text-transform:lowercase}.u-textCapitalize{text-transform:capitalize}.u-textInvert{color:#f2f2f2}.u-textMuted{opacity:.6}.u-textEmpty{color:#90b8c5;font-weight:600}.u-textMicro{font-size:.75rem}.u-textMini,.u-textMeta{font-size:.875rem}.u-textMeta{color:#90b8c5}.u-textLead{font-size:1.5rem;font-weight:300}.u-textPrimary{color:#03A6D7}.u-textSecondary{color:#20718A}.u-textHighlight{color:#03A6D7}.u-textSuccess{color:#5CCA7B}.u-textUnsure{color:#E9DF1B}.u-textNeutral{color:#bcd4dc}.u-textWarning{color:#FFA800}.u-textDanger{color:#FF3B3D}.u-textPilcrow:before{content:'\00b6';color:#bcd4dc;padding:0 .1875rem}.u-textTab{position:relative;display:inline-block;width:1.2em;text-align:center}.u-textTab:before{content:'\21E5';color:#bcd4dc}.u-textSpace{position:relative}.u-textSpace:before{position:absolute;content:'.';color:#bcd4dc}.Grid{display:block;font-size:0;margin:0;padding:0;text-align:left}.Grid--alignCenter{text-align:center}.Grid--alignRight{text-align:right}.Grid--alignMiddle>.Grid-cell{vertical-align:middle}.Grid--alignBottom>.Grid-cell{vertical-align:bottom}.Grid--withGutter{margin:0 -10px}.Grid--withGutter>.Grid-cell{padding:0 10px}.Grid-cell{box-sizing:border-box;display:inline-block;font-size:1rem;margin:0;padding:0;text-align:left;vertical-align:top;width:100%}.Grid-cell--center{display:block;margin:0 auto}html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}hr{box-sizing:content-box;height:0}pre{overflow:auto}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}::-webkit-input-placeholder{color:#a9bfc6}:-moz-placeholder,::-moz-placeholder{color:#a9bfc6}:-ms-input-placeholder{color:#a9bfc6}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:none}button{background:0 0;border:0;padding:0;text-align:inherit}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button:hover,button:active{outline:none}fieldset{border:0;margin:0;padding:0}input[type="text"],input[type="password"],input[type="date"],input[type="datetime"],input[type="email"],input[type="number"],input[type="search"],input[type="tel"],input[type="time"],input[type="url"],textarea{-webkit-appearance:none;outline:none;box-sizing:border-box}@-ms-viewport{width:device-width}@viewport{width:device-width}html{font-family:'Source Sans Pro',"Helvetica Neue",HelveticaNeue,Helvetica,Arial,sans-serif;font-size:16px;line-height:1.5;box-sizing:border-box;color:#444c54}*,*:before,*:after{box-sizing:inherit}body{min-width:320px;background:#ECEFF0}:active,:hover{outline:none}h1,h2,h3,h4,h5,h6{font-size:16px;margin:0;color:#20718A}a{color:#03A6D7;text-decoration:none;cursor:pointer}a:hover{color:#0395c2}a:active{color:#0285ac}ol,ul{list-style:none;margin:0;padding:0}ul:empty,ol:empty{display:none}img{max-width:100%}svg:not(:root){overflow:hidden}figure{margin:0}figcaption{color:gray}hr{width:100%;border-bottom:1px solid;border-color:rgba(32,113,138,.12);margin:rhythm(1)0;background:0 0}hr,iframe{border:0}[tabindex="-1"]:focus{outline:none!important}code{font-family:Monaco,Courier,monospace;margin:0;padding:0 .1875rem}code,kbd,pre{font-size:.8125rem;font-weight:400;color:#4d4d4d}pre,samp{font-family:Monaco,Courier,monospace;padding:0 .1875rem}samp{font-size:.8125rem;font-weight:400;color:#4d4d4d}samp,blockquote,dl,dd,p,pre{margin:0}kbd{margin:0 .1875rem;padding:.1875rem .5625rem;border:1px solid rgba(65,105,136,.07);border-bottom:3px solid rgba(65,105,136,.2);border-radius:.375rem;background-color:#fff;background-clip:padding;white-space:nowrap;display:inline-block;text-transform:uppercase;font-family:'Source Sans Pro',"Helvetica Neue",HelveticaNeue,Helvetica,Arial,sans-serif}.ButtonGroup{display:block;font-size:0;margin:0;list-style:none;padding:0}.ButtonGroup-item{display:block;font-size:1rem}.ButtonGroup-item>.Button{display:block;width:100%}.ButtonGroup-item>.Button:hover,.ButtonGroup-item>.Button:focus,.ButtonGroup-item>.Button:active,.ButtonGroup-item>.Button.is-pressed{z-index:1}.ButtonGroup--hz>.ButtonGroup-item{display:inline-block}.ButtonGroup--borderCollapse:not(.ButtonGroup--hz)>.ButtonGroup-item{margin-top:0}.ButtonGroup--borderCollapse:not(.ButtonGroup--hz)>.ButtonGroup-item:first-child{margin-top:0}.ButtonGroup--borderCollapse:not(.ButtonGroup--hz)>.ButtonGroup-item:not(:first-child):not(:last-child)>.Button{border-radius:0}.ButtonGroup--borderCollapse:not(.ButtonGroup--hz)>.ButtonGroup-item:first-child:not(:only-child)>.Button{border-bottom-left-radius:0;border-bottom-right-radius:0}.ButtonGroup--borderCollapse:not(.ButtonGroup--hz)>.ButtonGroup-item:last-child:not(:only-child)>.Button{border-top-left-radius:0;border-top-right-radius:0}.ButtonGroup--borderCollapse.ButtonGroup--hz>.ButtonGroup-item{margin-left:0}.ButtonGroup--borderCollapse.ButtonGroup--hz>.ButtonGroup-item:first-child{margin-left:0}.ButtonGroup--borderCollapse.ButtonGroup--hz>.ButtonGroup-item:not(:first-child):not(:last-child)>.Button{border-radius:0}.ButtonGroup--borderCollapse.ButtonGroup--hz>.ButtonGroup-item:first-child:not(:only-child)>.Button{border-bottom-right-radius:0;border-top-right-radius:0}.ButtonGroup--borderCollapse.ButtonGroup--hz>.ButtonGroup-item:last-child:not(:only-child)>.Button{border-bottom-left-radius:0;border-top-left-radius:0}.ButtonGroup--hz>.ButtonGroup-item{vertical-align:middle}.ButtonGroup--round .ButtonGroup-item:first-child .Button{border-top-left-radius:100px;border-bottom-left-radius:100px}.ButtonGroup--round .ButtonGroup-item:last-child .Button{border-top-right-radius:100px;border-bottom-right-radius:100px}.Button{-webkit-appearance:none;background:0 0;border-color:currentcolor;border-style:solid;border-width:0;box-sizing:border-box;color:transparent;cursor:pointer;display:inline-block;font:inherit;line-height:normal;margin:0;padding:.1875rem .75rem;position:relative;text-align:center;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;white-space:normal}.Button::-moz-focus-inner{border:0;padding:0}.Button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.Button:hover,.Button:focus,.Button:active{text-decoration:none}.Button:disabled,.Button.is-disabled{cursor:default;opacity:.6}.Button{-webkit-transition:all .25s cubic-bezier(.075,.82,.165,1);transition:all .25s cubic-bezier(.075,.82,.165,1);min-height:1.875rem;text-shadow:1px 1px 0 rgba(0,0,0,.15)}.Button:disabled,.Button.is-disabled{pointer-events:none}.Button:hover,.Button:active,.Button.is-active{outline:inherit}.Button--default{background-color:#deeaed}.Button--default:hover{background-color:#c8d3d5}.Button--default:active,.Button--default.is-active{background-color:#bdc7c9}.Button--primary{color:#fff;background-color:#03A6D7}.Button--primary:hover{background-color:#0395c2}.Button--primary:active,.Button--primary.is-active{background-color:#038db7}.Button--secondary{color:#fff;background-color:#20718A}.Button--secondary:hover{background-color:#1d667c}.Button--secondary:active,.Button--secondary.is-active{background-color:#1b6075}.Button--highlight{color:#fff;background-color:#03A6D7}.Button--highlight:hover{background-color:#0395c2}.Button--highlight:active,.Button--highlight.is-active{background-color:#038db7}.Button--success{color:#fff;background-color:#5CCA7B}.Button--success:hover{background-color:#53b66f}.Button--success:active,.Button--success.is-active{background-color:#4eac69}.Button--unsure{color:#fff;background-color:#E9DF1B}.Button--unsure:hover{background-color:#d2c918}.Button--unsure:active,.Button--unsure.is-active{background-color:#c6be17}.Button--neutral{color:#fff;background-color:#90b8c5}.Button--neutral:hover{background-color:#82a6b1}.Button--neutral:active,.Button--neutral.is-active{background-color:#7a9ca7}.Button--warning{color:#fff;background-color:#FFA800}.Button--warning:hover{background-color:#e69700}.Button--warning:active,.Button--warning.is-active{background-color:#d98f00}.Button--danger{color:#fff;background-color:#FF3B3D}.Button--danger:hover{background-color:#e63537}.Button--danger:active,.Button--danger.is-active{background-color:#d93234}.Button--invisible{background-color:transparent;color:#90b8c5}.Button--invisible:hover{background-color:#edf4f6;color:#639cad}.Button--invisible:active,.Button--invisible.is-active{color:#20718A;background-color:#e4eef1}.Button--snug{padding-left:.375rem;padding-right:.375rem}.Button--small{min-height:1.5rem;padding:.1875rem .75rem;font-size:.875rem}.InputGroup{position:relative;display:table;border-collapse:separate}.InputGroup-input,.InputGroup-addon,.InputGroup-button{display:table-cell;-webkit-transition:.2s cubic-bezier(.26,.47,.36,.94);transition:.2s cubic-bezier(.26,.47,.36,.94)}.InputGroup-input,.InputGroup-addon{background-color:transparent;padding:0 .375rem}.InputGroup-input{border:none;width:100%;color:#20718A}.InputGroup-addon{color:#639cad;text-align:center;width:1%;white-space:nowrap;vertical-align:middle}.InputGroup-addon:before{content:' '}.InputGroup.is-focused .InputGroup-input,.InputGroup.is-focused .InputGroup-addon{background-color:#fff}.InputGroup--bordered .InputGroup-input,.InputGroup--bordered .InputGroup-addon,.InputGroup--outlined .InputGroup-input,.InputGroup--outlined .InputGroup-addon{border-top:1px solid #a6c6d0;border-bottom:1px solid #a6c6d0}.InputGroup--bordered .InputGroup-input{border-left:1px solid #a6c6d0;border-right:1px solid #a6c6d0}.InputGroup--outlined .InputGroup-input:first-child,.InputGroup--outlined .InputGroup-addon:first-child{border-left:1px solid #a6c6d0}.InputGroup--outlined .InputGroup-input:last-child,.InputGroup--outlined .InputGroup-addon:last-child{border-right:1px solid #a6c6d0}.InputGroup--bordered.is-focused .InputGroup-input,.InputGroup--bordered.is-focused .InputGroup-addon,.InputGroup--outlined.is-focused .InputGroup-input,.InputGroup--outlined.is-focused .InputGroup-addon{border-color:#639cad}.InputGroup--rounded .InputGroup-input:first-child,.InputGroup--rounded .InputGroup-addon:first-child{border-bottom-left-radius:1.5rem;border-top-left-radius:1.5rem;padding-left:.5625rem}.InputGroup--rounded .InputGroup-input:last-child,.InputGroup--rounded .InputGroup-addon:last-child{border-bottom-right-radius:1.5rem;border-top-right-radius:1.5rem;padding-right:.5625rem}.Dropdown{position:relative;z-index:100;display:inline-block;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.Dropdown.is-active{z-index:900}.Dropdown-toggleIcon{display:inline-block;-webkit-transition:all .2s cubic-bezier(.175,.885,.32,1.275);transition:all .2s cubic-bezier(.175,.885,.32,1.275);text-align:center}.Dropdown.is-active .Dropdown-toggleIcon{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.Dropdown-content{position:absolute;z-index:800;top:100%;left:0;visibility:hidden;float:left;min-width:100%;margin:0;padding:0;-webkit-transition:all .2s cubic-bezier(.175,.885,.32,1.275);transition:all .2s cubic-bezier(.175,.885,.32,1.275);-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);text-align:left;opacity:0;background-color:#fff;background-clip:padding-box;box-shadow:0 0 1.5rem rgba(0,0,0,.1)}.Dropdown-content--Bordered{border:1px solid rgba(32,113,138,.12);border-bottom-width:2px}.Dropdown.is-active>.Dropdown-content{visibility:visible;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0);opacity:1}.Dropdown-title{font-size:.875rem;padding:.1875rem .375rem;background-color:transparent;border-bottom:1px solid rgba(32,113,138,.12);color:#79aab9}.Dropdown-item{display:block;padding:.1875rem .375rem;-webkit-transition:all .2s ease-out;transition:all .2s ease-out;color:#03A6D7}.Dropdown-item:hover{color:#fff;background-color:#03A6D7}.Dropdown--right .Dropdown-content{left:auto;right:0}.Header{background-color:#03A6D7;position:fixed;z-index:100;width:100%;top:0;box-shadow:0 .375rem 1.5rem rgba(0,0,0,.1)}.Header-item{height:3rem;display:inline-block;padding-top:.75rem;padding-bottom:.75rem}.Header-avatar{margin-top:.5625rem;margin-bottom:.5625rem;width:1.875rem;height:1.875rem;display:inline-block}.h1,.h2,.h3,.h4,.h5,.h6{font-family:'Source Sans Pro',"Helvetica Neue",HelveticaNeue,Helvetica,Arial,sans-serif;font-weight:600}.h1{font-size:36px}.h2{font-size:28px}.h3{font-size:24px}.h4{font-size:20px}.h5{font-size:18px}.h6{font-size:16px}.Heading--panel{font-size:1rem;font-weight:400;margin:0;text-transform:uppercase}.Icon{text-align:center;display:inline-block;-webkit-transition:.25s all cubic-bezier(.175,.885,.32,1.275);transition:.25s all cubic-bezier(.175,.885,.32,1.275)}.Icon.is-rotated{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.Icon-item{vertical-align:-25%;display:inline-block;width:1.5rem;height:1.5rem;fill:currentColor!important}.Icon--xlg .Icon-item{width:3rem;height:3rem}.Icon--lg .Icon-item{width:2.25rem;height:2.25rem}.Icon--sm .Icon-item{vertical-align:-15%;width:1.125rem;height:1.125rem}.Icon--xsm .Icon-item{vertical-align:-10%;width:.9375rem;height:.9375rem}.Icon--circle{position:relative;padding:.75rem}.Icon--circle:before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;border:2px solid;opacity:.2;border-radius:3rem}.Icon--circle.Icon--lg{border-width:3px}.Icon--circle.Icon--xlg{border-width:3px;padding:1.125rem}.Icon--circle.Icon--lg{padding:.9375rem}.Icon--circle.Icon--sm{border-width:1px;padding:.5625rem}.Icon--circle.Icon--xsm{border-width:1px;padding:.375rem}.Icon--stroked .Icon-item{fill:none;stroke:currentColor;stroke-width:3}.Icon--loader .Icon-item{position:relative}.Icon--loader-dot{position:absolute;left:0;top:36.1%;display:inline-block;width:27.8%;height:27.8%;-webkit-animation:bouncedelay .9s infinite cubic-bezier(.175,.885,.32,1.275);animation:bouncedelay .9s infinite cubic-bezier(.175,.885,.32,1.275);border-radius:3rem;background-color:currentColor;-webkit-animation-fill-mode:both;animation-fill-mode:both}.Icon--loader-dot:nth-of-type(2){left:36.1%;-webkit-animation-delay:.15s;animation-delay:.15s}.Icon--loader-dot:nth-of-type(3){right:0;left:auto;-webkit-animation-delay:.3s;animation-delay:.3s}@-webkit-keyframes bouncedelay{0%,90%,100%{-webkit-transform:scale(0,0);transform:scale(0,0);opacity:.2}40%{-webkit-transform:scale(1,1);transform:scale(1,1);opacity:1}}@keyframes bouncedelay{0%,90%,100%{-webkit-transform:scale(0,0);transform:scale(0,0);opacity:.2}40%{-webkit-transform:scale(1,1);transform:scale(1,1);opacity:1}}.Link{color:#03A6D7;text-decoration:none;cursor:pointer}.Link:hover{color:#0395c2}.Link:active{color:#0285ac}.Link--invert{opacity:.8}.Link--invert,.Link--invert:hover{color:#fff!important}.Link--invert:hover{opacity:1}.Link--invert:active,.Link--invert.is-active{opacity:.6}.Link--success{color:#5CCA7B!important}.Link--success:hover{color:#408d56 !important}.Link--success:active,.Link--success.is-active{color:#255131 !important}.Link--unsure{color:#E9DF1B!important}.Link--unsure:hover{color:#a39c13 !important}.Link--unsure:active,.Link--unsure.is-active{color:#5d590b !important}.Link--neutral{color:#bcd4dc !important}.Link--neutral:hover{color:#84949a !important}.Link--neutral:active,.Link--neutral.is-active{color:#4b5558 !important}.Link--warning{color:#FFA800!important}.Link--warning:hover{color:#b37600 !important}.Link--warning:active,.Link--warning.is-active{color:#664300 !important}.Link--danger{color:#FF3B3D!important}.Link--danger:hover{color:#b3292b !important}.Link--danger:active,.Link--danger.is-active{color:#661818 !important}.Difference{display:inline-block;padding:0 2px;border-radius:2px}.Difference ins{background-color:#c9eed3;text-decoration:none}.Difference del{background-color:#ffe0e0;text-decoration:none}.LogoLoader{position:relative;display:inline-block;margin-top:-.09375rem;width:2.4375rem;height:2.4375rem;color:#fff;border-radius:100px}.LogoLoader--inverted{color:#03A6D7}.LogoLoader-logo{-webkit-transition:all .25s cubic-bezier(.175,.885,.32,1.275);transition:all .25s cubic-bezier(.175,.885,.32,1.275);fill:currentColor}.LogoLoader-logo,.LogoLoader-svg{position:absolute;top:0;left:0;right:0;bottom:0}.LogoLoader-svg{overflow:visible}.LogoLoader path{-webkit-transform-origin:50% 50% 0;-ms-transform-origin:50% 50% 0;transform-origin:50% 50% 0}.LogoLoader:hover .LogoLoader-z{-webkit-animation:pop .3s cubic-bezier(.175,.885,.32,1.275);animation:pop .3s cubic-bezier(.175,.885,.32,1.275);-webkit-animation-iteration-count:2;animation-iteration-count:2;-webkit-animation-direction:alternate;animation-direction:alternate}.LogoLoader-z{-webkit-transform:scale(1,1);-ms-transform:scale(1,1);transform:scale(1,1);-webkit-transition:all .25s cubic-bezier(.175,.885,.32,1.275);transition:all .25s cubic-bezier(.175,.885,.32,1.275)}.LogoLoader .LogoLoader-logo{-webkit-transform-origin:50% 50% 0;-ms-transform-origin:50% 50% 0;transform-origin:50% 50% 0}.LogoLoader .LogoLoader-circle,.LogoLoader .LogoLoader-circlePulse{-webkit-transform:scale(1,1);-ms-transform:scale(1,1);transform:scale(1,1)}.LogoLoader.is-loading .LogoLoader-z,.LogoLoader.is-loading .LogoLoader-circle{-webkit-animation:pulseBegin 1s infinite linear;animation:pulseBegin 1s infinite linear}.LogoLoader.is-loading .LogoLoader-circle,.LogoLoader.is-loading .LogoLoader-circlePulse{-webkit-animation-delay:.1s;animation-delay:.1s}.LogoLoader.is-loading .LogoLoader-circlePulse{-webkit-animation:pulse 1s infinite linear;animation:pulse 1s infinite linear}@-webkit-keyframes pulseBegin{0%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(.6);transform:scale(.6)}40%{-webkit-transform:scale(1.2);transform:scale(1.2)}60%,100%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes pulseBegin{0%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(.6);transform:scale(.6)}40%{-webkit-transform:scale(1.2);transform:scale(1.2)}60%,100%{-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes pulse{0%{opacity:0}0%,20%{-webkit-transform:scale(.6);transform:scale(.6)}40%{-webkit-transform:scale(1.2);transform:scale(1.2);opacity:.5}60%{-webkit-transform:scale(1.6);transform:scale(1.6);opacity:.7}100%{-webkit-transform:scale(2);transform:scale(2);opacity:0}}@keyframes pulse{0%{opacity:0}0%,20%{-webkit-transform:scale(.6);transform:scale(.6)}40%{-webkit-transform:scale(1.2);transform:scale(1.2);opacity:.5}60%{-webkit-transform:scale(1.6);transform:scale(1.6);opacity:.7}100%{-webkit-transform:scale(2);transform:scale(2);opacity:0}}@-webkit-keyframes pop{to{-webkit-transform:rotate(15deg)scale(1.1,1.1);transform:rotate(15deg)scale(1.1,1.1)}}@keyframes pop{to{-webkit-transform:rotate(15deg)scale(1.1,1.1);transform:rotate(15deg)scale(1.1,1.1)}}.Progressbar{position:relative;width:100%;height:.75rem;margin:0;background-color:#bcd4dc}.Progressbar--sm{height:.375rem}.Progressbar--lg{height:1.5rem}.Progressbar-item{position:absolute;left:0;z-index:100;margin:0;padding:0;width:100%;height:100%;list-style:none}.Progressbar-approved{background-color:#03A6D7;z-index:200}.Progressbar-translated{background-color:#5CCA7B}.Progressbar-needsWork{background-color:#E9DF1B}.Progressbar-untranslated{background-color:#bcd4dc}.Modal{position:fixed;z-index:1000;top:0;right:0;bottom:0;left:0;display:block;visibility:hidden;overflow:auto;overflow-y:scroll;width:100%;height:100%;margin:0 auto;padding:4.5rem 1.5rem 1.5rem;-webkit-transition:all .15s linear;transition:all .15s linear;opacity:0;background-color:rgba(236,239,240,.95);-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:75rem;perspective:75rem;-webkit-overflow-scrolling:touch}.Modal.is-active{visibility:visible;opacity:1}.Modal-dialog{position:relative;width:90%;top:50%;left:50%;max-height:100%;min-width:300px;max-width:45rem;-webkit-transition:all .25s cubic-bezier(.175,.885,.32,1.1);transition:all .25s cubic-bezier(.175,.885,.32,1.1);-webkit-transform:translateX(-50%)translateY(100%);-ms-transform:translateX(-50%)translateY(100%);transform:translateX(-50%)translateY(100%);-webkit-transform-origin:0;-ms-transform-origin:0;transform-origin:0;background-color:#f7f9f9}.Modal.is-active .Modal-dialog{-webkit-transform:translateX(-50%)translateY(-50%);-ms-transform:translateX(-50%)translateY(-50%);transform:translateX(-50%)translateY(-50%)}.Modal-header{position:fixed;top:-3rem;left:0;right:0;border:1px solid rgba(32,113,138,.12);background-color:#fff;z-index:100}.Modal-title{font-size:1.375rem;font-weight:300;line-height:1.5rem;margin:0;padding:.75rem 2.25rem .75rem 1.5rem}.Modal-close{position:absolute;top:0;right:0;width:3rem;height:3rem;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;text-align:center;border-left:1px solid rgba(32,113,138,.12)}.Modal-close:hover{background-color:rgba(32,113,138,.05)}.Modal-close:active{background-color:rgba(32,113,138,.1)}.Modal-content{position:relative;max-height:100%;overflow:auto;background-clip:padding-box;border:1px solid rgba(32,113,138,.12);border-top-color:transparent;border-bottom-width:2px}.Modal-container.is-modal{overflow:hidden;height:100%}.Toggle,.Toggle-label{cursor:pointer}.Toggle{position:relative;display:inline-block;min-width:2.0625rem;margin:0 .09375rem;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:top}.Toggle-checkbox{position:absolute;cursor:none;top:0;left:0;width:100%;height:100%;opacity:0}.Toggle-label{font-weight:600;display:block;position:relative;padding:0 .5625rem;-webkit-transition:all .25s cubic-bezier(.075,.82,.165,1);transition:all .25s cubic-bezier(.075,.82,.165,1);text-align:center;color:currentColor}.Toggle-fakeCheckbox{opacity:1;position:absolute;top:0;left:0;width:100%;height:100%;content:'';background-color:transparent}.Toggle:hover>.Toggle-fakeCheckbox,.Toggle-checkbox:focus~.Toggle-fakeCheckbox{background-color:currentColor;opacity:.2}.Toggle-checkbox:checked~.Toggle-label,.Toggle.is-active~.Toggle-label{color:#fff}.Toggle-checkbox:checked~.Toggle-fakeCheckbox,.Toggle.is-active>.Toggle-fakeCheckbox{background-color:currentColor}.Toggle:hover>.Toggle-checkbox:checked~.Toggle-fakeCheckbox,.Toggle-checkbox:checked:focus~.Toggle-fakeCheckbox,.Toggle.is-active:hover>.Toggle-fakeCheckbox{opacity:.8}.Switch{padding-left:2.25rem;position:relative}.Switch-checkbox{position:absolute;margin-left:-9999px;visibility:hidden}.Switch-label{cursor:pointer}.Switch-label:before,.Switch-label:after{content:'';position:absolute;left:0;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);border-radius:1.125rem;-webkit-transition:all .2s ease-out;transition:all .2s ease-out}.Switch-label:before{width:1.875rem;height:1.125rem;background-color:#d2e3e8}.Switch-label:after{width:1.125rem;height:1.125rem;background-color:#79aab9;border:1px solid transparent;-webkit-transform:translateY(-50%)scale(.8,.8);-ms-transform:translateY(-50%)scale(.8,.8);transform:translateY(-50%)scale(.8,.8)}.Switch-labelText{color:#79aab9;font-size:.875rem}.Switch-checkbox:checked~.Switch-label:before{background-color:#20718A}.Switch-checkbox:checked~.Switch-label:after{background-color:#fff;-webkit-transform:translateY(-50%)translateX(66%)scale(.8,.8);-ms-transform:translateY(-50%)translateX(66%)scale(.8,.8);transform:translateY(-50%)translateX(66%)scale(.8,.8)}.Switch-checkbox:checked~.Switch-label .Switch-labelText{color:#20718A}.TransUnit{position:relative;margin:0;padding:0;cursor:text;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border-bottom:1px solid rgba(32,113,138,.12)}.TransUnit:focus{outline:0;box-shadow:none}.TransUnit.is-focused{z-index:100!important;opacity:1!important;background-color:#fff}.TransUnit:before,.TransUnit:after{position:absolute;z-index:-1;left:0;visibility:hidden;width:100%;height:1.5rem;content:'';-webkit-transform:scaleY(0);-ms-transform:scaleY(0);transform:scaleY(0);opacity:0;background-color:#fff;background-clip:padding-box}.TransUnit:before{box-shadow:0 -.375rem .75rem rgba(0,0,0,.04);-webkit-transform-origin:bottom;-ms-transform-origin:bottom;transform-origin:bottom;top:-1.125rem}.TransUnit:after{box-shadow:0 .375rem .75rem rgba(0,0,0,.04);-webkit-transform-origin:top;-ms-transform-origin:top;transform-origin:top;bottom:-1.125rem}.TransUnit.is-focused:before,.TransUnit.is-focused:after{visibility:visible;-webkit-transform:scaleY(1);-ms-transform:scaleY(1);transform:scaleY(1);opacity:1}.TransUnit.is-first{border-top:1px solid rgba(32,113,138,.12)}.TransUnit-container.is-unit-selected .TransUnit{opacity:.8}.TransUnit-panel{padding-top:1.125rem;padding-bottom:1.125rem;padding-left:1.5rem;list-style:none;vertical-align:top}.TransUnit-panel,.TransUnit-item{position:relative}.TransUnit-source{cursor:pointer;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.TransUnit.is-focused .TransUnit-source{cursor:text}.TransUnit-translation{cursor:text;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.TransUnit-panelHeader,.TransUnit-panelFooter,.TransUnit-itemHeader{position:absolute;z-index:200;right:0;left:0;width:100%;padding-right:1.125rem;padding-left:1.125rem;cursor:default}.TransUnit-panelHeader,.TransUnit-panelFooter{visibility:hidden;opacity:0}.TransUnit.is-focused .TransUnit-panelHeader,.TransUnit.is-focused .TransUnit-panelFooter{visibility:visible;opacity:1}.TransUnit-panelHeader{top:-1.125rem}.TransUnit-itemHeader{top:0}.TransUnit-panelFooter{bottom:-1.125rem}.TransUnit-heading{font-size:1rem;font-weight:400;line-height:2.25rem;display:inline-block;float:left;margin:0;vertical-align:top;text-transform:uppercase}.TransUnit-text{font-family:'Source Sans Pro',"Helvetica Neue",HelveticaNeue,Helvetica,Arial,sans-serif;font-size:16px;line-height:1.5;overflow:hidden;width:100%;min-height:1.5rem;margin:0;padding:1.125rem;resize:none;-webkit-transition:height .1s cubic-bezier(.075,.82,.165,1);transition:height .1s cubic-bezier(.075,.82,.165,1);white-space:pre-wrap;word-wrap:break-word;-moz-tab-size:8;tab-size:8;color:#444c54;border:none;background-color:transparent;box-shadow:none;-webkit-appearance:none}.TransUnit-text:focus{border:none;outline:none;background-color:transparent}.TransUnit-text span{font-weight:400!important;font-style:normal!important}.TransUnit-status,.TransUnit-status:before,.TransUnit-status:after{position:absolute;z-index:200;left:0;width:1.5rem;background-color:#bcd4dc}.TransUnit-status{top:-1;bottom:-1}.TransUnit-status.is-loading,.TransUnit-status.is-loading:before{background-image:-webkit-repeating-linear-gradient(45deg,transparent,transparent .375rem,rgba(255,255,255,.5).375rem,rgba(255,255,255,.5).75rem);background-image:repeating-linear-gradient(45deg,transparent,transparent .375rem,rgba(255,255,255,.5).375rem,rgba(255,255,255,.5).75rem);background-size:100% 1000px;-webkit-animation:loading 7s linear;animation:loading 7s linear;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.TransUnit-status:before{top:-1.125rem;height:100%;padding-top:1.125rem;padding-bottom:1.125rem;box-sizing:content-box;z-index:300;visibility:hidden;content:'';-webkit-transform:scaleY(.65);-ms-transform:scaleY(.65);transform:scaleY(.65)}.TransUnit-status:after{-webkit-transition:none;transition:none;z-index:400;top:0;box-sizing:content-box;width:1.3125rem;height:100%;content:'';background-color:#fff;opacity:.6}.TransUnit.is-focused .TransUnit-status:before{visibility:visible;-webkit-transform:scaleY(1);-ms-transform:scaleY(1);transform:scaleY(1)}.TransUnit.is-focused .TransUnit-status:after{top:-1.125rem;padding-top:1.125rem;padding-bottom:1.125rem;opacity:.8}.TransUnit-metaData{position:relative;right:0;left:0;height:100%;text-align:center}.TransUnit-metaDataItem{line-height:1.125rem}.TransUnit-metaDataButton{font-size:.75rem;line-height:.6000000000000001rem;opacity:.8}.TransUnit-metaDataButton:hover{opacity:1}.TransUnit-metaDataComments,.TransUnit-metaDataErrors{position:absolute;right:0;left:0}.TransUnit-metaDataComments{top:1.125rem}.TransUnit-metaDataErrors{top:2.625rem}.TransUnit-metaDataErrorsIcon{text-shadow:0 0 2px #fff}@media (min-width:0) and (max-width:740px){.TransUnit-Heading,.TransUnit-panelFooterLeftNav{padding-left:1.5rem}}@media (min-width:741px){.TransUnit,.TransUnit-item{display:table;width:100%;table-layout:fixed}.TransUnit-panel{display:table-cell;width:50%;padding-left:0}.TransUnit-source{padding-right:.75rem}.TransUnit-translation{padding-left:.75rem}.TransUnit-panelHeader--source,.TransUnit-panelFooter--source{padding-right:1.875rem;right:auto}.TransUnit-panelHeader--translation,.TransUnit-panelFooter--translation{padding-left:1.875rem;left:auto}.TransUnit-status,.TransUnit-status:before,.TransUnit-status:after{left:50%;margin-left:-.75rem}}.TransUnit--highlight .TransUnit-status,.TransUnit--highlight .TransUnit-status:before{background-color:#03A6D7}.TransUnit--success .TransUnit-status,.TransUnit--success .TransUnit-status:before{background-color:#5CCA7B}.TransUnit--unsure .TransUnit-status,.TransUnit--unsure .TransUnit-status:before{background-color:#E9DF1B}.TransUnit--warning .TransUnit-status,.TransUnit--warning .TransUnit-status:before{background-color:#FFA800}.TransUnit--danger .TransUnit-status,.TransUnit--danger .TransUnit-status:before{background-color:#FF3B3D}.TransUnit--secondary .TransUnit-status,.TransUnit--secondary .TransUnit-status:before{background-color:#20718A}.TransUnit--suggestion:hover{background-color:#fbfcfc}.TransUnit--suggestion .TransUnit-panel{padding-top:.75rem;padding-bottom:.75rem}.TransUnit--suggestion .TransUnit-item,.TransUnit--suggestion .TransUnit-details{padding-left:1.125rem;padding-right:1.125rem}.TransUnit--suggestion .TransUnit-itemHeader{margin-top:-1.125rem}.TransUnit--suggestion .TransUnit-item:nth-last-child(n+3):first-child,.TransUnit--suggestion .TransUnit-item:nth-last-child(n+3):first-child~.TransUnit-item{margin-top:1.5rem}.TransUnit--suggestion .TransUnit-details{margin-top:.375rem}@-webkit-keyframes loading{0%{background-position:0 0}100%{background-position:0 1000px}}@keyframes loading{0%{background-position:0 0}100%{background-position:0 1000px}}.Resizer{position:absolute;z-index:1000}.Resizer--vertical{cursor:ew-resize;width:12px;top:0;bottom:0}.Resizer--horizontal{height:12px;left:0;right:0;cursor:ns-resize}.Editor{overflow:hidden}.Editor-header,.Editor-loader{-webkit-transition:.2s all cubic-bezier(.175,.885,.32,1.275);transition:.2s all cubic-bezier(.175,.885,.32,1.275)}.Editor-header.is-minimised{-webkit-transform:translateY(-3rem);-ms-transform:translateY(-3rem);transform:translateY(-3rem)}.Editor-header.is-minimised .Editor-mainNav{visibility:hidden}.Editor-loader{position:absolute;z-index:900;top:0;left:50%;-webkit-transform:translate(-50%,.375rem);-ms-transform:translate(-50%,.375rem);transform:translate(-50%,.375rem)}.Editor-loader.is-minimised{-webkit-transform:translateX(-50%)scale(.75,.75);-ms-transform:translateX(-50%)scale(.75,.75);transform:translateX(-50%)scale(.75,.75)}.Editor-mainNav{height:3rem}.Editor-content{position:absolute;left:0;right:0;top:5.625rem;bottom:0;overflow:auto;overflow-y:scroll;width:100%;-webkit-overlow-scrolling:touch}.Editor-content.is-maximised{top:2.625rem}.Editor-translations{min-height:100%;padding:3rem 0;background:-webkit-linear-gradient(left,#d7e5ea ,#d7e5ea);background:linear-gradient(left,#d7e5ea ,#d7e5ea);background-position:left center;background-size:1.5rem 100%;background-repeat:no-repeat}.Editor-currentDoc,.Editor-currentLang{max-width:5.25rem}.Editor-suggestions{position:fixed;z-index:200;right:0;bottom:0;left:0;overflow:hidden;box-shadow:0 -.1875rem 1.5rem rgba(0,0,0,.1)}.Editor-suggestionsHeader{position:absolute;top:0;left:0;right:0;box-shadow:0 1px 1px rgba(0,0,0,.1);z-index:300;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.Editor-suggestionsBody{position:absolute;top:2.25rem;left:0;right:0;bottom:0;overflow:scroll;overflow-x:hidden;overflow-y:scroll}.Editor-suggestions.is-search-active .Editor-suggestionsBody{top:4.5rem}.Editor-suggestionsSearch{clear:both}@media (min-width:0) and (max-width:740px){.Editor-currentProject{max-width:5.25rem}}@media (min-width:741px){.Editor-translations{background:-webkit-linear-gradient(left,#d7e5ea ,#d7e5ea),-webkit-linear-gradient(left,#ECEFF0,#ECEFF0);background:linear-gradient(to right,#d7e5ea ,#d7e5ea),linear-gradient(to right,#ECEFF0,#ECEFF0);background-position:center,right;background-size:1.5rem 100%,50% 100%;background-repeat:no-repeat}}.fade{-webkit-transition:opacity .25s easein;transition:opacity .25s easein;opacity:0}.fade.in{opacity:1}[ng\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none!important} \ No newline at end of file +.u-cf:before,.u-cf:after{content:" ";display:table}.u-cf:after{clear:both}.u-nbfc{overflow:hidden!important}.u-nbfcAlt{display:table-cell!important;width:10000px!important}.u-floatLeft{float:left!important}.u-floatRight{float:right!important}@media (min-width:0) and (max-width:740px){.u-sm-floatNone{clear:both;float:none!important}}.u-bgFaint{opacity:.9}.u-bgHigh{background-color:#f5f6f7}.u-bgHigher{background-color:#fbfcfc}.u-bgHighest{background-color:#fff}.u-bgLow{background-color:#e5e8e9}.u-bgLower{background-color:#dee1e2}.u-bgLowest{background-color:#d7d9da}.u-bgPop{border:1px solid rgba(32,113,138,.12);border-bottom-width:2px}.u-bgNeutral{background-color:#ECEFF0}.u-bgPrimary{background-color:#03A6D7}.u-bgSecondary{background-color:#20718A}.u-bgDanger{background-color:#ffd8d8}.u-bgWarning{background-color:#fec}.u-bgUnsure{background-color:#fdfce8}.u-bgSuccess{background-color:#def4e5}.u-bgHighlight{background-color:#cdedf7}.u-block{display:block!important}.u-hidden{display:none!important}.u-hiddenVisually{position:absolute!important;overflow:hidden!important;width:1px!important;height:1px!important;padding:0!important;border:0!important;clip:rect(1px,1px,1px,1px)!important}.u-inline{display:inline!important}.u-inlineBlock{display:inline-block!important;max-width:100%}.u-table{display:table!important}.u-tableCell{display:table-cell!important}.u-tableRow{display:table-row!important}.u-round{border-radius:1000px!important}.u-round,.u-roundish{overflow:hidden!important}.u-roundish{border-radius:.5625rem!important}.u-rounded{border-radius:1.125rem!important;overflow:hidden!important}@media (min-width:0) and (max-width:740px){.u-sm-hidden{display:none!important}}@media (min-width:741px) and (max-width:960px){.u-md-hidden{display:none!important}}@media (max-width:960px){.u-ltemd-hidden{display:none!important}}@media (min-width:741px){.u-gtemd-hidden{display:none!important}}@media (min-width:961px) and (max-width:1270px){.u-lg-hidden{display:none!important}}@media (min-width:961px){.u-gtelg-hidden{display:none!important}}.u-dlUnstyled>dd{margin-left:0}.u-dlInline dt,.u-dlInline dd{display:inline-block;margin-right:.1875rem;margin-left:0}.u-listUnstyled{margin-bottom:0;padding-left:0;list-style:none}.u-listUnstyled>li{margin-left:0;list-style:none}.u-listInline{margin-left:-.1875rem;padding-left:0;list-style:none}.u-listInline>li{display:inline-block;padding-right:.1875rem;padding-left:.1875rem}.u-listHorizontal{font-size:0;list-style:none}.u-listHorizontal>li{font-size:1rem;display:inline-block;vertical-align:top}.u-posAbsolute,.u-posAbsoluteCenter{position:absolute!important}.u-posAbsoluteCenter{bottom:0!important;left:0!important;margin:auto!important;right:0!important;top:0!important}.u-posFixed{position:fixed!important;-webkit-backface-visibility:hidden;backface-visibility:hidden}.u-posRelative{position:relative!important}.u-posStatic{position:static!important}.u-posAbsoluteLeft{left:0!important}.u-posAbsoluteLeft,.u-posAbsoluteRight{bottom:0!important;position:absolute!important;top:0!important}.u-posAbsoluteRight{right:0!important}.u-posCenterCenter{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.u-sizeFit{display:block!important;float:left!important;width:auto!important}.u-sizeFitAlt{float:right!important}.u-sizeFitAlt,.u-sizeFill{display:block!important;width:auto!important}.u-sizeFill{overflow:hidden!important}.u-sizeFillAlt{display:table-cell!important;max-width:100%!important;width:10000px!important}.u-sizeFull{box-sizing:border-box!important;display:block!important;width:100%!important}.u-size1of12{width:8.333333333333332%!important}.u-size1of10{width:10%!important}.u-size1of8{width:12.5%!important}.u-size1of6,.u-size2of12{width:16.666666666666664%!important}.u-size1of5,.u-size2of10{width:20%!important}.u-size1of4,.u-size2of8,.u-size3of12{width:25%!important}.u-size3of10{width:30%!important}.u-size1of3,.u-size2of6,.u-size4of12{width:33.33333333333333%!important}.u-size3of8{width:37.5%!important}.u-size2of5,.u-size4of10{width:40%!important}.u-size5of12{width:41.66666666666667%!important}.u-size1of2,.u-size2of4,.u-size3of6,.u-size4of8,.u-size5of10,.u-size6of12{width:50%!important}.u-size7of12{width:58.333333333333336%!important}.u-size3of5,.u-size6of10{width:60%!important}.u-size5of8{width:62.5%!important}.u-size2of3,.u-size4of6,.u-size8of12{width:66.66666666666666%!important}.u-size7of10{width:70%!important}.u-size3of4,.u-size6of8,.u-size9of12{width:75%!important}.u-size4of5,.u-size8of10{width:80%!important}.u-size5of6,.u-size10of12{width:83.33333333333334%!important}.u-size7of8{width:87.5%!important}.u-size9of10{width:90%!important}.u-size11of12{width:91.66666666666666%!important}@media (min-width:0) and (max-width:740px){.u-sm-sizeFit{display:block!important;float:left!important;width:auto!important}.u-sm-sizeFitAlt{float:right!important}.u-sm-sizeFitAlt,.u-sm-sizeFill{display:block!important;width:auto!important}.u-sm-sizeFill{overflow:hidden!important}.u-sm-sizeFillAlt{display:table-cell!important;max-width:100%!important;width:10000px!important}.u-sm-sizeFull{box-sizing:border-box!important;display:block!important;width:100%!important}.u-sm-size1of12{width:8.333333333333332%!important}.u-sm-size1of10{width:10%!important}.u-sm-size1of8{width:12.5%!important}.u-sm-size1of6,.u-sm-size2of12{width:16.666666666666664%!important}.u-sm-size1of5,.u-sm-size2of10{width:20%!important}.u-sm-size1of4,.u-sm-size2of8,.u-sm-size3of12{width:25%!important}.u-sm-size3of10{width:30%!important}.u-sm-size1of3,.u-sm-size2of6,.u-sm-size4of12{width:33.33333333333333%!important}.u-sm-size3of8{width:37.5%!important}.u-sm-size2of5,.u-sm-size4of10{width:40%!important}.u-sm-size5of12{width:41.66666666666667%!important}.u-sm-size1of2,.u-sm-size2of4,.u-sm-size3of6,.u-sm-size4of8,.u-sm-size5of10,.u-sm-size6of12{width:50%!important}.u-sm-size7of12{width:58.333333333333336%!important}.u-sm-size3of5,.u-sm-size6of10{width:60%!important}.u-sm-size5of8{width:62.5%!important}.u-sm-size2of3,.u-sm-size4of6,.u-sm-size8of12{width:66.66666666666666%!important}.u-sm-size7of10{width:70%!important}.u-sm-size3of4,.u-sm-size6of8,.u-sm-size9of12{width:75%!important}.u-sm-size4of5,.u-sm-size8of10{width:80%!important}.u-sm-size5of6,.u-sm-size10of12{width:83.33333333333334%!important}.u-sm-size7of8{width:87.5%!important}.u-sm-size9of10{width:90%!important}.u-sm-size11of12{width:91.66666666666666%!important}}@media (min-width:741px) and (max-width:960px){.u-md-sizeFit{display:block!important;float:left!important;width:auto!important}.u-md-sizeFitAlt{float:right!important}.u-md-sizeFitAlt,.u-md-sizeFill{display:block!important;width:auto!important}.u-md-sizeFill{overflow:hidden!important}.u-md-sizeFillAlt{display:table-cell!important;max-width:100%!important;width:10000px!important}.u-md-sizeFull{box-sizing:border-box!important;display:block!important;width:100%!important}.u-md-size1of12{width:8.333333333333332%!important}.u-md-size1of10{width:10%!important}.u-md-size1of8{width:12.5%!important}.u-md-size1of6,.u-md-size2of12{width:16.666666666666664%!important}.u-md-size1of5,.u-md-size2of10{width:20%!important}.u-md-size1of4,.u-md-size2of8,.u-md-size3of12{width:25%!important}.u-md-size3of10{width:30%!important}.u-md-size1of3,.u-md-size2of6,.u-md-size4of12{width:33.33333333333333%!important}.u-md-size3of8{width:37.5%!important}.u-md-size2of5,.u-md-size4of10{width:40%!important}.u-md-size5of12{width:41.66666666666667%!important}.u-md-size1of2,.u-md-size2of4,.u-md-size3of6,.u-md-size4of8,.u-md-size5of10,.u-md-size6of12{width:50%!important}.u-md-size7of12{width:58.333333333333336%!important}.u-md-size3of5,.u-md-size6of10{width:60%!important}.u-md-size5of8{width:62.5%!important}.u-md-size2of3,.u-md-size4of6,.u-md-size8of12{width:66.66666666666666%!important}.u-md-size7of10{width:70%!important}.u-md-size3of4,.u-md-size6of8,.u-md-size9of12{width:75%!important}.u-md-size4of5,.u-md-size8of10{width:80%!important}.u-md-size5of6,.u-md-size10of12{width:83.33333333333334%!important}.u-md-size7of8{width:87.5%!important}.u-md-size9of10{width:90%!important}.u-md-size11of12{width:91.66666666666666%!important}}@media (min-width:961px) and (max-width:1270px){.u-lg-sizeFit{display:block!important;float:left!important;width:auto!important}.u-lg-sizeFitAlt{float:right!important}.u-lg-sizeFitAlt,.u-lg-sizeFill{display:block!important;width:auto!important}.u-lg-sizeFill{overflow:hidden!important}.u-lg-sizeFillAlt{display:table-cell!important;max-width:100%!important;width:10000px!important}.u-lg-sizeFull{box-sizing:border-box!important;display:block!important;width:100%!important}.u-lg-size1of12{width:8.333333333333332%!important}.u-lg-size1of10{width:10%!important}.u-lg-size1of8{width:12.5%!important}.u-lg-size1of6,.u-lg-size2of12{width:16.666666666666664%!important}.u-lg-size1of5,.u-lg-size2of10{width:20%!important}.u-lg-size1of4,.u-lg-size2of8,.u-lg-size3of12{width:25%!important}.u-lg-size3of10{width:30%!important}.u-lg-size1of3,.u-lg-size2of6,.u-lg-size4of12{width:33.33333333333333%!important}.u-lg-size3of8{width:37.5%!important}.u-lg-size2of5,.u-lg-size4of10{width:40%!important}.u-lg-size5of12{width:41.66666666666667%!important}.u-lg-size1of2,.u-lg-size2of4,.u-lg-size3of6,.u-lg-size4of8,.u-lg-size5of10,.u-lg-size6of12{width:50%!important}.u-lg-size7of12{width:58.333333333333336%!important}.u-lg-size3of5,.u-lg-size6of10{width:60%!important}.u-lg-size5of8{width:62.5%!important}.u-lg-size2of3,.u-lg-size4of6,.u-lg-size8of12{width:66.66666666666666%!important}.u-lg-size7of10{width:70%!important}.u-lg-size3of4,.u-lg-size6of8,.u-lg-size9of12{width:75%!important}.u-lg-size4of5,.u-lg-size8of10{width:80%!important}.u-lg-size5of6,.u-lg-size10of12{width:83.33333333333334%!important}.u-lg-size7of8{width:87.5%!important}.u-lg-size9of10{width:90%!important}.u-lg-size11of12{width:91.66666666666666%!important}}.u-sizeWidth-1-4{width:.375rem!important}.u-sizeWidth-1-2{width:.75rem!important}.u-sizeWidth-3-4{width:1.125rem!important}.u-sizeWidth-1{width:1.5rem!important}.u-sizeWidth-1_1-2{width:2.25rem!important}.u-sizeWidth-2{width:3rem!important}.u-sizeWidth-6{width:9rem!important}.u-sizeHeight-1-4{height:.375rem!important}.u-sizeHeight-1-2{height:.75rem!important}.u-sizeHeight-3-4{height:1.125rem!important}.u-sizeHeight-1{height:1.5rem!important}.u-sizeHeight-1_1-4{height:1.875rem!important}.u-sizeHeight-1_1-2{height:2.25rem!important}.u-sizeHeight-2{height:3rem!important}.u-sizeLineHeight-1-4{line-height:.375rem!important}.u-sizeLineHeight-1-2{line-height:.75rem!important}.u-sizeLineHeight-3-4{line-height:1.125rem!important}.u-sizeLineHeight-1{line-height:1.5rem!important}.u-sizeLineHeight-1_1-4{line-height:1.875rem!important}.u-sizeLineHeight-1_1-2{line-height:2.25rem!important}.u-sizeLineHeight-2{line-height:3rem!important}.u-sM-1-8{margin:.1875rem!important}.u-sM-1-4{margin:.375rem!important}.u-sM-1-2{margin:.75rem!important}.u-sM-3-4{margin:1.125rem!important}.u-sM-1{margin:1.5rem!important}.u-sM-1_1-2{margin:2.25rem!important}.u-sM-2{margin:3rem!important}.u-sMT-1-8{margin-top:.1875rem!important}.u-sMT-1-4{margin-top:.375rem!important}.u-sMT-1-2{margin-top:.75rem!important}.u-sMT-3-4{margin-top:1.125rem!important}.u-sMT-1{margin-top:1.5rem!important}.u-sMT-1_1-2{margin-top:2.25rem!important}.u-sMT-2{margin-top:3rem!important}.u-sMR-1-4{margin-right:.375rem!important}.u-sMR-1-2{margin-right:.75rem!important}.u-sMR-3-4{margin-right:1.125rem!important}.u-sMR-1{margin-right:1.5rem!important}.u-sMR-1_1-2{margin-right:2.25rem!important}.u-sMR-2{margin-right:3rem!important}.u-sMB-1-4{margin-bottom:.375rem!important}.u-sMB-1-2{margin-bottom:.75rem!important}.u-sMB-3-4{margin-bottom:1.125rem!important}.u-sMB-1{margin-bottom:1.5rem!important}.u-sMB-1_1-2{margin-bottom:2.25rem!important}.u-sMB-2{margin-bottom:3rem!important}.u-sML-1-4{margin-left:.375rem!important}.u-sML-1-2{margin-left:.75rem!important}.u-sML-3-4{margin-left:1.125rem!important}.u-sML-1{margin-left:1.5rem!important}.u-sML-1_1-2{margin-left:2.25rem!important}.u-sML-2{margin-left:3rem!important}.u-sMV-1-4{margin-top:.375rem!important;margin-bottom:.375rem!important}.u-sMV-1-2{margin-top:.75rem!important;margin-bottom:.75rem!important}.u-sMV-3-4{margin-top:1.125rem!important;margin-bottom:1.125rem!important}.u-sMV-1{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.u-sMV-1_1-2{margin-top:2.25rem!important;margin-bottom:2.25rem!important}.u-sMV-2{margin-top:3rem!important;margin-bottom:3rem!important}.u-sMH-1-4{margin-left:.375rem!important;margin-right:.375rem!important}.u-sMH-1-2{margin-left:.75rem!important;margin-right:.75rem!important}.u-sMH-3-4{margin-left:1.125rem!important;margin-right:1.125rem!important}.u-sMH-1{margin-left:1.5rem!important;margin-right:1.5rem!important}.u-sMH-1_1-2{margin-left:2.25rem!important;margin-right:2.25rem!important}.u-sMH-2{margin-left:3rem!important;margin-right:3rem!important}.u-sP-1-4{padding:.375rem!important}.u-sP-1-2{padding:.75rem!important}.u-sP-3-4{padding:1.125rem!important}.u-sP-1{padding:1.5rem!important}.u-sP-1_1-2{padding:2.25rem!important}.u-sP-2{padding:3rem!important}.u-sPT-1-4{padding-top:.375rem!important}.u-sPT-1-2{padding-top:.75rem!important}.u-sPT-3-4{padding-top:1.125rem!important}.u-sPT-1{padding-top:1.5rem!important}.u-sPT-1_1-2{padding-top:2.25rem!important}.u-sPT-2{padding-top:3rem!important}.u-sPR-1-4{padding-right:.375rem!important}.u-sPR-1-2{padding-right:.75rem!important}.u-sPR-3-4{padding-right:1.125rem!important}.u-sPR-1{padding-right:1.5rem!important}.u-sPR-1_1-2{padding-right:2.25rem!important}.u-sPR-2{padding-right:3rem!important}.u-sPB-1-4{padding-bottom:.375rem!important}.u-sPB-1-2{padding-bottom:.75rem!important}.u-sPB-3-4{padding-bottom:1.125rem!important}.u-sPB-1{padding-bottom:1.5rem!important}.u-sPB-1_1-2{padding-bottom:2.25rem!important}.u-sPB-2{padding-bottom:3rem!important}.u-sPL-1-4{padding-left:.375rem!important}.u-sPL-1-2{padding-left:.75rem!important}.u-sPL-3-4{padding-left:1.125rem!important}.u-sPL-1{padding-left:1.5rem!important}.u-sPL-1_1-2{padding-left:2.25rem!important}.u-sPL-2{padding-left:3rem!important}.u-sPV-1-4{padding-top:.375rem!important;padding-bottom:.375rem!important}.u-sPV-1-2{padding-top:.75rem!important;padding-bottom:.75rem!important}.u-sPV-3-4{padding-top:1.125rem!important;padding-bottom:1.125rem!important}.u-sPV-1{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.u-sPV-1_1-2{padding-top:2.25rem!important;padding-bottom:2.25rem!important}.u-sPV-2{padding-top:3rem!important;padding-bottom:3rem!important}.u-sPH-1-4{padding-left:.375rem!important;padding-right:.375rem!important}.u-sPH-1-2{padding-left:.75rem!important;padding-right:.75rem!important}.u-sPH-3-4{padding-left:1.125rem!important;padding-right:1.125rem!important}.u-sPH-1{padding-left:1.5rem!important;padding-right:1.5rem!important}.u-sPH-1_1-2{padding-left:2.25rem!important;padding-right:2.25rem!important}.u-sPH-2{padding-left:3rem!important;padding-right:3rem!important}.u-textBreak{word-wrap:break-word!important}.u-textCenter{text-align:center!important}.u-textLeft{text-align:left!important}.u-textRight{text-align:right!important}.u-textInheritColor{color:inherit!important}.u-textKern{text-rendering:optimizeLegibility;-webkit-font-feature-settings:"kern" 1;-moz-font-feature-settings:"kern" 1;font-feature-settings:"kern" 1;-webkit-font-kerning:normal;-moz-font-kerning:normal;font-kerning:normal}.u-textNoWrap,.u-textTruncate{white-space:nowrap!important}.u-textTruncate{max-width:100%;overflow:hidden!important;text-overflow:ellipsis!important;word-wrap:normal!important}.u-textUpper{text-transform:uppercase}.u-textLower{text-transform:lowercase}.u-textCapitalize{text-transform:capitalize}.u-textInvert{color:#f2f2f2}.u-textMuted{opacity:.6}.u-textEmpty{color:#90b8c5;font-weight:600}.u-textMicro{font-size:.75rem}.u-textMini,.u-textMeta{font-size:.875rem}.u-textMeta{color:#90b8c5}.u-textLead{font-size:1.5rem;font-weight:300}.u-textPrimary{color:#03A6D7}.u-textSecondary{color:#20718A}.u-textHighlight{color:#03A6D7}.u-textSuccess{color:#5CCA7B}.u-textUnsure{color:#E9DF1B}.u-textNeutral{color:#bcd4dc}.u-textWarning{color:#FFA800}.u-textDanger{color:#FF3B3D}.u-textPilcrow:before{content:'\00b6';color:#bcd4dc;padding:0 .1875rem}.u-textTab{position:relative;display:inline-block;width:1.2em;text-align:center}.u-textTab:before{content:'\21E5';color:#bcd4dc}.u-textSpace{position:relative}.u-textSpace:before{position:absolute;content:'.';color:#bcd4dc}.Grid{display:block;font-size:0;margin:0;padding:0;text-align:left}.Grid--alignCenter{text-align:center}.Grid--alignRight{text-align:right}.Grid--alignMiddle>.Grid-cell{vertical-align:middle}.Grid--alignBottom>.Grid-cell{vertical-align:bottom}.Grid--withGutter{margin:0 -10px}.Grid--withGutter>.Grid-cell{padding:0 10px}.Grid-cell{box-sizing:border-box;display:inline-block;font-size:1rem;margin:0;padding:0;text-align:left;vertical-align:top;width:100%}.Grid-cell--center{display:block;margin:0 auto}html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}hr{box-sizing:content-box;height:0}pre{overflow:auto}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}::-webkit-input-placeholder{color:#a9bfc6}:-moz-placeholder,::-moz-placeholder{color:#a9bfc6}:-ms-input-placeholder{color:#a9bfc6}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:none}button{background:0 0;border:0;padding:0;text-align:inherit}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button:hover,button:active{outline:none}fieldset{border:0;margin:0;padding:0}input[type="text"],input[type="password"],input[type="date"],input[type="datetime"],input[type="email"],input[type="number"],input[type="search"],input[type="tel"],input[type="time"],input[type="url"],textarea{-webkit-appearance:none;outline:none;box-sizing:border-box}@-ms-viewport{width:device-width}@viewport{width:device-width}html{font-family:'Source Sans Pro',"Helvetica Neue",HelveticaNeue,Helvetica,Arial,sans-serif;font-size:16px;line-height:1.5;box-sizing:border-box;color:#444c54}*,*:before,*:after{box-sizing:inherit}body{min-width:320px;background:#ECEFF0}:active,:hover{outline:none}h1,h2,h3,h4,h5,h6{font-size:16px;margin:0;color:#20718A}a{color:#03A6D7;text-decoration:none;cursor:pointer}a:hover{color:#0395c2}a:active{color:#0285ac}ol,ul{list-style:none;margin:0;padding:0}ul:empty,ol:empty{display:none}img{max-width:100%}svg:not(:root){overflow:hidden}figure{margin:0}figcaption{color:gray}hr{width:100%;border-bottom:1px solid;border-color:rgba(32,113,138,.12);margin:rhythm(1)0;background:0 0}hr,iframe{border:0}[tabindex="-1"]:focus{outline:none!important}code{font-family:Monaco,Courier,monospace;margin:0;padding:0 .1875rem}code,kbd,pre{font-size:.8125rem;font-weight:400;color:#4d4d4d}pre,samp{font-family:Monaco,Courier,monospace;padding:0 .1875rem}samp{font-size:.8125rem;font-weight:400;color:#4d4d4d}samp,blockquote,dl,dd,p,pre{margin:0}kbd{margin:0 .1875rem;padding:.1875rem .5625rem;border:1px solid rgba(65,105,136,.07);border-bottom:3px solid rgba(65,105,136,.2);border-radius:.375rem;background-color:#fff;background-clip:padding;white-space:nowrap;display:inline-block;text-transform:uppercase;font-family:'Source Sans Pro',"Helvetica Neue",HelveticaNeue,Helvetica,Arial,sans-serif}.ButtonGroup{display:block;font-size:0;margin:0;list-style:none;padding:0}.ButtonGroup-item{display:block;font-size:1rem}.ButtonGroup-item>.Button{display:block;width:100%}.ButtonGroup-item>.Button:hover,.ButtonGroup-item>.Button:focus,.ButtonGroup-item>.Button:active,.ButtonGroup-item>.Button.is-pressed{z-index:1}.ButtonGroup--hz>.ButtonGroup-item{display:inline-block}.ButtonGroup--borderCollapse:not(.ButtonGroup--hz)>.ButtonGroup-item{margin-top:0}.ButtonGroup--borderCollapse:not(.ButtonGroup--hz)>.ButtonGroup-item:first-child{margin-top:0}.ButtonGroup--borderCollapse:not(.ButtonGroup--hz)>.ButtonGroup-item:not(:first-child):not(:last-child)>.Button{border-radius:0}.ButtonGroup--borderCollapse:not(.ButtonGroup--hz)>.ButtonGroup-item:first-child:not(:only-child)>.Button{border-bottom-left-radius:0;border-bottom-right-radius:0}.ButtonGroup--borderCollapse:not(.ButtonGroup--hz)>.ButtonGroup-item:last-child:not(:only-child)>.Button{border-top-left-radius:0;border-top-right-radius:0}.ButtonGroup--borderCollapse.ButtonGroup--hz>.ButtonGroup-item{margin-left:0}.ButtonGroup--borderCollapse.ButtonGroup--hz>.ButtonGroup-item:first-child{margin-left:0}.ButtonGroup--borderCollapse.ButtonGroup--hz>.ButtonGroup-item:not(:first-child):not(:last-child)>.Button{border-radius:0}.ButtonGroup--borderCollapse.ButtonGroup--hz>.ButtonGroup-item:first-child:not(:only-child)>.Button{border-bottom-right-radius:0;border-top-right-radius:0}.ButtonGroup--borderCollapse.ButtonGroup--hz>.ButtonGroup-item:last-child:not(:only-child)>.Button{border-bottom-left-radius:0;border-top-left-radius:0}.ButtonGroup--hz>.ButtonGroup-item{vertical-align:middle}.ButtonGroup--round .ButtonGroup-item:first-child .Button{border-top-left-radius:100px;border-bottom-left-radius:100px}.ButtonGroup--round .ButtonGroup-item:last-child .Button{border-top-right-radius:100px;border-bottom-right-radius:100px}.Button{-webkit-appearance:none;background:0 0;border-color:currentcolor;border-style:solid;border-width:0;box-sizing:border-box;color:transparent;cursor:pointer;display:inline-block;font:inherit;line-height:normal;margin:0;padding:.1875rem .75rem;position:relative;text-align:center;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;white-space:normal}.Button::-moz-focus-inner{border:0;padding:0}.Button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.Button:hover,.Button:focus,.Button:active{text-decoration:none}.Button:disabled,.Button.is-disabled{cursor:default;opacity:.6}.Button{-webkit-transition:all .25s cubic-bezier(.075,.82,.165,1);transition:all .25s cubic-bezier(.075,.82,.165,1);min-height:1.875rem;text-shadow:1px 1px 0 rgba(0,0,0,.15)}.Button:disabled,.Button.is-disabled{pointer-events:none}.Button:hover,.Button:active,.Button.is-active{outline:inherit}.Button--default{background-color:#deeaed}.Button--default:hover{background-color:#c8d3d5}.Button--default:active,.Button--default.is-active{background-color:#bdc7c9}.Button--primary{color:#fff;background-color:#03A6D7}.Button--primary:hover{background-color:#0395c2}.Button--primary:active,.Button--primary.is-active{background-color:#038db7}.Button--secondary{color:#fff;background-color:#20718A}.Button--secondary:hover{background-color:#1d667c}.Button--secondary:active,.Button--secondary.is-active{background-color:#1b6075}.Button--highlight{color:#fff;background-color:#03A6D7}.Button--highlight:hover{background-color:#0395c2}.Button--highlight:active,.Button--highlight.is-active{background-color:#038db7}.Button--success{color:#fff;background-color:#5CCA7B}.Button--success:hover{background-color:#53b66f}.Button--success:active,.Button--success.is-active{background-color:#4eac69}.Button--unsure{color:#fff;background-color:#E9DF1B}.Button--unsure:hover{background-color:#d2c918}.Button--unsure:active,.Button--unsure.is-active{background-color:#c6be17}.Button--neutral{color:#fff;background-color:#90b8c5}.Button--neutral:hover{background-color:#82a6b1}.Button--neutral:active,.Button--neutral.is-active{background-color:#7a9ca7}.Button--warning{color:#fff;background-color:#FFA800}.Button--warning:hover{background-color:#e69700}.Button--warning:active,.Button--warning.is-active{background-color:#d98f00}.Button--danger{color:#fff;background-color:#FF3B3D}.Button--danger:hover{background-color:#e63537}.Button--danger:active,.Button--danger.is-active{background-color:#d93234}.Button--invisible{background-color:transparent;color:#90b8c5}.Button--invisible:hover{background-color:#edf4f6;color:#639cad}.Button--invisible:active,.Button--invisible.is-active{color:#20718A;background-color:#e4eef1}.Button--snug{padding-left:.375rem;padding-right:.375rem}.Button--small{min-height:1.5rem;padding:.1875rem .75rem;font-size:.875rem}.InputGroup{position:relative;display:table;border-collapse:separate}.InputGroup-input,.InputGroup-addon,.InputGroup-button{display:table-cell;-webkit-transition:.2s cubic-bezier(.26,.47,.36,.94);transition:.2s cubic-bezier(.26,.47,.36,.94)}.InputGroup-input,.InputGroup-addon{background-color:transparent;padding:0 .375rem}.InputGroup-input{border:none;width:100%;color:#20718A}.InputGroup-addon{color:#639cad;text-align:center;width:1%;white-space:nowrap;vertical-align:middle}.InputGroup-addon:before{content:' '}.InputGroup.is-focused .InputGroup-input,.InputGroup.is-focused .InputGroup-addon{background-color:#fff}.InputGroup--bordered .InputGroup-input,.InputGroup--bordered .InputGroup-addon,.InputGroup--outlined .InputGroup-input,.InputGroup--outlined .InputGroup-addon{border-top:1px solid #a6c6d0;border-bottom:1px solid #a6c6d0}.InputGroup--bordered .InputGroup-input{border-left:1px solid #a6c6d0;border-right:1px solid #a6c6d0}.InputGroup--outlined .InputGroup-input:first-child,.InputGroup--outlined .InputGroup-addon:first-child{border-left:1px solid #a6c6d0}.InputGroup--outlined .InputGroup-input:last-child,.InputGroup--outlined .InputGroup-addon:last-child{border-right:1px solid #a6c6d0}.InputGroup--bordered.is-focused .InputGroup-input,.InputGroup--bordered.is-focused .InputGroup-addon,.InputGroup--outlined.is-focused .InputGroup-input,.InputGroup--outlined.is-focused .InputGroup-addon{border-color:#639cad}.InputGroup--rounded .InputGroup-input:first-child,.InputGroup--rounded .InputGroup-addon:first-child{border-bottom-left-radius:1.5rem;border-top-left-radius:1.5rem;padding-left:.5625rem}.InputGroup--rounded .InputGroup-input:last-child,.InputGroup--rounded .InputGroup-addon:last-child{border-bottom-right-radius:1.5rem;border-top-right-radius:1.5rem;padding-right:.5625rem}.Dropdown{position:relative;z-index:100;display:inline-block;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.Dropdown.is-active{z-index:900}.Dropdown-toggleIcon{display:inline-block;-webkit-transition:all .2s cubic-bezier(.175,.885,.32,1.275);transition:all .2s cubic-bezier(.175,.885,.32,1.275);text-align:center}.Dropdown.is-active .Dropdown-toggleIcon{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.Dropdown-content{position:absolute;z-index:800;top:100%;left:0;visibility:hidden;float:left;overflow:auto;overflow-x:hidden;overflow-y:auto;max-height:18rem;min-width:120%;margin:0;padding:0;-webkit-transition:all .2s cubic-bezier(.175,.885,.32,1.275);transition:all .2s cubic-bezier(.175,.885,.32,1.275);-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);text-align:left;opacity:0;background-color:#fff;background-clip:padding-box;box-shadow:0 0 1.5rem rgba(0,0,0,.1)}.Dropdown-content--Bordered{border:1px solid rgba(32,113,138,.12);border-bottom-width:2px}.Dropdown.is-active>.Dropdown-content{visibility:visible;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0);opacity:1}.Dropdown-title{font-size:.875rem;padding:.1875rem .375rem;background-color:transparent;border-bottom:1px solid rgba(32,113,138,.12);color:#79aab9}.Dropdown-item{display:block;padding:.1875rem .375rem;-webkit-transition:all .2s ease-out;transition:all .2s ease-out;color:#03A6D7}.Dropdown-item:hover{color:#fff;background-color:#03A6D7}.Dropdown--right .Dropdown-content{left:auto;right:0}.Header{background-color:#03A6D7;position:fixed;z-index:100;width:100%;top:0;box-shadow:0 .375rem 1.5rem rgba(0,0,0,.1)}.Header-item{height:3rem;display:inline-block;padding-top:.75rem;padding-bottom:.75rem}.Header-avatar{margin-top:.5625rem;margin-bottom:.5625rem;width:1.875rem;height:1.875rem;display:inline-block}.h1,.h2,.h3,.h4,.h5,.h6{font-family:'Source Sans Pro',"Helvetica Neue",HelveticaNeue,Helvetica,Arial,sans-serif;font-weight:600}.h1{font-size:36px}.h2{font-size:28px}.h3{font-size:24px}.h4{font-size:20px}.h5{font-size:18px}.h6{font-size:16px}.Heading--panel{font-size:1rem;font-weight:400;margin:0;text-transform:uppercase}.Icon{text-align:center;display:inline-block;-webkit-transition:.25s all cubic-bezier(.175,.885,.32,1.275);transition:.25s all cubic-bezier(.175,.885,.32,1.275)}.Icon.is-rotated{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.Icon-item{vertical-align:-25%;display:inline-block;width:1.5rem;height:1.5rem;fill:currentColor!important}.Icon--xlg .Icon-item{width:3rem;height:3rem}.Icon--lg .Icon-item{width:2.25rem;height:2.25rem}.Icon--sm .Icon-item{vertical-align:-15%;width:1.125rem;height:1.125rem}.Icon--xsm .Icon-item{vertical-align:-10%;width:.9375rem;height:.9375rem}.Icon--circle{position:relative;padding:.75rem}.Icon--circle:before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;border:2px solid;opacity:.2;border-radius:3rem}.Icon--circle.Icon--lg{border-width:3px}.Icon--circle.Icon--xlg{border-width:3px;padding:1.125rem}.Icon--circle.Icon--lg{padding:.9375rem}.Icon--circle.Icon--sm{border-width:1px;padding:.5625rem}.Icon--circle.Icon--xsm{border-width:1px;padding:.375rem}.Icon--stroked .Icon-item{fill:none;stroke:currentColor;stroke-width:3}.Icon--loader .Icon-item{position:relative}.Icon--loader-dot{position:absolute;left:0;top:36.1%;display:inline-block;width:27.8%;height:27.8%;-webkit-animation:bouncedelay .9s infinite cubic-bezier(.175,.885,.32,1.275);animation:bouncedelay .9s infinite cubic-bezier(.175,.885,.32,1.275);border-radius:3rem;background-color:currentColor;-webkit-animation-fill-mode:both;animation-fill-mode:both}.Icon--loader-dot:nth-of-type(2){left:36.1%;-webkit-animation-delay:.15s;animation-delay:.15s}.Icon--loader-dot:nth-of-type(3){right:0;left:auto;-webkit-animation-delay:.3s;animation-delay:.3s}@-webkit-keyframes bouncedelay{0%,90%,100%{-webkit-transform:scale(0,0);transform:scale(0,0);opacity:.2}40%{-webkit-transform:scale(1,1);transform:scale(1,1);opacity:1}}@keyframes bouncedelay{0%,90%,100%{-webkit-transform:scale(0,0);transform:scale(0,0);opacity:.2}40%{-webkit-transform:scale(1,1);transform:scale(1,1);opacity:1}}.Link{color:#03A6D7;text-decoration:none;cursor:pointer}.Link:hover{color:#0395c2}.Link:active{color:#0285ac}.Link--invert{opacity:.8}.Link--invert,.Link--invert:hover{color:#fff!important}.Link--invert:hover{opacity:1}.Link--invert:active,.Link--invert.is-active{opacity:.6}.Link--success{color:#5CCA7B!important}.Link--success:hover{color:#408d56 !important}.Link--success:active,.Link--success.is-active{color:#255131 !important}.Link--unsure{color:#E9DF1B!important}.Link--unsure:hover{color:#a39c13 !important}.Link--unsure:active,.Link--unsure.is-active{color:#5d590b !important}.Link--neutral{color:#bcd4dc !important}.Link--neutral:hover{color:#84949a !important}.Link--neutral:active,.Link--neutral.is-active{color:#4b5558 !important}.Link--warning{color:#FFA800!important}.Link--warning:hover{color:#b37600 !important}.Link--warning:active,.Link--warning.is-active{color:#664300 !important}.Link--danger{color:#FF3B3D!important}.Link--danger:hover{color:#b3292b !important}.Link--danger:active,.Link--danger.is-active{color:#661818 !important}.Difference ins,.Difference del{padding:0 1px;border-radius:2px}.Difference ins{background-color:#c9eed3;text-decoration:none}.Difference del{background-color:#ffe0e0;text-decoration:none}.LogoLoader{position:relative;display:inline-block;margin-top:-.09375rem;width:2.4375rem;height:2.4375rem;color:#fff;border-radius:100px}.LogoLoader--inverted{color:#03A6D7}.LogoLoader-logo{-webkit-transition:all .25s cubic-bezier(.175,.885,.32,1.275);transition:all .25s cubic-bezier(.175,.885,.32,1.275);fill:currentColor}.LogoLoader-logo,.LogoLoader-svg{position:absolute;top:0;left:0;right:0;bottom:0}.LogoLoader-svg{overflow:visible}.LogoLoader path{-webkit-transform-origin:50% 50% 0;-ms-transform-origin:50% 50% 0;transform-origin:50% 50% 0}.LogoLoader:hover .LogoLoader-z{-webkit-animation:pop .3s cubic-bezier(.175,.885,.32,1.275);animation:pop .3s cubic-bezier(.175,.885,.32,1.275);-webkit-animation-iteration-count:2;animation-iteration-count:2;-webkit-animation-direction:alternate;animation-direction:alternate}.LogoLoader-z{-webkit-transform:scale(1,1);-ms-transform:scale(1,1);transform:scale(1,1);-webkit-transition:all .25s cubic-bezier(.175,.885,.32,1.275);transition:all .25s cubic-bezier(.175,.885,.32,1.275)}.LogoLoader .LogoLoader-logo{-webkit-transform-origin:50% 50% 0;-ms-transform-origin:50% 50% 0;transform-origin:50% 50% 0}.LogoLoader .LogoLoader-circle,.LogoLoader .LogoLoader-circlePulse{-webkit-transform:scale(1,1);-ms-transform:scale(1,1);transform:scale(1,1)}.LogoLoader.is-loading .LogoLoader-z,.LogoLoader.is-loading .LogoLoader-circle{-webkit-animation:pulseBegin 1s infinite linear;animation:pulseBegin 1s infinite linear}.LogoLoader.is-loading .LogoLoader-circle,.LogoLoader.is-loading .LogoLoader-circlePulse{-webkit-animation-delay:.1s;animation-delay:.1s}.LogoLoader.is-loading .LogoLoader-circlePulse{-webkit-animation:pulse 1s infinite linear;animation:pulse 1s infinite linear}@-webkit-keyframes pulseBegin{0%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(.6);transform:scale(.6)}40%{-webkit-transform:scale(1.2);transform:scale(1.2)}60%,100%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes pulseBegin{0%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(.6);transform:scale(.6)}40%{-webkit-transform:scale(1.2);transform:scale(1.2)}60%,100%{-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes pulse{0%{opacity:0}0%,20%{-webkit-transform:scale(.6);transform:scale(.6)}40%{-webkit-transform:scale(1.2);transform:scale(1.2);opacity:.5}60%{-webkit-transform:scale(1.6);transform:scale(1.6);opacity:.7}100%{-webkit-transform:scale(2);transform:scale(2);opacity:0}}@keyframes pulse{0%{opacity:0}0%,20%{-webkit-transform:scale(.6);transform:scale(.6)}40%{-webkit-transform:scale(1.2);transform:scale(1.2);opacity:.5}60%{-webkit-transform:scale(1.6);transform:scale(1.6);opacity:.7}100%{-webkit-transform:scale(2);transform:scale(2);opacity:0}}@-webkit-keyframes pop{to{-webkit-transform:rotate(15deg)scale(1.1,1.1);transform:rotate(15deg)scale(1.1,1.1)}}@keyframes pop{to{-webkit-transform:rotate(15deg)scale(1.1,1.1);transform:rotate(15deg)scale(1.1,1.1)}}.Progressbar{position:relative;width:100%;height:.75rem;margin:0;background-color:#bcd4dc}.Progressbar--sm{height:.375rem}.Progressbar--lg{height:1.5rem}.Progressbar-item{position:absolute;left:0;z-index:100;margin:0;padding:0;width:100%;height:100%;list-style:none}.Progressbar-approved{background-color:#03A6D7;z-index:200}.Progressbar-translated{background-color:#5CCA7B}.Progressbar-needsWork{background-color:#E9DF1B}.Progressbar-untranslated{background-color:#bcd4dc}.Modal{position:fixed;z-index:1000;top:0;right:0;bottom:0;left:0;display:block;visibility:hidden;overflow:auto;overflow-y:scroll;width:100%;height:100%;margin:0 auto;padding:4.5rem 1.5rem 1.5rem;-webkit-transition:all .15s linear;transition:all .15s linear;opacity:0;background-color:rgba(236,239,240,.95);-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:75rem;perspective:75rem;-webkit-overflow-scrolling:touch}.Modal.is-active{visibility:visible;opacity:1}.Modal-dialog{position:relative;width:90%;top:50%;left:50%;max-height:100%;min-width:300px;max-width:45rem;-webkit-transition:all .25s cubic-bezier(.175,.885,.32,1.1);transition:all .25s cubic-bezier(.175,.885,.32,1.1);-webkit-transform:translateX(-50%)translateY(100%);-ms-transform:translateX(-50%)translateY(100%);transform:translateX(-50%)translateY(100%);-webkit-transform-origin:0;-ms-transform-origin:0;transform-origin:0;background-color:#f7f9f9}.Modal.is-active .Modal-dialog{-webkit-transform:translateX(-50%)translateY(-50%);-ms-transform:translateX(-50%)translateY(-50%);transform:translateX(-50%)translateY(-50%)}.Modal-header{position:fixed;top:-3rem;left:0;right:0;border:1px solid rgba(32,113,138,.12);background-color:#fff;z-index:100}.Modal-title{font-size:1.375rem;font-weight:300;line-height:1.5rem;margin:0;padding:.75rem 2.25rem .75rem 1.5rem}.Modal-close{position:absolute;top:0;right:0;width:3rem;height:3rem;-webkit-transition:all .25s ease-out;transition:all .25s ease-out;text-align:center;border-left:1px solid rgba(32,113,138,.12)}.Modal-close:hover{background-color:rgba(32,113,138,.05)}.Modal-close:active{background-color:rgba(32,113,138,.1)}.Modal-content{position:relative;max-height:100%;overflow:auto;background-clip:padding-box;border:1px solid rgba(32,113,138,.12);border-top-color:transparent;border-bottom-width:2px}.Modal-container.is-modal{overflow:hidden;height:100%}.Toggle,.Toggle-label{cursor:pointer}.Toggle{position:relative;display:inline-block;min-width:2.0625rem;margin:0 .09375rem;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:top}.Toggle-checkbox{position:absolute;cursor:none;top:0;left:0;width:100%;height:100%;opacity:0}.Toggle-label{font-weight:600;display:block;position:relative;padding:0 .5625rem;-webkit-transition:all .25s cubic-bezier(.075,.82,.165,1);transition:all .25s cubic-bezier(.075,.82,.165,1);text-align:center;color:currentColor}.Toggle-fakeCheckbox{opacity:1;position:absolute;top:0;left:0;width:100%;height:100%;content:'';background-color:transparent}.Toggle:hover>.Toggle-fakeCheckbox,.Toggle-checkbox:focus~.Toggle-fakeCheckbox{background-color:currentColor;opacity:.2}.Toggle-checkbox:checked~.Toggle-label,.Toggle.is-active~.Toggle-label{color:#fff}.Toggle-checkbox:checked~.Toggle-fakeCheckbox,.Toggle.is-active>.Toggle-fakeCheckbox{background-color:currentColor}.Toggle:hover>.Toggle-checkbox:checked~.Toggle-fakeCheckbox,.Toggle-checkbox:checked:focus~.Toggle-fakeCheckbox,.Toggle.is-active:hover>.Toggle-fakeCheckbox{opacity:.8}.Switch{padding-left:2.25rem;position:relative}.Switch-checkbox{position:absolute;margin-left:-9999px;visibility:hidden}.Switch-label{cursor:pointer}.Switch-label:before,.Switch-label:after{content:'';position:absolute;left:0;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);border-radius:1.125rem;-webkit-transition:all .2s ease-out;transition:all .2s ease-out}.Switch-label:before{width:1.875rem;height:1.125rem;background-color:#d2e3e8}.Switch-label:after{width:1.125rem;height:1.125rem;background-color:#79aab9;border:1px solid transparent;-webkit-transform:translateY(-50%)scale(.8,.8);-ms-transform:translateY(-50%)scale(.8,.8);transform:translateY(-50%)scale(.8,.8)}.Switch-labelText{color:#79aab9;font-size:.875rem}.Switch-checkbox:checked~.Switch-label:before{background-color:#20718A}.Switch-checkbox:checked~.Switch-label:after{background-color:#fff;-webkit-transform:translateY(-50%)translateX(66%)scale(.8,.8);-ms-transform:translateY(-50%)translateX(66%)scale(.8,.8);transform:translateY(-50%)translateX(66%)scale(.8,.8)}.Switch-checkbox:checked~.Switch-label .Switch-labelText{color:#20718A}.TransUnit{position:relative;margin:0;padding:0;cursor:text;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border-bottom:1px solid rgba(32,113,138,.12)}.TransUnit:focus{outline:0;box-shadow:none}.TransUnit.is-focused{opacity:1!important;background-color:#fff}.TransUnit:before,.TransUnit:after{position:absolute;left:0;visibility:hidden;width:100%;height:1.5rem;content:'';-webkit-transform:scaleY(0);-ms-transform:scaleY(0);transform:scaleY(0);opacity:0;background-color:#fff;background-clip:padding-box}.TransUnit:before{box-shadow:0 -.375rem .75rem rgba(0,0,0,.04);-webkit-transform-origin:bottom;-ms-transform-origin:bottom;transform-origin:bottom;top:-1.125rem}.TransUnit:after{box-shadow:0 .375rem .75rem rgba(0,0,0,.04);-webkit-transform-origin:top;-ms-transform-origin:top;transform-origin:top;bottom:-1.125rem}.TransUnit.is-focused:before,.TransUnit.is-focused:after{visibility:visible;-webkit-transform:scaleY(1);-ms-transform:scaleY(1);transform:scaleY(1);opacity:1}.TransUnit.is-first{border-top:1px solid rgba(32,113,138,.12)}.TransUnit-container.is-unit-selected .TransUnit{opacity:.8}.TransUnit-panel{padding-top:1.125rem;padding-bottom:1.125rem;padding-left:1.5rem;list-style:none;vertical-align:top}.TransUnit-panel,.TransUnit-item{position:relative}.TransUnit-source{cursor:pointer;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.TransUnit.is-focused .TransUnit-source{cursor:text}.TransUnit-translation{cursor:text;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.TransUnit-panelHeader,.TransUnit-panelFooter,.TransUnit-itemHeader{position:absolute;z-index:200;right:0;left:0;width:100%;padding-right:1.125rem;padding-left:1.125rem;cursor:default}.TransUnit-panelHeader,.TransUnit-panelFooter{visibility:hidden;opacity:0}.TransUnit.is-focused .TransUnit-panelHeader,.TransUnit.is-focused .TransUnit-panelFooter{visibility:visible;opacity:1}.TransUnit-panelHeader{top:-1.125rem}.TransUnit-itemHeader{top:0}.TransUnit-panelFooter{bottom:-1.125rem}.TransUnit-heading{font-size:1rem;font-weight:400;line-height:2.25rem;display:inline-block;float:left;margin:0;vertical-align:top;text-transform:uppercase}.TransUnit-text{font-family:'Source Sans Pro',"Helvetica Neue",HelveticaNeue,Helvetica,Arial,sans-serif;font-size:16px;line-height:1.5;overflow:hidden;width:100%;min-height:1.5rem;margin:0;padding:1.125rem;resize:none;-webkit-transition:height .1s cubic-bezier(.075,.82,.165,1);transition:height .1s cubic-bezier(.075,.82,.165,1);white-space:pre-wrap;word-wrap:break-word;-moz-tab-size:8;tab-size:8;color:#444c54;border:none;background-color:transparent;box-shadow:none;-webkit-appearance:none}.TransUnit-text:focus{border:none;outline:none;background-color:transparent}.TransUnit-text span{font-weight:400!important;font-style:normal!important}.TransUnit-status,.TransUnit-status:before,.TransUnit-status:after{position:absolute;z-index:200;left:0;width:1.5rem;background-color:#bcd4dc}.TransUnit-status{top:-1;bottom:-1}.TransUnit-status.is-loading,.TransUnit-status.is-loading:before{background-image:-webkit-repeating-linear-gradient(45deg,transparent,transparent .375rem,rgba(255,255,255,.5).375rem,rgba(255,255,255,.5).75rem);background-image:repeating-linear-gradient(45deg,transparent,transparent .375rem,rgba(255,255,255,.5).375rem,rgba(255,255,255,.5).75rem);background-size:100% 1000px;-webkit-animation:loading 7s linear;animation:loading 7s linear;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.TransUnit-status:before{top:-1.125rem;height:100%;padding-top:1.125rem;padding-bottom:1.125rem;box-sizing:content-box;z-index:300;visibility:hidden;content:'';-webkit-transform:scaleY(.65);-ms-transform:scaleY(.65);transform:scaleY(.65)}.TransUnit-status:after{-webkit-transition:none;transition:none;z-index:400;top:0;box-sizing:content-box;width:1.3125rem;height:100%;content:'';background-color:#fff;opacity:.6}.TransUnit.is-focused .TransUnit-status:before{visibility:visible;-webkit-transform:scaleY(1);-ms-transform:scaleY(1);transform:scaleY(1)}.TransUnit.is-focused .TransUnit-status:after{top:-1.125rem;padding-top:1.125rem;padding-bottom:1.125rem;opacity:.8}.TransUnit-metaData{position:relative;right:0;left:0;height:100%;text-align:center}.TransUnit-metaDataItem{line-height:1.125rem}.TransUnit-metaDataButton{font-size:.75rem;line-height:.6000000000000001rem;opacity:.8}.TransUnit-metaDataButton:hover{opacity:1}.TransUnit-metaDataComments,.TransUnit-metaDataErrors{position:absolute;right:0;left:0}.TransUnit-metaDataComments{top:1.125rem}.TransUnit-metaDataErrors{top:2.625rem}.TransUnit-metaDataErrorsIcon{text-shadow:0 0 2px #fff}@media (min-width:0) and (max-width:740px){.TransUnit-Heading,.TransUnit-panelFooterLeftNav{padding-left:1.5rem}}@media (min-width:741px){.TransUnit,.TransUnit-item{display:table;width:100%;table-layout:fixed}.TransUnit-panel{display:table-cell;width:50%;padding-left:0}.TransUnit-source{padding-right:.75rem}.TransUnit-translation{padding-left:.75rem}.TransUnit-panelHeader--source,.TransUnit-panelFooter--source{padding-right:1.875rem;right:auto}.TransUnit-panelHeader--translation,.TransUnit-panelFooter--translation{padding-left:1.875rem;left:auto}.TransUnit-status,.TransUnit-status:before,.TransUnit-status:after{left:50%;margin-left:-.75rem}}.TransUnit--highlight .TransUnit-status,.TransUnit--highlight .TransUnit-status:before{background-color:#03A6D7}.TransUnit--success .TransUnit-status,.TransUnit--success .TransUnit-status:before{background-color:#5CCA7B}.TransUnit--unsure .TransUnit-status,.TransUnit--unsure .TransUnit-status:before{background-color:#E9DF1B}.TransUnit--warning .TransUnit-status,.TransUnit--warning .TransUnit-status:before{background-color:#FFA800}.TransUnit--danger .TransUnit-status,.TransUnit--danger .TransUnit-status:before{background-color:#FF3B3D}.TransUnit--secondary .TransUnit-status,.TransUnit--secondary .TransUnit-status:before{background-color:#20718A}.TransUnit--suggestion:hover{background-color:#fbfcfc}.TransUnit--suggestion .TransUnit-panel{padding-top:.75rem;padding-bottom:.75rem}.TransUnit--suggestion .TransUnit-item,.TransUnit--suggestion .TransUnit-details{padding-left:1.125rem;padding-right:1.125rem}.TransUnit--suggestion .TransUnit-itemHeader{margin-top:-1.125rem}.TransUnit--suggestion .TransUnit-item:nth-last-child(n+3):first-child,.TransUnit--suggestion .TransUnit-item:nth-last-child(n+3):first-child~.TransUnit-item{margin-top:1.5rem}.TransUnit--suggestion .TransUnit-details{margin-top:.375rem}@-webkit-keyframes loading{0%{background-position:0 0}100%{background-position:0 1000px}}@keyframes loading{0%{background-position:0 0}100%{background-position:0 1000px}}.Resizer{position:absolute;z-index:1000}.Resizer--vertical{cursor:ew-resize;width:12px;top:0;bottom:0}.Resizer--horizontal{height:12px;left:0;right:0;cursor:ns-resize}.Editor{overflow:hidden}.Editor-header,.Editor-loader{-webkit-transition:.2s all cubic-bezier(.175,.885,.32,1.275);transition:.2s all cubic-bezier(.175,.885,.32,1.275)}.Editor-header.is-minimised{-webkit-transform:translateY(-3rem);-ms-transform:translateY(-3rem);transform:translateY(-3rem)}.Editor-header.is-minimised .Editor-mainNav{visibility:hidden}.Editor-loader{position:absolute;z-index:900;top:0;left:50%;-webkit-transform:translate(-50%,.375rem);-ms-transform:translate(-50%,.375rem);transform:translate(-50%,.375rem)}.Editor-loader.is-minimised{-webkit-transform:translateX(-50%)scale(.75,.75);-ms-transform:translateX(-50%)scale(.75,.75);transform:translateX(-50%)scale(.75,.75)}.Editor-mainNav{height:3rem}.Editor-content{position:absolute;left:0;right:0;top:5.625rem;bottom:0;overflow:auto;overflow-y:scroll;width:100%;-webkit-overlow-scrolling:touch}.Editor-content.is-maximised{top:2.625rem}.Editor-translationsWrapper{height:100%}.Editor-translations{min-height:100%;padding:3rem 0;background:-webkit-linear-gradient(left,#d7e5ea ,#d7e5ea);background:linear-gradient(left,#d7e5ea ,#d7e5ea);background-position:left center;background-size:1.5rem 100%;background-repeat:no-repeat}.Editor-currentDoc,.Editor-currentLang{max-width:5.25rem}.Editor-suggestions{position:fixed;z-index:200;right:0;bottom:0;left:0;overflow:hidden;box-shadow:0 -.1875rem 1.5rem rgba(0,0,0,.1)}.Editor-suggestionsHeader{position:absolute;top:0;left:0;right:0;box-shadow:0 1px 1px rgba(0,0,0,.1);z-index:300;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.Editor-suggestionsBody{position:absolute;top:2.25rem;left:0;right:0;bottom:0;overflow:scroll;overflow-x:hidden;overflow-y:scroll}.Editor-suggestions.is-search-active .Editor-suggestionsBody{top:4.5rem}.Editor-suggestionsSearch{clear:both}@media (min-width:0) and (max-width:740px){.Editor-currentProject{max-width:5.25rem}}@media (min-width:741px){.Editor-translations{background:-webkit-linear-gradient(left,#d7e5ea ,#d7e5ea),-webkit-linear-gradient(left,#ECEFF0,#ECEFF0);background:linear-gradient(to right,#d7e5ea ,#d7e5ea),linear-gradient(to right,#ECEFF0,#ECEFF0);background-position:center,right;background-size:1.5rem 100%,50% 100%;background-repeat:no-repeat}}.fade{-webkit-transition:opacity .25s easein;transition:opacity .25s easein;opacity:0}.fade.in{opacity:1}[ng\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none!important} \ No newline at end of file diff --git a/zanata-war/src/main/webapp/app/js/app.js b/zanata-war/src/main/webapp/app/js/app.js index b645c45143..09788d81ad 100644 --- a/zanata-war/src/main/webapp/app/js/app.js +++ b/zanata-war/src/main/webapp/app/js/app.js @@ -1,3 +1,3 @@ -!function(){"use strict";angular.module("app",["ngResource","ngAnimate","ui.router","templates","cfp.hotkeys","focusOn","monospaced.elastic","gettext","diff-match-patch"])}(),function(){"use strict";function t(t,e,n,o){var r=function(t,e){return{request:function(t){return e.$broadcast("loadingStart"),t},requestError:function(n){return e.$broadcast("loadingStop"),console.error("Request error due to ",n),t.reject(n)},response:function(n){return e.$broadcast("loadingStop"),n||t.when(n)},responseError:function(n){return e.$broadcast("loadingStop"),401===n.status?console.error("Unauthorized access. Please login"):404===n.status?console.error("Service end point not found- ",n.config.url):console.error("Error in response ",n),t.reject(n)}}};r.$inject=["$q","$rootScope"],n.interceptors.push(r),e.otherwise("/"),t.state("editor",{url:"/:projectSlug/:versionSlug/translate",templateUrl:"editor/editor.html",controller:"EditorCtrl as editor",resolve:{url:["UrlService",function(t){return t.init()}]}}).state("editor.selectedContext",{url:"/:docId/:localeId",views:{"editor-content":{templateUrl:"editor/editor-content.html",controller:"EditorContentCtrl as editorContent"},"editor-suggestions":{templateUrl:"editor/editor-suggestions.html",controller:"EditorSuggestionsCtrl as editorSuggestions"},"editor-details":{templateUrl:"editor/editor-details.html",controller:"EditorDetailsCtrl as editorDetails"}}}).state("editor.selectedContext.tu",{url:"/?id&selected?states",reloadOnSearch:!1}),o.includeCheatSheet=!1}t.$inject=["$stateProvider","$urlRouterProvider","$httpProvider","hotkeysProvider"],angular.module("app").config(t)}(),function(){"use strict";angular.module("app").constant("_",window._).constant("str",window._.string).constant("Mousetrap",window.Mousetrap).constant("PRODUCTION",!0)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s){function c(){return o.getAllLocales()}function u(){return e.getMyInfo().then(function(t){d.myInfo=t,d.myInfo.locale=o.DEFAULT_LOCALE,d.myInfo.gravatarUrl=n.gravatarUrl(d.myInfo.gravatarHash,72)},function(t){r.displayError("Error loading my info: "+t)})}function l(){o.getUILocaleList().then(function(t){for(var e in t.locales){var n={localeId:t.locales[e],name:""};d.uiLocaleList.push(n)}d.myInfo.locale=o.getLocaleByLocaleId(d.uiLocaleList,o.DEFAULT_LOCALE.localeId),d.myInfo.locale||(d.myInfo.locale=o.DEFAULT_LOCALE)},function(t){r.displayInfo("Error loading UI locale. Default to '"+o.DEFAULT_LOCALE.name+"': "+t),d.myInfo.locale=o.DEFAULT_LOCALE})}var d=this;d.PRODUCTION=s,d.settings=e.settings,d.uiLocaleList=[o.DEFAULT_LOCALE],n.init().then(c).then(u).then(l),d.onChangeUILocale=function(t){d.myInfo.locale=t;var e=d.myInfo.locale.localeId;a.startsWith(e,o.DEFAULT_LOCALE.localeId,!0)?i.setCurrentLanguage(o.DEFAULT_LOCALE.localeId):i.loadRemote(n.uiTranslationURL(e)).then(function(){i.setCurrentLanguage(e)},function(t){r.displayInfo("Error loading UI locale. Default to '"+o.DEFAULT_LOCALE.name+"': "+t),i.setCurrentLanguage(o.DEFAULT_LOCALE),d.myInfo.locale=o.DEFAULT_LOCALE})},d.dashboardPage=function(){return n.DASHBOARD_PAGE}}t.$inject=["$scope","UserService","UrlService","LocaleService","MessageHandler","gettextCatalog","StringUtil","PRODUCTION"],angular.module("app").controller("AppCtrl",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s,c,u,l){function d(){v=r.readValue("status"),u.isUndefined(v)||(v=v.split(","),v=u.transform(v,function(t,e){return e=l.getServerId(e),t.push(e)})),I={status:v}}function f(t,e){var n,o,r,c,l=N.phrases;o=u.findIndex(l,function(t){return t.id===e.currentId}),r=Math.min(o+1,l.length-1),c=l[r].id,c!==e.currentId?i.emitEvent(i.EVENT.SELECT_TRANS_UNIT,{id:c,updateURL:!0,focus:!0},null):(n=l[o],i.emitEvent(i.EVENT.SAVE_TRANSLATION,{phrase:n,status:s.getSaveButtonStatus(n),locale:a.localeId,docId:a.docId}))}function S(t,e){var n,o,r,c,l=N.phrases;o=u.findIndex(l,function(t){return t.id===e.currentId}),r=Math.max(o-1,0),c=l[r].id,c!==e.currentId?i.emitEvent(i.EVENT.SELECT_TRANS_UNIT,{id:c,updateURL:!0,focus:!0},null):(n=l[o],i.emitEvent(i.EVENT.SAVE_TRANSLATION,{phrase:n,status:s.getSaveButtonStatus(n),locale:a.localeId,docId:a.docId}))}function g(t,e){var n,o,r=N.phrases,a=l.getStatusInfo(v);n=u.findIndex(r,function(t){return t.id===e.currentId});for(var s=n+1;sm&&(e.maxPageIndex=t%m!==0?e.maxPageIndex+=1:e.maxPageIndex),e.maxPageIndex=e.maxPageIndex-1<0?0:e.maxPageIndex-1,T(e.currentPageIndex)})}function T(t){var o=t*m;n.fetchAllPhrase(e.context,I,o,m).then(h)}function h(t){N.phrases=t}var v,I,m=50,N=this;return d(),N.phrases=[],e.updateContext(a.projectSlug,a.versionSlug,o.decodeDocId(a.docId),a.localeId),p(),t.$on(i.EVENT.FILTER_TRANS_UNIT,function(t,e){if(e.status.all===!0)c.search("status",null);else{var n=[];u.forEach(e.status,function(t,e){t&&n.push(e)}),c.search("status",n.join(","))}d(),p()}),t.$on(i.EVENT.GOTO_FIRST_PAGE,function(){e.currentPageIndex>0&&(e.currentPageIndex=0,E(e.currentPageIndex))}),t.$on(i.EVENT.GOTO_PREV_PAGE,function(){e.currentPageIndex>0&&(e.currentPageIndex-=1,E(e.currentPageIndex))}),t.$on(i.EVENT.GOTO_NEXT_PAGE,function(){e.currentPageIndex-1?!1:"INPUT"===t.tagName||"SELECT"===t.tagName||"TEXTAREA"===t.tagName||t.isContentEditable}function v(t){m(A.filter.status)?I(t):(A.filter.status.all=!1,t&&S.emitEvent(S.EVENT.FILTER_TRANS_UNIT,A.filter))}function I(t){A.filter.status.all=!0,A.filter.status.approved=!1,A.filter.status.translated=!1,A.filter.status.needsWork=!1,A.filter.status.untranslated=!1,t&&S.emitEvent(S.EVENT.FILTER_TRANS_UNIT,A.filter)}function m(t){return t.approved===t.translated&&t.translated===t.needsWork&&t.needsWork===t.untranslated}function N(){O()&&l.go("editor.selectedContext",{docId:A.context.docId,localeId:A.context.localeId})}function O(){return A.context.docId&&A.context.localeId}function _(t,e,o,r){n.getStatistics(t,e,o,r).then(function(t){A.wordStatistic=s.getWordStatistic(t),A.messageStatistic=s.getMsgStatistic(t)},function(t){d.displayError("Error loading statistic: "+t)})}var A=this;A.pageNumber=1,A.showCheatsheet=!1,A.shortcuts=E.mapValues(E.values(g.SHORTCUTS),function(t){var e=E.flatten(t.keyCombos,"combo");return{combos:E.map(e,function(t){return g.symbolizeKey(t)}),description:t.keyCombos[0].description}}),A.filter={status:{all:!0,approved:!1,translated:!1,needsWork:!1,untranslated:!1}},T(),p.bind("?",function(e){var n=e.srcElement;A.showCheatsheet||h(n)||(A.toggleKeyboardShortcutsModal(),t.$digest())},"keyup"),A.context=i.initContext(u.projectSlug,u.versionSlug,n.decodeDocId(u.docId),o.DEFAULT_LOCALE,o.DEFAULT_LOCALE.localeId,"READ_WRITE"),A.toggleKeyboardShortcutsModal=function(){A.showCheatsheet=!A.showCheatsheet};var C=a.SETTING.SHOW_SUGGESTIONS;t.showSuggestions=a.subscribe(C,function(e){t.showSuggestions=e}),A.toggleSuggestionPanel=function(){a.update(C,!t.showSuggestions)},A.versionPage=function(){return c.PROJECT_PAGE(A.context.projectSlug,A.context.versionSlug)},A.encodeDocId=function(t){return n.encodeDocId(t)},r.getProjectInfo(u.projectSlug).then(function(t){A.projectInfo=t},function(t){d.displayError("Error getting project information:"+t)}),o.getSupportedLocales(A.context.projectSlug,A.context.versionSlug).then(function(t){if(A.locales=t,!A.locales||A.locales.length<=0)d.displayError("No supported locales in "+A.context.projectSlug+" : "+A.context.versionSlug);else{var e=l.params.localeId,n=A.context;e?(n.localeId=e,o.containsLocale(A.locales,e)||(n.localeId=A.locales[0].localeId)):(n.localeId=A.locales[0].localeId,N())}},function(t){d.displayError("Error getting locale list: "+t)}),n.findAll(A.context.projectSlug,A.context.versionSlug).then(function(t){if(A.documents=t,!A.documents||A.documents.length<=0)d.displayError("No documents in "+A.context.projectSlug+" : "+A.context.versionSlug);else{var e=l.params.docId,o=A.context;e?(o.docId=n.decodeDocId(e),n.containsDoc(A.documents,o.docId)||(o.docId=A.documents[0].name)):(o.docId=A.documents[0].name,N())}},function(t){d.displayError("Error getting document list: "+t)}),f.$on(S.EVENT.SELECT_TRANS_UNIT,function(t,e){A.unitSelected=e.id,A.focused=e.focus}),f.$on(S.EVENT.CANCEL_EDIT,function(){A.unitSelected=!1,A.focused=!1}),f.$on(S.EVENT.REFRESH_STATISTIC,function(t,e){_(e.projectSlug,e.versionSlug,e.docId,e.localeId),A.context.docId=e.docId,A.context.localeId=e.localeId}),A.pageNumber=function(){return 0===i.maxPageIndex?i.currentPageIndex+1:i.currentPageIndex+1+" of "+(i.maxPageIndex+1)},A.getLocaleName=function(t){return o.getName(t)},A.firstPage=function(){S.emitEvent(S.EVENT.GOTO_FIRST_PAGE)},A.lastPage=function(){S.emitEvent(S.EVENT.GOTO_LAST_PAGE)},A.nextPage=function(){S.emitEvent(S.EVENT.GOTO_NEXT_PAGE)},A.previousPage=function(){S.emitEvent(S.EVENT.GOTO_PREV_PAGE)},A.resetFilter=function(){I(!0)},A.updateFilter=function(){v(!0)},this.settings=e.settings.editor,g.enableEditorKeys()}t.$inject=["$scope","UserService","DocumentService","LocaleService","ProjectService","EditorService","SettingsService","StatisticUtil","UrlService","$stateParams","$state","MessageHandler","$rootScope","EventService","EditorShortcuts","_","Mousetrap"],angular.module("app").controller("EditorCtrl",t)}(),function(){"use strict";function t(){var t=this;return t}angular.module("app").controller("EditorDetailsCtrl",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s,c,u){function l(t,e){return a.hasTranslationChanged(t)||t.status!==e}function d(t){var a=n.cloneDeep(S.context),l=g[t],d=e(o.TRANSLATION_URL,{},{update:{method:"PUT",params:{localeId:l.locale}}}),f={id:l.phrase.id,revision:l.phrase.revision||0,content:l.phrase.newTranslations[0],contents:l.phrase.newTranslations,status:u.getServerId(l.status.ID),plural:l.phrase.plural};d.update(f).$promise.then(function(t){var e=l.phrase.status.ID;i.onTransUnitUpdated(a,f.id,l.locale,t.revision,t.status,l.phrase),s.updateStatistic(a.projectSlug,a.versionSlug,l.docId,l.locale,e,u.getId(t.status),l.phrase.wordCount),r.emitEvent(r.EVENT.SAVE_COMPLETED,l.phrase)},function(t){c.displayWarning("Update translation failed for "+f.id+" -"+t),i.onTransUnitUpdateFailed(f.id),r.emitEvent(r.EVENT.SAVE_COMPLETED,l.phrase)}),delete g[t]}function f(t,e){return n.isEmpty(n.compact(t.newTranslations))?u.getStatusInfo("UNTRANSLATED"):e}var S=this,g={};return S.context={},S.currentPageIndex=0,S.maxPageIndex=0,S.initContext=function(t,e,n,o,r,i){return S.context={projectSlug:t,versionSlug:e,docId:n,srcLocale:o,localeId:r,mode:i},S.context},S.updateContext=function(t,e,n,o){S.context.projectSlug!==t&&(S.context.projectSlug=t),S.context.versionSlug!==e&&(S.context.versionSlug=e),S.context.docId!==n&&(S.context.docId=n),S.context.localeId!==o&&(S.context.localeId=o)},t.$on(r.EVENT.SAVE_TRANSLATION,function(t,e){var o=e.phrase,i=e.status;if(l(o,i)){if(n.has(g,o.id)){var a=g[o.id];a.phrase=o,a.status=i}else i=f(o,i),g[o.id]={phrase:o,status:i,locale:e.locale,docId:e.docId};r.emitEvent(r.EVENT.SAVE_INITIATED,e),d(o.id)}}),S}t.$inject=["$rootScope","$resource","_","UrlService","EventService","PhraseService","PhraseUtil","DocumentService","MessageHandler","TransStatusService"],angular.module("app").factory("EditorService",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s,c){function u(e){m.selectedTUCtrl&&(e.preventDefault(),t.emitEvent(t.EVENT.COPY_FROM_SOURCE,{phrase:m.selectedTUCtrl.getPhrase()}))}function l(e){m.selectedTUCtrl&&(e.preventDefault(),e.stopPropagation(),t.emitEvent(t.EVENT.GOTO_NEXT_ROW,v()))}function d(e){m.selectedTUCtrl&&(e.preventDefault(),e.stopPropagation(),t.emitEvent(t.EVENT.GOTO_PREVIOUS_ROW,v()))}function f(e){if(e.preventDefault(),e.stopPropagation(),N)m.cancelSaveAsModeIfOn(),m.selectedTUCtrl&&m.selectedTUCtrl.focusTranslation();else if(m.selectedTUCtrl){var n=m.selectedTUCtrl.getPhrase();r.hasTranslationChanged(n)?t.emitEvent(t.EVENT.UNDO_EDIT,n):t.emitEvent(t.EVENT.CANCEL_EDIT,n)}}function S(n){if(m.selectedTUCtrl){n.preventDefault();var o=m.selectedTUCtrl.getPhrase();t.emitEvent(t.EVENT.SAVE_TRANSLATION,{phrase:o,status:r.getSaveButtonStatus(o),locale:e.localeId,docId:e.docId})}}function g(e){e.preventDefault(),m.cancelSaveAsModeIfOn();var n=m.selectedTUCtrl.getPhrase();n&&(t.emitEvent(t.EVENT.TOGGLE_SAVE_OPTIONS,{id:n.id,open:!0}),I(n,"n","needsWork"),I(n,"t","translated"),I(n,"a","approved"))}function E(e){return function(n){n.preventDefault(),t.emitEvent(t.EVENT.COPY_FROM_SUGGESTION_N,e-1)}}function p(t,e,n,o,r){return this.defaultKey=t,this.keyCombos=[T(t,n,r,e)],o&&(this.otherKeys=o instanceof Array?o:[o],this.keyCombos.push(T(this.otherKeys,"",r,e))),this}function T(t,e,n,o){var r={allowIn:["TEXTAREA"],callback:o};return r.combo=t,e&&(r.description=e),n&&(r.action=n),r}function h(t){o.get(t.defaultKey)||n.forEach(t.keyCombos,function(t){o.add(t)})}function v(){return{currentId:m.selectedTUCtrl.getPhrase().id}}function I(t,e,n){var r=i.getStatusInfo(n);return o.add({combo:e,description:s.sprintf("Save as %s",n),allowIn:["INPUT","TEXTAREA"],action:"keydown",callback:function(e){m.saveTranslationCallBack(e,t,r)}})}var m=this,N=!1;return m.selectedTUCtrl=null,m.SHORTCUTS={COPY_SOURCE:new p("alt+c",u,"Copy source as translation","alt+g"),COPY_SUGGESTION_1:new p("mod+alt+1",E(1),"Copy first suggestion as translation"),COPY_SUGGESTION_2:new p("mod+alt+2",E(2),"Copy second suggestion as translation"),COPY_SUGGESTION_3:new p("mod+alt+3",E(3),"Copy third suggestion as translation"),COPY_SUGGESTION_4:new p("mod+alt+4",E(4),"Copy fourth suggestion as translation"),CANCEL_EDIT:new p("esc",f,"Cancel edit"),SAVE_AS_CURRENT_BUTTON_OPTION:new p("mod+s",S,"Save"),SAVE_AS_MODE:new p("mod+shift+s",g,"Save as…"),SAVE_AS_NEEDSWORK:{keyCombos:[{combo:"mod+shift+s n",description:"Save as needs work"}]},SAVE_AS_TRANSLATED:{keyCombos:[{combo:"mod+shift+s t",description:"Save as translated"}]},SAVE_AS_APPROVED:{keyCombos:[{combo:"mod+shift+s a",description:"Save as approved"}]},GOTO_NEXT_ROW_FAST:new p("mod+enter",l,"Save (if changed) and go to next string",["alt+k","alt+down"]),GOTO_PREVIOUS_ROW:new p("mod+shift+enter",d,"Save (if changed) and go to previous string",["alt+j","alt+up"])},m.enableEditorKeys=function(){o.get(m.SHORTCUTS.COPY_SOURCE.defaultKey)||n.forOwn(m.SHORTCUTS,function(t){t instanceof p&&h(t)})},m.disableEditorKeys=function(){n.forOwn(m.SHORTCUTS,function(t){n.forEach(t.keyCombos,function(t){m.deleteKeys(t.combo,t.action)})})},m.saveTranslationCallBack=function(n,o,r){N=!0,n.preventDefault(),n.stopPropagation(),t.emitEvent(t.EVENT.SAVE_TRANSLATION,{phrase:o,status:r,locale:e.localeId,docId:e.docId}),m.cancelSaveAsModeIfOn()},m.cancelSaveAsModeIfOn=function(){N&&m.selectedTUCtrl&&(N=!1,m.deleteKeys(["n","t","a"]),t.emitEvent(t.EVENT.TOGGLE_SAVE_OPTIONS,{id:m.selectedTUCtrl.getPhrase().id,open:!1}))},m.deleteKeys=function(t,e){var r=t instanceof Array?t:[t];e=e||"keydown",n.forEach(r,function(t){o.del(t),a.unbind(t,e)})},m.symbolizeKey=function(t){var e={command:"⌘",shift:"⇧",left:"←",right:"→",up:"↑",down:"↓","return":"↩",backspace:"⌫"};t=t.split("+");for(var n=0;n=0?"command":"ctrl"),t[n]=e[t[n]]||t[n];return t.join(" + ")},m}t.$inject=["EventService","$stateParams","_","hotkeys","PhraseUtil","TransStatusService","Mousetrap","str","$window"],angular.module("app").factory("EditorShortcuts",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s,c){function u(e){t.isTextSearch=e,t.isPhraseSearch=!e}function l(e){t.suggestions=e}function d(){t.search.isVisible=!1,u(!1),S()}function f(e,n){t.search.input.text="",t.search.isVisible=!0,!n&&e&&t.focusSearch(e),h.searchForText(),g()}function S(){t.searchStrings=o.getSearchStrings(),t.search.isLoading=o.isLoading(),l(o.getResults())}function g(){t.searchStrings=r.getSearchStrings(),t.search.isLoading=r.isLoading(),l(r.getResults())}function E(t){t&&i.emitEvent(i.EVENT.COPY_FROM_SUGGESTION,{suggestion:t})}var p=n.SETTING.SHOW_SUGGESTIONS,T=n.SETTING.SUGGESTIONS_SHOW_DIFFERENCE,h=this;return t.suggestions=[],t.hasSuggestions=!1,t.$watch("suggestions.length",function(e){t.hasSuggestions=0!==e}),t.searchStrings=[],t.hasSearch=!1,t.$watch("searchStrings.length",function(e){t.hasSearch=0!==e}),t.isTransUnitSelected=!1,t.isTextSearch=!1,t.isPhraseSearch=!0,t.search={isVisible:!1,isLoading:!1,input:{text:"",focused:!1}},t.$watch("search.input.text",function(){h.searchForText()}),t.show=n.subscribe(p,function(e){t.show=e,e&&(t.isTransUnitSelected?S():t.search.isVisible||f(null,!0))}),t.diff=n.subscribe(T,function(e){t.diff=e}),t.focusSearch=function(t){t&&t.preventDefault(),c("searchSugInput")},h.closeSuggestions=function(){n.update(p,!1),i.emitEvent(i.EVENT.SUGGESTIONS_SEARCH_TOGGLE,!1)},h.clearSearchResults=function(e,n){t.search.input.text="",!n&&e&&t.focusSearch(e)},h.searchForText=function(){var e=t.search.input.text;e.length>0&&(t.search.isLoading=!0),u(!0),i.emitEvent(i.EVENT.REQUEST_TEXT_SUGGESTIONS,e)},h.toggleSearch=function(){t.search.isVisible?i.emitEvent(i.EVENT.SUGGESTIONS_SEARCH_TOGGLE,!1):i.emitEvent(i.EVENT.SUGGESTIONS_SEARCH_TOGGLE,!0)},t.show&&!t.isTransUnitSelected&&f(),a.$on(i.EVENT.SELECT_TRANS_UNIT,function(){""===t.search.input.text&&t.search.isVisible&&i.emitEvent(i.EVENT.SUGGESTIONS_SEARCH_TOGGLE,!1),t.isTransUnitSelected=!0}),a.$on(i.EVENT.CANCEL_EDIT,function(){t.isTransUnitSelected=!1,t.show&&!t.search.isVisible&&f(null,!0)}),a.$on(i.EVENT.SUGGESTIONS_SEARCH_TOGGLE,function(t,e){e?f(t):d(t)}),a.$on("PhraseSuggestionsService:updated",function(){t.isPhraseSearch&&S()}),a.$on("TextSuggestionsService:updated",function(){t.isTextSearch&&g()}),a.$on(i.EVENT.COPY_FROM_SUGGESTION_N,function(e,n){t.show?(E(t.suggestions[n]),t.$broadcast("EditorSuggestionsCtrl:nth-suggestion-copied",n)):E(o.getResults()[n])}),h}t.$inject=["$scope","_","SettingsService","PhraseSuggestionsService","TextSuggestionsService","EventService","$rootScope","$timeout","focus"],angular.module("app").controller("EditorSuggestionsCtrl",t)}(),function(){"use strict";function t(){return{restrict:"A",link:function(t,e,n){return t.$on("blurOn",function(t,o){return o===n.blurOn?e[0].blur():void 0})}}}angular.module("app").directive("blurOn",t)}(),function(){"use strict";function t(t){return{restrict:"A",scope:{callback:"&clickElsewhere"},link:function(e,n){var o=function(t){n[0].contains(t.target)||e.$apply(e.callback(t))};t.on("click",o),e.$on("$destroy",function(){t.off("click",o)})}}}t.$inject=["$document"],angular.module("app").directive("clickElsewhere",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s){function c(t,e){return t+"-"+e}function u(t,e,n,o){var i=r.getWordStatistic(t),a=r.getMsgStatistic(t);if(i){o=parseInt(o);var s=parseInt(i[e])-o;i[e]=0>s?0:s,i[n]=parseInt(i[n])+o}if(a){var c=parseInt(a[e])-1;a[e]=0>c?0:c,a[n]=parseInt(a[n])+1}}var l=this,d={};return l.findAll=function(t,o){var r=e(n.DOCUMENT_LIST_URL,{},{query:{method:"GET",params:{projectSlug:t,versionSlug:o},isArray:!0}});return r.query().$promise},l.getStatistics=function(o,r,i,u){if(i&&u){var f=c(i,u);if(a.has(d,f))return t.when(d[f]);var S=l.encodeDocId(i),g=e(n.DOC_STATISTIC_URL,{},{query:{method:"GET",params:{projectSlug:o,versionSlug:r,docId:S,localeId:u},isArray:!0}});return g.query().$promise.then(function(t){return a.forEach(t,function(t){t[s.getId("needswork")]=t.needReview||0}),d[f]=t,d[f]})}},l.encodeDocId=function(t){return t?t.replace(/\//g,","):t},l.decodeDocId=function(t){return t?t.replace(/\,/g,"/"):t},l.containsDoc=function(t,e){return a.any(t,function(t){return o.equals(t.name,e,!0)})},l.updateStatistic=function(t,e,n,o,r,s,l){var f=c(n,o);a.has(d,f)&&(u(d[f],r,s,l),i.emitEvent(i.EVENT.REFRESH_STATISTIC,{projectSlug:t,versionSlug:e,docId:n,localeId:o}))},l}t.$inject=["$q","$resource","UrlService","StringUtil","StatisticUtil","EventService","_","TransStatusService"],angular.module("app").factory("DocumentService",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a){var s,c=this,u=t.$new(),l=o.openClass,d=angular.noop,f=e.onToggle?n(e.onToggle):angular.noop;this.init=function(o){c.$element=o,e.isOpen&&(s=n(e.isOpen),d=s.assign,t.$watch(s,function(t){u.isOpen=!!t}))},this.toggle=function(t){return u.isOpen=arguments.length?!!t:!u.isOpen,u.isOpen},this.isOpen=function(){return u.isOpen},u.getToggleElement=function(){return c.toggleElement},u.focusToggleElement=function(){c.toggleElement&&c.toggleElement[0].focus()},u.$watch("isOpen",function(e,n){i[e?"addClass":"removeClass"](c.$element,l),e?(a(function(){u.focusToggleElement()}),r.open(u)):r.close(u),d(t,e),angular.isDefined(e)&&e!==n&&f(t,{open:!!e})}),t.$on("$locationChangeSuccess",function(){u.isOpen=!1}),t.$on("$destroy",function(){u.$destroy()}),t.$on("openDropdown",function(){u.isOpen=!0}),t.$on("closeDropdown",function(){u.isOpen=!1})}t.$inject=["$scope","$attrs","$parse","dropdownConfig","DropdownService","$animate","$timeout"],angular.module("app").controller("DropdownCtrl",t)}(),function(){"use strict";function t(t){var e=null,n=this;n.open=function(n){e||(t.bind("click",o),t.bind("keydown",r)),e&&e!==n&&(e.isOpen=!1),e=n},n.close=function(n){e===n&&(e=null,t.unbind("click",o),t.unbind("keydown",r))};var o=function(t){if(e){var n=e.getToggleElement();t&&n&&n[0].contains(t.target)||e.$apply(function(){e.isOpen=!1})}},r=function(t){27===t.which&&(e.focusToggleElement(),o())}}t.$inject=["$document"],angular.module("app").service("DropdownService",t)}(),function(){"use strict";var t={openClass:"is-active"};angular.module("app").constant("dropdownConfig",t)}(),function(){"use strict";function t(){return{restrict:"EA",controller:"DropdownCtrl",link:function(t,e,n,o){o.init(e)}}}function e(){return{restrict:"A",require:"?^dropdown",scope:{callback:"&onCloseDropdown"},link:function(t,e,n,o){o.onCloseDropdown=t.callback}}}function n(){return{restrict:"EA",require:"?^dropdown",link:function(t,e,n,o){if(o){o.toggleElement=e;var r=function(r){r.preventDefault(),r.stopPropagation(),e.hasClass("disabled")||n.disabled||t.$apply(function(){o.toggle()})};e.bind("click",r),e.attr({"aria-haspopup":!0,"aria-expanded":!1}),t.$watch(o.isOpen,function(n){e.attr("aria-expanded",!!n),o.onCloseDropdown&&!n&&t.$applyAsync(o.onCloseDropdown)}),t.$on("$destroy",function(){e.unbind("click",r)})}}}}angular.module("app").directive("dropdown",t).directive("onCloseDropdown",e).directive("dropdownToggle",n)}(),function(){"use strict";function t(t){var e=this;return e.EVENT={LOADING_START:"loadingStart",LOADING_STOP:"loadingStop",SELECT_TRANS_UNIT:"selectTransUnit",COPY_FROM_SOURCE:"copyFromSource",COPY_FROM_SUGGESTION:"copyFromSuggestion",COPY_FROM_SUGGESTION_N:"copyFromSuggestionN",UNDO_EDIT:"undoEdit",CANCEL_EDIT:"cancelEdit",FOCUS_TRANSLATION:"focusTranslation",SAVE_TRANSLATION:"saveTranslation",SAVE_INITIATED:"saveInitiated",SAVE_COMPLETED:"saveCompleted",TRANSLATION_TEXT_MODIFIED:"translationTextModified",REFRESH_STATISTIC:"refreshStatistic",GOTO_PREV_PAGE:"gotoPreviousPage",GOTO_NEXT_PAGE:"gotoNextPage",GOTO_FIRST_PAGE:"gotoFirstPage",GOTO_LAST_PAGE:"gotoLastPage",GOTO_NEXT_ROW:"gotoNextRow",GOTO_PREVIOUS_ROW:"gotoPreviousRow",GOTO_NEXT_UNTRANSLATED:"gotoNextUntranslated",TOGGLE_SAVE_OPTIONS:"openSaveOptions",FILTER_TRANS_UNIT:"filterTransUnit",PHRASE_SUGGESTION_COUNT:"phraseSuggestionCount",REQUEST_PHRASE_SUGGESTIONS:"requestPhraseSuggestions",REQUEST_TEXT_SUGGESTIONS:"requestTextSuggestions",SUGGESTIONS_SEARCH_TOGGLE:"suggestionsSearchToggle",USER_SETTING_CHANGED:"userSettingChanged"},e.broadcastEvent=function(e,n,o){o=o||t,o.$broadcast(e,n)},e.emitEvent=function(e,n,o){o=o||t,o.$emit(e,n)},e}t.$inject=["$rootScope"],angular.module("app").factory("EventService",t)}(),function(){"use strict";function t(t){return{restrict:"E",required:["name"],scope:{name:"@",title:"@",size:"@"},link:function(e,n){var o="",r="",i="";n.addClass("Icon"),e.title&&(i=""+e.title+""),"loader"===e.name?(n.addClass("Icon--loader"),r='',n.html(t.trustAsHtml(r))):(o=''+i+"",n.html(t.trustAsHtml(o)))}}}t.$inject=["$sce"],angular.module("app").directive("icon",t)}(),function(){"use strict";function t(){return{displayError:function(t){console.error(t)},displayWarning:function(t){console.warn(t)},displayInfo:function(t){console.info(t)}}}angular.module("app").factory("MessageHandler",t)}(),function(){"use strict";function t(t,e,n,o,r){function i(e,n){var r=o(t.LOCALE_LIST_URL,{},{query:{method:"GET",params:{projectSlug:e,versionSlug:n},isArray:!0}});return r.query().$promise}function a(){var e=o(t.ALL_LOCALE_URL,{},{query:{method:"GET",isArray:!0}});return e.query().$promise.then(function(t){d=n.cleanResourceList(t)})}function s(){var e=o(t.uiTranslationListURL,{},{query:{method:"GET"}});return e.query().$promise}function c(t,n){return t?r.find(t,function(t){return e.equals(t.localeId,n,!0)}):void 0}function u(t,n){return r.any(t,function(t){return e.equals(t.localeId,n,!0)})}function l(t){var e=c(d,t);return e?e.name:t}var d=[];return{getSupportedLocales:i,getUILocaleList:s,getLocaleByLocaleId:c,getAllLocales:a,containsLocale:u,getName:l,DEFAULT_LOCALE:{localeId:"en-US",name:"English"}}}t.$inject=["UrlService","StringUtil","FilterUtil","$resource","_"],angular.module("app").factory("LocaleService",t)}(),function(){"use strict";function t(t){return{restrict:"EA",scope:{loading:"=",inverted:"="},link:function(e){e.classes="",e.$on(t.EVENT.LOADING_START,function(){e.classes+=" is-loading"}),e.$on(t.EVENT.LOADING_STOP,function(){e.classes=e.classes.replace("is-loading","")}),e.$watch("inverted",function(t){t?e.classes+=" LogoLoader--inverted":e.classes=e.classes.replace("LogoLoader--inverted","")})},templateUrl:"components/logo-loader/logo-loader.html"}}t.$inject=["EventService"],angular.module("app").directive("logoLoader",t)}(),function(){"use strict";function t(){}angular.module("app").factory("NotificationService",t)}(),function(){"use strict";function t(t,e,n,o,r,i){function a(t,e,n,o){return t+"-"+e+"-"+n+"-"+o}var s=this,c={},u={};return s.getStates=function(s,u,l,d){var f=a(s,u,l,d);if(i.has(c,f))return t.when(c[f]);var S=r.encodeDocId(l),g={query:{method:"GET",params:{projectSlug:s,versionSlug:u,docId:S,localeId:d},isArray:!0}},E=e(o.TRANSLATION_STATUS_URL,{},g);return E.query().$promise.then(function(t){return t=n.cleanResourceList(t),c[f]=t,c[f]})},s.getTransUnits=function(r,a){function s(t){t=n.cleanResourceMap(t);for(var e in t)u[e][a]=t[e][a],l[e]=u[e];return l}function c(t){t=n.cleanResourceMap(t);for(var e in t)u[e]=t[e],l[e]=u[e];return l}var l={},d=[],f=[];if(r.forEach(function(t){i.has(u,t)?u[t][a]?l[t]=u[t]:f.push(t):d.push(t)}),i.isEmpty(d)&&i.isEmpty(f))return t.when(l);var S,g;return i.isEmpty(d)||(S=e(o.TEXT_FLOWS_URL,{},{query:{method:"GET",params:{localeId:a,ids:d.join(",")}}})),i.isEmpty(f)||(g=e(o.TRANSLATION_URL,{},{query:{method:"GET",params:{localeId:a,ids:f.join(",")}}})),S&&g?S.query().$promise.then(c).then(g.query().$promise.then(s)):S?S.query().$promise.then(c):g?g.query().$promise.then(s):void 0},s.onTransUnitUpdated=function(t,e,n,o,r,s){var l=a(t.projectSlug,t.versionSlug,t.docId,n),d=i.find(c[l],function(t){return t.id===e});d&&(d.state=r);var f=u[e][n];f||(f={}),f.revision=parseInt(o),f.state=r,f.contents=s.newTranslations.slice()},s}t.$inject=["$q","$resource","FilterUtil","UrlService","DocumentService","_"],angular.module("app").factory("PhraseCache",t)}(),function(){"use strict";function t(t,e,n,o,r){function i(t,e){return o.find(e,function(e){return e.id===t})}function a(e,n){return n&&(e=t.filterResources(e,["status"],n)),o.map(e,function(t){return t.id})}var s={};return s.phrases=[],s.getPhraseCount=function(t,n){return e.getStates(t.projectSlug,t.versionSlug,t.docId,t.localeId).then(function(t){var e=a(t,n.status);return e.length})},s.fetchAllPhrase=function(t,r,i,c){function u(t){var n=a(t,r.status);return isNaN(i)||(n=isNaN(c)?n.slice(i):n.slice(i,i+c)),e.getTransUnits(n,S).then(l).then(f)}function l(t){return o.map(t,function(t,e){var o=t.source,r=t[S];return{id:parseInt(e),sources:o.plural?o.contents:[o.content],translations:d(o,r),newTranslations:d(o,r),plural:o.plural,status:n.getStatusInfo(r?r.state:"untranslated"),revision:r?parseInt(r.revision):0,wordCount:parseInt(o.wordCount)}})}function d(t,e){return t.plural?e&&e.contents?e.contents.slice():[]:e?[e.content]:[]}function f(n){return e.getStates(t.projectSlug,t.versionSlug,t.docId,S).then(function(t){return s.phrases=o.sortBy(n,function(e){var r=o.findIndex(t,function(t){return t.id===e.id});return r>=0?r:n.length}),s.phrases})}var S=t.localeId;return e.getStates(t.projectSlug,t.versionSlug,t.docId,S).then(u)},s.onTransUnitUpdated=function(t,o,r,a,c,u){e.onTransUnitUpdated(t,o,r,a,c,u);var l=i(o,s.phrases);l&&(l.translations=u.newTranslations.slice(),l.revision=a,l.status=n.getStatusInfo(c))},s.onTransUnitUpdateFailed=function(t){var e=i(t,s.phrases);e&&(e.newTranslations=e.translations.slice())},s.findNextId=function(t){return e.getStates(r.projectSlug,r.versionSlug,r.docId,r.localeId).then(function(e){var n,r;return n=o.findIndex(e,function(e){return e.id===t}),r=n+1=0?n-1:0,e[r].id})},s.findNextStatus=function(t,i){return e.getStates(r.projectSlug,r.versionSlug,r.docId,r.localeId).then(function(e){var r,a,s=n.getStatusInfo(i);r=o.findIndex(e,function(e){return e.id===t});for(var c=r+1;ce?e:n>t?n:t}function E(t,e){return/[0-9]*\.?[0-9]+%/.test(t)?Math.round(e*(parseInt(t.replace("%",""))/100)):parseInt(t)}r.height=parseInt(a.resizerHeight),r.actualHeight=r.height,r.position=E(t.get(t.SETTING.SUGGESTIONS_PANEL_HEIGHT),e.innerHeight),r.actualPosition=r.position,r.show=t.subscribe(t.SETTING.SHOW_SUGGESTIONS,function(t){r.show=t,c(t)}),c(r.show),i.addClass("Resizer"),"vertical"===a.resizer?(i.addClass("Resizer--vertical"),o(function(){l(r.actualPosition)})):(i.addClass("Resizer--horizontal"),o(function(){d(r.actualPosition)})),i.on("mousedown",function(t){t.preventDefault(),n.on("mousemove",u),n.on("mouseup",f)}),angular.element(e).bind("resize",function(){o.cancel(r.resizing),r.resizing=o(S)})}return{link:r}}t.$inject=["SettingsService","$window","$document","$timeout"],angular.module("app").directive("resizer",t)}(),function(){"use strict";function t(t,e,n,o){function r(e,n){c(n);var r={};r[e]=n,o.extend(f,r),t.emitEvent(t.EVENT.USER_SETTING_CHANGED,{setting:e,value:n})}function i(t){o.each(t,function(t,e){r(e,t)})}function a(t){return o.has(f,t)?f[t]:void console.error("Tried to look up setting with unrecognized key: %s",t)}function s(e,o){return n.$on(t.EVENT.USER_SETTING_CHANGED,function(t,n){n.setting===e&&o(n.value)}),a(e)}function c(t){switch(typeof t){case"boolean":case"number":case"string":break;default:throw new Error('Invalid type for setting value: "'+typeof t+'".')}}var u=this;u.SETTING={SUGGESTIONS_AUTOFILL_ON_ROW_SELECT:"suggestionsAutofillOnRowSelect",SUGGESTIONS_SHOW_DIFFERENCE:"suggestionsShowDifference",SHOW_SUGGESTIONS:"showSuggestions",SUGGESTIONS_PANEL_HEIGHT:"suggestionsPanelHeight"};var l=u.SETTING,d={};d[l.SUGGESTIONS_AUTOFILL_ON_ROW_SELECT]=!0,d[l.SUGGESTIONS_SHOW_DIFFERENCE]=!1,d[l.SHOW_SUGGESTIONS]=!0,d[l.SUGGESTIONS_PANEL_HEIGHT]="30%";var f=o.clone(d);return{SETTING:l,update:r,updateAll:i,get:a,subscribe:s}}t.$inject=["EventService","$q","$rootScope","_"],angular.module("app").factory("SettingsService",t)}(),function(){"use strict";function t(){function t(t,e){return t.replace(e.regex,e.template)}var e={space:{regex:/ /g,template:' '},newline:{regex:/\n/g,template:'\n'},tab:{regex:/\t/g,template:' '}};return{restrict:"A",required:["ngBind"],scope:{ngBind:"="},link:function(n,o){n.$watch("ngBind",function(n){n=t(n,e.space),n=t(n,e.newline),n=t(n,e.tab),o.html(n)})}}}angular.module("app").directive("renderWhitespaceCharacters",t)}(),function(){"use strict";function t(){var t=this;t.init=function(){var e=t.container[0],n=t.child[0],o=n.offsetWidth-e.offsetWidth;t.width=o/2}}angular.module("app").controller("ScrollbarWidthCtrl",t)}(),function(){"use strict";function t(){return{restrict:"A",controller:"ScrollbarWidthCtrl as scrollbarWidthCtrl",link:function(t,e,n,o){o.init(e)}}}function e(){return{restrict:"A",require:"?^scrollbarWidth",link:function(t,e,n,o){o&&e.css(n.scrollbarWidthElement,o.width)}}}function n(){return{restrict:"A",require:"?^scrollbarWidth",link:function(t,e,n,o){o&&(o.container=e)}}}function o(){return{restrict:"A",require:"?^scrollbarWidth",link:function(t,e,n,o){o&&(o.child=e)}}}angular.module("app").directive("scrollbarWidth",t).directive("scrollbarWidthElement",e).directive("scrollbarWidthContainer",n).directive("scrollbarWidthChild",o)}(),function(){"use strict";function t(t,e,n,o,r){function i(){return g}function a(){return E?E.sources:[]}function s(){return p}function c(t){m=t,T||u()}function u(){var t=v+f,e=t-Date.now(),n=e>0?e:f;T=o(function(){return T=null,h>=S?void u():void l()},n)}function l(){if(null!==m){var t=m;m=null,o.cancel(T),T=null,d(t)}}function d(t){E=t;var e=Date.now();v=e,h++,n.getSuggestionsForPhrase(t).then(function(t){e>I&&(I=e,p=t)},function(t){console.error("Error searching for phrase ",t)})["finally"](function(){h--,r.$broadcast("PhraseSuggestionsService:updated"),S>h&&l()})}var f=300,S=3,g=!1,E=null,p=[],T=null,h=0,v=Date.now(),I=Date.now(),m=null;return r.$on(e.EVENT.REQUEST_PHRASE_SUGGESTIONS,function(t,e){var n=e.phrase;if(!(m&&m.id===n.id||!m&&0===h&&E&&E.id===n.id)){if(h>=S)return void c(n);var o=v+f;if(Date.now()99.99&&100>t?"99.99":t>=99.9&&100>t?"99.9":Math.round(t)!==t?t.toFixed(1):t},i.topMatch=function(){return n.suggestion.matchDetails[0]},i.showSuggestionCopied=function(){i.copyButtonText="Copied",i.copyButtonDisabled=!0,r(function(){i.copyButtonDisabled=!1,i.copyButtonText="Copy Translation"},500)},i.copySuggestion=function(){i.showSuggestionCopied(),t.emitEvent(t.EVENT.COPY_FROM_SUGGESTION,{suggestion:n.suggestion})},n.$on("EditorSuggestionsCtrl:nth-suggestion-copied",function(t,e){e===n.index&&i.showSuggestionCopied()}),n.detail=i.topMatch(),n.user=n.detail.lastModifiedBy||"Annoymous",n.remaining=n.suggestion.matchDetails.length-1,n.isTextFlow="LOCAL_PROJECT"===n.detail.type,i}t.$inject=["EventService","$rootScope","$scope","_","$timeout"],angular.module("app").controller("SuggestionCtrl",t)}(),function(){"use strict";function t(t,e,n,o,r){function i(t){return s([t])}function a(t){return s(t.sources).then(function(n){return e.emitEvent(e.EVENT.PHRASE_SUGGESTION_COUNT,{id:t.id,count:n.length}),n})}function s(e){var o=t.context.srcLocale.localeId,i=t.context.localeId,a={query:{method:"POST",params:{from:o,to:i,searchType:"FUZZY_PLURAL"},isArray:!0}},s=r(n.SUGGESTIONS_URL,{},a);return s.query({},e).$promise.then(c)}function c(t){return o.chain(t).map(l).map(u).sortBy(["similarityPercent","bestMatchScore","bestMatchModificationDate","relevanceScore"]).reverse().value()}function u(t){var e,n,r=t.matchDetails[0];return"LOCAL_PROJECT"===r.type&&(e=r.lastModifiedDate,n="Translated"===r.contentState?0:1),"IMPORTED_TM"===r.type&&(e=r.lastChanged,n=2),o.assign({},t,{bestMatchScore:n,bestMatchModificationDate:e})}function l(t){var e=o.sortBy(t.matchDetails,d);return o.assign({},t,{matchDetails:e})}function d(t){if("IMPORTED_TM"===t.type)return"3"+t.lastChanged;if("LOCAL_PROJECT"===t.type){if("Translated"===t.contentState)return"2"+t.lastModifiedDate;if("Approved"===t.contentState)return"1"+t.lastModifiedDate}return"9"}return{getSuggestionsForPhrase:a,getSuggestionsForText:i}}t.$inject=["EditorService","EventService","UrlService","_","$resource"],angular.module("app").factory("SuggestionsService",t)}(),function(){"use strict";function t(t,e,n,o,r){function i(){return T>0}function a(){return g?[g]:[]}function s(){return E}function c(t){I=t,p||u()}function u(){var t=h+f,e=t-Date.now(),n=e>0?e:f;p=r(function(){return p=null,T>=S?void u():void l()},n)}function l(){if(null!==I){var t=I;I=null,r.cancel(p),p=null,d(t)}}function d(t){g=t;var e=Date.now();h=e,T++,n.getSuggestionsForText(t).then(function(t){e>v&&(v=e,E=t)},function(t){console.error("Error searching for text ",t)})["finally"](function(){T--,o.$broadcast("TextSuggestionsService:updated"),S>T&&l()})}var f=300,S=3,g=null,E=[],p=null,T=0,h=Date.now(),v=Date.now(),I=null;return o.$on(e.EVENT.REQUEST_TEXT_SUGGESTIONS,function(t,e){if(!(I&&I===e||!I&&0===T&&g===e)){if(""===e)return g=e,E=[],I=null,r.cancel(p),p=null,h=Date.now,v=Date.now(),void o.$broadcast("TextSuggestionsService:updated");if(T>=S)return void c(e);var n=h+f;if(Date.now()')}}}angular.module("app").directive("toggleCheckbox",t)}(),function(){"use strict";function t(t){function e(t){return t=angular.uppercase(t),t&&"NEW"!==t?"NEEDREVIEW"===t&&(t="NEEDSWORK"):t="UNTRANSLATED",t}function n(t){return t=angular.lowercase(t),t&&"untranslated"!==t?"needswork"===t?"NeedReview":t.charAt(0).toUpperCase()+t.slice(1).toLowerCase():"New"}var o=this,r={UNTRANSLATED:{ID:"untranslated",NAME:"Untranslated",CSSCLASS:"neutral"},NEEDSWORK:{ID:"needswork",NAME:"Needs Work",CSSCLASS:"unsure"},TRANSLATED:{ID:"translated",NAME:"Translated",CSSCLASS:"success"},APPROVED:{ID:"approved",NAME:"Approved",CSSCLASS:"highlight"}};return o.getAll=function(){return r},o.getAllAsArray=function(){return t.values(r)},o.getStatusInfo=function(t){return r[e(t)]},o.getId=function(t){return r[e(t)].ID},o.getServerId=function(t){return n(t)},o.getName=function(t){return r[e(t)].NAME},o.getCSSClass=function(t){return r[e(t)].CSSCLASS},o}t.$inject=["_"],angular.module("app").factory("TransStatusService",t)}(),function(){"use strict";function t(){return{restrict:"E",required:["editor"],scope:{editor:"="},templateUrl:"components/transUnitFilter/trans-unit-filter.html"}}angular.module("app").directive("transUnitFilter",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s,c,u,l,d){function f(){S.selected||e.$apply(function(){a.emitEvent(a.EVENT.SELECT_TRANS_UNIT,{id:e.phrase.id,updateURL:!0,focus:!0},e)})}var S=this;S.selected=!1,S.focused=!1,S.focusedTranslationIndex=0,S.hasTranslationChanged=l.hasTranslationChanged,S.focusTranslation=function(){S.selected&&c("phrase-"+e.phrase.id+"-"+S.focusedTranslationIndex)},S.onTextAreaFocus=function(t,n){S.focused=!0,r.isUndefined(n)||(S.focusedTranslationIndex=n),S.selected||a.emitEvent(a.EVENT.SELECT_TRANS_UNIT,{id:t.id,updateURL:!0,focus:!0},e)},S.translationTextModified=function(t){a.emitEvent(a.EVENT.TRANSLATION_TEXT_MODIFIED,t)},S.getPhrase=function(){return e.phrase},S.init=function(){i.addController(e.phrase.id,S),o.id&&parseInt(o.id)===e.phrase.id&&a.emitEvent(a.EVENT.SELECT_TRANS_UNIT,{id:o.id,updateURL:!1,focus:o.selected})},S.copySource=function(t,n,o){t.stopPropagation(),a.emitEvent(a.EVENT.COPY_FROM_SOURCE,{phrase:n,sourceIndex:o},e)},S.undoEdit=function(t,n){t.stopPropagation(),a.emitEvent(a.EVENT.UNDO_EDIT,n,e)},S.cancelEdit=function(t,n){t.stopPropagation(),a.emitEvent(a.EVENT.CANCEL_EDIT,n,e)},S.saveAs=function(t,e,n){u.saveTranslationCallBack(t,e,n)},S.getLocaleName=function(t){return s.getName(t)},S.toggleSaveAsOptions=function(t){a.broadcastEvent(t?"openDropdown":"closeDropdown",{},e),t&&c(e.phrase.id+"-saveAsOption-0")};var g=d.SETTING.SHOW_SUGGESTIONS;return e.showSuggestions=d.subscribe(g,function(t){e.showSuggestions=t}),t.$on(a.EVENT.SUGGESTIONS_SEARCH_TOGGLE,function(t,e){S.suggestionsSearchIsActive=e}),S.toggleSuggestionPanel=function(){S.suggestionsSearchIsActive?a.emitEvent(a.EVENT.SUGGESTIONS_SEARCH_TOGGLE,!1):d.update(g,!e.showSuggestions)},e.suggestionCount=0,t.$on(a.EVENT.PHRASE_SUGGESTION_COUNT,function(t,n){n.id===e.phrase.id&&(e.suggestionCount=n.count)}),S.cancelSaveAsMode=function(){u.cancelSaveAsModeIfOn()},e.$on("$destroy",function(){n.unbind("click",f),n.unbind("focus",f)}),S.updateSaveButton=function(t){S.saveButtonStatus=l.getSaveButtonStatus(e.phrase),S.saveButtonOptions=i.getSaveButtonOptions(S.saveButtonStatus,e.phrase),S.saveButtonText=S.saveButtonStatus.NAME,S.saveButtonDisabled=!l.hasTranslationChanged(t),S.loadingClass="",S.savingStatus=""},S.phraseSaving=function(t){S.loadingClass="is-loading",S.saveButtonStatus=S.savingStatus=t.status,S.saveButtonOptions=i.getSaveButtonOptions(S.saveButtonStatus,t.phrase),S.saveButtonText="Saving…",S.saveButtonDisabled=!0},S.saveButtonOptionsAvailable=function(){return!r.isEmpty(S.saveButtonOptions)},S.selectTransUnit=function(t){S.selected||a.emitEvent(a.EVENT.SELECT_TRANS_UNIT,{id:t.id,updateURL:!0,focus:!0},e)},S}t.$inject=["$rootScope","$scope","$element","$stateParams","_","TransUnitService","EventService","LocaleService","focus","EditorShortcuts","PhraseUtil","SettingsService"],angular.module("app").controller("TransUnitCtrl",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s,c,u,l,d,f){function S(t,e){var n=0;if(t.plural){var o=N[t.id];n=o.focusedTranslationIndex}t.newTranslations[n]=e,s.emitEvent(s.EVENT.TRANSLATION_TEXT_MODIFIED,t),s.emitEvent(s.EVENT.FOCUS_TRANSLATION,t)}function g(t,e){t.newTranslations=e.slice(),s.emitEvent(s.EVENT.TRANSLATION_TEXT_MODIFIED,t),s.emitEvent(s.EVENT.FOCUS_TRANSLATION,t)}function E(t,e){var n=N[e.id];n.updateSaveButton(e)}function p(t,e){var n=N[e.phrase.id];n.phraseSaving(e),s.emitEvent(s.EVENT.FOCUS_TRANSLATION,e.phrase)}function T(t,e){t.selected!==e&&(t.selected=e||!1)}function h(t,e){var n=N[e.id];n.focusTranslation()}function v(t,e){var n=[];return"untranslated"===t.ID?n:(n=i("filter")(c.getAllAsArray(),{ID:"!untranslated"}),e.plural&&(d.hasNoTranslation(e)?n=i("filter")(n,{ID:"!needswork"}):d.hasEmptyTranslation(e)&&(n=i("filter")(n,{ID:"!translated"}))),u&&(n=i("filter")(n,{ID:"!approved"})),i("filter")(n,{ID:"!"+t.ID}))}var I,m=this,N={};return m.addController=function(t,e){N[t]=e},m.getSaveButtonOptions=function(t,e){return v(t,e)},n.$on(s.EVENT.TOGGLE_SAVE_OPTIONS,function(t,e){var n=N[e.id];n&&n.toggleSaveAsOptions(e.open)}),n.$on(s.EVENT.SELECT_TRANS_UNIT,function(t,n){var i=N[n.id],u=N[I],f=n.updateURL;s.emitEvent(s.EVENT.REQUEST_PHRASE_SUGGESTIONS,{phrase:i.getPhrase()}),i?(l.selectedTUCtrl=i,I&&I!==n.id&&(T(u,!1),d.hasTranslationChanged(u.getPhrase())&&s.emitEvent(s.EVENT.SAVE_TRANSLATION,{phrase:u.getPhrase(),status:c.getStatusInfo("TRANSLATED"),locale:r.localeId,docId:r.docId})),E(t,i.getPhrase()),I=n.id,T(i,!0),s.emitEvent(s.EVENT.FOCUS_TRANSLATION,n),f&&("editor.selectedContext.tu"!==o.current.name?o.go("editor.selectedContext.tu",{id:n.id,selected:n.focus.toString()}):(e.search("id",n.id),e.search("selected",n.focus.toString())))):a.displayWarning("Trans-unit not found:"+n.id)}),n.$on(s.EVENT.COPY_FROM_SOURCE,function(e,n){var o=0;if(n.phrase.plural&&(o=n.sourceIndex,t.isUndefined(o))){var r=N[n.phrase.id];o=r.focusedTranslationIndex,n.phrase.sources.length1;if(s){var c=r.translations.length;if(a.lengthc&&(a=t.first(a,c)),g(r,a)}else S(r,a[0])}}),n.$on(s.EVENT.UNDO_EDIT,function(t,e){d.hasTranslationChanged(e)&&g(e,e.translations)}),n.$on(s.EVENT.CANCEL_EDIT,function(t,o){I&&(T(N[I],!1),I=!1,l.selectedTUCtrl=null),e.search("selected",null),o||e.search("id",null),o&&f(function(){return n.$broadcast("blurOn","phrase-"+o.id)})}),n.$on(s.EVENT.TRANSLATION_TEXT_MODIFIED,E),n.$on(s.EVENT.FOCUS_TRANSLATION,h),n.$on(s.EVENT.SAVE_INITIATED,p),n.$on(s.EVENT.SAVE_COMPLETED,E),m}t.$inject=["_","$location","$rootScope","$state","$stateParams","$filter","MessageHandler","EventService","TransStatusService","PRODUCTION","EditorShortcuts","PhraseUtil","$timeout"],angular.module("app").factory("TransUnitService",t)}(),function(){"use strict";function t(){return{restrict:"E",required:["phrase","editorContext"],scope:{phrase:"=",firstPhrase:"=",editorContext:"="},controller:"TransUnitCtrl as transUnitCtrl",templateUrl:"components/transUnit/trans-unit.html",link:function(t,e,n,o){o.init()}}}angular.module("app").directive("transUnit",t)}(),function(){"use strict";function t(t,e){function n(n){var o=t(e.USER_INFO_URL,{},{query:{method:"GET",params:{username:n}}});return o.query().$promise}function o(){var n=t(e.MY_INFO_URL,{},{query:{method:"GET"}});return n.query().$promise}return{settings:{editor:{hideMainNav:!1}},getUserInfo:n,getMyInfo:o}}t.$inject=["$resource","UrlService"],angular.module("app").factory("UserService",t)}(),function(){"use strict";function t(t,e){function n(t,n,o){return t&&n&&o?e.filter(t,function(t){return i(t,n,o)}):t}function o(t){var e={},n=Object.keys(t).filter(function(t){return-1===t.indexOf("$")});return n.forEach(function(n){e[n]=t[n]}),e}function r(t){var e=[],n=Object.keys(t).filter(function(t){return-1===t.indexOf("$")});return n.forEach(function(n){e.push(t[n])}),e}function i(n,o,r){return n&&o&&r?e.any(o,function(o){return e.any(r,function(e){return t.equals(n[o],e,!0)})}):!1}return{filterResources:n,cleanResourceList:r,cleanResourceMap:o}}t.$inject=["StringUtil","_"],angular.module("app").factory("FilterUtil",t)}(),function(){"use strict";function t(t,e){function n(e){return r(e)?t.getStatusInfo("untranslated"):i(e)?t.getStatusInfo("needswork"):o(e)?t.getStatusInfo("translated"):e.status}function o(t){var n=e.every(t.translations,function(e,n){return a(e)===a(t.newTranslations[n])});return!n}function r(t){return e.isEmpty(e.compact(t.newTranslations))}function i(t){return e.compact(t.newTranslations).length!==t.newTranslations.length}function a(t){return t||""}return{getSaveButtonStatus:n,hasTranslationChanged:o,hasNoTranslation:r,hasEmptyTranslation:i}}t.$inject=["TransStatusService","_"],angular.module("app").factory("PhraseUtil",t)}(),function(){"use strict";function t(){return{getWordStatistic:function(t){return"WORD"===t[0].unit?t[0]:t[1]},getMsgStatistic:function(t){return"MESSAGE"===t[0].unit?t[0]:t[1]}}}angular.module("app").factory("StatisticUtil",t)}(),function(){"use strict";function t(){function t(t,e,n){return n&&t&&e&&(t=t.toUpperCase(),e=e.toUpperCase()),0===t.lastIndexOf(e,0)}function e(t,e,n){return n&&t&&e&&(t=t.toUpperCase(),e=e.toUpperCase()),-1!==t.indexOf(e,t.length-e.length)}function n(t,e,n){return n&&t&&e&&(t=t.toUpperCase(),e=e.toUpperCase()),t===e}return{startsWith:t,endsWith:e,equals:n}}angular.module("app").factory("StringUtil",t)}(),function(){"use strict";function t(t,e,n,o,r){function i(){return l+Array.prototype.join.call(arguments,"")}function a(t){return function(e){return t(e)}}location.origin||(location.origin=window.location.protocol+"//"+window.location.hostname+(window.location.port?":"+window.location.port:""));var s=this,c="http://www.gravatar.com/avatar",u="config.json",l="",d={},f=location.origin+location.pathname+"translations";return s.serverContextPath="",s.init=function(){return l?n.when(l):e.get(u).then(function(t){var e=t.data;if(e.baseUrl)l=e.baseUrl;else{var n=e.appPath.replace(/^\//g,""),o=location.href.indexOf(n);s.serverContextPath=location.origin+location.pathname,o>=0&&(s.serverContextPath=location.href.substring(0,o)),s.serverContextPath=s.serverContextPath.replace(/\/?$/,"/"),l=s.serverContextPath+"rest"}d=r.mapValues({project:"/project/:projectSlug",docs:"/project/:projectSlug/version/:versionSlug/docs",locales:"/project/:projectSlug/version/:versionSlug/locales",status:"/project/:projectSlug/version/:versionSlug/doc/:docId/status/:localeId",textFlows:"/source+trans/:localeId",docStats:"/stats/project/:projectSlug/version/:versionSlug/doc/:docId/locale/:localeId",myInfo:"/user",userInfo:"/user/:username",translation:"/trans/:localeId",allLocales:"/locales",suggestions:"/suggestions"},a(i)),s.PROJECT_URL=d.project,s.LOCALE_LIST_URL=d.locales,s.DOCUMENT_LIST_URL=d.docs,s.TRANSLATION_STATUS_URL=d.status,s.TEXT_FLOWS_URL=d.textFlows,s.DOC_STATISTIC_URL=d.docStats,s.MY_INFO_URL=d.myInfo,s.USER_INFO_URL=d.userInfo,s.TRANSLATION_URL=d.translation,s.ALL_LOCALE_URL=d.allLocales,s.SUGGESTIONS_URL=d.suggestions,s.PROJECT_PAGE=function(t,e){return s.serverContextPath+"iteration/view/"+t+"/"+e},s.DASHBOARD_PAGE=s.serverContextPath+"dashboard"})},s.readValue=function(e){return t.search()[e]},s.gravatarUrl=function(t,e){return c+"/"+t+"?d=mm&r=g&s="+e},s.uiTranslationURL=function(t){return f+"/"+t+".json"},s.uiTranslationListURL=f+"/locales",s}t.$inject=["$location","$http","$q","$stateParams","_"],angular.module("app").factory("UrlService",t)}(); +!function(){"use strict";angular.module("app",["ngResource","ngAnimate","ui.router","templates","cfp.hotkeys","focusOn","monospaced.elastic","gettext","diff-match-patch"])}(),function(){"use strict";function t(t,e,n,o){var r=function(t,e){return{request:function(t){return e.$broadcast("loadingStart"),t},requestError:function(n){return e.$broadcast("loadingStop"),console.error("Request error due to ",n),t.reject(n)},response:function(n){return e.$broadcast("loadingStop"),n||t.when(n)},responseError:function(n){return e.$broadcast("loadingStop"),401===n.status?console.error("Unauthorized access. Please login"):404===n.status?console.error("Service end point not found- ",n.config.url):console.error("Error in response ",n),t.reject(n)}}};r.$inject=["$q","$rootScope"],n.interceptors.push(r),e.otherwise("/"),t.state("editor",{url:"/:projectSlug/:versionSlug/translate",templateUrl:"editor/editor.html",controller:"EditorCtrl as editor",resolve:{url:["UrlService",function(t){return t.init()}]}}).state("editor.selectedContext",{url:"/:docId/:localeId",views:{"editor-content":{templateUrl:"editor/editor-content.html",controller:"EditorContentCtrl as editorContent"},"editor-suggestions":{templateUrl:"editor/editor-suggestions.html",controller:"EditorSuggestionsCtrl as editorSuggestions"},"editor-details":{templateUrl:"editor/editor-details.html",controller:"EditorDetailsCtrl as editorDetails"}}}).state("editor.selectedContext.tu",{url:"/?id&selected?states",reloadOnSearch:!1}),o.includeCheatSheet=!1}t.$inject=["$stateProvider","$urlRouterProvider","$httpProvider","hotkeysProvider"],angular.module("app").config(t)}(),function(){"use strict";angular.module("app").constant("_",window._).constant("str",window._.string).constant("Mousetrap",window.Mousetrap).constant("PRODUCTION",!0)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s){function c(){return o.getAllLocales()}function u(){return e.getMyInfo().then(function(t){d.myInfo=t,d.myInfo.locale=o.DEFAULT_LOCALE,d.myInfo.gravatarUrl=n.gravatarUrl(d.myInfo.gravatarHash,72)},function(t){r.displayError("Error loading my info: "+t)})}function l(){o.getUILocaleList().then(function(t){for(var e in t.locales){var n={localeId:t.locales[e],name:""};d.uiLocaleList.push(n)}d.myInfo.locale=o.getLocaleByLocaleId(d.uiLocaleList,o.DEFAULT_LOCALE.localeId),d.myInfo.locale||(d.myInfo.locale=o.DEFAULT_LOCALE)},function(t){r.displayInfo("Error loading UI locale. Default to '"+o.DEFAULT_LOCALE.name+"': "+t),d.myInfo.locale=o.DEFAULT_LOCALE})}var d=this;d.PRODUCTION=s,d.settings=e.settings,d.uiLocaleList=[o.DEFAULT_LOCALE],n.init().then(c).then(u).then(l),d.onChangeUILocale=function(t){d.myInfo.locale=t;var e=d.myInfo.locale.localeId;a.startsWith(e,o.DEFAULT_LOCALE.localeId,!0)?i.setCurrentLanguage(o.DEFAULT_LOCALE.localeId):i.loadRemote(n.uiTranslationURL(e)).then(function(){i.setCurrentLanguage(e)},function(t){r.displayInfo("Error loading UI locale. Default to '"+o.DEFAULT_LOCALE.name+"': "+t),i.setCurrentLanguage(o.DEFAULT_LOCALE),d.myInfo.locale=o.DEFAULT_LOCALE})},d.dashboardPage=function(){return n.DASHBOARD_PAGE}}t.$inject=["$scope","UserService","UrlService","LocaleService","MessageHandler","gettextCatalog","StringUtil","PRODUCTION"],angular.module("app").controller("AppCtrl",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s,c,u,l){function d(){v=r.readValue("status"),u.isUndefined(v)||(v=v.split(","),v=u.transform(v,function(t,e){return e=l.getServerId(e),t.push(e)})),I={status:v}}function f(t,e){var n,o,r,c,l=N.phrases;o=u.findIndex(l,function(t){return t.id===e.currentId}),r=Math.min(o+1,l.length-1),c=l[r].id,c!==e.currentId?i.emitEvent(i.EVENT.SELECT_TRANS_UNIT,{id:c,updateURL:!0,focus:!0},null):(n=l[o],i.emitEvent(i.EVENT.SAVE_TRANSLATION,{phrase:n,status:s.getSaveButtonStatus(n),locale:a.localeId,docId:a.docId}))}function S(t,e){var n,o,r,c,l=N.phrases;o=u.findIndex(l,function(t){return t.id===e.currentId}),r=Math.max(o-1,0),c=l[r].id,c!==e.currentId?i.emitEvent(i.EVENT.SELECT_TRANS_UNIT,{id:c,updateURL:!0,focus:!0},null):(n=l[o],i.emitEvent(i.EVENT.SAVE_TRANSLATION,{phrase:n,status:s.getSaveButtonStatus(n),locale:a.localeId,docId:a.docId}))}function g(t,e){var n,o,r=N.phrases,a=l.getStatusInfo(v);n=u.findIndex(r,function(t){return t.id===e.currentId});for(var s=n+1;sm&&(e.maxPageIndex=t%m!==0?e.maxPageIndex+=1:e.maxPageIndex),e.maxPageIndex=e.maxPageIndex-1<0?0:e.maxPageIndex-1,T(e.currentPageIndex)})}function T(t){var o=t*m;n.fetchAllPhrase(e.context,I,o,m).then(h)}function h(t){N.phrases=t}var v,I,m=50,N=this;return d(),N.phrases=[],e.updateContext(a.projectSlug,a.versionSlug,o.decodeDocId(a.docId),a.localeId),p(),t.$on(i.EVENT.FILTER_TRANS_UNIT,function(t,e){if(e.status.all===!0)c.search("status",null);else{var n=[];u.forEach(e.status,function(t,e){t&&n.push(e)}),c.search("status",n.join(","))}d(),p()}),t.$on(i.EVENT.GOTO_FIRST_PAGE,function(){e.currentPageIndex>0&&(e.currentPageIndex=0,E(e.currentPageIndex))}),t.$on(i.EVENT.GOTO_PREV_PAGE,function(){e.currentPageIndex>0&&(e.currentPageIndex-=1,E(e.currentPageIndex))}),t.$on(i.EVENT.GOTO_NEXT_PAGE,function(){e.currentPageIndex-1?!1:"INPUT"===t.tagName||"SELECT"===t.tagName||"TEXTAREA"===t.tagName||t.isContentEditable}function v(t){m(A.filter.status)?I(t):(A.filter.status.all=!1,t&&S.emitEvent(S.EVENT.FILTER_TRANS_UNIT,A.filter))}function I(t){A.filter.status.all=!0,A.filter.status.approved=!1,A.filter.status.translated=!1,A.filter.status.needsWork=!1,A.filter.status.untranslated=!1,t&&S.emitEvent(S.EVENT.FILTER_TRANS_UNIT,A.filter)}function m(t){return t.approved===t.translated&&t.translated===t.needsWork&&t.needsWork===t.untranslated}function N(){O()&&l.go("editor.selectedContext",{docId:A.context.docId,localeId:A.context.localeId})}function O(){return A.context.docId&&A.context.localeId}function _(t,e,o,r){n.getStatistics(t,e,o,r).then(function(t){A.wordStatistic=s.getWordStatistic(t),A.messageStatistic=s.getMsgStatistic(t)},function(t){d.displayError("Error loading statistic: "+t)})}var A=this;A.pageNumber=1,A.showCheatsheet=!1,A.shortcuts=E.mapValues(E.values(g.SHORTCUTS),function(t){var e=E.flatten(t.keyCombos,"combo");return{combos:E.map(e,function(t){return g.symbolizeKey(t)}),description:t.keyCombos[0].description}}),A.filter={status:{all:!0,approved:!1,translated:!1,needsWork:!1,untranslated:!1}},T(),p.bind("?",function(e){var n=e.srcElement;A.showCheatsheet||h(n)||(A.toggleKeyboardShortcutsModal(),t.$digest())},"keyup"),A.context=i.initContext(u.projectSlug,u.versionSlug,n.decodeDocId(u.docId),o.DEFAULT_LOCALE,o.DEFAULT_LOCALE.localeId,"READ_WRITE"),A.toggleKeyboardShortcutsModal=function(){A.showCheatsheet=!A.showCheatsheet};var C=a.SETTING.SHOW_SUGGESTIONS;t.showSuggestions=a.subscribe(C,function(e){t.showSuggestions=e}),A.toggleSuggestionPanel=function(){a.update(C,!t.showSuggestions)},A.versionPage=function(){return c.PROJECT_PAGE(A.context.projectSlug,A.context.versionSlug)},A.encodeDocId=function(t){return n.encodeDocId(t)},r.getProjectInfo(u.projectSlug).then(function(t){A.projectInfo=t},function(t){d.displayError("Error getting project information:"+t)}),o.getSupportedLocales(A.context.projectSlug,A.context.versionSlug).then(function(t){if(A.locales=t,!A.locales||A.locales.length<=0)d.displayError("No supported locales in "+A.context.projectSlug+" : "+A.context.versionSlug);else{var e=l.params.localeId,n=A.context;e?(n.localeId=e,o.containsLocale(A.locales,e)||(n.localeId=A.locales[0].localeId)):(n.localeId=A.locales[0].localeId,N())}},function(t){d.displayError("Error getting locale list: "+t)}),n.findAll(A.context.projectSlug,A.context.versionSlug).then(function(t){if(A.documents=t,!A.documents||A.documents.length<=0)d.displayError("No documents in "+A.context.projectSlug+" : "+A.context.versionSlug);else{var e=l.params.docId,o=A.context;e?(o.docId=n.decodeDocId(e),n.containsDoc(A.documents,o.docId)||(o.docId=A.documents[0].name)):(o.docId=A.documents[0].name,N())}},function(t){d.displayError("Error getting document list: "+t)}),f.$on(S.EVENT.SELECT_TRANS_UNIT,function(t,e){A.unitSelected=e.id,A.focused=e.focus}),f.$on(S.EVENT.CANCEL_EDIT,function(){A.unitSelected=!1,A.focused=!1}),f.$on(S.EVENT.REFRESH_STATISTIC,function(t,e){_(e.projectSlug,e.versionSlug,e.docId,e.localeId),A.context.docId=e.docId,A.context.localeId=e.localeId}),A.pageNumber=function(){return 0===i.maxPageIndex?i.currentPageIndex+1:i.currentPageIndex+1+" of "+(i.maxPageIndex+1)},A.getLocaleName=function(t){return o.getName(t)},A.firstPage=function(){S.emitEvent(S.EVENT.GOTO_FIRST_PAGE)},A.lastPage=function(){S.emitEvent(S.EVENT.GOTO_LAST_PAGE)},A.nextPage=function(){S.emitEvent(S.EVENT.GOTO_NEXT_PAGE)},A.previousPage=function(){S.emitEvent(S.EVENT.GOTO_PREV_PAGE)},A.resetFilter=function(){I(!0)},A.updateFilter=function(){v(!0)},this.settings=e.settings.editor,g.enableEditorKeys()}t.$inject=["$scope","UserService","DocumentService","LocaleService","ProjectService","EditorService","SettingsService","StatisticUtil","UrlService","$stateParams","$state","MessageHandler","$rootScope","EventService","EditorShortcuts","_","Mousetrap"],angular.module("app").controller("EditorCtrl",t)}(),function(){"use strict";function t(){var t=this;return t}angular.module("app").controller("EditorDetailsCtrl",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s,c,u){function l(t,e){return a.hasTranslationChanged(t)||t.status!==e}function d(t){var a=n.cloneDeep(S.context),l=g[t],d=e(o.TRANSLATION_URL,{},{update:{method:"PUT",params:{localeId:l.locale}}}),f={id:l.phrase.id,revision:l.phrase.revision||0,content:l.phrase.newTranslations[0],contents:l.phrase.newTranslations,status:u.getServerId(l.status.ID),plural:l.phrase.plural};d.update(f).$promise.then(function(t){var e=l.phrase.status.ID;i.onTransUnitUpdated(a,f.id,l.locale,t.revision,t.status,l.phrase),s.updateStatistic(a.projectSlug,a.versionSlug,l.docId,l.locale,e,u.getId(t.status),l.phrase.wordCount),r.emitEvent(r.EVENT.SAVE_COMPLETED,l.phrase)},function(t){c.displayWarning("Update translation failed for "+f.id+" -"+t),i.onTransUnitUpdateFailed(f.id),r.emitEvent(r.EVENT.SAVE_COMPLETED,l.phrase)}),delete g[t]}function f(t,e){return n.isEmpty(n.compact(t.newTranslations))?u.getStatusInfo("UNTRANSLATED"):e}var S=this,g={};return S.context={},S.currentPageIndex=0,S.maxPageIndex=0,S.initContext=function(t,e,n,o,r,i){return S.context={projectSlug:t,versionSlug:e,docId:n,srcLocale:o,localeId:r,mode:i},S.context},S.updateContext=function(t,e,n,o){S.context.projectSlug!==t&&(S.context.projectSlug=t),S.context.versionSlug!==e&&(S.context.versionSlug=e),S.context.docId!==n&&(S.context.docId=n),S.context.localeId!==o&&(S.context.localeId=o)},t.$on(r.EVENT.SAVE_TRANSLATION,function(t,e){var o=e.phrase,i=e.status;if(l(o,i)){if(n.has(g,o.id)){var a=g[o.id];a.phrase=o,a.status=i}else i=f(o,i),g[o.id]={phrase:o,status:i,locale:e.locale,docId:e.docId};r.emitEvent(r.EVENT.SAVE_INITIATED,e),d(o.id)}}),S}t.$inject=["$rootScope","$resource","_","UrlService","EventService","PhraseService","PhraseUtil","DocumentService","MessageHandler","TransStatusService"],angular.module("app").factory("EditorService",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s,c){function u(e){m.selectedTUCtrl&&(e.preventDefault(),t.emitEvent(t.EVENT.COPY_FROM_SOURCE,{phrase:m.selectedTUCtrl.getPhrase()}))}function l(e){m.selectedTUCtrl&&(e.preventDefault(),e.stopPropagation(),t.emitEvent(t.EVENT.GOTO_NEXT_ROW,v()))}function d(e){m.selectedTUCtrl&&(e.preventDefault(),e.stopPropagation(),t.emitEvent(t.EVENT.GOTO_PREVIOUS_ROW,v()))}function f(e){if(e.preventDefault(),e.stopPropagation(),N)m.cancelSaveAsModeIfOn(),m.selectedTUCtrl&&m.selectedTUCtrl.focusTranslation();else if(m.selectedTUCtrl){var n=m.selectedTUCtrl.getPhrase();r.hasTranslationChanged(n)?t.emitEvent(t.EVENT.UNDO_EDIT,n):t.emitEvent(t.EVENT.CANCEL_EDIT,n)}}function S(n){if(m.selectedTUCtrl){n.preventDefault();var o=m.selectedTUCtrl.getPhrase();t.emitEvent(t.EVENT.SAVE_TRANSLATION,{phrase:o,status:r.getSaveButtonStatus(o),locale:e.localeId,docId:e.docId})}}function g(e){e.preventDefault(),m.cancelSaveAsModeIfOn();var n=m.selectedTUCtrl.getPhrase();n&&(t.emitEvent(t.EVENT.TOGGLE_SAVE_OPTIONS,{id:n.id,open:!0}),I(n,"n","needsWork"),I(n,"t","translated"),I(n,"a","approved"))}function E(e){return function(n){n.preventDefault(),t.emitEvent(t.EVENT.COPY_FROM_SUGGESTION_N,e-1)}}function p(t,e,n,o,r){return this.defaultKey=t,this.keyCombos=[T(t,n,r,e)],o&&(this.otherKeys=o instanceof Array?o:[o],this.keyCombos.push(T(this.otherKeys,"",r,e))),this}function T(t,e,n,o){var r={allowIn:["TEXTAREA"],callback:o};return r.combo=t,e&&(r.description=e),n&&(r.action=n),r}function h(t){o.get(t.defaultKey)||n.forEach(t.keyCombos,function(t){o.add(t)})}function v(){return{currentId:m.selectedTUCtrl.getPhrase().id}}function I(t,e,n){var r=i.getStatusInfo(n);return o.add({combo:e,description:s.sprintf("Save as %s",n),allowIn:["INPUT","TEXTAREA"],action:"keydown",callback:function(e){m.saveTranslationCallBack(e,t,r)}})}var m=this,N=!1;return m.selectedTUCtrl=null,m.SHORTCUTS={COPY_SOURCE:new p("alt+c",u,"Copy source as translation","alt+g"),COPY_SUGGESTION_1:new p("mod+alt+1",E(1),"Copy first suggestion as translation"),COPY_SUGGESTION_2:new p("mod+alt+2",E(2),"Copy second suggestion as translation"),COPY_SUGGESTION_3:new p("mod+alt+3",E(3),"Copy third suggestion as translation"),COPY_SUGGESTION_4:new p("mod+alt+4",E(4),"Copy fourth suggestion as translation"),CANCEL_EDIT:new p("esc",f,"Cancel edit"),SAVE_AS_CURRENT_BUTTON_OPTION:new p("mod+s",S,"Save"),SAVE_AS_MODE:new p("mod+shift+s",g,"Save as…"),SAVE_AS_NEEDSWORK:{keyCombos:[{combo:"mod+shift+s n",description:"Save as needs work"}]},SAVE_AS_TRANSLATED:{keyCombos:[{combo:"mod+shift+s t",description:"Save as translated"}]},SAVE_AS_APPROVED:{keyCombos:[{combo:"mod+shift+s a",description:"Save as approved"}]},GOTO_NEXT_ROW_FAST:new p("mod+enter",l,"Save (if changed) and go to next string",["alt+k","alt+down"]),GOTO_PREVIOUS_ROW:new p("mod+shift+enter",d,"Save (if changed) and go to previous string",["alt+j","alt+up"])},m.enableEditorKeys=function(){o.get(m.SHORTCUTS.COPY_SOURCE.defaultKey)||n.forOwn(m.SHORTCUTS,function(t){t instanceof p&&h(t)})},m.disableEditorKeys=function(){n.forOwn(m.SHORTCUTS,function(t){n.forEach(t.keyCombos,function(t){m.deleteKeys(t.combo,t.action)})})},m.saveTranslationCallBack=function(n,o,r){N=!0,n.preventDefault(),n.stopPropagation(),t.emitEvent(t.EVENT.SAVE_TRANSLATION,{phrase:o,status:r,locale:e.localeId,docId:e.docId}),m.cancelSaveAsModeIfOn()},m.cancelSaveAsModeIfOn=function(){N&&m.selectedTUCtrl&&(N=!1,m.deleteKeys(["n","t","a"]),t.emitEvent(t.EVENT.TOGGLE_SAVE_OPTIONS,{id:m.selectedTUCtrl.getPhrase().id,open:!1}))},m.deleteKeys=function(t,e){var r=t instanceof Array?t:[t];e=e||"keydown",n.forEach(r,function(t){o.del(t),a.unbind(t,e)})},m.symbolizeKey=function(t){var e={command:"⌘",shift:"⇧",left:"←",right:"→",up:"↑",down:"↓","return":"↩",backspace:"⌫"};t=t.split("+");for(var n=0;n=0?"command":"ctrl"),t[n]=e[t[n]]||t[n];return t.join(" + ")},m}t.$inject=["EventService","$stateParams","_","hotkeys","PhraseUtil","TransStatusService","Mousetrap","str","$window"],angular.module("app").factory("EditorShortcuts",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s,c){function u(e){t.isTextSearch=e,t.isPhraseSearch=!e}function l(e){t.suggestions=e}function d(){t.search.isVisible=!1,u(!1),S()}function f(e,n){t.search.input.text="",t.search.isVisible=!0,!n&&e&&t.focusSearch(e),h.searchForText(),g()}function S(){t.searchStrings=o.getSearchStrings(),t.search.isLoading=o.isLoading(),l(o.getResults())}function g(){t.searchStrings=r.getSearchStrings(),t.search.isLoading=r.isLoading(),l(r.getResults())}function E(t){t&&i.emitEvent(i.EVENT.COPY_FROM_SUGGESTION,{suggestion:t})}var p=n.SETTING.SHOW_SUGGESTIONS,T=n.SETTING.SUGGESTIONS_SHOW_DIFFERENCE,h=this;return t.suggestions=[],t.hasSuggestions=!1,t.$watch("suggestions.length",function(e){t.hasSuggestions=0!==e}),t.searchStrings=[],t.hasSearch=!1,t.$watch("searchStrings.length",function(e){t.hasSearch=0!==e}),t.isTransUnitSelected=!1,t.isTextSearch=!1,t.isPhraseSearch=!0,t.search={isVisible:!1,isLoading:!1,input:{text:"",focused:!1}},t.$watch("search.input.text",function(){h.searchForText()}),t.show=n.subscribe(p,function(e){t.show=e,e&&(t.isTransUnitSelected?S():t.search.isVisible||f(null,!0))}),t.diff=n.subscribe(T,function(e){t.diff=e}),t.focusSearch=function(t){t&&t.preventDefault(),c("searchSugInput")},h.closeSuggestions=function(){n.update(p,!1),i.emitEvent(i.EVENT.SUGGESTIONS_SEARCH_TOGGLE,!1)},h.clearSearchResults=function(e,n){t.search.input.text="",!n&&e&&t.focusSearch(e)},h.searchForText=function(){var e=t.search.input.text;e.length>0&&(t.search.isLoading=!0),u(!0),i.emitEvent(i.EVENT.REQUEST_TEXT_SUGGESTIONS,e)},h.toggleSearch=function(){t.search.isVisible?i.emitEvent(i.EVENT.SUGGESTIONS_SEARCH_TOGGLE,!1):i.emitEvent(i.EVENT.SUGGESTIONS_SEARCH_TOGGLE,!0)},t.show&&!t.isTransUnitSelected&&f(),a.$on(i.EVENT.SELECT_TRANS_UNIT,function(){""===t.search.input.text&&t.search.isVisible&&i.emitEvent(i.EVENT.SUGGESTIONS_SEARCH_TOGGLE,!1),t.isTransUnitSelected=!0}),a.$on(i.EVENT.CANCEL_EDIT,function(){t.isTransUnitSelected=!1,t.show&&!t.search.isVisible&&f(null,!0)}),a.$on(i.EVENT.SUGGESTIONS_SEARCH_TOGGLE,function(t,e){e?f(t):d(t)}),a.$on("PhraseSuggestionsService:updated",function(){t.isPhraseSearch&&S()}),a.$on("TextSuggestionsService:updated",function(){t.isTextSearch&&g()}),a.$on(i.EVENT.COPY_FROM_SUGGESTION_N,function(e,n){t.show?(E(t.suggestions[n]),t.$broadcast("EditorSuggestionsCtrl:nth-suggestion-copied",n)):E(o.getResults()[n])}),h}t.$inject=["$scope","_","SettingsService","PhraseSuggestionsService","TextSuggestionsService","EventService","$rootScope","$timeout","focus"],angular.module("app").controller("EditorSuggestionsCtrl",t)}(),function(){"use strict";function t(){return{restrict:"A",link:function(t,e,n){return t.$on("blurOn",function(t,o){return o===n.blurOn?e[0].blur():void 0})}}}angular.module("app").directive("blurOn",t)}(),function(){"use strict";function t(t){return{restrict:"A",scope:{callback:"&clickElsewhere"},link:function(e,n){var o=function(t){n[0].contains(t.target)||e.$apply(e.callback(t))};t.on("click",o),e.$on("$destroy",function(){t.off("click",o)})}}}t.$inject=["$document"],angular.module("app").directive("clickElsewhere",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s){function c(t,e){return t+"-"+e}function u(t,e,n,o){var i=r.getWordStatistic(t),a=r.getMsgStatistic(t);if(i){o=parseInt(o);var s=parseInt(i[e])-o;i[e]=0>s?0:s,i[n]=parseInt(i[n])+o}if(a){var c=parseInt(a[e])-1;a[e]=0>c?0:c,a[n]=parseInt(a[n])+1}}var l=this,d={};return l.findAll=function(t,o){var r=e(n.DOCUMENT_LIST_URL,{},{query:{method:"GET",params:{projectSlug:t,versionSlug:o},isArray:!0}});return r.query().$promise},l.getStatistics=function(o,r,i,u){if(i&&u){var f=c(i,u);if(a.has(d,f))return t.when(d[f]);var S=l.encodeDocId(i),g=e(n.DOC_STATISTIC_URL,{},{query:{method:"GET",params:{projectSlug:o,versionSlug:r,docId:S,localeId:u},isArray:!0}});return g.query().$promise.then(function(t){return a.forEach(t,function(t){t[s.getId("needswork")]=t.needReview||0}),d[f]=t,d[f]})}},l.encodeDocId=function(t){return t?t.replace(/\//g,","):t},l.decodeDocId=function(t){return t?t.replace(/\,/g,"/"):t},l.containsDoc=function(t,e){return a.any(t,function(t){return o.equals(t.name,e,!0)})},l.updateStatistic=function(t,e,n,o,r,s,l){var f=c(n,o);a.has(d,f)&&(u(d[f],r,s,l),i.emitEvent(i.EVENT.REFRESH_STATISTIC,{projectSlug:t,versionSlug:e,docId:n,localeId:o}))},l}t.$inject=["$q","$resource","UrlService","StringUtil","StatisticUtil","EventService","_","TransStatusService"],angular.module("app").factory("DocumentService",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a){var s,c=this,u=t.$new(),l=o.openClass,d=angular.noop,f=e.onToggle?n(e.onToggle):angular.noop;this.init=function(o){c.$element=o,e.isOpen&&(s=n(e.isOpen),d=s.assign,t.$watch(s,function(t){u.isOpen=!!t}))},this.toggle=function(t){return u.isOpen=arguments.length?!!t:!u.isOpen,u.isOpen},this.isOpen=function(){return u.isOpen},u.getToggleElement=function(){return c.toggleElement},u.focusToggleElement=function(){c.toggleElement&&c.toggleElement[0].focus()},u.$watch("isOpen",function(e,n){i[e?"addClass":"removeClass"](c.$element,l),e?(a(function(){u.focusToggleElement()}),r.open(u)):r.close(u),d(t,e),angular.isDefined(e)&&e!==n&&f(t,{open:!!e})}),t.$on("$locationChangeSuccess",function(){u.isOpen=!1}),t.$on("$destroy",function(){u.$destroy()}),t.$on("openDropdown",function(){u.isOpen=!0}),t.$on("closeDropdown",function(){u.isOpen=!1})}t.$inject=["$scope","$attrs","$parse","dropdownConfig","DropdownService","$animate","$timeout"],angular.module("app").controller("DropdownCtrl",t)}(),function(){"use strict";function t(t){var e=null,n=this;n.open=function(n){e||(t.bind("click",o),t.bind("keydown",r)),e&&e!==n&&(e.isOpen=!1),e=n},n.close=function(n){e===n&&(e=null,t.unbind("click",o),t.unbind("keydown",r))};var o=function(t){if(e){var n=e.getToggleElement();t&&n&&n[0].contains(t.target)||e.$apply(function(){e.isOpen=!1})}},r=function(t){27===t.which&&(e.focusToggleElement(),o())}}t.$inject=["$document"],angular.module("app").service("DropdownService",t)}(),function(){"use strict";var t={openClass:"is-active"};angular.module("app").constant("dropdownConfig",t)}(),function(){"use strict";function t(){return{restrict:"EA",controller:"DropdownCtrl",link:function(t,e,n,o){o.init(e)}}}function e(){return{restrict:"A",require:"?^dropdown",scope:{callback:"&onCloseDropdown"},link:function(t,e,n,o){o.onCloseDropdown=t.callback}}}function n(){return{restrict:"EA",require:"?^dropdown",link:function(t,e,n,o){if(o){o.toggleElement=e;var r=function(r){r.preventDefault(),r.stopPropagation(),e.hasClass("disabled")||n.disabled||t.$apply(function(){o.toggle()})};e.bind("click",r),e.attr({"aria-haspopup":!0,"aria-expanded":!1}),t.$watch(o.isOpen,function(n){e.attr("aria-expanded",!!n),o.onCloseDropdown&&!n&&t.$applyAsync(o.onCloseDropdown)}),t.$on("$destroy",function(){e.unbind("click",r)})}}}}angular.module("app").directive("dropdown",t).directive("onCloseDropdown",e).directive("dropdownToggle",n)}(),function(){"use strict";function t(t){var e=this;return e.EVENT={LOADING_START:"loadingStart",LOADING_STOP:"loadingStop",SELECT_TRANS_UNIT:"selectTransUnit",COPY_FROM_SOURCE:"copyFromSource",COPY_FROM_SUGGESTION:"copyFromSuggestion",COPY_FROM_SUGGESTION_N:"copyFromSuggestionN",UNDO_EDIT:"undoEdit",CANCEL_EDIT:"cancelEdit",FOCUS_TRANSLATION:"focusTranslation",SAVE_TRANSLATION:"saveTranslation",SAVE_INITIATED:"saveInitiated",SAVE_COMPLETED:"saveCompleted",TRANSLATION_TEXT_MODIFIED:"translationTextModified",REFRESH_STATISTIC:"refreshStatistic",GOTO_PREV_PAGE:"gotoPreviousPage",GOTO_NEXT_PAGE:"gotoNextPage",GOTO_FIRST_PAGE:"gotoFirstPage",GOTO_LAST_PAGE:"gotoLastPage",GOTO_NEXT_ROW:"gotoNextRow",GOTO_PREVIOUS_ROW:"gotoPreviousRow",GOTO_NEXT_UNTRANSLATED:"gotoNextUntranslated",TOGGLE_SAVE_OPTIONS:"openSaveOptions",FILTER_TRANS_UNIT:"filterTransUnit",PHRASE_SUGGESTION_COUNT:"phraseSuggestionCount",REQUEST_PHRASE_SUGGESTIONS:"requestPhraseSuggestions",REQUEST_TEXT_SUGGESTIONS:"requestTextSuggestions",SUGGESTIONS_SEARCH_TOGGLE:"suggestionsSearchToggle",USER_SETTING_CHANGED:"userSettingChanged"},e.broadcastEvent=function(e,n,o){o=o||t,o.$broadcast(e,n)},e.emitEvent=function(e,n,o){o=o||t,o.$emit(e,n)},e}t.$inject=["$rootScope"],angular.module("app").factory("EventService",t)}(),function(){"use strict";function t(t){return{restrict:"E",required:["name"],scope:{name:"@",title:"@",size:"@"},link:function(e,n){var o="",r="",i="";n.addClass("Icon"),e.title&&(i=""+e.title+""),"loader"===e.name?(n.addClass("Icon--loader"),r='',n.html(t.trustAsHtml(r))):(o=''+i+"",n.html(t.trustAsHtml(o)))}}}t.$inject=["$sce"],angular.module("app").directive("icon",t)}(),function(){"use strict";function t(t,e,n,o,r){function i(e,n){var r=o(t.LOCALE_LIST_URL,{},{query:{method:"GET",params:{projectSlug:e,versionSlug:n},isArray:!0}});return r.query().$promise}function a(){var e=o(t.ALL_LOCALE_URL,{},{query:{method:"GET",isArray:!0}});return e.query().$promise.then(function(t){d=n.cleanResourceList(t)})}function s(){var e=o(t.uiTranslationListURL,{},{query:{method:"GET"}});return e.query().$promise}function c(t,n){return t?r.find(t,function(t){return e.equals(t.localeId,n,!0)}):void 0}function u(t,n){return r.any(t,function(t){return e.equals(t.localeId,n,!0)})}function l(t){var e=c(d,t);return e?e.name:t}var d=[];return{getSupportedLocales:i,getUILocaleList:s,getLocaleByLocaleId:c,getAllLocales:a,containsLocale:u,getName:l,DEFAULT_LOCALE:{localeId:"en-US",name:"English"}}}t.$inject=["UrlService","StringUtil","FilterUtil","$resource","_"],angular.module("app").factory("LocaleService",t)}(),function(){"use strict";function t(t){return{restrict:"EA",scope:{loading:"=",inverted:"="},link:function(e){e.classes="",e.$on(t.EVENT.LOADING_START,function(){e.classes+=" is-loading"}),e.$on(t.EVENT.LOADING_STOP,function(){e.classes=e.classes.replace("is-loading","")}),e.$watch("inverted",function(t){t?e.classes+=" LogoLoader--inverted":e.classes=e.classes.replace("LogoLoader--inverted","")})},templateUrl:"components/logo-loader/logo-loader.html"}}t.$inject=["EventService"],angular.module("app").directive("logoLoader",t)}(),function(){"use strict";function t(){return{displayError:function(t){console.error(t)},displayWarning:function(t){console.warn(t)},displayInfo:function(t){console.info(t)}}}angular.module("app").factory("MessageHandler",t)}(),function(){"use strict";function t(){}angular.module("app").factory("NotificationService",t)}(),function(){"use strict";function t(t,e,n,o,r,i){function a(t,e,n,o){return t+"-"+e+"-"+n+"-"+o}var s=this,c={},u={};return s.getStates=function(s,u,l,d){var f=a(s,u,l,d);if(i.has(c,f))return t.when(c[f]);var S=r.encodeDocId(l),g={query:{method:"GET",params:{projectSlug:s,versionSlug:u,docId:S,localeId:d},isArray:!0}},E=e(o.TRANSLATION_STATUS_URL,{},g);return E.query().$promise.then(function(t){return t=n.cleanResourceList(t),c[f]=t,c[f]})},s.getTransUnits=function(r,a){function s(t){t=n.cleanResourceMap(t);for(var e in t)u[e][a]=t[e][a],l[e]=u[e];return l}function c(t){t=n.cleanResourceMap(t);for(var e in t)u[e]=t[e],l[e]=u[e];return l}var l={},d=[],f=[];if(r.forEach(function(t){i.has(u,t)?u[t][a]?l[t]=u[t]:f.push(t):d.push(t)}),i.isEmpty(d)&&i.isEmpty(f))return t.when(l);var S,g;return i.isEmpty(d)||(S=e(o.TEXT_FLOWS_URL,{},{query:{method:"GET",params:{localeId:a,ids:d.join(",")}}})),i.isEmpty(f)||(g=e(o.TRANSLATION_URL,{},{query:{method:"GET",params:{localeId:a,ids:f.join(",")}}})),S&&g?S.query().$promise.then(c).then(g.query().$promise.then(s)):S?S.query().$promise.then(c):g?g.query().$promise.then(s):void 0},s.onTransUnitUpdated=function(t,e,n,o,r,s){var l=a(t.projectSlug,t.versionSlug,t.docId,n),d=i.find(c[l],function(t){return t.id===e});d&&(d.state=r);var f=u[e][n];f||(f={}),f.revision=parseInt(o),f.state=r,f.contents=s.newTranslations.slice()},s}t.$inject=["$q","$resource","FilterUtil","UrlService","DocumentService","_"],angular.module("app").factory("PhraseCache",t)}(),function(){"use strict";function t(t,e,n,o,r){function i(t,e){return o.find(e,function(e){return e.id===t})}function a(e,n){return n&&(e=t.filterResources(e,["status"],n)),o.map(e,function(t){return t.id})}var s={};return s.phrases=[],s.getPhraseCount=function(t,n){return e.getStates(t.projectSlug,t.versionSlug,t.docId,t.localeId).then(function(t){var e=a(t,n.status);return e.length})},s.fetchAllPhrase=function(t,r,i,c){function u(t){var n=a(t,r.status);return isNaN(i)||(n=isNaN(c)?n.slice(i):n.slice(i,i+c)),e.getTransUnits(n,S).then(l).then(f)}function l(t){return o.map(t,function(t,e){var o=t.source,r=t[S];return{id:parseInt(e),sources:o.plural?o.contents:[o.content],translations:d(o,r),newTranslations:d(o,r),plural:o.plural,status:n.getStatusInfo(r?r.state:"untranslated"),revision:r?parseInt(r.revision):0,wordCount:parseInt(o.wordCount)}})}function d(t,e){return t.plural?e&&e.contents?e.contents.slice():[]:e?[e.content]:[]}function f(n){return e.getStates(t.projectSlug,t.versionSlug,t.docId,S).then(function(t){return s.phrases=o.sortBy(n,function(e){var r=o.findIndex(t,function(t){return t.id===e.id});return r>=0?r:n.length}),s.phrases})}var S=t.localeId;return e.getStates(t.projectSlug,t.versionSlug,t.docId,S).then(u)},s.onTransUnitUpdated=function(t,o,r,a,c,u){e.onTransUnitUpdated(t,o,r,a,c,u);var l=i(o,s.phrases);l&&(l.translations=u.newTranslations.slice(),l.revision=a,l.status=n.getStatusInfo(c))},s.onTransUnitUpdateFailed=function(t){var e=i(t,s.phrases);e&&(e.newTranslations=e.translations.slice())},s.findNextId=function(t){return e.getStates(r.projectSlug,r.versionSlug,r.docId,r.localeId).then(function(e){var n,r;return n=o.findIndex(e,function(e){return e.id===t}),r=n+1=0?n-1:0,e[r].id})},s.findNextStatus=function(t,i){return e.getStates(r.projectSlug,r.versionSlug,r.docId,r.localeId).then(function(e){var r,a,s=n.getStatusInfo(i);r=o.findIndex(e,function(e){return e.id===t});for(var c=r+1;c '},newline:{regex:/\n/g,template:'\n'},tab:{regex:/\t/g,template:' '}};return{restrict:"A",required:["ngBind"],scope:{ngBind:"="},link:function(n,o){n.$watch("ngBind",function(n){n=t(n,e.space),n=t(n,e.newline),n=t(n,e.tab),o.html(n)})}}}angular.module("app").directive("renderWhitespaceCharacters",t)}(),function(){"use strict";function t(t,e,n,o){function r(r,i,a){function s(){t.update(t.SETTING.SUGGESTIONS_PANEL_HEIGHT,r.actualPosition)}function c(t){if(t)r.actualPosition=r.position,r.actualHeight=r.height;else{var e=r.actualPosition;r.position=e,r.actualPosition=0,r.actualHeight=0}setTimeout(S)}function u(t){"vertical"===a.resizer?l(t.pageX):d(e.innerHeight-t.pageY)}function l(t){var n=t,o=angular.element(document.querySelector(a.resizerLeft)),s=angular.element(document.querySelector(a.resizerRight)),c=E(a.resizerMax,e.innerHeight),u=a.resizerMin||parseInt(a.resizerWidth);r.actualPosition=n,n=g(n,c,u),i.css({left:n-r.actualHeight/2+"px"}),o.css({width:n+"px"}),s.css({left:n+"px"})}function d(t){var n=t,o=angular.element(document.querySelector(a.resizerTop)),s=angular.element(document.querySelector(a.resizerBottom)),c=E(a.resizerMax,e.innerHeight),u=a.resizerMin||r.actualHeight;r.actualPosition=n,n=g(n,c,u),i.css({bottom:n-r.actualHeight/2+"px"}),o.css({bottom:n+"px"}),s.css({height:n+"px"})}function f(){n.unbind("mousemove",u),n.unbind("mouseup",f),s()}function S(){"vertical"===a.resizer?l(r.actualPosition):d(r.actualPosition)}function g(t,e,n){return e&&t>e?e:n>t?n:t}function E(t,e){return/[0-9]*\.?[0-9]+%/.test(t)?Math.round(e*(parseInt(t.replace("%",""))/100)):parseInt(t)}r.height=parseInt(a.resizerHeight),r.actualHeight=r.height,r.position=E(t.get(t.SETTING.SUGGESTIONS_PANEL_HEIGHT),e.innerHeight),r.actualPosition=r.position,r.show=t.subscribe(t.SETTING.SHOW_SUGGESTIONS,function(t){r.show=t,c(t)}),c(r.show),i.addClass("Resizer"),"vertical"===a.resizer?(i.addClass("Resizer--vertical"),o(function(){l(r.actualPosition)})):(i.addClass("Resizer--horizontal"),o(function(){d(r.actualPosition)})),i.on("mousedown",function(t){t.preventDefault(),n.on("mousemove",u),n.on("mouseup",f)}),angular.element(e).bind("resize",function(){o.cancel(r.resizing),r.resizing=o(S)})}return{link:r}}t.$inject=["SettingsService","$window","$document","$timeout"],angular.module("app").directive("resizer",t)}(),function(){"use strict";function t(){var t=this;t.init=function(){var e=t.container[0],n=t.child[0],o=n.offsetWidth-e.offsetWidth;t.width=o/2}}angular.module("app").controller("ScrollbarWidthCtrl",t)}(),function(){"use strict";function t(){return{restrict:"A",controller:"ScrollbarWidthCtrl as scrollbarWidthCtrl",link:function(t,e,n,o){o.init(e)}}}function e(){return{restrict:"A",require:"?^scrollbarWidth",link:function(t,e,n,o){o&&e.css(n.scrollbarWidthElement,o.width)}}}function n(){return{restrict:"A",require:"?^scrollbarWidth",link:function(t,e,n,o){o&&(o.container=e)}}}function o(){return{restrict:"A",require:"?^scrollbarWidth",link:function(t,e,n,o){o&&(o.child=e)}}}angular.module("app").directive("scrollbarWidth",t).directive("scrollbarWidthElement",e).directive("scrollbarWidthContainer",n).directive("scrollbarWidthChild",o)}(),function(){"use strict";function t(t,e,n,o){function r(e,n){c(n);var r={};r[e]=n,o.extend(f,r),t.emitEvent(t.EVENT.USER_SETTING_CHANGED,{setting:e,value:n})}function i(t){o.each(t,function(t,e){r(e,t)})}function a(t){return o.has(f,t)?f[t]:void console.error("Tried to look up setting with unrecognized key: %s",t)}function s(e,o){return n.$on(t.EVENT.USER_SETTING_CHANGED,function(t,n){n.setting===e&&o(n.value)}),a(e)}function c(t){switch(typeof t){case"boolean":case"number":case"string":break;default:throw new Error('Invalid type for setting value: "'+typeof t+'".')}}var u=this;u.SETTING={SUGGESTIONS_AUTOFILL_ON_ROW_SELECT:"suggestionsAutofillOnRowSelect",SUGGESTIONS_SHOW_DIFFERENCE:"suggestionsShowDifference",SHOW_SUGGESTIONS:"showSuggestions",SUGGESTIONS_PANEL_HEIGHT:"suggestionsPanelHeight"};var l=u.SETTING,d={};d[l.SUGGESTIONS_AUTOFILL_ON_ROW_SELECT]=!0,d[l.SUGGESTIONS_SHOW_DIFFERENCE]=!1,d[l.SHOW_SUGGESTIONS]=!0,d[l.SUGGESTIONS_PANEL_HEIGHT]="30%";var f=o.clone(d);return{SETTING:l,update:r,updateAll:i,get:a,subscribe:s}}t.$inject=["EventService","$q","$rootScope","_"],angular.module("app").factory("SettingsService",t)}(),function(){"use strict";function t(t,e,n,o,r){function i(){return g}function a(){return E?E.sources:[]}function s(){return p}function c(t){m=t,T||u()}function u(){var t=v+f,e=t-Date.now(),n=e>0?e:f;T=o(function(){return T=null,h>=S?void u():void l()},n)}function l(){if(null!==m){var t=m;m=null,o.cancel(T),T=null,d(t)}}function d(t){E=t;var e=Date.now();v=e,h++,n.getSuggestionsForPhrase(t).then(function(t){e>I&&(I=e,p=t)},function(t){console.error("Error searching for phrase ",t)})["finally"](function(){h--,r.$broadcast("PhraseSuggestionsService:updated"),S>h&&l()})}var f=300,S=3,g=!1,E=null,p=[],T=null,h=0,v=Date.now(),I=Date.now(),m=null;return r.$on(e.EVENT.REQUEST_PHRASE_SUGGESTIONS,function(t,e){var n=e.phrase;if(!(m&&m.id===n.id||!m&&0===h&&E&&E.id===n.id)){if(h>=S)return void c(n);var o=v+f;if(Date.now()99.99&&100>t?"99.99":t>=99.9&&100>t?"99.9":Math.round(t)!==t?t.toFixed(1):t},i.topMatch=function(){return n.suggestion.matchDetails[0]},i.showSuggestionCopied=function(){i.copyButtonText="Copied",i.copyButtonDisabled=!0,r(function(){i.copyButtonDisabled=!1,i.copyButtonText="Copy Translation"},500)},i.copySuggestion=function(){i.showSuggestionCopied(),t.emitEvent(t.EVENT.COPY_FROM_SUGGESTION,{suggestion:n.suggestion})},n.$on("EditorSuggestionsCtrl:nth-suggestion-copied",function(t,e){e===n.index&&i.showSuggestionCopied()}),n.detail=i.topMatch(),n.user=n.detail.lastModifiedBy||"Annoymous",n.remaining=n.suggestion.matchDetails.length-1,n.isTextFlow="LOCAL_PROJECT"===n.detail.type,i}t.$inject=["EventService","$rootScope","$scope","_","$timeout"],angular.module("app").controller("SuggestionCtrl",t)}(),function(){"use strict";function t(t,e,n,o,r){function i(t){return s([t])}function a(t){return s(t.sources).then(function(n){return e.emitEvent(e.EVENT.PHRASE_SUGGESTION_COUNT,{id:t.id,count:n.length}),n})}function s(e){var o=t.context.srcLocale.localeId,i=t.context.localeId,a={query:{method:"POST",params:{from:o,to:i,searchType:"FUZZY_PLURAL"},isArray:!0}},s=r(n.SUGGESTIONS_URL,{},a);return s.query({},e).$promise.then(c)}function c(t){return o.chain(t).map(l).map(u).sortBy(["similarityPercent","bestMatchScore","bestMatchModificationDate","relevanceScore"]).reverse().value()}function u(t){var e,n,r=t.matchDetails[0];return"LOCAL_PROJECT"===r.type&&(e=r.lastModifiedDate,n="Translated"===r.contentState?0:1),"IMPORTED_TM"===r.type&&(e=r.lastChanged,n=2),o.assign({},t,{bestMatchScore:n,bestMatchModificationDate:e})}function l(t){var e=o.sortBy(t.matchDetails,d);return o.assign({},t,{matchDetails:e})}function d(t){if("IMPORTED_TM"===t.type)return"3"+t.lastChanged;if("LOCAL_PROJECT"===t.type){if("Translated"===t.contentState)return"2"+t.lastModifiedDate;if("Approved"===t.contentState)return"1"+t.lastModifiedDate}return"9"}return{getSuggestionsForPhrase:a,getSuggestionsForText:i}}t.$inject=["EditorService","EventService","UrlService","_","$resource"],angular.module("app").factory("SuggestionsService",t)}(),function(){"use strict";function t(t,e,n,o,r){function i(){return T>0}function a(){return g?[g]:[]}function s(){return E}function c(t){I=t,p||u()}function u(){var t=h+f,e=t-Date.now(),n=e>0?e:f;p=r(function(){return p=null,T>=S?void u():void l()},n)}function l(){if(null!==I){var t=I;I=null,r.cancel(p),p=null,d(t)}}function d(t){g=t;var e=Date.now();h=e,T++,n.getSuggestionsForText(t).then(function(t){e>v&&(v=e,E=t)},function(t){console.error("Error searching for text ",t)})["finally"](function(){T--,o.$broadcast("TextSuggestionsService:updated"),S>T&&l()})}var f=300,S=3,g=null,E=[],p=null,T=0,h=Date.now(),v=Date.now(),I=null;return o.$on(e.EVENT.REQUEST_TEXT_SUGGESTIONS,function(t,e){if(!(I&&I===e||!I&&0===T&&g===e)){if(""===e)return g=e,E=[],I=null,r.cancel(p),p=null,h=Date.now,v=Date.now(),void o.$broadcast("TextSuggestionsService:updated");if(T>=S)return void c(e);var n=h+f;if(Date.now()')}}}angular.module("app").directive("toggleCheckbox",t)}(),function(){"use strict";function t(t){function e(t){return t=angular.uppercase(t),t&&"NEW"!==t?"NEEDREVIEW"===t&&(t="NEEDSWORK"):t="UNTRANSLATED",t}function n(t){return t=angular.lowercase(t),t&&"untranslated"!==t?"needswork"===t?"NeedReview":t.charAt(0).toUpperCase()+t.slice(1).toLowerCase():"New"}var o=this,r={UNTRANSLATED:{ID:"untranslated",NAME:"Untranslated",CSSCLASS:"neutral"},NEEDSWORK:{ID:"needswork",NAME:"Needs Work",CSSCLASS:"unsure"},TRANSLATED:{ID:"translated",NAME:"Translated",CSSCLASS:"success"},APPROVED:{ID:"approved",NAME:"Approved",CSSCLASS:"highlight"}};return o.getAll=function(){return r},o.getAllAsArray=function(){return t.values(r)},o.getStatusInfo=function(t){return r[e(t)]},o.getId=function(t){return r[e(t)].ID},o.getServerId=function(t){return n(t)},o.getName=function(t){return r[e(t)].NAME},o.getCSSClass=function(t){return r[e(t)].CSSCLASS},o}t.$inject=["_"],angular.module("app").factory("TransStatusService",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s,c,u,l,d){function f(){S.selected||e.$apply(function(){a.emitEvent(a.EVENT.SELECT_TRANS_UNIT,{id:e.phrase.id,updateURL:!0,focus:!0},e)})}var S=this;S.selected=!1,S.focused=!1,S.focusedTranslationIndex=0,S.hasTranslationChanged=l.hasTranslationChanged,S.focusTranslation=function(){S.selected&&c("phrase-"+e.phrase.id+"-"+S.focusedTranslationIndex)},S.onTextAreaFocus=function(t,n){S.focused=!0,r.isUndefined(n)||(S.focusedTranslationIndex=n),S.selected||a.emitEvent(a.EVENT.SELECT_TRANS_UNIT,{id:t.id,updateURL:!0,focus:!0},e)},S.translationTextModified=function(t){a.emitEvent(a.EVENT.TRANSLATION_TEXT_MODIFIED,t)},S.getPhrase=function(){return e.phrase},S.init=function(){i.addController(e.phrase.id,S),o.id&&parseInt(o.id)===e.phrase.id&&a.emitEvent(a.EVENT.SELECT_TRANS_UNIT,{id:o.id,updateURL:!1,focus:o.selected})},S.copySource=function(t,n,o){t.stopPropagation(),a.emitEvent(a.EVENT.COPY_FROM_SOURCE,{phrase:n,sourceIndex:o},e)},S.undoEdit=function(t,n){t.stopPropagation(),a.emitEvent(a.EVENT.UNDO_EDIT,n,e)},S.cancelEdit=function(t,n){t.stopPropagation(),a.emitEvent(a.EVENT.CANCEL_EDIT,n,e)},S.saveAs=function(t,e,n){u.saveTranslationCallBack(t,e,n)},S.getLocaleName=function(t){return s.getName(t)},S.toggleSaveAsOptions=function(t){a.broadcastEvent(t?"openDropdown":"closeDropdown",{},e),t&&c(e.phrase.id+"-saveAsOption-0")};var g=d.SETTING.SHOW_SUGGESTIONS;return e.showSuggestions=d.subscribe(g,function(t){e.showSuggestions=t}),t.$on(a.EVENT.SUGGESTIONS_SEARCH_TOGGLE,function(t,e){S.suggestionsSearchIsActive=e}),S.toggleSuggestionPanel=function(){S.suggestionsSearchIsActive?a.emitEvent(a.EVENT.SUGGESTIONS_SEARCH_TOGGLE,!1):d.update(g,!e.showSuggestions)},e.suggestionCount=0,t.$on(a.EVENT.PHRASE_SUGGESTION_COUNT,function(t,n){n.id===e.phrase.id&&(e.suggestionCount=n.count)}),S.cancelSaveAsMode=function(){u.cancelSaveAsModeIfOn()},e.$on("$destroy",function(){n.unbind("click",f),n.unbind("focus",f)}),S.updateSaveButton=function(t){S.saveButtonStatus=l.getSaveButtonStatus(e.phrase),S.saveButtonOptions=i.getSaveButtonOptions(S.saveButtonStatus,e.phrase),S.saveButtonText=S.saveButtonStatus.NAME,S.saveButtonDisabled=!l.hasTranslationChanged(t),S.loadingClass="",S.savingStatus=""},S.phraseSaving=function(t){S.loadingClass="is-loading",S.saveButtonStatus=S.savingStatus=t.status,S.saveButtonOptions=i.getSaveButtonOptions(S.saveButtonStatus,t.phrase),S.saveButtonText="Saving…",S.saveButtonDisabled=!0},S.saveButtonOptionsAvailable=function(){return!r.isEmpty(S.saveButtonOptions)},S.selectTransUnit=function(t){S.selected||a.emitEvent(a.EVENT.SELECT_TRANS_UNIT,{id:t.id,updateURL:!0,focus:!0},e)},S}t.$inject=["$rootScope","$scope","$element","$stateParams","_","TransUnitService","EventService","LocaleService","focus","EditorShortcuts","PhraseUtil","SettingsService"],angular.module("app").controller("TransUnitCtrl",t)}(),function(){"use strict";function t(t,e,n,o,r,i,a,s,c,u,l,d,f){function S(t,e){var n=0;if(t.plural){var o=N[t.id];n=o.focusedTranslationIndex}t.newTranslations[n]=e,s.emitEvent(s.EVENT.TRANSLATION_TEXT_MODIFIED,t),s.emitEvent(s.EVENT.FOCUS_TRANSLATION,t)}function g(t,e){t.newTranslations=e.slice(),s.emitEvent(s.EVENT.TRANSLATION_TEXT_MODIFIED,t),s.emitEvent(s.EVENT.FOCUS_TRANSLATION,t)}function E(t,e){var n=N[e.id];n.updateSaveButton(e)}function p(t,e){var n=N[e.phrase.id];n.phraseSaving(e),s.emitEvent(s.EVENT.FOCUS_TRANSLATION,e.phrase)}function T(t,e){t.selected!==e&&(t.selected=e||!1)}function h(t,e){var n=N[e.id];n.focusTranslation()}function v(t,e){var n=[];return"untranslated"===t.ID?n:(n=i("filter")(c.getAllAsArray(),{ID:"!untranslated"}),e.plural&&(d.hasNoTranslation(e)?n=i("filter")(n,{ID:"!needswork"}):d.hasEmptyTranslation(e)&&(n=i("filter")(n,{ID:"!translated"}))),u&&(n=i("filter")(n,{ID:"!approved"})),i("filter")(n,{ID:"!"+t.ID}))}var I,m=this,N={};return m.addController=function(t,e){N[t]=e},m.getSaveButtonOptions=function(t,e){return v(t,e)},n.$on(s.EVENT.TOGGLE_SAVE_OPTIONS,function(t,e){var n=N[e.id];n&&n.toggleSaveAsOptions(e.open)}),n.$on(s.EVENT.SELECT_TRANS_UNIT,function(t,n){var i=N[n.id],u=N[I],f=n.updateURL;s.emitEvent(s.EVENT.REQUEST_PHRASE_SUGGESTIONS,{phrase:i.getPhrase()}),i?(l.selectedTUCtrl=i,I&&I!==n.id&&(T(u,!1),d.hasTranslationChanged(u.getPhrase())&&s.emitEvent(s.EVENT.SAVE_TRANSLATION,{phrase:u.getPhrase(),status:c.getStatusInfo("TRANSLATED"),locale:r.localeId,docId:r.docId})),E(t,i.getPhrase()),I=n.id,T(i,!0),s.emitEvent(s.EVENT.FOCUS_TRANSLATION,n),f&&("editor.selectedContext.tu"!==o.current.name?o.go("editor.selectedContext.tu",{id:n.id,selected:n.focus.toString()}):(e.search("id",n.id),e.search("selected",n.focus.toString())))):a.displayWarning("Trans-unit not found:"+n.id)}),n.$on(s.EVENT.COPY_FROM_SOURCE,function(e,n){var o=0;if(n.phrase.plural&&(o=n.sourceIndex,t.isUndefined(o))){var r=N[n.phrase.id];o=r.focusedTranslationIndex,n.phrase.sources.length1;if(s){var c=r.translations.length;if(a.lengthc&&(a=t.first(a,c)),g(r,a)}else S(r,a[0])}}),n.$on(s.EVENT.UNDO_EDIT,function(t,e){d.hasTranslationChanged(e)&&g(e,e.translations)}),n.$on(s.EVENT.CANCEL_EDIT,function(t,o){I&&(T(N[I],!1),I=!1,l.selectedTUCtrl=null),e.search("selected",null),o||e.search("id",null),o&&f(function(){return n.$broadcast("blurOn","phrase-"+o.id)})}),n.$on(s.EVENT.TRANSLATION_TEXT_MODIFIED,E),n.$on(s.EVENT.FOCUS_TRANSLATION,h),n.$on(s.EVENT.SAVE_INITIATED,p),n.$on(s.EVENT.SAVE_COMPLETED,E),m}t.$inject=["_","$location","$rootScope","$state","$stateParams","$filter","MessageHandler","EventService","TransStatusService","PRODUCTION","EditorShortcuts","PhraseUtil","$timeout"],angular.module("app").factory("TransUnitService",t)}(),function(){"use strict";function t(){return{restrict:"E",required:["phrase","editorContext"],scope:{phrase:"=",firstPhrase:"=",editorContext:"="},controller:"TransUnitCtrl as transUnitCtrl",templateUrl:"components/transUnit/trans-unit.html",link:function(t,e,n,o){o.init()}}}angular.module("app").directive("transUnit",t)}(),function(){"use strict";function t(){return{restrict:"E",required:["editor"],scope:{editor:"="},templateUrl:"components/transUnitFilter/trans-unit-filter.html"}}angular.module("app").directive("transUnitFilter",t)}(),function(){"use strict";function t(t,e){function n(n){var o=t(e.USER_INFO_URL,{},{query:{method:"GET",params:{username:n}}});return o.query().$promise}function o(){var n=t(e.MY_INFO_URL,{},{query:{method:"GET"}});return n.query().$promise}return{settings:{editor:{hideMainNav:!1}},getUserInfo:n,getMyInfo:o}}t.$inject=["$resource","UrlService"],angular.module("app").factory("UserService",t)}(),function(){"use strict";function t(t,e){function n(t,n,o){return t&&n&&o?e.filter(t,function(t){return i(t,n,o)}):t}function o(t){var e={},n=Object.keys(t).filter(function(t){return-1===t.indexOf("$")});return n.forEach(function(n){e[n]=t[n]}),e}function r(t){var e=[],n=Object.keys(t).filter(function(t){return-1===t.indexOf("$")});return n.forEach(function(n){e.push(t[n])}),e}function i(n,o,r){return n&&o&&r?e.any(o,function(o){return e.any(r,function(e){return t.equals(n[o],e,!0)})}):!1}return{filterResources:n,cleanResourceList:r,cleanResourceMap:o}}t.$inject=["StringUtil","_"],angular.module("app").factory("FilterUtil",t)}(),function(){"use strict";function t(t,e){function n(e){return r(e)?t.getStatusInfo("untranslated"):i(e)?t.getStatusInfo("needswork"):o(e)?t.getStatusInfo("translated"):e.status}function o(t){var n=e.every(t.translations,function(e,n){return a(e)===a(t.newTranslations[n])});return!n}function r(t){return e.isEmpty(e.compact(t.newTranslations))}function i(t){return e.compact(t.newTranslations).length!==t.newTranslations.length}function a(t){return t||""}return{getSaveButtonStatus:n,hasTranslationChanged:o,hasNoTranslation:r,hasEmptyTranslation:i}}t.$inject=["TransStatusService","_"],angular.module("app").factory("PhraseUtil",t)}(),function(){"use strict";function t(){return{getWordStatistic:function(t){return"WORD"===t[0].unit?t[0]:t[1]},getMsgStatistic:function(t){return"MESSAGE"===t[0].unit?t[0]:t[1]}}}angular.module("app").factory("StatisticUtil",t)}(),function(){"use strict";function t(){function t(t,e,n){return n&&t&&e&&(t=t.toUpperCase(),e=e.toUpperCase()),0===t.lastIndexOf(e,0)}function e(t,e,n){return n&&t&&e&&(t=t.toUpperCase(),e=e.toUpperCase()),-1!==t.indexOf(e,t.length-e.length)}function n(t,e,n){return n&&t&&e&&(t=t.toUpperCase(),e=e.toUpperCase()),t===e}return{startsWith:t,endsWith:e,equals:n}}angular.module("app").factory("StringUtil",t)}(),function(){"use strict";function t(t,e,n,o,r){function i(){return l+Array.prototype.join.call(arguments,"")}function a(t){return function(e){return t(e)}}location.origin||(location.origin=window.location.protocol+"//"+window.location.hostname+(window.location.port?":"+window.location.port:""));var s=this,c="http://www.gravatar.com/avatar",u="config.json",l="",d={},f=location.origin+location.pathname+"translations";return s.serverContextPath="",s.init=function(){return l?n.when(l):e.get(u).then(function(t){var e=t.data;if(e.baseUrl)l=e.baseUrl;else{var n=e.appPath.replace(/^\//g,""),o=location.href.indexOf(n);s.serverContextPath=location.origin+location.pathname,o>=0&&(s.serverContextPath=location.href.substring(0,o)),s.serverContextPath=s.serverContextPath.replace(/\/?$/,"/"),l=s.serverContextPath+"rest"}d=r.mapValues({project:"/project/:projectSlug",docs:"/project/:projectSlug/version/:versionSlug/docs",locales:"/project/:projectSlug/version/:versionSlug/locales",status:"/project/:projectSlug/version/:versionSlug/doc/:docId/status/:localeId",textFlows:"/source+trans/:localeId",docStats:"/stats/project/:projectSlug/version/:versionSlug/doc/:docId/locale/:localeId",myInfo:"/user",userInfo:"/user/:username",translation:"/trans/:localeId",allLocales:"/locales",suggestions:"/suggestions"},a(i)),s.PROJECT_URL=d.project,s.LOCALE_LIST_URL=d.locales,s.DOCUMENT_LIST_URL=d.docs,s.TRANSLATION_STATUS_URL=d.status,s.TEXT_FLOWS_URL=d.textFlows,s.DOC_STATISTIC_URL=d.docStats,s.MY_INFO_URL=d.myInfo,s.USER_INFO_URL=d.userInfo,s.TRANSLATION_URL=d.translation,s.ALL_LOCALE_URL=d.allLocales,s.SUGGESTIONS_URL=d.suggestions,s.PROJECT_PAGE=function(t,e){return s.serverContextPath+"iteration/view/"+t+"/"+e},s.DASHBOARD_PAGE=s.serverContextPath+"dashboard"})},s.readValue=function(e){return t.search()[e]},s.gravatarUrl=function(t,e){return c+"/"+t+"?d=mm&r=g&s="+e},s.uiTranslationURL=function(t){return f+"/"+t+".json"},s.uiTranslationListURL=f+"/locales",s}t.$inject=["$location","$http","$q","$stateParams","_"],angular.module("app").factory("UrlService",t)}(); //# sourceMappingURL=../maps/app.js.map \ No newline at end of file diff --git a/zanata-war/src/main/webapp/app/js/templates.js b/zanata-war/src/main/webapp/app/js/templates.js index 796fc201c1..6417c95742 100644 --- a/zanata-war/src/main/webapp/app/js/templates.js +++ b/zanata-war/src/main/webapp/app/js/templates.js @@ -1,4 +1,4 @@ -angular.module("templates", []).run(["$templateCache", function($templateCache) {$templateCache.put("editor/editor-content.html","
\n
\n
    0\">\n
  • \n \n
  • \n
\n
\n \n

No content

\n
\n
\n
\n"); +angular.module("templates", []).run(["$templateCache", function($templateCache) {$templateCache.put("editor/editor-content.html","
\n
\n
    0\">\n
  • \n \n
  • \n
\n
\n \n

No content

\n
\n
\n
\n"); $templateCache.put("editor/editor-details.html","\n"); $templateCache.put("editor/editor-header.html","\n \n\n
\n \n \n \n
\n"); $templateCache.put("editor/editor-suggestions.html","
\n
\n\n\n"); @@ -7,9 +7,9 @@ $templateCache.put("components/icon/icon.html","\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n"); $templateCache.put("components/progressbar/progressbar.html","\n \n \n \n \n\n"); $templateCache.put("components/suggestions/suggestion.html","
1\">\n
\n
\n
\n \n
\n
\n Singular Form\n Plural Form\n
\n
\n
\n
\n \n
\n
    \n
  • {{detail.projectName}}
  • \n
  • {{detail.version}}
  • \n
  • {{detail.documentName}}
  • \n\n
  • {{detail.transMemorySlug}}
  • \n\n
  • 0\"> {{remaining}} more occurrences
  • \n
\n
\n
\n
\n
\n
\n Singular Form\n Plural Form\n
\n
\n
\n
\n
\n \n Last updated {{detail.lastChanged | date: \'mediumDate\'}}\n Approved by {{user}} on {{detail.lastModifiedDate | date: \'mediumDate\'}}\n Translated by {{user}} on {{detail.lastModifiedDate | date: \'mediumDate\'}}\n
\n
\n
    \n
  • \n
  • \n \n
  • \n
\n
\n
\n
\n
\n"); -$templateCache.put("components/transUnitFilter/trans-unit-filter.html","
    \n
  • \n
    \n \n \n
    \n
  • \n
  • \n
    \n \n \n
    \n
  • \n
  • \n
    \n \n \n
    \n
  • \n
  • \n
    \n \n \n
    \n
  • \n
  • \n
    \n \n \n
    \n
  • \n \n
  • \n
  • \n \n
  • \n
\n"); $templateCache.put("components/transUnit/trans-unit-status.html","
\n \n
    \n
  • \n \n
  • \n
  • \n \n
  • \n
\n
\n"); $templateCache.put("components/transUnit/trans-unit.html","
\n\n \n\n
\n \n\n
\n
\n Singular Form\n Plural Form\n
    \n
  • \n \n
  • \n
\n
\n
\n    
\n \n
\n\n
\n \n
\n
\n Singular Form\n Plural Form\n
\n \n
\n \n
\n\n
\n"); +$templateCache.put("components/transUnitFilter/trans-unit-filter.html","
    \n
  • \n
    \n \n \n
    \n
  • \n
  • \n
    \n \n \n
    \n
  • \n
  • \n
    \n \n \n
    \n
  • \n
  • \n
    \n \n \n
    \n
  • \n
  • \n
    \n \n \n
    \n
  • \n \n
  • \n
  • \n \n
  • \n
\n"); $templateCache.put("components/transUnit/source/footer.html","
\n
\n \n
\n
\n"); $templateCache.put("components/transUnit/source/header.html","
\n

{{::editorContext.srcLocale.name}} {{::editorContext.srcLocale.localeId}}\n

\n
    \n
  • \n
  • \n
  • \n \n
  • \n
  • \n \n
  • \n
\n
\n"); $templateCache.put("components/transUnit/translation/footer.html","
\n
\n
    \n
  • \n \n
  • \n
  • 0\">\n \n
  • \n
\n
\n
\n \n Save as\n \n \n
\n
\n \n
\n
\n \n
\n
\n
    \n
  • \n \n
  • \n
\n
\n
\n
\n"); diff --git a/zanata-war/src/main/webapp/app/maps/app.js.map b/zanata-war/src/main/webapp/app/maps/app.js.map index 024f73fa4c..b379d84ea4 100644 --- a/zanata-war/src/main/webapp/app/maps/app.js.map +++ b/zanata-war/src/main/webapp/app/maps/app.js.map @@ -1 +1 @@ -{"version":3,"sources":["app.js","AppConfig.js","AppConstants.js","AppCtrl.js","editor/EditorContentCtrl.js","editor/EditorCtrl.js","editor/EditorDetailsCtrl.js","editor/EditorService.js","editor/EditorShortcuts.js","editor/EditorSuggestionsCtrl.js","components/blur-on/blurOnDirective.js","components/clickElsewhere/clickElsewhereDirective.js","components/document/DocumentService.js","components/dropdown/DropdownController.js","components/dropdown/DropdownService.js","components/dropdown/dropdown.js","components/dropdown/dropdownDirective.js","components/event/EventService.js","components/icon/iconDirective.js","components/message/MessageHandler.js","components/locale/LocaleService.js","components/logo-loader/logoLoaderDirective.js","components/notification/NotificationService.js","components/phrases/PhraseCache.js","components/phrases/PhraseService.js","components/progressbar/progressbarDirective.js","components/project/ProjectService.js","components/resizer/resizerDirective.js","components/settings/SettingsService.js","components/renderWhitespaceCharacters/renderWhitespaceCharacters.js","components/scrollbar-width/ScrollbarWidthCtrl.js","components/scrollbar-width/scrollbarWidthDirective.js","components/suggestions/PhraseSuggestionsService.js","components/suggestions/SuggestionCtrl.js","components/suggestions/SuggestionsService.js","components/suggestions/TextSuggestionsService.js","components/suggestions/suggestionDirective.js","components/toggle/toggleDirective.js","components/transStatus/TransStatusService.js","components/transUnitFilter/transUnitFilterDirective.js","components/transUnit/TransUnitCtrl.js","components/transUnit/TransUnitService.js","components/transUnit/transUnitDirective.js","components/user/UserService.js","components/util/FilterUtil.js","components/util/PhraseUtil.js","components/util/StatisticUtil.js","components/util/StringUtil.js","components/util/UrlService.js"],"names":[],"mappings":"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","file":"app.js","sourcesContent":["(function() {\n 'use strict';\n\n /**\n * Root application\n * app.js\n */\n angular.module(\n 'app', [\n 'ngResource',\n 'ngAnimate',\n 'ui.router',\n 'templates',\n 'cfp.hotkeys',\n 'focusOn',\n 'monospaced.elastic',\n 'gettext',\n 'diff-match-patch'\n ]);\n\n})();\n","(function() {\n 'use strict';\n\n /**\n * @name AppConfig\n * @description Main config for the entire app\n * @ngInject\n */\n function AppConfig($stateProvider, $urlRouterProvider, $httpProvider,\n hotkeysProvider) {\n\n //Can't use injection for EventService as this module is out of the scope\n var interceptor = function($q, $rootScope) {\n return {\n request: function(config) {\n // See EventService.EVENT.LOADING_START\n $rootScope.$broadcast('loadingStart');\n return config;\n },\n requestError: function(rejection) {\n // See EventService.EVENT.LOADING_STOP\n $rootScope.$broadcast('loadingStop');\n console.error('Request error due to ', rejection);\n return $q.reject(rejection);\n },\n response: function(response) {\n // See EventService.EVENT.LOADING_STOP\n $rootScope.$broadcast('loadingStop');\n return response || $q.when(response);\n },\n responseError: function(rejection) {\n // See EventService.EVENT.LOADING_STOP\n $rootScope.$broadcast('loadingStop');\n if (rejection.status === 401) {\n console.error('Unauthorized access. Please login');\n } else if (rejection.status === 404) {\n console.error('Service end point not found- ',\n rejection.config.url);\n } else {\n console.error('Error in response ', rejection);\n }\n return $q.reject(rejection);\n }\n };\n };\n\n $httpProvider.interceptors.push(interceptor);\n\n // For any unmatched url, redirect to /editor\n $urlRouterProvider.otherwise('/');\n\n $stateProvider\n .state('editor', {\n url: '/:projectSlug/:versionSlug/translate',\n templateUrl: 'editor/editor.html',\n controller: 'EditorCtrl as editor',\n resolve: {\n url : function(UrlService) {\n return UrlService.init();\n }\n }\n }).state('editor.selectedContext', {\n url: '/:docId/:localeId',\n views: {\n 'editor-content': {\n templateUrl: 'editor/editor-content.html',\n controller: 'EditorContentCtrl as editorContent'\n },\n 'editor-suggestions': {\n templateUrl: 'editor/editor-suggestions.html',\n controller: 'EditorSuggestionsCtrl as editorSuggestions'\n },\n 'editor-details': {\n templateUrl: 'editor/editor-details.html',\n controller: 'EditorDetailsCtrl as editorDetails'\n }\n }\n }).state('editor.selectedContext.tu', {\n url: '/?id&selected?states',\n reloadOnSearch: false\n });\n\n hotkeysProvider.includeCheatSheet = false;\n\n // $locationProvider.html5Mode(true);\n // .hashPrefix('!');\n }\n\n angular\n .module('app')\n .config(AppConfig);\n\n})();\n\n\n\n","(function() {\n 'use strict';\n\n /**\n * AddConstants\n * \"Global\" app variables. Don't worry David, they're not really global.\n */\n angular\n .module('app')\n .constant('_', window._)\n .constant('str', window._.string)\n .constant('Mousetrap', window.Mousetrap)\n // Toggle to hide/show features that are ready for production\n .constant('PRODUCTION', true);\n\n})();\n\n\n","(function() {\n 'use strict';\n\n /**\n * @name AppCtrl\n * @description Main controler for the entire app\n * @ngInject\n */\n function AppCtrl($scope, UserService, UrlService, LocaleService,\n MessageHandler, gettextCatalog, StringUtil, PRODUCTION) {\n var appCtrl = this;\n\n // See AppConstants.js\n appCtrl.PRODUCTION = PRODUCTION;\n appCtrl.settings = UserService.settings;\n appCtrl.uiLocaleList = [ LocaleService.DEFAULT_LOCALE ];\n\n /*\n Not used for the time being. But should show loading when change state\n $scope.$on('$stateChangeStart', function(event, toState) {\n if (toState.resolve) {\n }\n });\n\n $scope.$on('$stateChangeSuccess', function(event, toState) {\n if (toState.resolve) {\n }\n });\n */\n\n UrlService.init().then(loadLocales).\n then(loadUserInformation).\n then(loadUILocale);\n\n // On UI locale changes listener\n appCtrl.onChangeUILocale = function(locale) {\n appCtrl.myInfo.locale = locale;\n var uiLocaleId = appCtrl.myInfo.locale.localeId;\n if (!StringUtil.startsWith(uiLocaleId,\n LocaleService.DEFAULT_LOCALE.localeId, true)) {\n gettextCatalog.loadRemote(UrlService.uiTranslationURL(uiLocaleId))\n .then(\n function() {\n gettextCatalog.setCurrentLanguage(uiLocaleId);\n },\n function(error) {\n MessageHandler.displayInfo('Error loading UI locale. ' +\n 'Default to \\'' + LocaleService.DEFAULT_LOCALE.name +\n '\\': ' + error);\n gettextCatalog.setCurrentLanguage(\n LocaleService.DEFAULT_LOCALE);\n appCtrl.myInfo.locale = LocaleService.DEFAULT_LOCALE;\n });\n } else {\n gettextCatalog.setCurrentLanguage(\n LocaleService.DEFAULT_LOCALE.localeId);\n }\n };\n\n appCtrl.dashboardPage = function() {\n return UrlService.DASHBOARD_PAGE;\n };\n\n function loadLocales() {\n return LocaleService.getAllLocales();\n }\n\n function loadUserInformation() {\n return UserService.getMyInfo().then(\n function(myInfo) {\n appCtrl.myInfo = myInfo;\n appCtrl.myInfo.locale = LocaleService.DEFAULT_LOCALE;\n appCtrl.myInfo.gravatarUrl = UrlService.gravatarUrl(\n appCtrl.myInfo.gravatarHash, 72);\n }, function(error) {\n MessageHandler.displayError('Error loading my info: ' + error);\n });\n }\n\n function loadUILocale() {\n LocaleService.getUILocaleList().then(\n function(translationList) {\n for ( var i in translationList.locales) {\n var language = {\n 'localeId' : translationList.locales[i],\n 'name' : ''\n };\n appCtrl.uiLocaleList.push(language);\n }\n appCtrl.myInfo.locale = LocaleService.getLocaleByLocaleId(\n appCtrl.uiLocaleList, LocaleService.DEFAULT_LOCALE.localeId);\n if (!appCtrl.myInfo.locale) {\n appCtrl.myInfo.locale = LocaleService.DEFAULT_LOCALE;\n }\n },\n function(error) {\n MessageHandler.displayInfo('Error loading UI locale. ' +\n 'Default to \\'' + LocaleService.DEFAULT_LOCALE.name +\n '\\': ' + error);\n appCtrl.myInfo.locale = LocaleService.DEFAULT_LOCALE;\n });\n }\n }\n\n angular\n .module('app')\n .controller('AppCtrl', AppCtrl);\n\n})();\n\n\n\n","(function() {\n 'use strict';\n\n /**\n * EditorContentCtrl.js\n * @ngInject\n */\n function EditorContentCtrl($rootScope, EditorService, PhraseService,\n DocumentService, UrlService, EventService,\n $stateParams, PhraseUtil, $location, _,\n TransStatusService) {\n\n //TODO: move pager to directives/convert to infinite scroll\n var COUNT_PER_PAGE = 50,\n editorContentCtrl = this, status, filter;\n refreshFilterQueryFromUrl();\n\n editorContentCtrl.phrases = [];\n\n EditorService.updateContext($stateParams.projectSlug,\n $stateParams.versionSlug, DocumentService.decodeDocId($stateParams.docId),\n $stateParams.localeId);\n\n init();\n\n $rootScope.$on(EventService.EVENT.FILTER_TRANS_UNIT,\n function (event, filter) {\n if(filter.status.all === true) {\n $location.search('status', null);\n } else {\n var queries = [];\n _.forEach(filter.status, function(val, key) {\n if(val) {\n queries.push(key);\n }\n });\n $location.search('status', queries.join(','));\n }\n refreshFilterQueryFromUrl();\n init();\n });\n\n function refreshFilterQueryFromUrl() {\n status = UrlService.readValue('status');\n\n if(!_.isUndefined(status)) {\n status = status.split(',');\n status = _.transform(status, function(result, state) {\n state = TransStatusService.getServerId(state);\n return result.push(state);\n });\n }\n filter = {\n 'status': status\n };\n }\n\n\n $rootScope.$on(EventService.EVENT.GOTO_FIRST_PAGE,\n function () {\n if(EditorService.currentPageIndex > 0) {\n EditorService.currentPageIndex = 0;\n changePage(EditorService.currentPageIndex);\n }\n });\n\n $rootScope.$on(EventService.EVENT.GOTO_PREV_PAGE,\n function () {\n if(EditorService.currentPageIndex > 0) {\n EditorService.currentPageIndex -= 1;\n changePage(EditorService.currentPageIndex);\n }\n });\n\n $rootScope.$on(EventService.EVENT.GOTO_NEXT_PAGE,\n function () {\n if(EditorService.currentPageIndex < EditorService.maxPageIndex) {\n EditorService.currentPageIndex +=1;\n changePage(EditorService.currentPageIndex);\n }\n });\n\n $rootScope.$on(EventService.EVENT.GOTO_LAST_PAGE,\n function () {\n if(EditorService.currentPageIndex < EditorService.maxPageIndex) {\n EditorService.currentPageIndex = EditorService.maxPageIndex;\n changePage(EditorService.currentPageIndex);\n }\n });\n\n /*\n TODO: after moving to infinite scroll, all these go to event handler\n should move back to TransUnitService and use PhraseService.findNextId etc\n */\n // EventService.EVENT.GOTO_NEXT_ROW listener\n $rootScope.$on(EventService.EVENT.GOTO_NEXT_ROW, goToNextRow);\n\n // EventService.EVENT.GOTO_PREVIOUS_ROW listener\n $rootScope.$on(EventService.EVENT.GOTO_PREVIOUS_ROW, goToPreviousRow);\n\n // EventService.EVENT.GOTO_NEXT_UNTRANSLATED listener\n $rootScope.$on(EventService.EVENT.GOTO_NEXT_UNTRANSLATED,\n goToNextUntranslated);\n\n function goToNextRow(event, data) {\n var phrases = editorContentCtrl.phrases,\n phrase,\n currentIndex,\n nextIndex,\n nextId;\n\n currentIndex = _.findIndex(phrases, function (phrase) {\n return phrase.id === data.currentId;\n });\n nextIndex = Math.min(currentIndex + 1, phrases.length - 1);\n nextId = phrases[nextIndex].id;\n\n if (nextId !== data.currentId) {\n EventService.emitEvent(EventService.EVENT.SELECT_TRANS_UNIT,\n {\n 'id': nextId,\n 'updateURL': true,\n 'focus': true\n }, null);\n } else {\n // we have reach the end\n phrase = phrases[currentIndex];\n EventService.emitEvent(EventService.EVENT.SAVE_TRANSLATION,\n {\n 'phrase': phrase,\n 'status': PhraseUtil.getSaveButtonStatus(phrase),\n 'locale': $stateParams.localeId,\n 'docId': $stateParams.docId\n });\n }\n }\n\n function goToPreviousRow(event, data) {\n var phrases = editorContentCtrl.phrases,\n phrase,\n currentIndex,\n previousIndex,\n prevId;\n\n currentIndex = _.findIndex(phrases, function (phrase) {\n return phrase.id === data.currentId;\n });\n previousIndex = Math.max(currentIndex - 1, 0);\n prevId = phrases[previousIndex].id;\n\n if (prevId !== data.currentId) {\n EventService.emitEvent(EventService.EVENT.SELECT_TRANS_UNIT,\n {\n 'id': prevId,\n 'updateURL': true,\n 'focus': true\n }, null);\n } else {\n phrase = phrases[currentIndex];\n // have reach the start\n EventService.emitEvent(EventService.EVENT.SAVE_TRANSLATION,\n {\n 'phrase': phrase,\n 'status': PhraseUtil.getSaveButtonStatus(phrase),\n 'locale': $stateParams.localeId,\n 'docId': $stateParams.docId\n });\n }\n }\n\n function goToNextUntranslated(event, data) {\n var phrases = editorContentCtrl.phrases,\n requestStatus = TransStatusService.getStatusInfo(status),\n currentIndex,\n nextStatusInfo;\n\n currentIndex = _.findIndex(phrases, function (phrase) {\n return phrase.id === data.currentId;\n });\n\n for (var i = currentIndex + 1; i < phrases.length; i++) {\n nextStatusInfo = TransStatusService.getStatusInfo(\n phrases[i].state);\n if (nextStatusInfo.ID === requestStatus.ID) {\n EventService.emitEvent(EventService.EVENT.SELECT_TRANS_UNIT,\n {\n 'id': phrases[i].id,\n 'updateURL': true,\n 'focus': true\n }, null);\n return;\n }\n }\n // can not find next untranslated\n //TransUnitService.saveCurrentRowIfModifiedAndUnfocus(data);\n }\n\n function changePage(pageIndex) {\n loadPhrase(pageIndex);\n EventService.emitEvent(EventService.EVENT.CANCEL_EDIT);\n }\n\n /**\n * Load transUnit\n *\n * @param projectSlug\n * @param versionSlug\n * @param docId\n * @param localeId\n */\n function init() {\n EventService.emitEvent(EventService.EVENT.REFRESH_STATISTIC,\n {\n projectSlug: EditorService.context.projectSlug,\n versionSlug: EditorService.context.versionSlug,\n docId: EditorService.context.docId,\n localeId: EditorService.context.localeId\n }\n );\n\n PhraseService.getPhraseCount(EditorService.context, filter).\n then(function(count) {\n EditorService.maxPageIndex = parseInt(count / COUNT_PER_PAGE);\n if(count > COUNT_PER_PAGE) {\n EditorService.maxPageIndex = count % COUNT_PER_PAGE !== 0 ?\n EditorService.maxPageIndex +=1 : EditorService.maxPageIndex;\n }\n\n EditorService.maxPageIndex = EditorService.maxPageIndex -1 < 0 ? 0 :\n EditorService.maxPageIndex -1;\n\n loadPhrase(EditorService.currentPageIndex);\n });\n }\n\n function loadPhrase(pageIndex) {\n var startIndex = pageIndex * COUNT_PER_PAGE;\n PhraseService.fetchAllPhrase(EditorService.context, filter,\n startIndex, COUNT_PER_PAGE).then(displayPhrases);\n }\n\n function displayPhrases(phrases) {\n editorContentCtrl.phrases = phrases;\n }\n\n return editorContentCtrl;\n }\n\n angular\n .module('app')\n .controller('EditorContentCtrl', EditorContentCtrl);\n})();\n","(function() {\n 'use strict';\n\n /**\n * EditorCtrl.js\n * @ngInject\n */\n function EditorCtrl($scope, UserService, DocumentService, LocaleService,\n ProjectService, EditorService, SettingsService, StatisticUtil,\n UrlService, $stateParams, $state, MessageHandler, $rootScope,\n EventService, EditorShortcuts, _, Mousetrap) {\n var editorCtrl = this;\n editorCtrl.pageNumber = 1;\n editorCtrl.showCheatsheet = false;\n editorCtrl.shortcuts = _.mapValues(\n _.values(EditorShortcuts.SHORTCUTS), function(shortcutInfo) {\n // second combo (secondary keys) is an array. We have to flatten it\n var keyCombos = _.flatten(shortcutInfo.keyCombos, 'combo');\n return {\n combos: _.map(keyCombos, function(key) {\n return EditorShortcuts.symbolizeKey(key);\n }),\n description: shortcutInfo.keyCombos[0].description\n };\n });\n\n //tu status to include for display\n editorCtrl.filter = {\n 'status' : {\n 'all': true,\n 'approved' : false,\n 'translated' : false,\n 'needsWork': false,\n 'untranslated': false\n }\n };\n\n processFilterQuery();\n\n //This is just processing UI during startup,\n //phrase filtering are done in EditorContentCtrl during init\n function processFilterQuery() {\n //process filter query\n var status = UrlService.readValue('status');\n\n if(!_.isUndefined(status)) {\n status = status.split(',');\n _.forEach(status, function(val) {\n if(!_.isUndefined(editorCtrl.filter.status[val])) {\n editorCtrl.filter.status[val] = true;\n }\n });\n updateFilter();\n }\n }\n\n Mousetrap.bind('?', function(event) {\n var srcElement = event.srcElement;\n if (!editorCtrl.showCheatsheet && !stopCheatsheetCallback(srcElement)) {\n editorCtrl.toggleKeyboardShortcutsModal();\n $scope.$digest();\n }\n }, 'keyup');\n\n /**\n * Mousetrap by default stops callback on input elements BUT\n * hotkeys monkey patched it!!!\n * TODO change this hack once we remove angular hotkeys\n */\n function stopCheatsheetCallback(element) {\n // if the element has the class \"mousetrap\" then no need to stop\n if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {\n return false;\n }\n\n // stop for input, select, and textarea\n return element.tagName === 'INPUT' || element.tagName === 'SELECT' ||\n element.tagName === 'TEXTAREA' || element.isContentEditable;\n }\n\n //TODO: cross domain rest\n //TODO: Unit test\n\n //Working URL: http://localhost:8000/#/tiny-project/1/translate or\n // http://localhost:8000/#/tiny-project/1/translate/hello.txt/fr\n editorCtrl.context = EditorService.initContext($stateParams.projectSlug,\n $stateParams.versionSlug, DocumentService.decodeDocId($stateParams.docId),\n LocaleService.DEFAULT_LOCALE, LocaleService.DEFAULT_LOCALE.localeId,\n 'READ_WRITE');\n\n editorCtrl.toggleKeyboardShortcutsModal = function() {\n editorCtrl.showCheatsheet = !editorCtrl.showCheatsheet;\n };\n\n var SHOW_SUGGESTIONS = SettingsService.SETTING.SHOW_SUGGESTIONS;\n $scope.showSuggestions = SettingsService.subscribe(SHOW_SUGGESTIONS,\n function (show) {\n $scope.showSuggestions = show;\n });\n editorCtrl.toggleSuggestionPanel = function () {\n SettingsService.update(SHOW_SUGGESTIONS, !$scope.showSuggestions);\n };\n\n\n editorCtrl.versionPage = function() {\n return UrlService.PROJECT_PAGE(editorCtrl.context.projectSlug,\n editorCtrl.context.versionSlug);\n };\n\n editorCtrl.encodeDocId = function(docId) {\n return DocumentService.encodeDocId(docId);\n };\n\n ProjectService.getProjectInfo($stateParams.projectSlug).then(\n function(projectInfo) {\n editorCtrl.projectInfo = projectInfo;\n },\n function(error) {\n MessageHandler.displayError('Error getting project ' +\n 'information:' + error);\n });\n\n LocaleService.getSupportedLocales(editorCtrl.context.projectSlug,\n editorCtrl.context.versionSlug).then(\n function(locales) {\n editorCtrl.locales = locales;\n if (!editorCtrl.locales || editorCtrl.locales.length <= 0) {\n //redirect if no supported locale in version\n MessageHandler.displayError('No supported locales in ' +\n editorCtrl.context.projectSlug + ' : ' +\n editorCtrl.context.versionSlug);\n } else {\n //if localeId is not defined in url, set to first from list\n var selectedLocaleId = $state.params.localeId;\n var context = editorCtrl.context;\n\n if (!selectedLocaleId) {\n context.localeId = editorCtrl.locales[0].localeId;\n transitionToEditorSelectedView();\n } else {\n context.localeId = selectedLocaleId;\n if (!LocaleService.containsLocale(editorCtrl.locales,\n selectedLocaleId)) {\n context.localeId = editorCtrl.locales[0].localeId;\n }\n }\n }\n }, function(error) {\n MessageHandler.displayError('Error getting locale list: ' + error);\n });\n\n DocumentService.findAll(editorCtrl.context.projectSlug,\n editorCtrl.context.versionSlug).then(\n function(documents) {\n editorCtrl.documents = documents;\n\n if (!editorCtrl.documents || editorCtrl.documents.length <= 0) {\n //redirect if no documents in version\n MessageHandler.displayError('No documents in ' +\n editorCtrl.context.projectSlug + ' : ' +\n editorCtrl.context.versionSlug);\n } else {\n //if docId is not defined in url, set to first from list\n var selectedDocId = $state.params.docId,\n context = editorCtrl.context;\n if (!selectedDocId) {\n context.docId = editorCtrl.documents[0].name;\n transitionToEditorSelectedView();\n } else {\n context.docId = DocumentService.decodeDocId(selectedDocId);\n if (!DocumentService.containsDoc(editorCtrl.documents,\n context.docId)) {\n context.docId = editorCtrl.documents[0].name;\n }\n }\n }\n }, function(error) {\n MessageHandler.displayError('Error getting document list: ' + error);\n });\n\n $rootScope.$on(EventService.EVENT.SELECT_TRANS_UNIT,\n function (event, data) {\n editorCtrl.unitSelected = data.id;\n editorCtrl.focused = data.focus;\n });\n\n $rootScope.$on(EventService.EVENT.CANCEL_EDIT,\n function () {\n editorCtrl.unitSelected = false;\n editorCtrl.focused = false;\n });\n\n $rootScope.$on(EventService.EVENT.REFRESH_STATISTIC,\n function (event, data) {\n\n loadStatistic(data.projectSlug, data.versionSlug, data.docId,\n data.localeId);\n\n editorCtrl.context.docId = data.docId;\n editorCtrl.context.localeId = data.localeId;\n });\n\n editorCtrl.pageNumber = function() {\n if(EditorService.maxPageIndex === 0) {\n return EditorService.currentPageIndex + 1;\n } else {\n return (EditorService.currentPageIndex + 1) + ' of ' +\n (EditorService.maxPageIndex + 1);\n }\n };\n\n editorCtrl.getLocaleName = function(localeId) {\n return LocaleService.getName(localeId);\n };\n\n editorCtrl.firstPage = function() {\n EventService.emitEvent(EventService.EVENT.GOTO_FIRST_PAGE);\n };\n\n editorCtrl.lastPage = function() {\n EventService.emitEvent(EventService.EVENT.GOTO_LAST_PAGE);\n };\n\n\n editorCtrl.nextPage = function() {\n EventService.emitEvent(EventService.EVENT.GOTO_NEXT_PAGE);\n };\n\n editorCtrl.previousPage = function() {\n EventService.emitEvent(EventService.EVENT.GOTO_PREV_PAGE);\n };\n\n editorCtrl.resetFilter = function() {\n resetFilter(true);\n };\n\n editorCtrl.updateFilter = function() {\n updateFilter(true);\n };\n\n function updateFilter(fireEvent) {\n if(isStatusSame(editorCtrl.filter.status)) {\n resetFilter(fireEvent);\n } else {\n editorCtrl.filter.status.all = false;\n if(fireEvent) {\n EventService.emitEvent(EventService.EVENT.FILTER_TRANS_UNIT,\n editorCtrl.filter);\n }\n }\n }\n\n function resetFilter(fireEvent) {\n editorCtrl.filter.status.all = true;\n editorCtrl.filter.status.approved = false;\n editorCtrl.filter.status.translated = false;\n editorCtrl.filter.status.needsWork = false;\n editorCtrl.filter.status.untranslated = false;\n\n if(fireEvent) {\n EventService.emitEvent(EventService.EVENT.FILTER_TRANS_UNIT,\n editorCtrl.filter);\n }\n }\n\n function isStatusSame(statuses) {\n return statuses.approved === statuses.translated &&\n statuses.translated === statuses.needsWork &&\n statuses.needsWork === statuses.untranslated;\n }\n\n function transitionToEditorSelectedView() {\n if (isDocumentAndLocaleSelected()) {\n $state.go('editor.selectedContext', {\n 'docId': editorCtrl.context.docId,\n 'localeId': editorCtrl.context.localeId\n });\n }\n }\n\n function isDocumentAndLocaleSelected() {\n return editorCtrl.context.docId && editorCtrl.context.localeId;\n }\n\n /**\n * Load document statistics (word and message)\n *\n * @param projectSlug\n * @param versionSlug\n * @param docId\n * @param localeId\n */\n function loadStatistic(projectSlug, versionSlug, docId, localeId) {\n DocumentService.getStatistics(projectSlug, versionSlug, docId, localeId)\n .then(function(statistics) {\n editorCtrl.wordStatistic = StatisticUtil\n .getWordStatistic(statistics);\n editorCtrl.messageStatistic = StatisticUtil\n .getMsgStatistic(statistics);\n },\n function(error) {\n MessageHandler.displayError('Error loading statistic: ' + error);\n });\n }\n\n this.settings = UserService.settings.editor;\n\n EditorShortcuts.enableEditorKeys();\n }\n\n angular\n .module('app')\n .controller('EditorCtrl', EditorCtrl);\n})();\n","(function() {\n 'use strict';\n\n /**\n * EditorDetailsCtrl.js\n * @ngInject\n */\n function EditorDetailsCtrl() {\n var editorDetailsCtrl = this;\n\n return editorDetailsCtrl;\n }\n\n angular\n .module('app')\n .controller('EditorDetailsCtrl', EditorDetailsCtrl);\n})();\n","(function () {\n 'use strict';\n\n /**\n * EditorService.js\n * //TODO: parse editorContext in functions\n * @ngInject\n */\n function EditorService($rootScope, $resource, _, UrlService,\n EventService, PhraseService, PhraseUtil, DocumentService, MessageHandler,\n TransStatusService) {\n var editorService = this,\n queue = {};\n\n editorService.context = {};\n\n editorService.currentPageIndex = 0;\n editorService.maxPageIndex = 0;\n\n editorService.initContext =\n function (projectSlug, versionSlug, docId, srcLocale, localeId, mode) {\n editorService.context = {\n projectSlug: projectSlug,\n versionSlug: versionSlug,\n docId: docId,\n srcLocale: srcLocale,\n localeId: localeId,\n mode: mode // READ_WRITE, READ_ONLY, REVIEW\n };\n return editorService.context;\n };\n\n editorService.updateContext = function(projectSlug, versionSlug, docId,\n localeId) {\n if(editorService.context.projectSlug !== projectSlug) {\n editorService.context.projectSlug = projectSlug;\n }\n if(editorService.context.versionSlug !== versionSlug) {\n editorService.context.versionSlug = versionSlug;\n }\n if(editorService.context.docId !== docId) {\n editorService.context.docId = docId;\n }\n if(editorService.context.localeId !== localeId) {\n editorService.context.localeId = localeId;\n }\n };\n\n /**\n * EventService.EVENT.SAVE_TRANSLATION listener\n * Perform save translation with given status\n *\n * - queue save translation request (1 global queue, 1 for each TU)\n * - if queue contains request id, replace old request with new request\n */\n $rootScope.$on(EventService.EVENT.SAVE_TRANSLATION,\n function (event, data) {\n var phrase = data.phrase,\n status = data.status;\n if (!needToSavePhrase(phrase, status)) {\n // nothing has changed\n return;\n }\n\n //update pending queue if contains\n if (_.has(queue, phrase.id)) {\n var pendingRequest = queue[phrase.id];\n pendingRequest.phrase = phrase;\n pendingRequest.status = status;\n } else {\n status = resolveTranslationState(phrase, status);\n queue[phrase.id] = {\n 'phrase': phrase,\n 'status': status,\n 'locale': data.locale,\n 'docId': data.docId\n };\n }\n EventService.emitEvent(EventService.EVENT.SAVE_INITIATED, data);\n processSaveRequest(phrase.id);\n });\n\n function needToSavePhrase(phrase, status) {\n return PhraseUtil.hasTranslationChanged(phrase) ||\n phrase.status !== status;\n }\n\n // Process save translation request\n function processSaveRequest(id) {\n var context = _.cloneDeep(editorService.context);\n\n var request = queue[id];\n\n var Translation = $resource(UrlService.TRANSLATION_URL, {}, {\n update: {\n method: 'PUT',\n params: {\n localeId: request.locale\n }\n }\n });\n var data = {\n id: request.phrase.id,\n revision: request.phrase.revision || 0,\n content: request.phrase.newTranslations[0],\n contents: request.phrase.newTranslations,\n // Return status object to PascalCase Id for the server\n status: TransStatusService.getServerId(request.status.ID),\n plural: request.phrase.plural\n };\n\n Translation.update(data).$promise.then(\n function(response) {\n var oldStatus = request.phrase.status.ID;\n\n PhraseService.onTransUnitUpdated(context, data.id, request.locale,\n response.revision, response.status, request.phrase);\n\n DocumentService.updateStatistic(context.projectSlug,\n context.versionSlug, request.docId, request.locale,\n oldStatus, TransStatusService.getId(response.status),\n request.phrase.wordCount);\n\n EventService.emitEvent(EventService.EVENT.SAVE_COMPLETED,\n request.phrase);\n },\n function(response) {\n MessageHandler.displayWarning('Update translation failed for ' +\n data.id + ' -' + response);\n PhraseService.onTransUnitUpdateFailed(data.id);\n EventService.emitEvent(EventService.EVENT.SAVE_COMPLETED,\n request.phrase);\n });\n delete queue[id];\n }\n\n function resolveTranslationState(phrase, requestStatus) {\n if (_.isEmpty(_.compact(phrase.newTranslations))) {\n return TransStatusService.getStatusInfo('UNTRANSLATED');\n }\n return requestStatus;\n }\n\n return editorService;\n }\n\n angular\n .module('app')\n .factory('EditorService', EditorService);\n\n})();\n\n","(function () {\n 'use strict';\n\n /**\n * @name EditorShortcuts\n * @description service for editor keyboard shortcuts\n * @ngInject\n */\n function EditorShortcuts(EventService, $stateParams, _, hotkeys, PhraseUtil,\n TransStatusService, Mousetrap, str, $window) {\n var editorShortcuts = this,\n inSaveAsMode = false;\n\n // this will be set by TransUnitService\n // on EVENT.SELECT_TRANS_UNIT and unset on EVENT.CANCEL_EDIT\n editorShortcuts.selectedTUCtrl = null;\n\n function copySourceCallback(event) {\n if (editorShortcuts.selectedTUCtrl) {\n event.preventDefault();\n EventService.emitEvent(EventService.EVENT.COPY_FROM_SOURCE,\n {'phrase': editorShortcuts.selectedTUCtrl.getPhrase()});\n }\n }\n\n function gotoNextRowCallback(event) {\n if (editorShortcuts.selectedTUCtrl) {\n event.preventDefault();\n event.stopPropagation();\n EventService.emitEvent(EventService.EVENT.GOTO_NEXT_ROW,\n currentContext());\n }\n }\n\n function gotoPreviousRowCallback(event) {\n if (editorShortcuts.selectedTUCtrl) {\n event.preventDefault();\n event.stopPropagation();\n EventService.emitEvent(EventService.EVENT.GOTO_PREVIOUS_ROW,\n currentContext());\n }\n }\n\n function cancelEditCallback(event) {\n event.preventDefault();\n event.stopPropagation();\n if (inSaveAsMode) {\n editorShortcuts.cancelSaveAsModeIfOn();\n if (editorShortcuts.selectedTUCtrl) {\n editorShortcuts.selectedTUCtrl.focusTranslation();\n }\n } else if (editorShortcuts.selectedTUCtrl) {\n var phrase = editorShortcuts.selectedTUCtrl.getPhrase();\n if (PhraseUtil.hasTranslationChanged(phrase)) {\n // if it has changed translation, undo edit\n EventService.emitEvent(EventService.EVENT.UNDO_EDIT,\n phrase);\n } else {\n // otherwise cancel edit\n EventService.emitEvent(EventService.EVENT.CANCEL_EDIT,\n phrase);\n }\n }\n }\n\n function saveAsCurrentButtonOptionCallback(event) {\n if (editorShortcuts.selectedTUCtrl) {\n event.preventDefault();\n var phrase = editorShortcuts.selectedTUCtrl.getPhrase();\n EventService.emitEvent(EventService.EVENT.SAVE_TRANSLATION,\n {\n 'phrase': phrase,\n 'status': PhraseUtil.getSaveButtonStatus(phrase),\n 'locale': $stateParams.localeId,\n 'docId': $stateParams.docId\n });\n }\n }\n\n /**\n * This is to mimic sequence shortcut.\n * e.g. press ctlr-shift-s then press 'n' to save as\n * 'needs work'.\n */\n function saveAsModeCallback(event) {\n event.preventDefault();\n editorShortcuts.cancelSaveAsModeIfOn();\n var phrase = editorShortcuts.selectedTUCtrl.getPhrase();\n if (phrase) {\n EventService.emitEvent(EventService.EVENT.TOGGLE_SAVE_OPTIONS,\n {\n 'id': phrase.id,\n 'open': true\n });\n\n addSaveAsModeExtensionKey(phrase, 'n', 'needsWork');\n addSaveAsModeExtensionKey(phrase, 't', 'translated');\n addSaveAsModeExtensionKey(phrase, 'a', 'approved');\n }\n }\n\n /**\n * Generate a callback that will copy one of the suggestions to the editor.\n *\n * @param {number} oneBasedIndex the 1-based index of the suggestion that\n * this callback will copy\n * @return {function} callback that will copy the nth suggestion.\n */\n function copySuggestionCallback(oneBasedIndex) {\n return (function (event) {\n event.preventDefault();\n EventService.emitEvent(EventService.EVENT.COPY_FROM_SUGGESTION_N,\n oneBasedIndex-1);\n });\n }\n\n /**\n * mod will be replaced by ctrl if on windows/linux or cmd if on mac.\n * By default it listens on keydown event.\n */\n editorShortcuts.SHORTCUTS = {\n COPY_SOURCE: new ShortcutInfo(\n 'alt+c', copySourceCallback, 'Copy source as translation', 'alt+g'),\n\n COPY_SUGGESTION_1: new ShortcutInfo(\n 'mod+alt+1', copySuggestionCallback(1),\n 'Copy first suggestion as translation'),\n\n COPY_SUGGESTION_2: new ShortcutInfo(\n 'mod+alt+2', copySuggestionCallback(2),\n 'Copy second suggestion as translation'),\n\n COPY_SUGGESTION_3: new ShortcutInfo(\n 'mod+alt+3', copySuggestionCallback(3),\n 'Copy third suggestion as translation'),\n\n COPY_SUGGESTION_4: new ShortcutInfo(\n 'mod+alt+4', copySuggestionCallback(4),\n 'Copy fourth suggestion as translation'),\n\n CANCEL_EDIT: new ShortcutInfo('esc', cancelEditCallback, 'Cancel edit'),\n\n SAVE_AS_CURRENT_BUTTON_OPTION: new ShortcutInfo(\n 'mod+s', saveAsCurrentButtonOptionCallback, 'Save'),\n\n SAVE_AS_MODE: new ShortcutInfo(\n 'mod+shift+s', saveAsModeCallback, 'Save as…'),\n\n // this is just so we can show it in cheatsheet.\n // see app/editor/EditorCtrl.shortcuts\n SAVE_AS_NEEDSWORK: {\n keyCombos: [{combo: 'mod+shift+s n', description: 'Save as needs work'}]\n },\n\n SAVE_AS_TRANSLATED: {\n keyCombos: [{combo: 'mod+shift+s t', description: 'Save as translated'}]\n },\n\n SAVE_AS_APPROVED: {\n keyCombos: [{combo: 'mod+shift+s a', description: 'Save as approved'}]\n },\n\n GOTO_NEXT_ROW_FAST: new ShortcutInfo(\n 'mod+enter', gotoNextRowCallback,\n 'Save (if changed) and go to next string',\n ['alt+k', 'alt+down']),\n\n GOTO_PREVIOUS_ROW: new ShortcutInfo(\n 'mod+shift+enter', gotoPreviousRowCallback,\n 'Save (if changed) and go to previous string',\n ['alt+j', 'alt+up'])\n /*\n Disable for now until status navigation implementation\n GOTO_NEXT_UNTRANSLATED: new ShortcutInfo(\n 'tab+u', gotoToNextUntranslatedCallback)\n */\n };\n\n /*\n Disable for now until status navigation implementation\n\n function gotoToNextUntranslatedCallback(event) {\n event.preventDefault();\n event.stopPropagation();\n if (editorShortcuts.selectedTUCtrl) {\n EventService.emitEvent(EventService.EVENT.GOTO_NEXT_UNTRANSLATED,\n currentContext());\n }\n // the shortcut is a tab + u combination\n // we don't want other tab event to trigger\n tabCombinationPressed = true;\n }\n */\n\n /**\n *\n * @param {string} defaultKey default key combo for a shortcut\n * @param {function} callback callback to execute\n * @param {string} [description]\n * optional. If not empty will apply to default key (shows in cheatsheet)\n * @param {(string|string[])} [otherKeys]\n * optional other keys that will do the same (won't show in cheatsheet)\n * @param {string} [action] optional event to listen to. e.g. 'keyup'\n * @returns {EditorShortcuts.ShortcutInfo}\n * @constructor\n */\n function ShortcutInfo(defaultKey, callback, description, otherKeys, action)\n {\n this.defaultKey = defaultKey;\n this.keyCombos = [\n singleKeyConfig(defaultKey, description, action, callback)\n ];\n if (otherKeys) {\n this.otherKeys = otherKeys instanceof Array ? otherKeys : [otherKeys];\n this.keyCombos.push(\n singleKeyConfig(this.otherKeys, '', action, callback));\n }\n return this;\n }\n\n function singleKeyConfig(combo, description, action, callback) {\n var keyConfig = {\n allowIn: ['TEXTAREA'],\n callback: callback\n };\n keyConfig.combo = combo;\n if (description) {\n keyConfig.description = description;\n }\n if (action) {\n keyConfig.action = action;\n }\n return keyConfig;\n }\n\n editorShortcuts.enableEditorKeys = function () {\n // here we only check copy source shortcut since we always enable keys in\n // bundle.\n if (!hotkeys.get(editorShortcuts.SHORTCUTS.COPY_SOURCE.defaultKey)) {\n _.forOwn(editorShortcuts.SHORTCUTS, function(value) {\n if (value instanceof ShortcutInfo) { // a hack to handle sequence keys\n enableShortcut(value);\n }\n });\n }\n };\n\n editorShortcuts.disableEditorKeys = function () {\n _.forOwn(editorShortcuts.SHORTCUTS, function(value) {\n _.forEach(value.keyCombos, function(hotkey) {\n editorShortcuts.deleteKeys(hotkey.combo, hotkey.action);\n });\n });\n };\n\n function enableShortcut(shortcutInfo) {\n if (!hotkeys.get(shortcutInfo.defaultKey)) {\n _.forEach(shortcutInfo.keyCombos,\n function(combo) {\n hotkeys.add(combo);\n });\n }\n }\n\n function currentContext() {\n return {\n 'currentId': editorShortcuts.selectedTUCtrl.getPhrase().id\n };\n }\n\n function addSaveAsModeExtensionKey(phrase, combo, status) {\n var statusInfo = TransStatusService.getStatusInfo(status);\n return hotkeys.add({\n combo: combo,\n description: str.sprintf('Save as %s', status),\n allowIn: ['INPUT', 'TEXTAREA'],\n action: 'keydown',\n callback: function (event) {\n editorShortcuts.saveTranslationCallBack(event, phrase, statusInfo);\n }\n });\n }\n\n editorShortcuts.saveTranslationCallBack = function(event, phrase,\n statusInfo) {\n inSaveAsMode = true;\n\n event.preventDefault();\n event.stopPropagation();\n\n EventService.emitEvent(EventService.EVENT.SAVE_TRANSLATION,\n {\n 'phrase': phrase,\n 'status': statusInfo,\n 'locale': $stateParams.localeId,\n 'docId': $stateParams.docId\n });\n editorShortcuts.cancelSaveAsModeIfOn();\n };\n\n editorShortcuts.cancelSaveAsModeIfOn = function() {\n if (inSaveAsMode && editorShortcuts.selectedTUCtrl) {\n inSaveAsMode = false;\n editorShortcuts.deleteKeys(['n', 't', 'a']);\n EventService.emitEvent(EventService.EVENT.TOGGLE_SAVE_OPTIONS,\n {\n 'id': editorShortcuts.selectedTUCtrl.getPhrase().id,\n 'open': false\n });\n }\n };\n\n /**\n * This is a workaround for augular-hotkeys not being able to delete hotkey.\n * @see https://github.com/chieffancypants/angular-hotkeys/issues/100\n *\n * @param {(string|string[])} keys single key or array of keys to be deleted\n * @param {string} [action='keydown'] 'keyup' or 'keydown' etc.\n */\n editorShortcuts.deleteKeys = function(keys, action) {\n var keysToDelete = keys instanceof Array ? keys : [keys];\n action = action || 'keydown';\n _.forEach(keysToDelete, function(key) {\n hotkeys.del(key);\n Mousetrap.unbind(key, action);\n });\n };\n\n /**\n * Copied from angular-hotkeys.\n * Convert strings like cmd into symbols like ⌘\n * @param {String} combo Key combination, e.g. 'mod+f'\n * @return {String} The key combination with symbols\n */\n editorShortcuts.symbolizeKey = function (combo) {\n var map = {\n command: '⌘',\n shift: '⇧',\n left: '←',\n right: '→',\n up: '↑',\n down: '↓',\n 'return': '↩',\n backspace: '⌫'\n };\n combo = combo.split('+');\n\n for (var i = 0; i < combo.length; i++) {\n // try to resolve command / ctrl based on OS:\n if (combo[i] === 'mod') {\n if ($window.navigator &&\n $window.navigator.platform.indexOf('Mac') >= 0) {\n combo[i] = 'command';\n } else {\n combo[i] = 'ctrl';\n }\n }\n\n combo[i] = map[combo[i]] || combo[i];\n }\n\n return combo.join(' + ');\n };\n\n return editorShortcuts;\n }\n\n angular\n .module('app')\n .factory('EditorShortcuts', EditorShortcuts);\n})();\n\n","(function() {\n 'use strict';\n\n /**\n * EditorSuggestionsCtrl.js\n * @ngInject\n */\n function EditorSuggestionsCtrl($scope, _, SettingsService,\n PhraseSuggestionsService, TextSuggestionsService, EventService,\n $rootScope, $timeout, focus) {\n var SHOW_SUGGESTIONS_SETTING = SettingsService.SETTING.SHOW_SUGGESTIONS;\n var SUGGESTIONS_SHOW_DIFFERENCE_SETTING =\n SettingsService.SETTING.SUGGESTIONS_SHOW_DIFFERENCE;\n\n var editorSuggestionsCtrl = this;\n\n $scope.suggestions = [];\n $scope.hasSuggestions = false;\n $scope.$watch('suggestions.length', function (length) {\n $scope.hasSuggestions = length !== 0;\n });\n\n /* @type {string[]} */\n $scope.searchStrings = [];\n $scope.hasSearch = false;\n $scope.$watch('searchStrings.length', function (length) {\n $scope.hasSearch = length !== 0;\n });\n\n // TODO initialize with current trans unit selection state.\n $scope.isTransUnitSelected = false;\n\n // These must always be opposites. Probably change to an enum.\n $scope.isTextSearch = false;\n $scope.isPhraseSearch = true;\n\n function setTextSearch(active) {\n $scope.isTextSearch = active;\n $scope.isPhraseSearch = !active;\n }\n\n $scope.search = {\n isVisible: false,\n isLoading: false,\n input: {\n text: '',\n focused: false\n }\n };\n\n $scope.$watch('search.input.text', function () {\n editorSuggestionsCtrl.searchForText();\n });\n\n $scope.show = SettingsService.subscribe(SHOW_SUGGESTIONS_SETTING,\n function (show) {\n $scope.show = show;\n\n if (show) {\n if ($scope.isTransUnitSelected) {\n updatePhraseDisplay();\n } else {\n if (!$scope.search.isVisible) {\n showSearch(null, true);\n }\n }\n }\n\n });\n\n $scope.diff = SettingsService.subscribe(SUGGESTIONS_SHOW_DIFFERENCE_SETTING,\n function (diff) {\n $scope.diff = diff;\n });\n\n $scope.focusSearch = function($event) {\n if ($event) {\n $event.preventDefault();\n }\n focus('searchSugInput');\n };\n\n editorSuggestionsCtrl.closeSuggestions = function () {\n SettingsService.update(SHOW_SUGGESTIONS_SETTING, false);\n EventService.emitEvent(EventService.EVENT.SUGGESTIONS_SEARCH_TOGGLE,\n false);\n };\n\n editorSuggestionsCtrl.clearSearchResults =\n function($event, dontFocusInput) {\n // just remove the text, service will handle updating to empty results.\n $scope.search.input.text = '';\n\n if (!dontFocusInput && $event) {\n $scope.focusSearch($event);\n }\n };\n\n editorSuggestionsCtrl.searchForText = function () {\n var newText = $scope.search.input.text;\n if (newText.length > 0) {\n $scope.search.isLoading = true;\n }\n setTextSearch(true);\n EventService.emitEvent(EventService.EVENT.REQUEST_TEXT_SUGGESTIONS,\n newText);\n };\n\n editorSuggestionsCtrl.toggleSearch = function() {\n if ($scope.search.isVisible) {\n EventService.emitEvent(EventService.EVENT.SUGGESTIONS_SEARCH_TOGGLE,\n false);\n }\n else {\n EventService.emitEvent(EventService.EVENT.SUGGESTIONS_SEARCH_TOGGLE,\n true);\n }\n };\n\n // Init\n if ($scope.show && !$scope.isTransUnitSelected) {\n showSearch();\n }\n\n // TODO inline this\n function displaySuggestions(suggestions) {\n $scope.suggestions = suggestions;\n }\n\n function hideSearch() {\n $scope.search.isVisible = false;\n setTextSearch(false);\n updatePhraseDisplay();\n }\n\n function showSearch($event, dontFocusInput) {\n $scope.search.input.text = '';\n $scope.search.isVisible = true;\n if (!dontFocusInput && $event) {\n $scope.focusSearch($event);\n }\n editorSuggestionsCtrl.searchForText();\n updateTextDisplay();\n }\n\n $rootScope.$on(EventService.EVENT.SELECT_TRANS_UNIT,\n function () {\n // Automatically switch back to phrase search when no search is entered\n if ($scope.search.input.text === '' && $scope.search.isVisible) {\n EventService.emitEvent(EventService.EVENT.SUGGESTIONS_SEARCH_TOGGLE,\n false);\n }\n $scope.isTransUnitSelected = true;\n });\n\n $rootScope.$on(EventService.EVENT.CANCEL_EDIT,\n function () {\n $scope.isTransUnitSelected = false;\n if ($scope.show && !$scope.search.isVisible) {\n showSearch(null, true);\n }\n });\n\n $rootScope.$on(EventService.EVENT.SUGGESTIONS_SEARCH_TOGGLE,\n function(event, activate) {\n if (activate) {\n showSearch(event);\n }\n else {\n hideSearch(event);\n }\n });\n\n // Automatic suggestions search on row select\n $rootScope.$on('PhraseSuggestionsService:updated', function () {\n if ($scope.isPhraseSearch) {\n updatePhraseDisplay();\n }\n });\n\n /**\n * Update all the state to match the latest from the phrase search.\n */\n function updatePhraseDisplay() {\n $scope.searchStrings = PhraseSuggestionsService.getSearchStrings();\n $scope.search.isLoading = PhraseSuggestionsService.isLoading();\n displaySuggestions(PhraseSuggestionsService.getResults());\n }\n\n\n // Manual suggestions search\n $rootScope.$on('TextSuggestionsService:updated', function () {\n if ($scope.isTextSearch) {\n updateTextDisplay();\n }\n });\n\n /**\n * Update all the state to match the latest from the text search service.\n */\n function updateTextDisplay() {\n $scope.searchStrings = TextSuggestionsService.getSearchStrings();\n $scope.search.isLoading = TextSuggestionsService.isLoading();\n displaySuggestions(TextSuggestionsService.getResults());\n }\n\n $rootScope.$on(EventService.EVENT.COPY_FROM_SUGGESTION_N,\n function (event, matchIndex) {\n\n if ($scope.show) {\n // copy visible suggestion with that index\n copySuggestion($scope.suggestions[matchIndex]);\n\n // event for copy button on suggestion to display 'copied'\n $scope.$broadcast('EditorSuggestionsCtrl:nth-suggestion-copied',\n matchIndex);\n\n } else {\n // copy suggestion from background phrase search\n copySuggestion(PhraseSuggestionsService.getResults()[matchIndex]);\n }\n\n });\n\n\n function copySuggestion(suggestion) {\n if (suggestion) {\n EventService.emitEvent(EventService.EVENT.COPY_FROM_SUGGESTION,\n { suggestion: suggestion });\n }\n }\n\n return editorSuggestionsCtrl;\n }\n\n angular\n .module('app')\n .controller('EditorSuggestionsCtrl', EditorSuggestionsCtrl);\n})();\n","(function() {\n 'use strict';\n\n /**\n * @name blur-on\n * @description When you put attribute 'blur-on=\"something\"',\n * you can then blur this element. It works the same way as focus-on library.\n */\n function blurOn() {\n return {\n restrict: 'A',\n link: function(scope, elem, attr) {\n return scope.$on('blurOn', function (e, name) {\n if (name === attr.blurOn) {\n return elem[0].blur();\n }\n });\n }\n };\n }\n\n angular\n .module('app')\n .directive('blurOn', blurOn);\n\n})();\n","(function() {\n 'use strict';\n\n /**\n * @name clickElsewhere\n * @description Initiate expression when clicking somewhere else\n * @ngInject\n */\n function clickElsewhere($document) {\n return {\n restrict: 'A',\n scope: {\n callback: '&clickElsewhere'\n },\n link: function(scope, element) {\n var handler = function(e) {\n if (!element[0].contains(e.target)) {\n scope.$apply(scope.callback(e));\n }\n };\n\n $document.on('click', handler);\n\n scope.$on('$destroy', function() {\n $document.off('click', handler);\n });\n }\n };\n }\n\n angular\n .module('app')\n .directive('clickElsewhere', clickElsewhere);\n\n})();\n","(function() {\n 'use strict';\n\n /**\n * Handle server communication on document related\n * information in project-version.\n *\n * DocumentService.js\n * @ngInject\n */\n function DocumentService($q, $resource, UrlService, StringUtil,\n StatisticUtil, EventService, _, TransStatusService) {\n var documentService = this,\n statisticMap = {};\n\n /**\n * Finds all documents in given project version\n *\n * @param _projectSlug\n * @param _versionSlug\n * @returns {$promise|*|N.$promise}\n */\n documentService.findAll = function findAll(_projectSlug, _versionSlug) {\n var Documents = $resource(UrlService.DOCUMENT_LIST_URL, {}, {\n query: {\n method: 'GET',\n params: {\n projectSlug: _projectSlug,\n versionSlug: _versionSlug\n },\n isArray: true\n }\n });\n return Documents.query().$promise;\n };\n\n /**\n * Get statistic of document in locale (word and message)\n *\n * @param _projectSlug\n * @param _versionSlug\n * @param _docId\n * @param _localeId\n * @returns {*}\n */\n documentService.getStatistics = function (_projectSlug, _versionSlug,\n _docId, _localeId) {\n if (_docId && _localeId) {\n var key = generateStatisticKey(_docId, _localeId);\n if (_.has(statisticMap, key)) {\n return $q.when(statisticMap[key]);\n } else {\n var encodedDocId = documentService.encodeDocId(_docId);\n var Statistics = $resource(UrlService.DOC_STATISTIC_URL, {}, {\n query: {\n method: 'GET',\n params: {\n projectSlug: _projectSlug,\n versionSlug: _versionSlug,\n docId: encodedDocId,\n localeId: _localeId\n },\n isArray: true\n }\n });\n return Statistics.query().$promise.then(function(statistics) {\n\n // Make needReview(server) available to needswork\n _.forEach(statistics, function(statistic) {\n statistic[TransStatusService.getId('needswork')] =\n statistic.needReview || 0;\n });\n\n statisticMap[key] = statistics;\n return statisticMap[key];\n });\n }\n }\n };\n\n /**\n * Encode docId, replace '/' with ',' when REST call\n * @param docId\n * @returns {*}\n */\n documentService.encodeDocId = function(docId) {\n return docId ? docId.replace(/\\//g, ',') : docId;\n };\n\n /**\n * Encode docId, replace ',' with '/' when REST call\n * @param docId\n * @returns {*}\n */\n documentService.decodeDocId = function(docId) {\n return docId ? docId.replace(/\\,/g, '/') : docId;\n };\n\n documentService.containsDoc = function (documents, docId) {\n return _.any(documents, function(document) {\n return StringUtil.equals(document.name, docId, true);\n });\n };\n\n documentService.updateStatistic = function(projectSlug, versionSlug, docId,\n localeId, oldState,\n newState, wordCount) {\n var key = generateStatisticKey(docId, localeId);\n if(_.has(statisticMap, key)) {\n adjustStatistic(statisticMap[key], oldState, newState,\n wordCount);\n\n EventService.emitEvent(EventService.EVENT.REFRESH_STATISTIC,\n {\n projectSlug: projectSlug,\n versionSlug: versionSlug,\n docId: docId,\n localeId: localeId\n }\n );\n }\n };\n\n //Generate unique key from docId and localeId for statistic cache\n function generateStatisticKey(docId, localeId) {\n return docId + '-' + localeId;\n }\n\n /**\n * Adjust statistic based on translation change of state\n * word - -wordCount of oldState, +wordCount of newState\n * msg - -1 of oldState, +1 of newState\n */\n function adjustStatistic(statistics, oldState, newState, wordCount) {\n\n var wordStatistic = StatisticUtil.getWordStatistic(statistics),\n msgStatistic = StatisticUtil.getMsgStatistic(statistics);\n\n if(wordStatistic) {\n wordCount = parseInt(wordCount);\n var wordOldState = parseInt(wordStatistic[oldState]) - wordCount;\n wordStatistic[oldState] = wordOldState < 0 ? 0 : wordOldState;\n wordStatistic[newState] = parseInt(wordStatistic[newState]) + wordCount;\n }\n\n if(msgStatistic) {\n var msgOldState = parseInt(msgStatistic[oldState]) - 1;\n msgStatistic[oldState] = msgOldState < 0 ? 0 : msgOldState;\n msgStatistic[newState] = parseInt(msgStatistic[newState]) + 1;\n }\n }\n\n return documentService;\n }\n\n angular\n .module('app')\n .factory('DocumentService', DocumentService);\n})();\n","(function() {\n 'use strict';\n\n /**\n * @name DropdownCtrl\n *\n * @description\n * Handle dropdown events between directives\n *\n * @ngInject\n */\n function DropdownCtrl($scope, $attrs, $parse, dropdownConfig,\n DropdownService, $animate, $timeout) {\n var dropdownCtrl = this,\n // create a child scope so we are not polluting original one\n scope = $scope.$new(),\n openClass = dropdownConfig.openClass,\n getIsOpen,\n setIsOpen = angular.noop,\n toggleInvoker = $attrs.onToggle ?\n $parse($attrs.onToggle) : angular.noop;\n\n this.init = function(element) {\n dropdownCtrl.$element = element;\n\n if ($attrs.isOpen) {\n getIsOpen = $parse($attrs.isOpen);\n setIsOpen = getIsOpen.assign;\n\n $scope.$watch(getIsOpen, function(value) {\n scope.isOpen = !!value;\n });\n }\n };\n\n this.toggle = function(open) {\n scope.isOpen = arguments.length ? !!open : !scope.isOpen;\n return scope.isOpen;\n };\n\n // Allow other directives to watch status\n this.isOpen = function() {\n return scope.isOpen;\n };\n\n scope.getToggleElement = function() {\n return dropdownCtrl.toggleElement;\n };\n\n scope.focusToggleElement = function() {\n if (dropdownCtrl.toggleElement) {\n dropdownCtrl.toggleElement[0].focus();\n }\n };\n\n scope.$watch('isOpen', function(isOpen, wasOpen) {\n $animate[isOpen ? 'addClass' : 'removeClass']\n (dropdownCtrl.$element, openClass);\n\n if (isOpen) {\n // need to wrap it in a timeout\n // see http://stackoverflow.com/questions/12729122/\n // prevent-error-digest-already-in-progress-when-calling-scope-apply\n $timeout(function() {\n scope.focusToggleElement();\n });\n DropdownService.open(scope);\n } else {\n DropdownService.close(scope);\n }\n\n setIsOpen($scope, isOpen);\n if (angular.isDefined(isOpen) && isOpen !== wasOpen) {\n toggleInvoker($scope, {\n open: !!isOpen\n });\n }\n });\n\n $scope.$on('$locationChangeSuccess', function() {\n scope.isOpen = false;\n });\n\n $scope.$on('$destroy', function() {\n scope.$destroy();\n });\n\n $scope.$on('openDropdown', function() {\n scope.isOpen = true;\n });\n\n $scope.$on('closeDropdown', function() {\n scope.isOpen = false;\n });\n }\n\n angular\n .module('app')\n .controller('DropdownCtrl', DropdownCtrl);\n\n})();\n","(function() {\n 'use strict';\n\n /**\n * @name dropdownService\n *\n * @description\n * Handle dropdown events between directives\n *\n * @ngInject\n */\n\n function DropdownService($document) {\n var openScope = null,\n dropdownService = this;\n\n dropdownService.open = function(dropdownScope) {\n if (!openScope) {\n $document.bind('click', closeDropdown);\n $document.bind('keydown', escapeKeyBind);\n }\n\n if (openScope && openScope !== dropdownScope) {\n openScope.isOpen = false;\n }\n\n openScope = dropdownScope;\n };\n\n dropdownService.close = function(dropdownScope) {\n if (openScope === dropdownScope) {\n openScope = null;\n $document.unbind('click', closeDropdown);\n $document.unbind('keydown', escapeKeyBind);\n }\n };\n\n var closeDropdown = function(evt) {\n if (!openScope) {\n return;\n }\n var toggleElement = openScope.getToggleElement();\n if (evt && toggleElement && toggleElement[0].contains(evt.target)) {\n return;\n }\n\n openScope.$apply(function() {\n openScope.isOpen = false;\n });\n };\n\n var escapeKeyBind = function(evt) {\n if (evt.which === 27) {\n openScope.focusToggleElement();\n closeDropdown();\n }\n };\n }\n\n angular\n .module('app')\n .service('DropdownService', DropdownService);\n\n})();\n\n","(function() {\n 'use strict';\n\n /**\n * @name Dropdown\n *\n * @description\n * Custom module for dropdowns\n *\n */\n var dropdownConfig = {\n openClass: 'is-active'\n };\n\n angular\n .module('app')\n .constant('dropdownConfig', dropdownConfig);\n\n})();\n","(function() {\n 'use strict';\n\n /**\n * @name dropdown\n *\n * @description\n * Main dropdown container\n *\n */\n\n function dropdown() {\n return {\n restrict: 'EA',\n controller: 'DropdownCtrl',\n link: function(scope, element, attrs, dropdownCtrl) {\n dropdownCtrl.init(element);\n }\n };\n }\n\n function onCloseDropdown() {\n return {\n restrict: 'A',\n require: '?^dropdown',\n scope: {\n callback: '&onCloseDropdown'\n },\n link: function(scope, elem, attrs, dropdownCtrl) {\n dropdownCtrl.onCloseDropdown = scope.callback;\n }\n };\n }\n\n /**\n * @name dropdown-toggle\n *\n * @description\n * Main dropdown toggle\n *\n */\n\n function dropdownToggle() {\n return {\n restrict: 'EA',\n require: '?^dropdown',\n link: function(scope, element, attrs, dropdownCtrl) {\n if (!dropdownCtrl) {\n return;\n }\n\n dropdownCtrl.toggleElement = element;\n\n var toggleDropdown = function(event) {\n event.preventDefault();\n event.stopPropagation();\n\n if (!element.hasClass('disabled') && !attrs.disabled) {\n scope.$apply(function() {\n dropdownCtrl.toggle();\n });\n }\n };\n\n element.bind('click', toggleDropdown);\n\n // WAI-ARIA\n element.attr({\n 'aria-haspopup': true,\n 'aria-expanded': false\n });\n scope.$watch(dropdownCtrl.isOpen, function(isOpen) {\n element.attr('aria-expanded', !!isOpen);\n if (dropdownCtrl.onCloseDropdown && !isOpen) {\n scope.$applyAsync(dropdownCtrl.onCloseDropdown);\n }\n });\n\n scope.$on('$destroy', function() {\n element.unbind('click', toggleDropdown);\n });\n }\n };\n }\n\n angular\n .module('app')\n .directive('dropdown', dropdown)\n .directive('onCloseDropdown', onCloseDropdown)\n .directive('dropdownToggle', dropdownToggle);\n\n})();\n\n","(function () {\n 'use strict';\n\n /**\n * EventService.js\n * Broadcast events service in app.\n * Usage: EventService.emitEvent( event, data, scope)\n * See EventService.emitEvent\n *\n * @ngInject\n */\n function EventService($rootScope) {\n var eventService = this;\n\n /**\n * @enum {string}\n */\n eventService.EVENT = {\n /**\n * Loading Events\n *\n * Broadcast from AppConfig\n */\n LOADING_START: 'loadingStart',\n LOADING_STOP: 'loadingStop',\n\n /**\n * scroll to trans unit\n * data: {id: number, updateURL: boolean, focus: boolean}\n * id: (transunit id),\n * updateURL: (flag on whether to update url with trans unit id)\n * focus: flag on whether to have row in view and focused\n */\n SELECT_TRANS_UNIT: 'selectTransUnit',\n\n //data: {phrase: Phrase, sourceIndex:sourceIndex}\n COPY_FROM_SOURCE: 'copyFromSource',\n\n // data: { suggestion: Suggestion }\n COPY_FROM_SUGGESTION: 'copyFromSuggestion',\n\n /**\n * Emit this to trigger copying of the nth suggestion to the selected row.\n *\n * data: number (zero-based index of suggestion to copy)\n */\n COPY_FROM_SUGGESTION_N: 'copyFromSuggestionN',\n\n //data: {phrase: Phrase}\n UNDO_EDIT: 'undoEdit',\n\n //data: {phrase: Phrase}\n CANCEL_EDIT: 'cancelEdit',\n\n //data:phrase\n FOCUS_TRANSLATION: 'focusTranslation',\n\n /**\n * data: {\n * phrase: Phrase, status: StatusInfo, locale: string, docId: string\n * }\n * phrase:\n * status: Object. Request save state\n * locale: target locale\n * docId: docId\n */\n SAVE_TRANSLATION: 'saveTranslation',\n\n /**\n * Translation save in this editor is being sent to the server and\n * is waiting on a response.\n */\n SAVE_INITIATED: 'saveInitiated',\n\n /**\n * Translation save in this editor has been completed\n * (Server has responded with a success or error).\n */\n SAVE_COMPLETED: 'saveCompleted',\n\n /**\n * The text in the translation editor textbox has been edited and\n * not yet saved.\n */\n TRANSLATION_TEXT_MODIFIED: 'translationTextModified',\n\n /**\n * refresh ui statistic - changes in doc or locale\n *\n * data: {projectSlug: string, versionSlug: string,\n * docId: string, localeId: string}\n */\n REFRESH_STATISTIC: 'refreshStatistic',\n\n GOTO_PREV_PAGE: 'gotoPreviousPage',\n\n GOTO_NEXT_PAGE: 'gotoNextPage',\n\n GOTO_FIRST_PAGE: 'gotoFirstPage',\n\n GOTO_LAST_PAGE: 'gotoLastPage',\n\n /**\n * data: { currentId: number }\n */\n GOTO_NEXT_ROW: 'gotoNextRow',\n GOTO_PREVIOUS_ROW: 'gotoPreviousRow',\n GOTO_NEXT_UNTRANSLATED: 'gotoNextUntranslated',\n\n /**\n * Toggle save as options dropdown.\n * data: {id: number, open: boolean}\n */\n TOGGLE_SAVE_OPTIONS: 'openSaveOptions',\n\n\n /**\n * data: {filter: refer to editorCtrl.filter}\n */\n FILTER_TRANS_UNIT: 'filterTransUnit',\n\n /**\n * Reports the number of suggestions that are available for a phrase.\n *\n * data: { id: number, count: number }\n */\n PHRASE_SUGGESTION_COUNT: 'phraseSuggestionCount',\n\n /**\n * Fire to request suggestions from translation memory, etc.\n *\n * data: { phrase: Phrase }\n */\n REQUEST_PHRASE_SUGGESTIONS: 'requestPhraseSuggestions',\n\n /**\n * Fire for manual suggestions search using a single string.\n *\n * data: string\n */\n REQUEST_TEXT_SUGGESTIONS: 'requestTextSuggestions',\n\n /**\n * Fired every time search is toggled\n *\n * @type {Boolean}\n */\n SUGGESTIONS_SEARCH_TOGGLE: 'suggestionsSearchToggle',\n\n /**\n * Indicates a single user setting has changed.\n *\n * Event handlers should switch on the setting name to determine whether\n * it is a setting they are interested in.\n *\n * data: { setting: string, value: boolean|number|string }\n */\n USER_SETTING_CHANGED: 'userSettingChanged'\n };\n\n /**\n * Firing an event downwards of scope\n *\n * @param event - eventService.EVENT type\n * @param data - data for the event\n * @param scope - scope of event to to fire, $rootScope if empty\n */\n eventService.broadcastEvent = function(event, data, scope) {\n scope = scope || $rootScope;\n scope.$broadcast(event, data);\n };\n\n /**\n * Firing an event upwards of scope\n *\n * @param event - eventService.EVENT types\n * @param data - data for the event\n * @param scope - scope of event to to fire, $rootScope if empty\n */\n eventService.emitEvent = function(event, data, scope) {\n scope = scope || $rootScope;\n scope.$emit(event, data);\n };\n\n return eventService;\n }\n\n angular\n .module('app')\n .factory('EventService', EventService);\n})();\n","(function() {\n 'use strict';\n\n /**\n * @name icon\n * @description declarative svg icons\n * @ngInject\n */\n function icon($sce) {\n return {\n restrict: 'E',\n required: ['name'],\n scope: {\n name: '@',\n title: '@',\n size: '@'\n },\n // templateUrl: 'components/icon/icon.html',\n link: function(scope, element) {\n var svg = '',\n loader = '',\n titleHtml = '';\n\n element.addClass('Icon');\n\n if (scope.title) {\n titleHtml = '' + scope.title + '';\n }\n\n if (scope.name === 'loader') {\n // Can't seem to animate svg symbols\n element.addClass('Icon--loader');\n loader = '' +\n '' +\n '' +\n '' +\n '' +\n '';\n element.html($sce.trustAsHtml(loader));\n }\n else {\n // Stupid hack to make svg work\n svg = '' +\n '' +\n '' +\n titleHtml +\n '';\n element.html($sce.trustAsHtml(svg));\n }\n }\n };\n }\n\n angular\n .module('app')\n .directive('icon', icon);\n\n})();\n","(function() {\n 'use strict';\n\n /**\n * MessageHandler.js\n * @ngInject\n */\n function MessageHandler() {\n return {\n displayError: function(msg) {\n console.error(msg);\n },\n displayWarning: function(msg) {\n console.warn(msg);\n },\n displayInfo: function(msg) {\n console.info(msg);\n }\n };\n }\n\n angular\n .module('app')\n .factory('MessageHandler', MessageHandler);\n\n})();\n","(function() {\n 'use strict';\n\n /**\n * Handle locales related information.\n *\n * LocaleService.js\n * @ngInject\n */\n function LocaleService(UrlService, StringUtil, FilterUtil, $resource, _) {\n\n var locales = [];\n\n /**\n * Get project-version supported locales\n * @param projectSlug\n * @param versionSlug\n * @returns {$promise|*}\n */\n function getSupportedLocales(projectSlug, versionSlug) {\n\n var Locales = $resource(UrlService.LOCALE_LIST_URL, {}, {\n query: {\n method: 'GET',\n params: {\n projectSlug: projectSlug,\n versionSlug: versionSlug\n },\n isArray: true\n }\n });\n\n return Locales.query().$promise;\n }\n\n //Returns all locales supported in Zanata instance\n function getAllLocales() {\n var Locales = $resource(UrlService.ALL_LOCALE_URL, {}, {\n query: {\n method: 'GET',\n isArray: true\n }\n });\n return Locales.query().$promise.then(function(results) {\n locales = FilterUtil.cleanResourceList(results);\n });\n }\n\n function getUILocaleList() {\n var list = $resource(UrlService.uiTranslationListURL, {}, {\n query: {\n method: 'GET'\n }\n });\n\n return list.query().$promise;\n }\n\n function getLocaleByLocaleId(locales, localeId) {\n if(locales) {\n return _.find(locales, function(locale) {\n return StringUtil.equals(locale.localeId, localeId, true);\n });\n }\n }\n\n function containsLocale (locales, localeId) {\n return _.any(locales, function(locale) {\n return StringUtil.equals(locale.localeId, localeId, true);\n });\n }\n\n function getName(localeId) {\n var locale = getLocaleByLocaleId(locales, localeId);\n if(locale) {\n return locale.name;\n }\n return localeId;\n }\n\n return {\n getSupportedLocales : getSupportedLocales,\n getUILocaleList : getUILocaleList,\n getLocaleByLocaleId : getLocaleByLocaleId,\n getAllLocales : getAllLocales,\n containsLocale : containsLocale,\n getName : getName,\n DEFAULT_LOCALE: {\n 'localeId' : 'en-US',\n 'name' : 'English'\n }\n };\n }\n\n angular\n .module('app')\n .factory('LocaleService', LocaleService);\n})();\n","(function() {\n\n 'use strict';\n\n /**\n * @name logoLoader\n *\n * @description\n * Logo that is activated on global loading state\n *\n * @ngInject\n */\n function logoLoader(EventService) {\n return {\n restrict: 'EA',\n scope: {\n loading: '=',\n inverted: '='\n },\n link: function(scope) {\n scope.classes = '';\n\n scope.$on(EventService.EVENT.LOADING_START, function() {\n scope.classes += ' is-loading';\n });\n\n scope.$on(EventService.EVENT.LOADING_STOP, function() {\n scope.classes = scope.classes.replace('is-loading', '');\n });\n\n scope.$watch('inverted', function(newInverted) {\n if (newInverted) {\n scope.classes += ' LogoLoader--inverted';\n } else {\n scope.classes = scope.classes.replace('LogoLoader--inverted', '');\n }\n });\n },\n templateUrl: 'components/logo-loader/logo-loader.html'\n };\n }\n\n angular\n .module('app')\n .directive('logoLoader', logoLoader);\n\n})();\n","(function() {\n 'use strict';\n\n /**\n * Handle notification in editor\n *\n * NotificationService.js\n * @ngInject\n */\n function NotificationService() {\n\n }\n\n angular\n .module('app')\n .factory('NotificationService', NotificationService);\n\n})();\n","(function () {\n 'use strict';\n\n /**\n * PhraseCache.js\n * Stores textflow, states in local cache.\n * TODO: use angular-data for storage\n * @ngInject\n */\n function PhraseCache($q, $resource, FilterUtil, UrlService, DocumentService,\n _) {\n var phraseCache = this,\n states = {}, //ids and states of all tu in order\n transUnits = {};\n\n phraseCache.getStates =\n function (projectSlug, versionSlug, documentId, localeId) {\n var key = generateKey(projectSlug, versionSlug, documentId, localeId);\n if (_.has(states, key)) {\n return $q.when(states[key]);\n } else {\n var encodedDocId = DocumentService.encodeDocId(documentId);\n var methods = {\n query: {\n method: 'GET',\n params: {\n projectSlug: projectSlug,\n versionSlug: versionSlug,\n docId: encodedDocId,\n localeId: localeId\n },\n isArray: true\n }\n },\n States = $resource(UrlService.TRANSLATION_STATUS_URL, {}, methods);\n return States.query().$promise.then(function (state) {\n state = FilterUtil.cleanResourceList(state);\n states[key] = state;\n return states[key];\n });\n }\n };\n\n phraseCache.getTransUnits = function (ids, localeId) {\n var results = {},\n missingTUId = [],\n missingLocaleTUId = [];\n ids.forEach(function (id) {\n if (_.has(transUnits, id)) {\n if(transUnits[id][localeId]) {\n results[id] = transUnits[id];\n } else {\n missingLocaleTUId.push(id);\n }\n } else {\n missingTUId.push(id);\n }\n });\n if (_.isEmpty(missingTUId) && _.isEmpty(missingLocaleTUId)) {\n return $q.when(results);\n }\n else {\n var TextFlows, Translations;\n if(!_.isEmpty(missingTUId)) {\n TextFlows = $resource(UrlService.TEXT_FLOWS_URL, {}, {\n query: {\n method: 'GET',\n params: {\n localeId: localeId,\n ids: missingTUId.join(',')\n }\n }\n });\n }\n if(!_.isEmpty(missingLocaleTUId)) {\n Translations = $resource(UrlService.TRANSLATION_URL, {}, {\n query: {\n method: 'GET',\n params: {\n localeId: localeId,\n ids: missingLocaleTUId.join(',')\n }\n }\n });\n }\n\n //need to create chain of promises\n if(TextFlows && Translations) {\n return TextFlows.query().$promise.then(updateCacheWithNewTU).\n then(Translations.query().$promise.then(updateCacheWithExistingTU));\n } else if(TextFlows) {\n return TextFlows.query().$promise.then(updateCacheWithNewTU);\n } else if(Translations) {\n return Translations.query().$promise.then(updateCacheWithExistingTU);\n }\n }\n\n function updateCacheWithExistingTU(newTransUnits) {\n newTransUnits = FilterUtil.cleanResourceMap(newTransUnits);\n for (var key in newTransUnits) {\n //push to cache\n transUnits[key][localeId] = newTransUnits[key][localeId];\n results[key] = transUnits[key]; //merge with results\n }\n return results;\n }\n\n function updateCacheWithNewTU(newTransUnits) {\n newTransUnits = FilterUtil.cleanResourceMap(newTransUnits);\n for (var key in newTransUnits) {\n transUnits[key] = newTransUnits[key]; //push to cache\n results[key] = transUnits[key]; //merge with results\n }\n return results;\n }\n };\n\n /**\n * On translation updated from server\n * @param id\n * @param localeId\n * @param revision\n * @param state\n * @param content\n * @param contents\n */\n phraseCache.onTransUnitUpdated =\n function (context, id, localeId, revision, status, phrase) {\n\n var key = generateKey(context.projectSlug, context.versionSlug,\n context.docId, localeId);\n\n var stateEntry = _.find(states[key], function(stateEntry) {\n return stateEntry.id === id;\n });\n //Update states cache\n if(stateEntry) {\n stateEntry.state = status;\n }\n\n //Update transUnits cache\n var translation = transUnits[id][localeId];\n if (!translation) {\n translation = {};\n }\n translation.revision = parseInt(revision);\n translation.state = status;\n translation.contents = phrase.newTranslations.slice();\n };\n\n function generateKey(projectId, versionId, documentId, localeId) {\n return projectId + '-' + versionId + '-' +\n documentId + '-' + localeId;\n }\n\n return phraseCache;\n }\n\n angular\n .module('app')\n .factory('PhraseCache', PhraseCache);\n\n})();\n","(function () {\n 'use strict';\n\n /**\n * @typedef {Object} Phrase\n * @property {number} id text flow id\n * @property {string[]} sources source contents\n * @property {string[]} translations original translation\n * @property {string[]} newTranslations translations in the editor\n * @property {boolean} plural whether it's in plural form\n * @property {StatusInfo} status information about this phrase\n * @property {number} revision translation revision number\n * @property {number} wordCount source word count\n */\n /**\n * @name PhraseService\n * @description Provides a list of phrases for the current document(s)\n *\n * @ngInject\n */\n function PhraseService(FilterUtil, PhraseCache, TransStatusService, _,\n $stateParams) {\n var phraseService = {};\n\n phraseService.phrases = []; //current displayed phrases\n\n // FIXME use an object for all the ID arguments - in general we will only\n // need to modify such an object sporadically when switching document\n // or locale, and it is neater than passing them all\n // around separately.\n\n phraseService.getPhraseCount = function(context, filter) {\n return PhraseCache.getStates(context.projectSlug, context.versionSlug,\n context.docId, context.localeId).then(function(states) {\n var ids = getIds(states, filter.status);\n return ids.length;\n });\n };\n\n /**\n * Fetch each of the text flows appearing in the given states data.\n */\n phraseService.fetchAllPhrase = function (context, filter,\n offset, maxResult) {\n\n var localeId = context.localeId;\n\n return PhraseCache.getStates(context.projectSlug, context.versionSlug,\n context.docId, localeId).then(getTransUnits);\n\n function getTransUnits(states) {\n var ids = getIds(states, filter.status);\n if (!isNaN(offset)) {\n if(!isNaN(maxResult)) {\n ids = ids.slice(offset, offset + maxResult);\n } else {\n ids = ids.slice(offset);\n }\n }\n // Reading for chaining promises https://github.com/kriskowal/q\n // (particularly \"Sequences\").\n return PhraseCache.getTransUnits(ids, localeId).\n then(transformToPhrases).then(sortPhrases);\n }\n\n /**\n * Converts text flow data from the API into the form expected in the\n * editor.\n *\n * @returns {Phrase[]}\n */\n function transformToPhrases(transUnits) {\n return _.map(transUnits, function(transUnit, id) {\n var source = transUnit.source,\n trans = transUnit[localeId];\n return {\n id: parseInt(id),\n sources: source.plural ? source.contents : [source.content],\n // Original translation\n translations: extractTranslations(source, trans),\n // Translation from editor\n newTranslations: extractTranslations(source, trans),\n plural: source.plural,\n // Conform the status from the server, return an object\n status: trans ? TransStatusService.getStatusInfo(trans.state) :\n TransStatusService.getStatusInfo('untranslated'),\n revision: trans ? parseInt(trans.revision) : 0,\n wordCount: parseInt(source.wordCount)\n };\n });\n }\n\n function extractTranslations(source, trans) {\n if(source.plural) {\n return trans && trans.contents ? trans.contents.slice() : [];\n }\n return trans ? [trans.content] : [];\n }\n\n function sortPhrases(phrases) {\n return PhraseCache.getStates(context.projectSlug, context.versionSlug,\n context.docId, localeId).then(function(states) {\n phraseService.phrases = _.sortBy(phrases, function(phrase) {\n var index = _.findIndex(states, function(state) {\n return state.id === phrase.id;\n });\n return index >= 0 ? index : phrases.length;\n });\n return phraseService.phrases;\n });\n }\n };\n\n //update phrase,statuses and textFlows with given tu id\n phraseService.onTransUnitUpdated = function(context, id, localeId, revision,\n status, phrase) {\n\n PhraseCache.onTransUnitUpdated(context, id, localeId, revision, status,\n phrase);\n\n var cachedPhrase = findPhrase(id, phraseService.phrases);\n //update phrase if found\n if(cachedPhrase) {\n cachedPhrase.translations = phrase.newTranslations.slice();\n cachedPhrase.revision = revision;\n cachedPhrase.status = TransStatusService.getStatusInfo(status);\n }\n };\n\n //rollback content of phrase\n phraseService.onTransUnitUpdateFailed = function(id) {\n var phrase = findPhrase(id, phraseService.phrases);\n if(phrase) {\n phrase.newTranslations = phrase.translations.slice();\n }\n };\n\n // find next Id from phrases states\n phraseService.findNextId = function(currentId) {\n return PhraseCache.getStates($stateParams.projectSlug,\n $stateParams.versionSlug, $stateParams.docId,\n $stateParams.localeId)\n .then(function (states) {\n var currentIndex,\n nextIndex;\n currentIndex = _.findIndex(states, function (state) {\n return state.id === currentId;\n });\n nextIndex = currentIndex + 1 < states.length ?\n currentIndex + 1 : states.length - 1;\n return states[nextIndex].id;\n });\n };\n\n // find previous id from phrases states\n phraseService.findPreviousId = function(currentId) {\n return PhraseCache.getStates($stateParams.projectSlug,\n $stateParams.versionSlug, $stateParams.docId,\n $stateParams.localeId)\n .then(function (states) {\n var currentIndex,\n previousIndex;\n currentIndex = _.findIndex(states, function (state) {\n return state.id === currentId;\n });\n previousIndex = currentIndex - 1 >= 0 ? currentIndex - 1 : 0;\n return states[previousIndex].id;\n });\n };\n\n // find next phrase with requested status\n phraseService.findNextStatus = function(currentId, status) {\n return PhraseCache.getStates($stateParams.projectSlug,\n $stateParams.versionSlug, $stateParams.docId,\n $stateParams.localeId)\n .then(function (statusList) {\n var currentIndex,\n nextStatusInfo,\n requestStatus = TransStatusService.getStatusInfo(status);\n\n currentIndex = _.findIndex(statusList, function (state) {\n return state.id === currentId;\n });\n\n for (var i = currentIndex + 1; i < statusList.length; i++) {\n nextStatusInfo = TransStatusService.getStatusInfo(\n statusList[i].state);\n if (nextStatusInfo.ID === requestStatus.ID) {\n return statusList[i].id;\n }\n }\n return currentId;\n });\n };\n\n function findPhrase(id, phrases) {\n return _.find(phrases, function(phrase) {\n return phrase.id === id;\n });\n }\n\n function getIds(resources, states) {\n if(states) {\n resources = FilterUtil.filterResources(resources, ['status'], states);\n }\n return _.map(resources, function (item) {\n return item.id;\n });\n }\n\n // Does not appear to be used anywhere. Removing until phrase-caching code\n // is added.\n // phraseService.findById = function(phraseId) {\n // var deferred = $q.defer();\n // var phrase = phrases[phraseId];\n // deferred.resolve(phrase);\n // return deferred.promise;\n // };\n\n return phraseService;\n }\n\n angular\n .module('app')\n .factory('PhraseService', PhraseService);\n\n})();\n\n","(function() {\n 'use strict';\n\n /**\n * @name progressbar\n * @description progressbar container\n * @ngInject\n */\n function progressbar() {\n return {\n restrict: 'E',\n required: 'progressbarStatistic',\n scope: {\n statistic: '=progressbarStatistic',\n size: '@' //large, full, or empty\n },\n templateUrl: 'components/progressbar/progressbar.html',\n controller: function($scope) {\n /**\n * Need to set to true for complex object watch. Performance issue.\n * https://docs.angularjs.org/api/ng/type/$rootScope.Scope\n */\n $scope.$watch('statistic', function(statistic) {\n if (statistic) {\n $scope.style = getStyle(statistic);\n }\n }, true);\n }\n };\n }\n\n function getStyle(statistic) {\n var total = statistic.total,\n widthApproved = getWidthPercent(statistic.approved, total),\n widthTranslated = getWidthPercent(statistic.translated, total),\n marginLeftTranslated = widthApproved,\n widthNeedsWork = getWidthPercent(statistic.needswork, total),\n marginLeftNeedsWork = widthApproved + widthTranslated,\n widthUntranslated = getWidthPercent(statistic.untranslated, total),\n marginLeftUntranslated = widthApproved +\n widthTranslated + widthNeedsWork,\n style = {};\n\n style.approved = {\n 'width': widthApproved + '%',\n 'marginLeft': 0\n };\n style.translated = {\n 'width': widthTranslated + '%',\n 'marginLeft': marginLeftTranslated + '%'\n };\n style.needsWork = {\n 'width': widthNeedsWork + '%',\n 'marginLeft': marginLeftNeedsWork + '%'\n };\n style.untranslated = {\n 'width': widthUntranslated + '%',\n 'marginLeft': marginLeftUntranslated + '%'\n };\n return style;\n }\n\n function getWidthPercent(value, total) {\n var percent = 0;\n if (value) {\n percent = value / total * 100;\n }\n return percent;\n }\n\n angular\n .module('app')\n .directive('progressbar', progressbar);\n\n})();\n","(function() {\n 'use strict';\n\n /**\n * Handle communication with server on Project related information.\n * ProjectService.js\n * @ngInject\n */\n\n function ProjectService(UrlService, $resource) {\n\n /**\n * Get project's information\n *\n * @param projectSlug\n * @returns {$promise|*|N.$promise}\n */\n function getProjectInfo(projectSlug) {\n var methods = {\n query: {\n method: 'GET',\n params: {\n projectSlug: projectSlug\n }\n }\n };\n\n var Locales = $resource(UrlService.PROJECT_URL, {}, methods);\n return Locales.query().$promise;\n }\n\n return {\n getProjectInfo: getProjectInfo\n };\n }\n angular\n .module('app')\n .factory('ProjectService', ProjectService);\n})();\n","(function() {\n 'use strict';\n\n /**\n * Represents a draggable resizer.\n *\n * @param $window\n * @param $document\n * @param $timeout\n * @returns {Function}\n */\n function resizer(SettingsService, $window, $document, $timeout) {\n\n function link(scope, element, attrs) {\n\n /**\n * The height to use for the resizer when it is visible.\n *\n * @type {Number}\n */\n scope.height = parseInt(attrs.resizerHeight);\n\n /**\n * The current height of the resizer to display.\n *\n * @type {Number}\n */\n scope.actualHeight = scope.height;\n\n scope.position = normalisePercentage(SettingsService.get(\n SettingsService.SETTING.SUGGESTIONS_PANEL_HEIGHT), $window.innerHeight);\n scope.actualPosition = scope.position;\n\n scope.show =\n SettingsService.subscribe(SettingsService.SETTING.SHOW_SUGGESTIONS,\n function (show) {\n scope.show = show;\n setBottomPanelVisibility(show);\n });\n\n /**\n * Persist the current size as a setting.\n */\n function saveCurrentSize() {\n SettingsService.update(SettingsService.SETTING.SUGGESTIONS_PANEL_HEIGHT,\n scope.actualPosition);\n }\n\n function setBottomPanelVisibility(showing) {\n if (showing) {\n scope.actualPosition = scope.position;\n scope.actualHeight = scope.height;\n } else {\n // save resizer position so it can be restored\n // does not appear to set properly without an intermediate variable\n var currentPos = scope.actualPosition;\n scope.position = currentPos;\n scope.actualPosition = 0;\n scope.actualHeight = 0;\n }\n\n // Panel only renders properly if resizer is adjusted in a later frame\n setTimeout(adjustResizer);\n }\n\n setBottomPanelVisibility(scope.show);\n\n element.addClass('Resizer');\n\n // Initial Resize\n if (attrs.resizer === 'vertical') {\n element.addClass('Resizer--vertical');\n $timeout(function (){\n adjustVerticalPanel(scope.actualPosition);\n });\n }\n else {\n element.addClass('Resizer--horizontal');\n $timeout(function (){\n adjustHorizontalPanel(scope.actualPosition);\n });\n }\n\n element.on('mousedown', function(event) {\n event.preventDefault();\n $document.on('mousemove', mousemove);\n $document.on('mouseup', mouseup);\n });\n\n angular.element($window).bind('resize', function() {\n $timeout.cancel(scope.resizing);\n scope.resizing = $timeout(adjustResizer);\n });\n\n function mousemove(event) {\n if (attrs.resizer === 'vertical') {\n adjustVerticalPanel(event.pageX);\n } else {\n adjustHorizontalPanel($window.innerHeight - event.pageY);\n }\n }\n\n function adjustVerticalPanel(resizerPositionX) {\n var x = resizerPositionX,\n leftPanel = angular.element(document\n .querySelector(attrs.resizerLeft)),\n rightPanel = angular.element(document\n .querySelector(attrs.resizerRight)),\n maximumPanelSize =\n normalisePercentage(attrs.resizerMax, $window.innerHeight),\n minimumPanelSize = attrs.resizerMin ||\n parseInt(attrs.resizerWidth);\n\n scope.actualPosition = x;\n x = restrictMinOrMax(x, maximumPanelSize, minimumPanelSize);\n\n element.css({\n left: (x - (scope.actualHeight / 2)) + 'px'\n });\n\n leftPanel.css({\n width: x + 'px'\n });\n\n rightPanel.css({\n left: x + 'px'\n });\n }\n\n function adjustHorizontalPanel(resizerPositionY) {\n var y = resizerPositionY,\n topPanel = angular.element(document\n .querySelector(attrs.resizerTop)),\n bottomPanel = angular.element(document\n .querySelector(attrs.resizerBottom)),\n maximumPanelSize =\n normalisePercentage(attrs.resizerMax, $window.innerHeight),\n minimumPanelSize = attrs.resizerMin || scope.actualHeight;\n\n scope.actualPosition = y;\n y = restrictMinOrMax(y, maximumPanelSize, minimumPanelSize);\n\n element.css({\n bottom: (y - (scope.actualHeight / 2)) + 'px'\n });\n\n topPanel.css({\n bottom: y + 'px'\n });\n\n bottomPanel.css({\n height: y + 'px'\n });\n }\n\n function mouseup() {\n $document.unbind('mousemove', mousemove);\n $document.unbind('mouseup', mouseup);\n\n // Now that a new value has stopped rapidly changing, persist it.\n saveCurrentSize();\n }\n\n function adjustResizer() {\n if (attrs.resizer === 'vertical') {\n adjustVerticalPanel(scope.actualPosition);\n }\n else {\n adjustHorizontalPanel(scope.actualPosition);\n }\n }\n\n function restrictMinOrMax(currentSize, maxSize, minSize) {\n // Maximum\n if (maxSize && currentSize > maxSize) {\n return maxSize;\n }\n // Minimum\n else if (currentSize < minSize) {\n return minSize;\n }\n else {\n return currentSize;\n }\n }\n\n function normalisePercentage(fraction, whole) {\n if ((/[0-9]*\\.?[0-9]+%/).test(fraction)) {\n return Math.round(whole * (parseInt(fraction.replace('%','')) / 100));\n }\n else {\n return parseInt(fraction);\n }\n }\n\n }\n\n return {\n link: link\n };\n }\n\n angular\n .module('app')\n .directive('resizer', resizer);\n\n})();\n","(function() {\n 'use strict';\n\n\n /**\n * The name of a setting, used as a unique key for lookup and storage.\n * @typedef {string} SettingKey\n */\n\n /**\n * The value for a setting.\n *\n * @typedef {(string|number|boolean)} SettingValue\n */\n\n /**\n * Service for persisted user settings.\n *\n * @constructor\n */\n function SettingsService(EventService, $q, $rootScope, _) {\n var settingsService = this;\n\n /**\n * All valid settings keys.\n *\n * These enum constants should be used for all settings operations.\n *\n * @type {Object<*, SettingKey>}\n */\n settingsService.SETTING = {\n SUGGESTIONS_AUTOFILL_ON_ROW_SELECT: 'suggestionsAutofillOnRowSelect',\n SUGGESTIONS_SHOW_DIFFERENCE: 'suggestionsShowDifference',\n SHOW_SUGGESTIONS: 'showSuggestions',\n SUGGESTIONS_PANEL_HEIGHT: 'suggestionsPanelHeight'\n };\n\n var SETTING = settingsService.SETTING;\n\n /**\n * Settings enum, with default values that indicate the type\n * @enum {SettingValue}\n */\n var defaultSettings = {};\n defaultSettings[SETTING.SUGGESTIONS_AUTOFILL_ON_ROW_SELECT] = true;\n defaultSettings[SETTING.SUGGESTIONS_SHOW_DIFFERENCE] = false;\n defaultSettings[SETTING.SHOW_SUGGESTIONS] = true;\n defaultSettings[SETTING.SUGGESTIONS_PANEL_HEIGHT] = '30%';\n\n /**\n * Local settings cache.\n *\n * @type {Object}\n */\n var settings = _.clone(defaultSettings);\n\n\n /*\n\n TODO save settings to the server, prefer sending as a batch if possible\n (i.e. when updateAll is used, and future option to ensure only one save\n request at a time and use _.extend to combine all the queued settings\n while waiting).\n\n */\n\n /**\n * Update a single setting to have the given value.\n *\n * This will trigger a user setting update event.\n *\n * @param {SettingKey} setting the name of the setting to update\n * @param {SettingValue} value the new value for the setting\n */\n function update(setting, value) {\n validateSettingValue(value);\n var settingObj = {};\n settingObj[setting] = value;\n _.extend(settings, settingObj);\n\n EventService.emitEvent(EventService.EVENT.USER_SETTING_CHANGED, {\n setting: setting,\n value: value\n });\n }\n\n /**\n * Update multiple settings from a map of setting names and values.\n *\n * An event is triggered for each setting.\n *\n * @param {Object} settings\n */\n function updateAll(settings) {\n _.each(settings, function (value, key) {\n update(key, value);\n });\n }\n\n /**\n * Get the currently stored value for a setting.\n *\n * This should only be used to fetch the initial value or when a setting\n * is used once. To track changes to a setting, subscribe to the\n * USER_SETTING_CHANGED event and check the setting property of the event\n * payload.\n *\n * @param {SettingKey} setting name of the setting to look up\n */\n function get(setting) {\n if (_.has(settings, setting)) {\n return settings[setting];\n }\n // Incorrect key is a programmer error - default should be set for all\n // user settings that are used.\n console.error('Tried to look up setting with unrecognized key: %s',\n setting);\n }\n\n /**\n * Register an action to perform when a user setting value changes, and get\n * the current value.\n *\n * @param {SettingKey} setting the setting to get and subscribe to\n * @param {function} callback called with the new value\n * @return {SettingValue} the current value of the setting\n */\n function subscribe(setting, callback) {\n $rootScope.$on(EventService.EVENT.USER_SETTING_CHANGED,\n function (event, data) {\n if (data.setting === setting) {\n callback(data.value);\n }\n });\n return get(setting);\n }\n\n /**\n * Throw an error if the value is not the correct type for the setting.\n *\n * @param {SettingValue} value\n */\n function validateSettingValue(value) {\n switch (typeof value) {\n case 'boolean':\n case 'number':\n case 'string':\n break;\n default:\n throw new Error('Invalid type for setting value: \"' + typeof value +\n '\".');\n }\n }\n\n\n\n return {\n SETTING: SETTING,\n update: update,\n updateAll: updateAll,\n get: get,\n subscribe: subscribe\n };\n }\n\n angular\n .module('app')\n .factory('SettingsService', SettingsService);\n})();\n","(function() {\n 'use strict';\n\n /**\n * @name display-character\n * @description display whitespace character with symbol(HTML),\n * *NOTE*, need to wrap around
 tag\n   * @ngInject\n   */\n  function renderWhitespaceCharacters() {\n    var WHITESPACES = {\n      'space' : {\n        'regex' : / /g,\n        'template' : ' '\n      },\n      'newline' : {\n        'regex' : /\\n/g,\n        'template' : '\\n'\n      },\n      'tab' : {\n        'regex' : /\\t/g,\n        'template' : '\\t'\n      }\n    };\n\n    return {\n      restrict: 'A',\n      required: ['ngBind'],\n      scope: {\n        ngBind: '='\n      },\n\n      link: function compile(scope, element) {\n        scope.$watch('ngBind', function (value) {\n          value = replaceChar(value, WHITESPACES.space);\n          value = replaceChar(value, WHITESPACES.newline);\n          value = replaceChar(value, WHITESPACES.tab);\n          element.html(value);\n        });\n      }\n    };\n\n    function replaceChar(value, whitespaceChar) {\n      return value.replace(whitespaceChar.regex, whitespaceChar.template);\n    }\n  }\n\n  angular\n    .module('app')\n    .directive('renderWhitespaceCharacters', renderWhitespaceCharacters);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name ScrollbarWidthCtrl\n   *\n   * @description\n   * Handle dropdown events between directives\n   *\n   * @ngInject\n   */\n  function ScrollbarWidthCtrl() {\n    var scrollbarWidthCtrl = this;\n\n    scrollbarWidthCtrl.init = function() {\n      var container = scrollbarWidthCtrl.container[0],\n          child = scrollbarWidthCtrl.child[0],\n          scrollbarWidth = child.offsetWidth - container.offsetWidth;\n\n      scrollbarWidthCtrl.width = scrollbarWidth / 2;\n    };\n\n  }\n\n  angular\n    .module('app')\n    .controller('ScrollbarWidthCtrl', ScrollbarWidthCtrl);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name scrollbarWidth\n   *\n   * @description\n   * Scrollbar width container\n   * Needed for the controller to reference all properties\n   */\n  function scrollbarWidth() {\n    return {\n      restrict: 'A',\n      controller: 'ScrollbarWidthCtrl as scrollbarWidthCtrl',\n      link: function(scope, element, attrs, scrollbarWidthCtrl) {\n        scrollbarWidthCtrl.init(element);\n      }\n    };\n  }\n\n  /**\n   * @name scrollbarWidthElement\n   *\n   * @description\n   * The element to add the scrollbar width to\n   */\n  function scrollbarWidthElement() {\n    return {\n      restrict: 'A',\n      require: '?^scrollbarWidth',\n      link: function(scope, element, attrs, scrollbarWidthCtrl) {\n        if (!scrollbarWidthCtrl) {\n          return;\n        }\n        // Use the attribute to decide which property to set\n        element.css(attrs.scrollbarWidthElement, scrollbarWidthCtrl.width);\n      }\n    };\n  }\n\n  /**\n   * @name scrollbarWidthContainer\n   *\n   * @description\n   * Get the scrollbar container width\n   */\n  function scrollbarWidthContainer() {\n    return {\n      restrict: 'A',\n      require: '?^scrollbarWidth',\n      link: function(scope, element, attrs, scrollbarWidthCtrl) {\n        if (!scrollbarWidthCtrl) {\n          return;\n        }\n        scrollbarWidthCtrl.container = element;\n      }\n    };\n  }\n\n  /**\n   * @name scrollbarWidthChild\n   *\n   * @description\n   * Get the scrollbar child width\n   */\n  function scrollbarWidthChild() {\n    return {\n      restrict: 'A',\n      require: '?^scrollbarWidth',\n      link: function(scope, element, attrs, scrollbarWidthCtrl) {\n        if (!scrollbarWidthCtrl) {\n          return;\n        }\n        scrollbarWidthCtrl.child = element;\n      }\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('scrollbarWidth', scrollbarWidth)\n    .directive('scrollbarWidthElement', scrollbarWidthElement)\n    .directive('scrollbarWidthContainer', scrollbarWidthContainer)\n    .directive('scrollbarWidthChild', scrollbarWidthChild);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * PhraseSuggestionsService.js\n   * @ngInject\n   */\n  function PhraseSuggestionsService(_, EventService, SuggestionsService,\n                                    $timeout, $rootScope) {\n    // TODO extract common code from TextSuggestionsService and here\n\n    /* Minimum time in milliseconds to wait between requesting results */\n    var DELAY = 300;\n    var MAX_ACTIVE_REQUESTS = 3;\n\n    /* @type {boolean} */\n    var loading = false;\n\n    /* @type {Phrase} */\n    var searchPhrase = null;\n\n    /* @type {Array} */\n    var results = [];\n\n    /**\n     * @return {boolean} true if results have been requested and not delivered\n     */\n    function isLoading() {\n      return loading;\n    }\n\n    /**\n     *\n     * @return {string[]} strings that were used to search, or null if no search\n     *                    has been performed.\n     */\n    function getSearchStrings() {\n      return searchPhrase ? searchPhrase.sources : [];\n    }\n\n    /**\n     * Get results for the current search\n     * @return {Array} results for the current search. Empty if\n     *                             no search has been performed.\n     */\n    function getResults() {\n      return results;\n    }\n\n\n\n\n    var pendingSearchHandle = null;\n\n    /* Number of requests that are in progress */\n    var activeRequests = 0;\n    /* Time that most recent search was started */\n    var latestSearchTimestamp = Date.now();\n    var latestResultsTimestamp = Date.now();\n\n    /* Search data for a pending search. Will be overwritten whenever a new\n     * search is queued */\n    var pendingSearch = null;\n\n    /**\n     * Make this the next search that will occur when a search is eligible, and\n     * ensure that an appropriate timer is running to initiate the pending\n     * search.\n     *\n     * @param {Phrase} searchPhrase\n     */\n    function deferSearch(searchPhrase) {\n      pendingSearch = searchPhrase;\n      if (pendingSearchHandle) {\n        // timer is already running, no need to start\n        return;\n      }\n\n      // no timer yet, start one\n      waitToRunPendingSearch();\n    }\n\n    function waitToRunPendingSearch() {\n      var eligibleSearchTime = latestSearchTimestamp + DELAY;\n      var timeUntilCanSearch = eligibleSearchTime - Date.now();\n\n      var delay = timeUntilCanSearch > 0 ? timeUntilCanSearch : DELAY;\n\n      pendingSearchHandle = $timeout(function () {\n        pendingSearchHandle = null;\n\n        if (activeRequests >= MAX_ACTIVE_REQUESTS) {\n          // too many requests, keep waiting\n          waitToRunPendingSearch();\n          return;\n        }\n\n        // run the actual search\n        runPendingSearch();\n      }, delay);\n    }\n\n    /**\n     * Initiate the pending search, and set appropriate variables.\n     */\n    function runPendingSearch() {\n      if (pendingSearch === null) {\n        // no pending search, skip\n        return;\n      }\n\n      var search = pendingSearch;\n      pendingSearch = null;\n      $timeout.cancel(pendingSearchHandle);\n      pendingSearchHandle = null;\n\n      searchByPhrase(search);\n    }\n\n    /**\n     * Perform a search, and set appropriate variables.\n     *\n     * @param {Phrase} phrase\n     */\n    function searchByPhrase(phrase) {\n      searchPhrase = phrase;\n      var timestamp = Date.now();\n      latestSearchTimestamp = timestamp;\n      activeRequests++;\n\n      // Run the search and notify listeners when it is done\n      SuggestionsService.getSuggestionsForPhrase(phrase).then(\n        function (suggestions) {\n          // Only update results if this search is more recent than the\n          // current results.\n          if (timestamp > latestResultsTimestamp) {\n            latestResultsTimestamp = timestamp;\n            results = suggestions;\n          }\n        },\n        function (error) {\n          console.error('Error searching for phrase ', error);\n        }).finally(function () {\n          activeRequests--;\n          $rootScope.$broadcast('PhraseSuggestionsService:updated');\n          if (activeRequests < MAX_ACTIVE_REQUESTS) {\n            runPendingSearch();\n          }\n        });\n    }\n\n\n    $rootScope.$on(EventService.EVENT.REQUEST_PHRASE_SUGGESTIONS,\n      function (event, wrapper) {\n        /* @type {Phrase} */\n        var data = wrapper.phrase;\n\n        if (pendingSearch && pendingSearch.id === data.id) {\n          // search already pending\n          return;\n        }\n\n        if (!pendingSearch && activeRequests === 0 && searchPhrase &&\n            searchPhrase.id === data.id) {\n          // search is identical and there are no other searches to replace it\n          return;\n        }\n\n        if (activeRequests >= MAX_ACTIVE_REQUESTS) {\n          // too many requests, queue this one instead\n          deferSearch(data);\n          return;\n        }\n\n        var eligibleSearchTime = latestSearchTimestamp + DELAY;\n\n        if (Date.now() < eligibleSearchTime) {\n          // Too early to search, defer the search\n          deferSearch(data);\n          return;\n        }\n\n        results = [];\n        $rootScope.$broadcast('PhraseSuggestionsService:updated');\n        searchByPhrase(data);\n      });\n\n    return {\n      isLoading: isLoading,\n      getSearchStrings: getSearchStrings,\n      getResults: getResults\n    };\n  }\n\n  angular\n    .module('app')\n    .factory('PhraseSuggestionsService', PhraseSuggestionsService);\n})();\n","(function () {\n  'use strict';\n\n  /**\n   * SuggestionCtrl.js\n   * @ngInject\n   */\n  function SuggestionCtrl(EventService, $rootScope, $scope, _, $timeout) {\n    var suggestionCtrl = this;\n\n    suggestionCtrl.copyButtonText = 'Copy Translation';\n\n    while ($scope.search.length < $scope.suggestion.sourceContents.length) {\n      $scope.search.push('');\n    }\n\n    /**\n     * Get a modifier for the row class that will determine display colours.\n     *\n     * Intended to be used to generate css class for the row:\n     *\n     *     TransUnit--{{suggestionCtrl.rowDisplayType()}}\n     *\n     * @return {string} modifier to append to the TransUnit-- css class\n     */\n\n    suggestionCtrl.rowDisplayType = function () {\n      /* @type {MatchDetail} */\n      var topMatch = suggestionCtrl.topMatch();\n\n      if (topMatch.type === 'IMPORTED_TM') {\n        return 'secondary';\n      }\n      if (topMatch.type === 'LOCAL_PROJECT') {\n        if (topMatch.contentState === 'Translated') {\n          return 'success';\n        }\n        if (topMatch.contentState === 'Approved') {\n          return 'highlight';\n        }\n      }\n      console.error('Unable to generate row display type for top match');\n    };\n\n    /**\n     *\n     * @returns {string}\n     */\n    suggestionCtrl.percentDisplayType = function () {\n      var type = suggestionCtrl.rowDisplayType();\n      return type.charAt(0).toUpperCase() + type.substring(1);\n    };\n\n    /**\n     * Return correct percentage to display.\n     *\n     * I am using this instead of Angular's number display because the number\n     * display forces a particular number of decimal places rather than just\n     * limiting to the specified number, and because we should never show 100%\n     * unless it is exactly 100%.\n     */\n    suggestionCtrl.percent = function () {\n      var percent = $scope.suggestion.similarityPercent;\n\n      // Prevent very high percentages displaying as 100%\n      if (percent > 99.99 && percent < 100) {\n        return '99.99';\n      }\n      if (percent >= 99.90 && percent < 100) {\n        return '99.9';\n      }\n\n      // Limit any inexact percentages to a single decimal place\n      if (Math.round(percent) !== percent) {\n        return percent.toFixed(1);\n      }\n\n      return percent;\n    };\n\n    /**\n     * Return the details for the best match according to the following\n     * criteria:\n     *\n     *  - Content state and type: Approved > Translated > Imported\n     *  - Last modified: older modifications take higher priority.\n     *\n     * @return {MatchDetail} the best match\n     */\n    suggestionCtrl.topMatch = function () {\n      return $scope.suggestion.matchDetails[0];\n    };\n\n    suggestionCtrl.showSuggestionCopied = function () {\n      suggestionCtrl.copyButtonText = 'Copied';\n      suggestionCtrl.copyButtonDisabled = true;\n      $timeout(function() {\n        suggestionCtrl.copyButtonDisabled = false;\n        suggestionCtrl.copyButtonText = 'Copy Translation';\n      }, 500);\n    };\n\n    /**\n     * Request this suggestion to be copied to the selected translation field.\n     *\n     * Generates a COPY_FROM_SUGGESTION event.\n     */\n    suggestionCtrl.copySuggestion = function () {\n      suggestionCtrl.showSuggestionCopied();\n      EventService.emitEvent(EventService.EVENT.COPY_FROM_SUGGESTION,\n        { suggestion: $scope.suggestion });\n    };\n\n    $scope.$on('EditorSuggestionsCtrl:nth-suggestion-copied',\n      function (event, index) {\n        if (index === $scope.index) {\n          suggestionCtrl.showSuggestionCopied();\n        }\n    });\n\n    $scope.detail = suggestionCtrl.topMatch();\n    // Will be undefined for imported matches\n    $scope.user = $scope.detail.lastModifiedBy || 'Annoymous';\n    $scope.remaining = $scope.suggestion.matchDetails.length - 1;\n    $scope.isTextFlow = $scope.detail.type === 'LOCAL_PROJECT';\n\n    return suggestionCtrl;\n  }\n\n  angular\n    .module('app')\n    .controller('SuggestionCtrl', SuggestionCtrl);\n})();\n\n","(function() {\n  'use strict';\n\n  /**\n   * @typedef {Object} ImportedMatchDetail\n   * @param {string} type - 'IMPORTED_TM'\n   * @param {number} transMemoryUnitId - numeric identifier for this translation\n   *                         memory unit on the server\n   * @param {string} transMemorySlug - identifier for the translation memory\n   *                         that contains this translation unit\n   * @param {string} transUnitId - optional identifier for this translation unit\n   * @param {string} lastChanged - date that this text flow was last changed, in\n   *                         ISO-8601 format\n   */\n\n  /**\n   * @typedef {Object} LocalMatchDetail\n   * @param {string} type - 'LOCAL_PROJECT'\n   * @param {number} textFlowId - numeric identifier for this text flow on the\n   *                         server\n   * @param {string} contentState - 'Translated' or 'Approved'\n   * @param {string} projectId - identifier for the project that this text flow\n   *                         is in\n   * @param {string} projectName - display name for the project that this text\n   *                         flow is in\n   * @param {string} version - identifier for the version that this text flow is\n   *                         in\n   * @param {string} documentPath - file path of the document that contains this\n   *                         text flow.\n   * @param {string} documentName - file name of the document that contains this\n   *                         text flow, without the file path\n   * @param {string} resId - natural id for this text flow within the document\n   * @param {string} lastModifiedDate - date that this text flow was last\n   *                         changed, in ISO-8601 format\n   * @param {string} lastModifiedBy - username of the user who last modified\n   *                         this text flow\n   */\n\n  /**\n   * @typedef {(ImportedMatchDetail|LocalMatchDetail)} MatchDetail\n   */\n\n  /**\n   * @typedef {Object} Suggestion\n   * @param {number} relevanceScore - score from the search engine indicating\n   *                         how close a match it considers this to the query.\n   *                         It is sensible to compare scores within a query,\n   *                         but not between queries.\n   * @param {number} similarityPercent - proportion of the characters in\n   *                         sourceContents that match the query\n   * @param {Array} sourceContents - suggested source text that is\n   *                                similar to the search\n   * @param {Array} targetContents - translations of the suggested\n   *                                source text\n   * @param {Array} matchDetails - summary of all the sources with\n   *                                     the same source and target contents\n   */\n\n  /**\n   * Provide suggestions based on given source text.\n   *\n   * SuggestionsService.js\n   * @ngInject\n   */\n  function SuggestionsService(EditorService, EventService, UrlService, _,\n                              $resource) {\n\n    /**\n     * Get a list of suggestions for how to translate a piece of text.\n     *\n     * @param {string} searchText\n     * @return {Promise>} suggestions for translating the\n     *                                      given text\n     */\n    function getSuggestionsForText(searchText) {\n      return getSuggestionsForContents([searchText]);\n    }\n\n    /**\n     * Get a list of suggestions for how to translate a phrase.\n     *\n     * @param {Phrase} phrase the source text to find suggestions for\n     * @returns {Promise>} suggestions for translating the\n     *                                       given phrase\n     */\n    function getSuggestionsForPhrase(phrase) {\n      return getSuggestionsForContents(phrase.sources)\n        .then(function (suggestions) {\n          EventService.emitEvent(EventService.EVENT.PHRASE_SUGGESTION_COUNT,\n            { id: phrase.id, count: suggestions.length });\n          return suggestions;\n        });\n    }\n\n    /**\n     * Get a list of suggestions for how to translate a list of strings.\n     *\n     * @param contents {Array} source strings to find matches for\n     * @returns {Promise>}\n     */\n    function getSuggestionsForContents(contents) {\n      var sourceLocale = EditorService.context.srcLocale.localeId;\n      var transLocale = EditorService.context.localeId;\n\n      var postQuery = {\n        query: {\n          method: 'POST',\n          params: {\n            from: sourceLocale,\n            to: transLocale,\n            searchType: 'FUZZY_PLURAL'\n          },\n          isArray: true\n        }\n      };\n\n      var Suggestions = $resource(UrlService.SUGGESTIONS_URL, {}, postQuery);\n      return Suggestions.query({}, contents).$promise.then(sortSuggestions);\n    }\n\n    /**\n     * Sort suggestions so better matches are at the top, and details are in\n     * order from most to least relevant.\n     *\n     * @param {Suggestion[]} suggestions\n     * @return {Suggestion[]} the given suggestions in order.\n     */\n    function sortSuggestions(suggestions) {\n      return _.chain(suggestions)\n        .map(sortDetails)\n        .map(addBestMatchScores)\n        .sortBy(['similarityPercent', 'bestMatchScore',\n                 'bestMatchModificationDate', 'relevanceScore'])\n        .reverse()\n        .value();\n    }\n\n    /**\n     * Add properties 'bestMatchScore' and 'bestMatchModificationDate' to a\n     * suggestion to help with sorting.\n     *\n     * Higher scores are considered better, since the final results are in\n     * descending order.\n     *\n     * @param {Suggestion} suggestion\n     * @return {Suggestion}\n     */\n    function addBestMatchScores (suggestion) {\n      var date, score;\n      var topMatch = suggestion.matchDetails[0];\n\n      if (topMatch.type === 'LOCAL_PROJECT') {\n        date = topMatch.lastModifiedDate;\n        score = topMatch.contentState === 'Translated' ? 0 : 1;\n      }\n\n      if (topMatch.type === 'IMPORTED_TM') {\n        date = topMatch.lastChanged;\n        score = 2;\n      }\n\n      return _.assign({}, suggestion, {\n        bestMatchScore: score,\n        bestMatchModificationDate: date\n      });\n    }\n\n    /**\n     * Sort the match details of a suggestion by type and date.\n     *\n     * @param {Suggestion} suggestion to sort details\n     * @return {Suggestion} the given suggestion with details in correct order\n     */\n    function sortDetails (suggestion) {\n      var sortedDetails = _.sortBy(suggestion.matchDetails, typeAndDateSort);\n      return _.assign({}, suggestion, { matchDetails: sortedDetails });\n    }\n\n    // TODO use sortByAll when lodash version is increased\n    /**\n     * Return a string that will naturally sort local project details before\n     * imported TM details, approved state above translated state, and older\n     * modification dates first, in that priority order.\n     *\n     * @param {MatchDetail} detail\n     * @return {string} representation of order that will sort appropriately.\n     */\n    function typeAndDateSort (detail) {\n\n      if (detail.type === 'IMPORTED_TM') {\n        return '3' + detail.lastChanged;\n      }\n      if (detail.type === 'LOCAL_PROJECT') {\n        if (detail.contentState === 'Translated') {\n          return '2' + detail.lastModifiedDate;\n        }\n        if (detail.contentState === 'Approved') {\n          return '1' + detail.lastModifiedDate;\n        }\n      }\n      // Unrecognized, sort last\n      return '9';\n    }\n\n\n\n    return {\n      getSuggestionsForPhrase: getSuggestionsForPhrase,\n      getSuggestionsForText: getSuggestionsForText\n    };\n  }\n\n  angular\n    .module('app')\n    .factory('SuggestionsService', SuggestionsService);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * TextSuggestionsService.js\n   * @ngInject\n   */\n  function TextSuggestionsService(_, EventService, SuggestionsService,\n                                    $rootScope, $timeout) {\n\n    /* Minimum time in milliseconds to wait between requesting results */\n    var DELAY = 300;\n    var MAX_ACTIVE_REQUESTS = 3;\n\n    /* @type {string} */\n    var searchText = null;\n\n    /* @type {Array} */\n    var results = [];\n\n    /**\n     * @return {boolean} true if results have been requested and not delivered\n     */\n    function isLoading() {\n      return activeRequests > 0;\n    }\n\n    /**\n     *\n     * @return {string[]} strings that were used to search, or null if no search\n     *                    has been performed.\n     */\n    function getSearchStrings() {\n      return searchText ? [searchText] : [];\n    }\n\n    /**\n     * Get results for the current search\n     * @return {Array} results for the current search. Empty if\n     *                             no search has been performed.\n     */\n    function getResults() {\n      return results;\n    }\n\n\n    var pendingSearchHandle = null;\n\n    /* Number of requests that are in progress */\n    var activeRequests = 0;\n    /* Time that most recent search was started */\n    var latestSearchTimestamp = Date.now();\n    var latestResultsTimestamp = Date.now();\n\n    /* Search text for a pending search. Will be overwritten whenever a new\n     * search is queued */\n    var pendingSearch = null;\n\n    /**\n     * Make this the next search that will occur when a search is eligible, and\n     * ensure that an appropriate timer is running to initiate the pending\n     * search.\n     *\n     * @param {string} searchText\n     */\n    function deferSearch(searchText) {\n      pendingSearch = searchText;\n      if (pendingSearchHandle) {\n        // timer is already running, no need to start\n        return;\n      }\n\n      // no timer yet, start one\n      waitToRunPendingSearch();\n    }\n\n    function waitToRunPendingSearch() {\n      var eligibleSearchTime = latestSearchTimestamp + DELAY;\n      var timeUntilCanSearch = eligibleSearchTime - Date.now();\n\n      var delay = timeUntilCanSearch > 0 ? timeUntilCanSearch : DELAY;\n\n      pendingSearchHandle = $timeout(function () {\n        pendingSearchHandle = null;\n\n        if (activeRequests >= MAX_ACTIVE_REQUESTS) {\n          // too many requests, keep waiting\n          waitToRunPendingSearch();\n          return;\n        }\n\n        // run the actual search\n        runPendingSearch();\n      }, delay);\n    }\n\n    /**\n     * Initiate the pending search, and set appropriate variables.\n     */\n    function runPendingSearch() {\n      if (pendingSearch === null) {\n        // no pending search, skip\n        return;\n      }\n\n      var search = pendingSearch;\n      pendingSearch = null;\n      $timeout.cancel(pendingSearchHandle);\n      pendingSearchHandle = null;\n\n      searchByText(search);\n    }\n\n    /**\n     * Perform a search, and set appropriate variables.\n     *\n     * @param {string} text\n     */\n    function searchByText(text) {\n      searchText = text;\n      var timestamp = Date.now();\n      latestSearchTimestamp = timestamp;\n      activeRequests++;\n\n      // Run the search and notify listeners when it is done\n      SuggestionsService.getSuggestionsForText(text).then(\n        function (suggestions) {\n          // Only update results if this search is more recent than the\n          // current results.\n          if (timestamp > latestResultsTimestamp) {\n            latestResultsTimestamp = timestamp;\n            results = suggestions;\n          }\n        },\n        function (error) {\n          console.error('Error searching for text ', error);\n        }).finally(function () {\n          activeRequests--;\n          $rootScope.$broadcast('TextSuggestionsService:updated');\n          if (activeRequests < MAX_ACTIVE_REQUESTS) {\n            runPendingSearch();\n          }\n        });\n    }\n\n\n    $rootScope.$on(EventService.EVENT.REQUEST_TEXT_SUGGESTIONS,\n      function (event, data) {\n\n        if (pendingSearch && pendingSearch === data) {\n          // search already pending\n          return;\n        }\n\n        if (!pendingSearch && activeRequests === 0 && searchText === data) {\n          // search is identical and there are no other searches to replace it\n          return;\n        }\n\n        // Empty search can update immediately\n        if (data === '') {\n          searchText = data;\n          //loading = false;\n          results = [];\n\n          // Ensure that earlier active searches will not overwrite results.\n          pendingSearch = null;\n          $timeout.cancel(pendingSearchHandle);\n          pendingSearchHandle = null;\n          latestSearchTimestamp = Date.now;\n          latestResultsTimestamp = Date.now();\n\n          $rootScope.$broadcast('TextSuggestionsService:updated');\n          return;\n        }\n\n        if (activeRequests >= MAX_ACTIVE_REQUESTS) {\n          // too many requests, queue this one instead\n          deferSearch(data);\n          return;\n        }\n\n        var eligibleSearchTime = latestSearchTimestamp + DELAY;\n\n        if (Date.now() < eligibleSearchTime) {\n          // Too early to search, defer the search\n          deferSearch(data);\n          return;\n        }\n\n        results = [];\n        $rootScope.$broadcast('TextSuggestionsService:updated');\n        searchByText(data);\n      });\n\n    return {\n      isLoading: isLoading,\n      getSearchStrings: getSearchStrings,\n      getResults: getResults\n    };\n  }\n\n  angular\n    .module('app')\n    .factory('TextSuggestionsService', TextSuggestionsService);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name suggestion\n   * @description suggestion container\n   * @ngInject\n   */\n  function suggestion() {\n    return {\n      // Only use the template on elements with this name (not on things that\n      // have an attribute or class called 'suggestion'.\n      restrict: 'E',\n      //required: ['suggestion'],\n\n      // Specify an isolated scope for the suggestion component.\n      scope: {\n        // make variable 'suggestion' available in the template's scope, and\n        // bind its value from the attribute with the same name.\n        // (a different name for the attribute can be specified after the =\n        suggestion: '=',\n        index: '=',\n        search: '=',\n        diffEnabled: '='\n\n        // If I put & instead of = in front of a name, it will run it in the\n        // parent scope instead of this directive's isolated scope. Good for\n        // callbacks.\n      },\n      controller: 'SuggestionCtrl as suggestionCtrl',\n      templateUrl: 'components/suggestions/suggestion.html'\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('suggestion', suggestion);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name toggle-checkbox\n   * @description Add an extra element to a checkbox to\n   * so we can style it differently\n   * @ngInject\n   */\n  function toggleCheckbox() {\n    return {\n      restrict: 'A',\n      link: function(scope, element) {\n        element.after('');\n      }\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('toggleCheckbox', toggleCheckbox);\n\n})();\n","(function () {\n  'use strict';\n\n  /**\n   * @typedef {Object} StatusInfo\n   * @property {string} ID lower case translation status (content state)\n   * @property {string} NAME capitalized representation\n   * @property {string} CSSCLASS css class to use for this status\n   *\n   */\n  /**\n   * TransStatusService.js\n   *\n   * @ngInject\n   */\n  function TransStatusService(_) {\n    var transStatusService = this,\n        STATUSES = {\n          'UNTRANSLATED': {\n            'ID': 'untranslated',\n            'NAME': 'Untranslated',\n            'CSSCLASS': 'neutral'\n          },\n          'NEEDSWORK': {\n            'ID': 'needswork',\n            'NAME': 'Needs Work',\n            'CSSCLASS': 'unsure'\n          },\n          'TRANSLATED' : {\n            'ID': 'translated',\n            'NAME': 'Translated',\n            'CSSCLASS': 'success'\n          },\n          'APPROVED': {\n            'ID': 'approved',\n            'NAME': 'Approved',\n            'CSSCLASS': 'highlight'\n          }\n        };\n\n    transStatusService.getAll = function() {\n      return STATUSES;\n    };\n\n    transStatusService.getAllAsArray = function() {\n      return _.values(STATUSES);\n    };\n\n    /**\n     *\n     * @param {string} statusKey string representation of the status.\n     * @returns {StatusInfo}\n     */\n    transStatusService.getStatusInfo = function(statusKey) {\n      return STATUSES[conformStatus(statusKey)];\n    };\n\n    transStatusService.getId = function(statusKey) {\n      return STATUSES[conformStatus(statusKey)].ID;\n    };\n\n    transStatusService.getServerId = function(statusId) {\n      return serverStatusId(statusId);\n    };\n\n    transStatusService.getName = function(statusKey) {\n      return STATUSES[conformStatus(statusKey)].NAME;\n    };\n\n    transStatusService.getCSSClass = function(statusKey) {\n      return STATUSES[conformStatus(statusKey)].CSSCLASS;\n    };\n\n    /**\n     * Conform it to uppercase for lookups and\n     * temporary fix for server sending \"needReview\"\n     * instead of needswork status\n     * @param  {string} status\n     * @return {string}        new value to use\n     */\n    function conformStatus(statusKey) {\n      statusKey = angular.uppercase(statusKey);\n      if (!statusKey || statusKey === 'NEW') {\n        statusKey = 'UNTRANSLATED';\n      } else if (statusKey === 'NEEDREVIEW') {\n        statusKey = 'NEEDSWORK';\n      }\n      return statusKey;\n    }\n\n    /**\n     * Conform it to PascalCase for lookups and\n     * temporary fix for server receiving \"needReview\"\n     * instead of needswork status\n     * @param  {string} status\n     * @return {string}        new value to use\n     */\n    function serverStatusId(statusId) {\n      statusId = angular.lowercase(statusId);\n      if (!statusId || statusId === 'untranslated') {\n        return 'New';\n      } else if (statusId === 'needswork') {\n        return 'NeedReview';\n      }\n      return statusId.charAt(0).toUpperCase() + statusId.slice(1).toLowerCase();\n    }\n\n    return transStatusService;\n  }\n\n  angular\n    .module('app')\n    .factory('TransStatusService', TransStatusService);\n})();\n\n","(function() {\n  'use strict';\n\n  /**\n   * @name trans-unit\n   * @description transUnit container\n   * @ngInject\n   */\n  function transUnitFilter() {\n    return {\n      restrict: 'E',\n      required: ['editor'],\n      scope: {\n        editor: '='\n      },\n      templateUrl: 'components/transUnitFilter/trans-unit-filter.html'\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('transUnitFilter', transUnitFilter);\n\n})();\n","(function () {\n  'use strict';\n\n  /**\n   * TransUnitCtrl.js\n   * @ngInject\n   */\n  function TransUnitCtrl($rootScope, $scope, $element, $stateParams, _,\n                         TransUnitService, EventService, LocaleService, focus,\n                         EditorShortcuts, PhraseUtil, SettingsService) {\n\n    var transUnitCtrl = this;\n\n    transUnitCtrl.selected = false;\n    transUnitCtrl.focused = false;\n    transUnitCtrl.focusedTranslationIndex = 0;\n\n    transUnitCtrl.hasTranslationChanged =\n      PhraseUtil.hasTranslationChanged;\n\n    transUnitCtrl.focusTranslation = function() {\n      if(transUnitCtrl.selected) {\n        focus('phrase-' + $scope.phrase.id + '-' +\n        transUnitCtrl.focusedTranslationIndex);\n      }\n    };\n\n    // when user clicked on TU or using tab to nav\n    transUnitCtrl.onTextAreaFocus = function(phrase, index) {\n      transUnitCtrl.focused = true;\n      if (!_.isUndefined(index)) {\n        transUnitCtrl.focusedTranslationIndex = index;\n      }\n      if(!transUnitCtrl.selected) {\n        EventService.emitEvent(EventService.EVENT.SELECT_TRANS_UNIT,\n          {'id': phrase.id,\n            'updateURL': true,\n            'focus': true\n          }, $scope);\n      }\n    };\n\n    transUnitCtrl.translationTextModified = function(phrase) {\n      EventService.emitEvent(EventService.EVENT.TRANSLATION_TEXT_MODIFIED,\n          phrase);\n    };\n\n    transUnitCtrl.getPhrase = function() {\n      return $scope.phrase;\n    };\n\n    transUnitCtrl.init = function() {\n      TransUnitService.addController($scope.phrase.id, transUnitCtrl);\n      if($stateParams.id && parseInt($stateParams.id) === $scope.phrase.id) {\n        EventService.emitEvent(EventService.EVENT.SELECT_TRANS_UNIT,\n          {'id': $stateParams.id,\n            'updateURL': false,\n            'focus' : $stateParams.selected});\n      }\n    };\n\n    transUnitCtrl.copySource = function($event, phrase, sourceIndex) {\n      $event.stopPropagation(); //prevent click event of TU\n      EventService.emitEvent(EventService.EVENT.COPY_FROM_SOURCE,\n        {'phrase': phrase, 'sourceIndex': sourceIndex}, $scope);\n    };\n\n    transUnitCtrl.undoEdit = function($event, phrase) {\n      $event.stopPropagation(); //prevent click event of TU\n      EventService.emitEvent(EventService.EVENT.UNDO_EDIT,\n        phrase, $scope);\n    };\n\n    transUnitCtrl.cancelEdit = function($event, phrase) {\n      $event.stopPropagation(); //prevent click event of TU\n      EventService.emitEvent(EventService.EVENT.CANCEL_EDIT,\n        phrase, $scope);\n    };\n\n    transUnitCtrl.saveAs = function($event, phrase, status) {\n      EditorShortcuts.saveTranslationCallBack($event, phrase, status);\n    };\n\n    transUnitCtrl.getLocaleName = function(localeId) {\n      return LocaleService.getName(localeId);\n    };\n\n    transUnitCtrl.toggleSaveAsOptions = function(open) {\n      EventService.broadcastEvent( open ? 'openDropdown': 'closeDropdown',\n        {}, $scope);\n      if (open) {\n        // focus on the first dropdown option\n        focus($scope.phrase.id + '-saveAsOption-0');\n      }\n    };\n\n    var SHOW_SUGGESTIONS = SettingsService.SETTING.SHOW_SUGGESTIONS;\n    $scope.showSuggestions = SettingsService.subscribe(SHOW_SUGGESTIONS,\n      function (show) {\n        $scope.showSuggestions = show;\n      });\n\n    $rootScope.$on(EventService.EVENT.SUGGESTIONS_SEARCH_TOGGLE,\n      function(event, data) {\n        transUnitCtrl.suggestionsSearchIsActive = data;\n      });\n\n    transUnitCtrl.toggleSuggestionPanel = function () {\n      if (transUnitCtrl.suggestionsSearchIsActive) {\n        EventService.emitEvent(EventService.EVENT.SUGGESTIONS_SEARCH_TOGGLE,\n          false);\n      }\n      else {\n        SettingsService.update(SHOW_SUGGESTIONS, !$scope.showSuggestions);\n      }\n    };\n\n    $scope.suggestionCount = 0;\n    $rootScope.$on(EventService.EVENT.PHRASE_SUGGESTION_COUNT,\n      function (event, data) {\n        if (data.id === $scope.phrase.id) {\n          $scope.suggestionCount = data.count;\n        }\n      });\n\n    transUnitCtrl.cancelSaveAsMode = function() {\n      EditorShortcuts.cancelSaveAsModeIfOn();\n    };\n\n    $scope.$on('$destroy', function () {\n      $element.unbind('click', onTransUnitClick);\n      $element.unbind('focus', onTransUnitClick);\n    });\n\n    transUnitCtrl.updateSaveButton = function (phrase) {\n      transUnitCtrl.saveButtonStatus =\n        PhraseUtil.getSaveButtonStatus($scope.phrase);\n      transUnitCtrl.saveButtonOptions =\n        TransUnitService.getSaveButtonOptions(transUnitCtrl.saveButtonStatus,\n          $scope.phrase);\n      transUnitCtrl.saveButtonText = transUnitCtrl.saveButtonStatus.NAME;\n      transUnitCtrl.saveButtonDisabled =\n        !PhraseUtil.hasTranslationChanged(phrase);\n      transUnitCtrl.loadingClass = '';\n      transUnitCtrl.savingStatus = '';\n    };\n\n    transUnitCtrl.phraseSaving = function (data) {\n      transUnitCtrl.loadingClass = 'is-loading';\n      transUnitCtrl.saveButtonStatus =\n        transUnitCtrl.savingStatus = data.status;\n      transUnitCtrl.saveButtonOptions =\n        TransUnitService.getSaveButtonOptions(transUnitCtrl.saveButtonStatus,\n          data.phrase);\n      transUnitCtrl.saveButtonText = 'Saving…';\n      transUnitCtrl.saveButtonDisabled = true;\n    };\n\n    transUnitCtrl.saveButtonOptionsAvailable = function() {\n      return !_.isEmpty(transUnitCtrl.saveButtonOptions);\n    };\n\n    transUnitCtrl.selectTransUnit = function(phrase) {\n      if (!transUnitCtrl.selected) {\n        EventService.emitEvent(EventService.EVENT.SELECT_TRANS_UNIT,\n                               {'id': phrase.id,\n                                 'updateURL': true,\n                                 'focus': true\n                               }, $scope);\n      }\n    };\n\n    function onTransUnitClick() {\n      if(!transUnitCtrl.selected) {\n        $scope.$apply(function () {\n          EventService.emitEvent(EventService.EVENT.SELECT_TRANS_UNIT,\n            {'id': $scope.phrase.id,\n              'updateURL': true,\n              'focus': true}, $scope);\n        });\n      }\n    }\n\n    return transUnitCtrl;\n  }\n\n  angular\n    .module('app')\n    .controller('TransUnitCtrl', TransUnitCtrl);\n})();\n\n","(function () {\n  'use strict';\n\n  /**\n   * TransUnitService\n   *\n   * See PhraseService.transformToPhrases function for phrase definition.\n   *\n   * @ngInject\n   */\n  function TransUnitService(_, $location, $rootScope, $state, $stateParams,\n    $filter, MessageHandler, EventService, TransStatusService, PRODUCTION,\n    EditorShortcuts, PhraseUtil, $timeout) {\n    var transUnitService = this,\n        controllerList = {},\n        selectedTUId;\n\n    transUnitService.addController = function(id, controller) {\n      controllerList[id] = controller;\n    };\n\n    transUnitService.getSaveButtonOptions = function(saveButtonStatus, phrase) {\n      return filterSaveButtonOptions(saveButtonStatus, phrase);\n    };\n\n    $rootScope.$on(EventService.EVENT.TOGGLE_SAVE_OPTIONS,\n      function(event, data) {\n        var transUnitCtrl = controllerList[data.id];\n        if (transUnitCtrl) {\n          transUnitCtrl.toggleSaveAsOptions(data.open);\n        }\n    });\n\n    /**\n     * EventService.EVENT.SELECT_TRANS_UNIT listener\n     * - Select and focus a trans-unit.\n     * - Perform implicit save on previous selected TU if changed\n     * - Update url with TU id without reload state\n     */\n    $rootScope.$on(EventService.EVENT.SELECT_TRANS_UNIT,\n      function (event, data) {\n        var newTuController = controllerList[data.id],\n            oldTUController = controllerList[selectedTUId],\n            updateURL = data.updateURL;\n\n        EventService.emitEvent(EventService.EVENT.REQUEST_PHRASE_SUGGESTIONS,\n          {\n            'phrase' : newTuController.getPhrase()\n          });\n\n        if(newTuController) {\n          EditorShortcuts.selectedTUCtrl = newTuController;\n\n          if (selectedTUId && selectedTUId !== data.id) {\n            setSelected(oldTUController, false);\n\n            //perform implicit save if changed\n            if(PhraseUtil.hasTranslationChanged(\n              oldTUController.getPhrase())) {\n              EventService.emitEvent(EventService.EVENT.SAVE_TRANSLATION,\n                {\n                  'phrase' : oldTUController.getPhrase(),\n                  'status' : TransStatusService.getStatusInfo('TRANSLATED'),\n                  'locale' : $stateParams.localeId,\n                  'docId'  : $stateParams.docId\n                });\n            }\n          }\n\n          updateSaveButton(event, newTuController.getPhrase());\n          selectedTUId = data.id;\n          setSelected(newTuController, true);\n\n          EventService.emitEvent(EventService.EVENT.FOCUS_TRANSLATION, data);\n\n          //Update url without reload state\n          if(updateURL) {\n            if($state.current.name !== 'editor.selectedContext.tu') {\n              $state.go('editor.selectedContext.tu', {\n                'id': data.id,\n                'selected': data.focus.toString()\n              });\n            } else {\n              $location.search('id', data.id);\n              $location.search('selected', data.focus.toString());\n            }\n          }\n        } else {\n          MessageHandler.displayWarning('Trans-unit not found:' + data.id);\n        }\n      });\n\n    /**\n     * EventService.EVENT.COPY_FROM_SOURCE listener\n     * Copy translation from source\n     */\n    $rootScope.$on(EventService.EVENT.COPY_FROM_SOURCE,\n      function (event, data) {\n        var sourceIndex = 0;\n        if(data.phrase.plural) {\n          //clicked copy source button\n          sourceIndex = data.sourceIndex;\n          if(_.isUndefined(sourceIndex)) {\n            //copy source key shortcut, copy corresponding source to target\n            var transUnitCtrl = controllerList[data.phrase.id];\n            sourceIndex = transUnitCtrl.focusedTranslationIndex;\n            if(data.phrase.sources.length <\n              transUnitCtrl.focusedTranslationIndex + 1) {\n              sourceIndex = data.phrase.sources.length - 1;\n            }\n          }\n        }\n        setTranslationText(data.phrase, data.phrase.sources[sourceIndex]);\n      });\n\n    $rootScope.$on(EventService.EVENT.COPY_FROM_SUGGESTION,\n      function (event, data) {\n        if (selectedTUId) {\n          var transUnitCtrl = controllerList[selectedTUId];\n          var phrase = transUnitCtrl.getPhrase();\n\n          var suggestion = data.suggestion;\n          var targets = suggestion.targetContents;\n\n          var copyAsPlurals = phrase.plural && targets.length > 1;\n\n\n          if (copyAsPlurals) {\n            var pluralCount = phrase.translations.length;\n\n            if (targets.length < pluralCount) {\n              var lastSuggestion = _.last(targets);\n              // pad suggestions with last suggestion, but only when there are\n              // no translations entered for the extra plural forms.\n              targets = _.assign(phrase.translations.slice(), targets,\n                function (current, suggested) {\n                  if (suggested) return suggested;\n                  if (current) return current;\n                  return lastSuggestion;\n                });\n            }\n            if (targets.length > pluralCount) {\n              targets = _.first(targets, pluralCount);\n            }\n\n            setAllTranslations(phrase, targets);\n          } else {\n            setTranslationText(phrase, targets[0]);\n          }\n        }\n      });\n\n    /**\n     * EventService.EVENT.UNDO_EDIT listener\n     * Cancel edit and restore translation\n     */\n    $rootScope.$on(EventService.EVENT.UNDO_EDIT,\n      function (event, phrase) {\n        if (PhraseUtil.hasTranslationChanged(phrase)) {\n          setAllTranslations(phrase, phrase.translations);\n        }\n      });\n\n    /**\n     * EventService.EVENT.CANCEL_EDIT listener\n     * Cancel edit and restore translation\n     */\n    $rootScope.$on(EventService.EVENT.CANCEL_EDIT,\n      function (event, phrase) {\n        if(selectedTUId) {\n          setSelected(controllerList[selectedTUId], false);\n          selectedTUId = false;\n          EditorShortcuts.selectedTUCtrl = null;\n        }\n\n        $location.search('selected', null);\n        if(!phrase) {\n          $location.search('id', null);\n        }\n\n        // EditorContentCtrl#changePage doesn't provide a phrase object\n        if (phrase) {\n          $timeout(function() {\n            return $rootScope.$broadcast('blurOn', 'phrase-' + phrase.id);\n          });\n        }\n      });\n\n    /**\n     * EventService.EVENT.TRANSLATION_TEXT_MODIFIED listener\n     *\n     */\n    $rootScope.$on(EventService.EVENT.TRANSLATION_TEXT_MODIFIED,\n       updateSaveButton);\n\n    /**\n     * EventService.EVENT.FOCUS_TRANSLATION listener\n     *\n     */\n    $rootScope.$on(EventService.EVENT.FOCUS_TRANSLATION,\n       setFocus);\n\n    /**\n      * EventService.EVENT.SAVE_COMPLETED listener\n      *\n      */\n    $rootScope.$on(EventService.EVENT.SAVE_INITIATED,\n       phraseSaving);\n\n    /**\n      * EventService.EVENT.SAVE_COMPLETED listener\n      *\n      */\n    $rootScope.$on(EventService.EVENT.SAVE_COMPLETED,\n       updateSaveButton);\n\n    function setTranslationText(phrase, newText) {\n      var index = 0;\n      if (phrase.plural) {\n        var transUnitCtrl = controllerList[phrase.id];\n        index = transUnitCtrl.focusedTranslationIndex;\n      }\n      phrase.newTranslations[index] = newText;\n      EventService.emitEvent(EventService.EVENT.TRANSLATION_TEXT_MODIFIED,\n        phrase);\n      EventService.emitEvent(EventService.EVENT.FOCUS_TRANSLATION,\n        phrase);\n    }\n\n    function setAllTranslations(phrase, newTexts) {\n      //need slice() for new instance of array\n      phrase.newTranslations = newTexts.slice();\n\n      EventService.emitEvent(EventService.EVENT.TRANSLATION_TEXT_MODIFIED,\n        phrase);\n      EventService.emitEvent(EventService.EVENT.FOCUS_TRANSLATION,\n        phrase);\n    }\n\n    function updateSaveButton(event, phrase) {\n       var transUnitCtrl = controllerList[phrase.id];\n       transUnitCtrl.updateSaveButton(phrase);\n    }\n\n    function phraseSaving(event, data) {\n      var transUnitCtrl = controllerList[data.phrase.id];\n      transUnitCtrl.phraseSaving(data);\n      EventService.emitEvent(EventService.EVENT.FOCUS_TRANSLATION,\n        data.phrase);\n    }\n\n    function setSelected(transUnitCtrl, isSelected) {\n      //This check is to prevent selected event being triggered repeatedly.\n      if(transUnitCtrl.selected !== isSelected) {\n        transUnitCtrl.selected = isSelected || false;\n      }\n    }\n\n    function setFocus(event, phrase) {\n      var transUnitCtrl = controllerList[phrase.id];\n      transUnitCtrl.focusTranslation();\n    }\n\n    /**\n     * Filters the dropdown options for saving a translation\n     * Unless the translation is empty, remove untranslated as an option\n     * Filter the current default save state out of the list and show remaining\n     *\n     * @param  {Object} saveStatus The current default translation *save* status\n     * @return {Array}             Is used to construct the dropdown list\n     */\n    function filterSaveButtonOptions(saveStatus, phrase) {\n      var filteredOptions = [];\n      if (saveStatus.ID === 'untranslated') {\n        return filteredOptions;\n      }\n      filteredOptions = $filter('filter')\n      (TransStatusService.getAllAsArray(), {ID: '!untranslated'});\n\n      if(phrase.plural) {\n        if(PhraseUtil.hasNoTranslation(phrase)) {\n          filteredOptions = $filter('filter')\n          (filteredOptions, {ID: '!needswork'});\n        } else if(PhraseUtil.hasEmptyTranslation(phrase)) {\n            filteredOptions = $filter('filter')\n            (filteredOptions, {ID: '!translated'});\n        }\n      }\n\n      if (PRODUCTION) {\n        filteredOptions = $filter('filter')\n        (filteredOptions, {ID: '!approved'});\n      }\n\n      return $filter('filter')(filteredOptions, {ID: '!'+saveStatus.ID});\n    }\n\n    return transUnitService;\n  }\n\n  angular\n    .module('app')\n    .factory('TransUnitService', TransUnitService);\n})();\n\n\n","(function() {\n  'use strict';\n\n  /**\n   * @name trans-unit\n   * @description transUnit container\n   * @ngInject\n   */\n  function transUnit() {\n    return {\n      restrict: 'E',\n      required: ['phrase', 'editorContext'],\n      scope: {\n        phrase: '=',\n        firstPhrase: '=',\n        editorContext: '='\n      },\n      controller: 'TransUnitCtrl as transUnitCtrl',\n      templateUrl: 'components/transUnit/trans-unit.html',\n      link: function(scope, element, attr, TransUnitCtrl) {\n        TransUnitCtrl.init();\n      }\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('transUnit', transUnit);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * UserService.js\n   *\n   * @ngInject\n   */\n  function UserService($resource, UrlService) {\n\n    function getUserInfo(username) {\n      var UserInfo = $resource(UrlService.USER_INFO_URL, {}, {\n        query: {\n          method: 'GET',\n          params: {\n            username: username\n          }\n        }\n      });\n      return UserInfo.query().$promise;\n    }\n\n    function getMyInfo() {\n      var MyInfo = $resource(UrlService.MY_INFO_URL, {}, {\n        query: {\n          method: 'GET'\n        }\n      });\n      return MyInfo.query().$promise;\n    }\n\n    return {\n      settings: {\n        editor: {\n          hideMainNav: false\n        }\n      },\n      getUserInfo: getUserInfo,\n      getMyInfo: getMyInfo\n    };\n  }\n  angular\n    .module('app')\n    .factory('UserService', UserService);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * FilterUtil.js\n   *\n   * @ngInject\n   */\n  function FilterUtil(StringUtil, _) {\n\n    /**\n     * Filter in resources on given fields with matched terms\n     *\n     * @param resources - list of resources\n     * @param fields - list of fields to check\n     * @param terms - list of term to check\n     * @returns {*}\n     */\n    function filterResources(resources, fields, terms) {\n      if(!resources || !fields || !terms) {\n        return resources;\n      }\n      return _.filter(resources, function (resource) {\n        return isInclude(resource, fields, terms);\n      });\n    }\n\n    /**\n     * Filter out properties starting with $ (added by promise)\n     * @param resources\n     */\n    function cleanResourceMap(resources) {\n      var filteredList = {};\n      var ids = Object.keys(resources).filter(function (id) {\n        return id.indexOf('$') === -1;\n      });\n      ids.forEach(function(id) {\n        filteredList[id] = (resources[id]);\n      });\n      return filteredList;\n    }\n\n    function cleanResourceList(resources) {\n      var filteredList = [];\n      var ids = Object.keys(resources).filter(function (id) {\n        return id.indexOf('$') === -1;\n      });\n      ids.forEach(function(id) {\n        filteredList.push(resources[id]);\n      });\n      return filteredList;\n    }\n\n\n    function isInclude(resource, fields, terms) {\n      if(!resource || !fields || !terms) {\n        return false;\n      }\n      return _.any(fields, function(field) {\n        return _.any(terms, function(term) {\n          return StringUtil.equals(resource[field], term, true);\n        });\n      });\n    }\n\n    return {\n      filterResources  : filterResources,\n      cleanResourceList:cleanResourceList,\n      cleanResourceMap   : cleanResourceMap\n    };\n  }\n  angular\n    .module('app')\n    .factory('FilterUtil', FilterUtil);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * PhraseUtil.js\n   *\n   * @ngInject\n   */\n  function PhraseUtil(TransStatusService, _) {\n\n    function getSaveButtonStatus(phrase) {\n      if (hasNoTranslation(phrase)) {\n        return TransStatusService.getStatusInfo('untranslated');\n      }\n      else if (hasEmptyTranslation(phrase)) {\n        return TransStatusService.getStatusInfo('needswork');\n      }\n      else if (hasTranslationChanged(phrase)) {\n        return TransStatusService.getStatusInfo('translated');\n      }\n      else {\n        return phrase.status;\n      }\n    }\n\n    function hasTranslationChanged(phrase) {\n      // on Firefox with input method turned on,\n      // when hitting tab it seems to turn undefined value into ''\n      var allSame = _.every(phrase.translations,\n        function(translation, index) {\n          return nullToEmpty(translation) ===\n            nullToEmpty(phrase.newTranslations[index]);\n        });\n      return !allSame;\n    }\n\n    function hasNoTranslation(phrase) {\n      return _.isEmpty(_.compact(phrase.newTranslations));\n    }\n\n    function hasEmptyTranslation(phrase) {\n      return _.compact(phrase.newTranslations).length !==\n        phrase.newTranslations.length;\n    }\n\n    function nullToEmpty(value) {\n      return value || '';\n    }\n\n    return {\n      getSaveButtonStatus  : getSaveButtonStatus,\n      hasTranslationChanged : hasTranslationChanged,\n      hasNoTranslation : hasNoTranslation,\n      hasEmptyTranslation : hasEmptyTranslation\n    };\n  }\n  angular\n    .module('app')\n    .factory('PhraseUtil', PhraseUtil);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * Utility method for handling $resource.statistic\n   *\n   * StatisticUtil.js\n   * @ngInject\n   *\n   */\n\n  function StatisticUtil() {\n    return {\n      getWordStatistic: function(statistics) {\n        return statistics[0].unit === 'WORD' ? statistics[0] : statistics[1];\n      },\n      getMsgStatistic: function(statistics) {\n        return statistics[0].unit === 'MESSAGE' ? statistics[0] : statistics[1];\n      }\n    };\n  }\n  angular\n    .module('app')\n    .factory('StatisticUtil', StatisticUtil);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * StringUtil\n   *\n   * @ngInject\n   */\n\n  function StringUtil() {\n    function startsWith(str, prefix, ignoreCase) {\n      if (ignoreCase && str && prefix) {\n        str = str.toUpperCase();\n        prefix = prefix.toUpperCase();\n      }\n      return str.lastIndexOf(prefix, 0) === 0;\n    }\n\n    function endsWith(str, suffix, ignoreCase) {\n      if (ignoreCase && str && suffix) {\n        str = str.toUpperCase();\n        suffix = suffix.toUpperCase();\n      }\n      return str.indexOf(suffix, str.length - suffix.length) !== -1;\n    }\n\n    function equals(from, to, ignoreCase) {\n      if (ignoreCase && from && to) {\n        from = from.toUpperCase();\n        to = to.toUpperCase();\n      }\n      return from === to;\n    }\n\n    return {\n      startsWith : startsWith,\n      endsWith   : endsWith,\n      equals     : equals\n    };\n  }\n  angular\n    .module('app')\n    .factory('StringUtil', StringUtil);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * Utility to handles URL related request.\n   *\n   * UrlService.js\n   * @ngInject\n   */\n  function UrlService($location, $http, $q, $stateParams, _) {\n    //IE doesn't support location.origin\n    if (!location.origin) {\n      location.origin =\n        window.location.protocol + '//' + window.location.hostname +\n        (window.location.port ? (':' + window.location.port) : '');\n    }\n\n    var urlService = this,\n      gravatarBaseUrl = 'http://www.gravatar.com/avatar',\n      configFile = 'config.json',\n      baseUrl = '',\n      urls = {},\n      uiTranslationsURL = location.origin + location.pathname +\n        'translations';\n\n    urlService.serverContextPath = '';\n\n    urlService.init = function () {\n      if (baseUrl) {\n        return $q.when(baseUrl);\n      }\n      else {\n        /**\n         * Temporary solution to handle dynamic context path deployed for\n         * Zanata server in JBOSS (/ or /zanata).\n         *\n         * If config.baseUrl exist and not empty,\n         * baseUrl = config.baseUrl\n         *\n         * ELSE\n         * baseUrl = full.url - appPath onwards\n         */\n        return $http.get(configFile).then(function (response) {\n          var config = response.data;\n          if (config.baseUrl) {\n            baseUrl = config.baseUrl;\n          } else {\n            var deployPath = config.appPath.replace(/^\\//g, ''),\n                index = location.href.indexOf(deployPath);\n\n            urlService.serverContextPath = location.origin + location.pathname;\n            if(index >= 0) {\n              urlService.serverContextPath = location.href.substring(0, index);\n            }\n            urlService.serverContextPath = urlService.serverContextPath.\n              replace(/\\/?$/, '/');\n            baseUrl = urlService.serverContextPath + 'rest';\n          }\n\n          /* jshint -W101 */\n          // URLs over multiple lines are hard to read, allowing long lines here.\n          // Warnings for jshint are turned off/on with -/+ before the warning code.\n          // See: https://github.com/jshint/jshint/blob/2.1.4/src/shared/messages.js\n          urls = _.mapValues({\n            project: '/project/:projectSlug',\n            docs: '/project/:projectSlug/version/:versionSlug/docs',\n            locales: '/project/:projectSlug/version/:versionSlug/locales',\n            status: '/project/:projectSlug/version/:versionSlug/doc/:docId/status/:localeId',\n            textFlows: '/source+trans/:localeId',\n            docStats: '/stats/project/:projectSlug/version/:versionSlug/doc/:docId/locale/:localeId',\n            myInfo: '/user',\n            userInfo: '/user/:username',\n            translation: '/trans/:localeId',\n            allLocales: '/locales',\n            suggestions: '/suggestions'\n          }, unary(restUrl));\n          /* jshint +W101 */\n\n          urlService.PROJECT_URL = urls.project;\n          urlService.LOCALE_LIST_URL = urls.locales;\n          urlService.DOCUMENT_LIST_URL = urls.docs;\n          urlService.TRANSLATION_STATUS_URL = urls.status;\n          urlService.TEXT_FLOWS_URL = urls.textFlows;\n          urlService.DOC_STATISTIC_URL = urls.docStats;\n          urlService.MY_INFO_URL = urls.myInfo;\n          urlService.USER_INFO_URL = urls.userInfo;\n          urlService.TRANSLATION_URL = urls.translation;\n          urlService.ALL_LOCALE_URL = urls.allLocales;\n          urlService.SUGGESTIONS_URL = urls.suggestions;\n\n          urlService.PROJECT_PAGE = function(projectSlug, versionSlug) {\n            return urlService.serverContextPath + 'iteration/view/' +\n              projectSlug + '/' +  versionSlug;\n          };\n\n          urlService.DASHBOARD_PAGE = urlService.serverContextPath +\n            'dashboard';\n        });\n      }\n    };\n\n    /**\n     * Get the value of a query string parameter.\n     */\n    urlService.readValue = function (key) {\n      return $location.search()[key];\n    };\n\n    urlService.gravatarUrl = function (gravatarHash, size) {\n      return gravatarBaseUrl + '/' + gravatarHash +\n        '?d=mm&r=g&s=' + size;\n    };\n\n    urlService.uiTranslationURL = function (locale) {\n      return uiTranslationsURL + '/' + locale + '.json';\n    };\n\n    urlService.uiTranslationListURL = uiTranslationsURL + '/locales';\n\n    return urlService;\n\n    /**\n     * Create a REST URL by appending all the given URL part arguments to the\n     * base URL.\n     *\n     * No separators will be added or removed, so all parts should include\n     * leading / and exclude trailing / to avoid problems.\n     */\n    function restUrl() {\n      return baseUrl + Array.prototype.join.call(arguments, '');\n    }\n\n    /**\n     * Decorate a function to ignore all but the first argument.\n     */\n    function unary(fun) {\n      return function(arg) {\n        return fun(arg);\n      };\n    }\n  }\n\n  angular\n    .module('app')\n    .factory('UrlService', UrlService);\n})();\n"],"sourceRoot":"/source/"}
\ No newline at end of file
+{"version":3,"sources":["app.js","AppConfig.js","AppConstants.js","AppCtrl.js","editor/EditorContentCtrl.js","editor/EditorCtrl.js","editor/EditorDetailsCtrl.js","editor/EditorService.js","editor/EditorShortcuts.js","editor/EditorSuggestionsCtrl.js","components/blur-on/blurOnDirective.js","components/clickElsewhere/clickElsewhereDirective.js","components/document/DocumentService.js","components/dropdown/DropdownController.js","components/dropdown/DropdownService.js","components/dropdown/dropdown.js","components/dropdown/dropdownDirective.js","components/event/EventService.js","components/icon/iconDirective.js","components/locale/LocaleService.js","components/logo-loader/logoLoaderDirective.js","components/message/MessageHandler.js","components/notification/NotificationService.js","components/phrases/PhraseCache.js","components/phrases/PhraseService.js","components/progressbar/progressbarDirective.js","components/project/ProjectService.js","components/renderWhitespaceCharacters/renderWhitespaceCharacters.js","components/resizer/resizerDirective.js","components/scrollbar-width/ScrollbarWidthCtrl.js","components/scrollbar-width/scrollbarWidthDirective.js","components/settings/SettingsService.js","components/suggestions/PhraseSuggestionsService.js","components/suggestions/SuggestionCtrl.js","components/suggestions/SuggestionsService.js","components/suggestions/TextSuggestionsService.js","components/suggestions/suggestionDirective.js","components/toggle/toggleDirective.js","components/transStatus/TransStatusService.js","components/transUnit/TransUnitCtrl.js","components/transUnit/TransUnitService.js","components/transUnit/transUnitDirective.js","components/transUnitFilter/transUnitFilterDirective.js","components/user/UserService.js","components/util/FilterUtil.js","components/util/PhraseUtil.js","components/util/StatisticUtil.js","components/util/StringUtil.js","components/util/UrlService.js"],"names":[],"mappings":"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","file":"app.js","sourcesContent":["(function() {\n  'use strict';\n\n  /**\n   * Root application\n   * app.js\n   */\n  angular.module(\n    'app', [\n      'ngResource',\n      'ngAnimate',\n      'ui.router',\n      'templates',\n      'cfp.hotkeys',\n      'focusOn',\n      'monospaced.elastic',\n      'gettext',\n      'diff-match-patch'\n    ]);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name AppConfig\n   * @description Main config for the entire app\n   * @ngInject\n   */\n  function AppConfig($stateProvider, $urlRouterProvider, $httpProvider,\n    hotkeysProvider) {\n\n    //Can't use injection for EventService as this module is out of the scope\n    var interceptor = function($q, $rootScope) {\n      return {\n        request: function(config) {\n          // See EventService.EVENT.LOADING_START\n          $rootScope.$broadcast('loadingStart');\n          return config;\n        },\n        requestError: function(rejection) {\n          // See EventService.EVENT.LOADING_STOP\n          $rootScope.$broadcast('loadingStop');\n          console.error('Request error due to ', rejection);\n          return $q.reject(rejection);\n        },\n        response: function(response) {\n          // See EventService.EVENT.LOADING_STOP\n          $rootScope.$broadcast('loadingStop');\n          return response || $q.when(response);\n        },\n        responseError: function(rejection) {\n          // See EventService.EVENT.LOADING_STOP\n          $rootScope.$broadcast('loadingStop');\n          if (rejection.status === 401) {\n            console.error('Unauthorized access. Please login');\n          } else if (rejection.status === 404) {\n            console.error('Service end point not found- ',\n              rejection.config.url);\n          } else {\n            console.error('Error in response ', rejection);\n          }\n          return $q.reject(rejection);\n        }\n      };\n    };\n\n    $httpProvider.interceptors.push(interceptor);\n\n    // For any unmatched url, redirect to /editor\n    $urlRouterProvider.otherwise('/');\n\n    $stateProvider\n      .state('editor', {\n        url: '/:projectSlug/:versionSlug/translate',\n        templateUrl: 'editor/editor.html',\n        controller: 'EditorCtrl as editor',\n        resolve: {\n          url : function(UrlService) {\n            return UrlService.init();\n          }\n        }\n      }).state('editor.selectedContext', {\n        url: '/:docId/:localeId',\n        views: {\n          'editor-content': {\n            templateUrl: 'editor/editor-content.html',\n            controller: 'EditorContentCtrl as editorContent'\n          },\n          'editor-suggestions': {\n            templateUrl: 'editor/editor-suggestions.html',\n            controller: 'EditorSuggestionsCtrl as editorSuggestions'\n          },\n          'editor-details': {\n            templateUrl: 'editor/editor-details.html',\n            controller: 'EditorDetailsCtrl as editorDetails'\n          }\n        }\n      }).state('editor.selectedContext.tu', {\n        url: '/?id&selected?states',\n        reloadOnSearch: false\n      });\n\n      hotkeysProvider.includeCheatSheet = false;\n\n  //   $locationProvider.html5Mode(true);\n  //     .hashPrefix('!');\n  }\n\n  angular\n    .module('app')\n    .config(AppConfig);\n\n})();\n\n\n\n","(function() {\n  'use strict';\n\n  /**\n   * AddConstants\n   * \"Global\" app variables. Don't worry David, they're not really global.\n   */\n  angular\n    .module('app')\n    .constant('_', window._)\n    .constant('str', window._.string)\n    .constant('Mousetrap', window.Mousetrap)\n    // Toggle to hide/show features that are ready for production\n    .constant('PRODUCTION', true);\n\n})();\n\n\n","(function() {\n  'use strict';\n\n  /**\n   * @name AppCtrl\n   * @description Main controler for the entire app\n   * @ngInject\n   */\n  function AppCtrl($scope, UserService, UrlService, LocaleService,\n                   MessageHandler, gettextCatalog, StringUtil, PRODUCTION) {\n    var appCtrl = this;\n\n    // See AppConstants.js\n    appCtrl.PRODUCTION = PRODUCTION;\n    appCtrl.settings = UserService.settings;\n    appCtrl.uiLocaleList = [ LocaleService.DEFAULT_LOCALE ];\n\n    /*\n      Not used for the time being. But should show loading when change state\n      $scope.$on('$stateChangeStart', function(event, toState) {\n        if (toState.resolve) {\n        }\n      });\n\n      $scope.$on('$stateChangeSuccess', function(event, toState) {\n        if (toState.resolve) {\n        }\n      });\n    */\n\n    UrlService.init().then(loadLocales).\n      then(loadUserInformation).\n      then(loadUILocale);\n\n    // On UI locale changes listener\n    appCtrl.onChangeUILocale = function(locale) {\n      appCtrl.myInfo.locale = locale;\n      var uiLocaleId = appCtrl.myInfo.locale.localeId;\n      if (!StringUtil.startsWith(uiLocaleId,\n        LocaleService.DEFAULT_LOCALE.localeId, true)) {\n        gettextCatalog.loadRemote(UrlService.uiTranslationURL(uiLocaleId))\n            .then(\n                function() {\n                  gettextCatalog.setCurrentLanguage(uiLocaleId);\n                },\n                function(error) {\n                  MessageHandler.displayInfo('Error loading UI locale. ' +\n                    'Default to \\'' + LocaleService.DEFAULT_LOCALE.name +\n                    '\\': ' + error);\n                  gettextCatalog.setCurrentLanguage(\n                    LocaleService.DEFAULT_LOCALE);\n                  appCtrl.myInfo.locale = LocaleService.DEFAULT_LOCALE;\n                });\n      } else {\n        gettextCatalog.setCurrentLanguage(\n          LocaleService.DEFAULT_LOCALE.localeId);\n      }\n    };\n\n    appCtrl.dashboardPage = function() {\n      return UrlService.DASHBOARD_PAGE;\n    };\n\n    function loadLocales() {\n      return LocaleService.getAllLocales();\n    }\n\n    function loadUserInformation() {\n      return UserService.getMyInfo().then(\n        function(myInfo) {\n          appCtrl.myInfo = myInfo;\n          appCtrl.myInfo.locale = LocaleService.DEFAULT_LOCALE;\n          appCtrl.myInfo.gravatarUrl = UrlService.gravatarUrl(\n            appCtrl.myInfo.gravatarHash, 72);\n        }, function(error) {\n          MessageHandler.displayError('Error loading my info: ' + error);\n        });\n    }\n\n    function loadUILocale() {\n      LocaleService.getUILocaleList().then(\n        function(translationList) {\n          for ( var i in translationList.locales) {\n            var language = {\n              'localeId' : translationList.locales[i],\n              'name' : ''\n            };\n            appCtrl.uiLocaleList.push(language);\n          }\n          appCtrl.myInfo.locale = LocaleService.getLocaleByLocaleId(\n            appCtrl.uiLocaleList, LocaleService.DEFAULT_LOCALE.localeId);\n          if (!appCtrl.myInfo.locale) {\n            appCtrl.myInfo.locale = LocaleService.DEFAULT_LOCALE;\n          }\n        },\n        function(error) {\n          MessageHandler.displayInfo('Error loading UI locale. ' +\n            'Default to \\'' + LocaleService.DEFAULT_LOCALE.name +\n            '\\': ' + error);\n          appCtrl.myInfo.locale = LocaleService.DEFAULT_LOCALE;\n        });\n    }\n  }\n\n  angular\n    .module('app')\n    .controller('AppCtrl', AppCtrl);\n\n})();\n\n\n\n","(function() {\n  'use strict';\n\n  /**\n   * EditorContentCtrl.js\n   * @ngInject\n   */\n  function EditorContentCtrl($rootScope, EditorService, PhraseService,\n                             DocumentService, UrlService, EventService,\n                             $stateParams, PhraseUtil, $location, _,\n                             TransStatusService) {\n\n    //TODO: move pager to directives/convert to infinite scroll\n    var COUNT_PER_PAGE = 50,\n        editorContentCtrl = this, status, filter;\n    refreshFilterQueryFromUrl();\n\n    editorContentCtrl.phrases = [];\n\n    EditorService.updateContext($stateParams.projectSlug,\n      $stateParams.versionSlug, DocumentService.decodeDocId($stateParams.docId),\n      $stateParams.localeId);\n\n    init();\n\n    $rootScope.$on(EventService.EVENT.FILTER_TRANS_UNIT,\n      function (event, filter) {\n        if(filter.status.all === true) {\n          $location.search('status', null);\n        } else {\n          var queries = [];\n          _.forEach(filter.status, function(val, key) {\n            if(val) {\n              queries.push(key);\n            }\n          });\n          $location.search('status', queries.join(','));\n        }\n        refreshFilterQueryFromUrl();\n        init();\n      });\n\n    function refreshFilterQueryFromUrl() {\n      status = UrlService.readValue('status');\n\n      if(!_.isUndefined(status)) {\n        status = status.split(',');\n        status = _.transform(status, function(result, state) {\n          state = TransStatusService.getServerId(state);\n          return result.push(state);\n        });\n      }\n      filter = {\n        'status': status\n      };\n    }\n\n\n    $rootScope.$on(EventService.EVENT.GOTO_FIRST_PAGE,\n      function () {\n        if(EditorService.currentPageIndex > 0) {\n          EditorService.currentPageIndex = 0;\n          changePage(EditorService.currentPageIndex);\n        }\n      });\n\n    $rootScope.$on(EventService.EVENT.GOTO_PREV_PAGE,\n      function () {\n        if(EditorService.currentPageIndex > 0) {\n          EditorService.currentPageIndex -= 1;\n          changePage(EditorService.currentPageIndex);\n        }\n      });\n\n    $rootScope.$on(EventService.EVENT.GOTO_NEXT_PAGE,\n      function () {\n        if(EditorService.currentPageIndex < EditorService.maxPageIndex) {\n          EditorService.currentPageIndex +=1;\n          changePage(EditorService.currentPageIndex);\n        }\n      });\n\n    $rootScope.$on(EventService.EVENT.GOTO_LAST_PAGE,\n      function () {\n        if(EditorService.currentPageIndex < EditorService.maxPageIndex) {\n          EditorService.currentPageIndex = EditorService.maxPageIndex;\n          changePage(EditorService.currentPageIndex);\n        }\n      });\n\n    /*\n      TODO: after moving to infinite scroll, all these go to event handler\n      should move back to TransUnitService and use PhraseService.findNextId etc\n     */\n    // EventService.EVENT.GOTO_NEXT_ROW listener\n    $rootScope.$on(EventService.EVENT.GOTO_NEXT_ROW, goToNextRow);\n\n    // EventService.EVENT.GOTO_PREVIOUS_ROW listener\n    $rootScope.$on(EventService.EVENT.GOTO_PREVIOUS_ROW, goToPreviousRow);\n\n    // EventService.EVENT.GOTO_NEXT_UNTRANSLATED listener\n    $rootScope.$on(EventService.EVENT.GOTO_NEXT_UNTRANSLATED,\n                   goToNextUntranslated);\n\n    function goToNextRow(event, data) {\n      var phrases = editorContentCtrl.phrases,\n        phrase,\n        currentIndex,\n        nextIndex,\n        nextId;\n\n      currentIndex = _.findIndex(phrases, function (phrase) {\n        return phrase.id === data.currentId;\n      });\n      nextIndex = Math.min(currentIndex + 1, phrases.length - 1);\n      nextId = phrases[nextIndex].id;\n\n      if (nextId !== data.currentId) {\n        EventService.emitEvent(EventService.EVENT.SELECT_TRANS_UNIT,\n                               {\n                                 'id': nextId,\n                                 'updateURL': true,\n                                 'focus': true\n                               }, null);\n      } else {\n        // we have reach the end\n        phrase = phrases[currentIndex];\n        EventService.emitEvent(EventService.EVENT.SAVE_TRANSLATION,\n           {\n             'phrase': phrase,\n             'status': PhraseUtil.getSaveButtonStatus(phrase),\n             'locale': $stateParams.localeId,\n             'docId': $stateParams.docId\n           });\n      }\n    }\n\n    function goToPreviousRow(event, data) {\n      var phrases = editorContentCtrl.phrases,\n        phrase,\n        currentIndex,\n        previousIndex,\n        prevId;\n\n      currentIndex = _.findIndex(phrases, function (phrase) {\n        return phrase.id === data.currentId;\n      });\n      previousIndex = Math.max(currentIndex - 1, 0);\n      prevId = phrases[previousIndex].id;\n\n      if (prevId !== data.currentId) {\n        EventService.emitEvent(EventService.EVENT.SELECT_TRANS_UNIT,\n                               {\n                                 'id': prevId,\n                                 'updateURL': true,\n                                 'focus': true\n                               }, null);\n      } else {\n        phrase = phrases[currentIndex];\n        // have reach the start\n        EventService.emitEvent(EventService.EVENT.SAVE_TRANSLATION,\n           {\n             'phrase': phrase,\n             'status': PhraseUtil.getSaveButtonStatus(phrase),\n             'locale': $stateParams.localeId,\n             'docId': $stateParams.docId\n           });\n      }\n    }\n\n    function goToNextUntranslated(event, data) {\n      var phrases = editorContentCtrl.phrases,\n        requestStatus = TransStatusService.getStatusInfo(status),\n        currentIndex,\n        nextStatusInfo;\n\n      currentIndex = _.findIndex(phrases, function (phrase) {\n        return phrase.id === data.currentId;\n      });\n\n      for (var i = currentIndex + 1; i < phrases.length; i++) {\n        nextStatusInfo = TransStatusService.getStatusInfo(\n          phrases[i].state);\n        if (nextStatusInfo.ID === requestStatus.ID) {\n          EventService.emitEvent(EventService.EVENT.SELECT_TRANS_UNIT,\n                                 {\n                                   'id': phrases[i].id,\n                                   'updateURL': true,\n                                   'focus': true\n                                 }, null);\n          return;\n        }\n      }\n      // can not find next untranslated\n      //TransUnitService.saveCurrentRowIfModifiedAndUnfocus(data);\n    }\n\n    function changePage(pageIndex) {\n      loadPhrase(pageIndex);\n      EventService.emitEvent(EventService.EVENT.CANCEL_EDIT);\n    }\n\n    /**\n     * Load transUnit\n     *\n     * @param projectSlug\n     * @param versionSlug\n     * @param docId\n     * @param localeId\n     */\n    function init() {\n      EventService.emitEvent(EventService.EVENT.REFRESH_STATISTIC,\n        {\n          projectSlug: EditorService.context.projectSlug,\n          versionSlug: EditorService.context.versionSlug,\n          docId: EditorService.context.docId,\n          localeId: EditorService.context.localeId\n        }\n      );\n\n      PhraseService.getPhraseCount(EditorService.context, filter).\n        then(function(count) {\n          EditorService.maxPageIndex = parseInt(count / COUNT_PER_PAGE);\n          if(count > COUNT_PER_PAGE) {\n            EditorService.maxPageIndex = count % COUNT_PER_PAGE !== 0 ?\n              EditorService.maxPageIndex +=1 : EditorService.maxPageIndex;\n          }\n\n          EditorService.maxPageIndex =  EditorService.maxPageIndex -1 < 0 ? 0 :\n            EditorService.maxPageIndex -1;\n\n          loadPhrase(EditorService.currentPageIndex);\n      });\n    }\n\n    function loadPhrase(pageIndex) {\n      var startIndex = pageIndex * COUNT_PER_PAGE;\n      PhraseService.fetchAllPhrase(EditorService.context, filter,\n        startIndex, COUNT_PER_PAGE).then(displayPhrases);\n    }\n\n    function displayPhrases(phrases) {\n      editorContentCtrl.phrases = phrases;\n    }\n\n    return editorContentCtrl;\n  }\n\n  angular\n    .module('app')\n    .controller('EditorContentCtrl', EditorContentCtrl);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * EditorCtrl.js\n   * @ngInject\n   */\n  function EditorCtrl($scope, UserService, DocumentService, LocaleService,\n    ProjectService, EditorService, SettingsService, StatisticUtil,\n    UrlService, $stateParams, $state, MessageHandler, $rootScope,\n    EventService, EditorShortcuts, _, Mousetrap) {\n    var editorCtrl = this;\n    editorCtrl.pageNumber = 1;\n    editorCtrl.showCheatsheet = false;\n    editorCtrl.shortcuts = _.mapValues(\n      _.values(EditorShortcuts.SHORTCUTS), function(shortcutInfo) {\n        // second combo (secondary keys) is an array. We have to flatten it\n        var keyCombos = _.flatten(shortcutInfo.keyCombos, 'combo');\n        return {\n        combos: _.map(keyCombos, function(key) {\n          return EditorShortcuts.symbolizeKey(key);\n        }),\n        description: shortcutInfo.keyCombos[0].description\n      };\n    });\n\n    //tu status to include for display\n    editorCtrl.filter = {\n      'status' : {\n        'all': true,\n        'approved' : false,\n        'translated' : false,\n        'needsWork': false,\n        'untranslated': false\n      }\n    };\n\n    processFilterQuery();\n\n    //This is just processing UI during startup,\n    //phrase filtering are done in EditorContentCtrl during init\n    function processFilterQuery() {\n      //process filter query\n      var status = UrlService.readValue('status');\n\n      if(!_.isUndefined(status)) {\n        status = status.split(',');\n        _.forEach(status, function(val) {\n          if(!_.isUndefined(editorCtrl.filter.status[val])) {\n            editorCtrl.filter.status[val] = true;\n          }\n        });\n        updateFilter();\n      }\n    }\n\n    Mousetrap.bind('?', function(event) {\n      var srcElement = event.srcElement;\n      if (!editorCtrl.showCheatsheet && !stopCheatsheetCallback(srcElement)) {\n        editorCtrl.toggleKeyboardShortcutsModal();\n        $scope.$digest();\n      }\n    }, 'keyup');\n\n    /**\n     * Mousetrap by default stops callback on input elements BUT\n     * hotkeys monkey patched it!!!\n     * TODO change this hack once we remove angular hotkeys\n     */\n    function stopCheatsheetCallback(element) {\n      // if the element has the class \"mousetrap\" then no need to stop\n      if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {\n        return false;\n      }\n\n      // stop for input, select, and textarea\n      return element.tagName === 'INPUT' || element.tagName === 'SELECT' ||\n        element.tagName === 'TEXTAREA' || element.isContentEditable;\n    }\n\n    //TODO: cross domain rest\n    //TODO: Unit test\n\n    //Working URL: http://localhost:8000/#/tiny-project/1/translate or\n    // http://localhost:8000/#/tiny-project/1/translate/hello.txt/fr\n    editorCtrl.context = EditorService.initContext($stateParams.projectSlug,\n      $stateParams.versionSlug, DocumentService.decodeDocId($stateParams.docId),\n      LocaleService.DEFAULT_LOCALE, LocaleService.DEFAULT_LOCALE.localeId,\n      'READ_WRITE');\n\n    editorCtrl.toggleKeyboardShortcutsModal = function() {\n      editorCtrl.showCheatsheet = !editorCtrl.showCheatsheet;\n    };\n\n    var SHOW_SUGGESTIONS = SettingsService.SETTING.SHOW_SUGGESTIONS;\n    $scope.showSuggestions = SettingsService.subscribe(SHOW_SUGGESTIONS,\n      function (show) {\n        $scope.showSuggestions = show;\n      });\n    editorCtrl.toggleSuggestionPanel = function () {\n      SettingsService.update(SHOW_SUGGESTIONS, !$scope.showSuggestions);\n    };\n\n\n    editorCtrl.versionPage = function() {\n      return UrlService.PROJECT_PAGE(editorCtrl.context.projectSlug,\n        editorCtrl.context.versionSlug);\n    };\n\n    editorCtrl.encodeDocId = function(docId) {\n      return DocumentService.encodeDocId(docId);\n    };\n\n    ProjectService.getProjectInfo($stateParams.projectSlug).then(\n      function(projectInfo) {\n        editorCtrl.projectInfo = projectInfo;\n      },\n      function(error) {\n        MessageHandler.displayError('Error getting project ' +\n          'information:' + error);\n      });\n\n    LocaleService.getSupportedLocales(editorCtrl.context.projectSlug,\n      editorCtrl.context.versionSlug).then(\n      function(locales) {\n        editorCtrl.locales = locales;\n        if (!editorCtrl.locales || editorCtrl.locales.length <= 0) {\n          //redirect if no supported locale in version\n          MessageHandler.displayError('No supported locales in ' +\n            editorCtrl.context.projectSlug + ' : ' +\n            editorCtrl.context.versionSlug);\n        } else {\n          //if localeId is not defined in url, set to first from list\n          var selectedLocaleId = $state.params.localeId;\n          var context = editorCtrl.context;\n\n          if (!selectedLocaleId) {\n            context.localeId = editorCtrl.locales[0].localeId;\n            transitionToEditorSelectedView();\n          } else {\n            context.localeId = selectedLocaleId;\n            if (!LocaleService.containsLocale(editorCtrl.locales,\n              selectedLocaleId)) {\n              context.localeId = editorCtrl.locales[0].localeId;\n            }\n          }\n        }\n      }, function(error) {\n        MessageHandler.displayError('Error getting locale list: ' + error);\n      });\n\n    DocumentService.findAll(editorCtrl.context.projectSlug,\n      editorCtrl.context.versionSlug).then(\n      function(documents) {\n        editorCtrl.documents = documents;\n\n        if (!editorCtrl.documents || editorCtrl.documents.length <= 0) {\n          //redirect if no documents in version\n          MessageHandler.displayError('No documents in ' +\n            editorCtrl.context.projectSlug + ' : ' +\n            editorCtrl.context.versionSlug);\n        } else {\n          //if docId is not defined in url, set to first from list\n          var selectedDocId = $state.params.docId,\n              context = editorCtrl.context;\n          if (!selectedDocId) {\n            context.docId = editorCtrl.documents[0].name;\n            transitionToEditorSelectedView();\n          } else {\n            context.docId = DocumentService.decodeDocId(selectedDocId);\n            if (!DocumentService.containsDoc(editorCtrl.documents,\n              context.docId)) {\n              context.docId = editorCtrl.documents[0].name;\n            }\n          }\n        }\n      }, function(error) {\n        MessageHandler.displayError('Error getting document list: ' + error);\n      });\n\n    $rootScope.$on(EventService.EVENT.SELECT_TRANS_UNIT,\n      function (event, data) {\n        editorCtrl.unitSelected = data.id;\n        editorCtrl.focused = data.focus;\n      });\n\n    $rootScope.$on(EventService.EVENT.CANCEL_EDIT,\n      function () {\n        editorCtrl.unitSelected = false;\n        editorCtrl.focused = false;\n      });\n\n    $rootScope.$on(EventService.EVENT.REFRESH_STATISTIC,\n      function (event, data) {\n\n        loadStatistic(data.projectSlug, data.versionSlug, data.docId,\n          data.localeId);\n\n        editorCtrl.context.docId = data.docId;\n        editorCtrl.context.localeId = data.localeId;\n      });\n\n    editorCtrl.pageNumber = function() {\n      if(EditorService.maxPageIndex === 0) {\n        return EditorService.currentPageIndex + 1;\n      } else {\n        return (EditorService.currentPageIndex + 1) + ' of ' +\n          (EditorService.maxPageIndex + 1);\n      }\n    };\n\n    editorCtrl.getLocaleName = function(localeId) {\n      return LocaleService.getName(localeId);\n    };\n\n    editorCtrl.firstPage = function() {\n      EventService.emitEvent(EventService.EVENT.GOTO_FIRST_PAGE);\n    };\n\n    editorCtrl.lastPage = function() {\n      EventService.emitEvent(EventService.EVENT.GOTO_LAST_PAGE);\n    };\n\n\n    editorCtrl.nextPage = function() {\n      EventService.emitEvent(EventService.EVENT.GOTO_NEXT_PAGE);\n    };\n\n    editorCtrl.previousPage = function() {\n      EventService.emitEvent(EventService.EVENT.GOTO_PREV_PAGE);\n    };\n\n    editorCtrl.resetFilter = function() {\n      resetFilter(true);\n    };\n\n    editorCtrl.updateFilter = function() {\n      updateFilter(true);\n    };\n\n    function updateFilter(fireEvent) {\n      if(isStatusSame(editorCtrl.filter.status)) {\n        resetFilter(fireEvent);\n      } else {\n        editorCtrl.filter.status.all = false;\n        if(fireEvent) {\n          EventService.emitEvent(EventService.EVENT.FILTER_TRANS_UNIT,\n            editorCtrl.filter);\n        }\n      }\n    }\n\n    function resetFilter(fireEvent) {\n      editorCtrl.filter.status.all = true;\n      editorCtrl.filter.status.approved = false;\n      editorCtrl.filter.status.translated = false;\n      editorCtrl.filter.status.needsWork = false;\n      editorCtrl.filter.status.untranslated = false;\n\n      if(fireEvent) {\n        EventService.emitEvent(EventService.EVENT.FILTER_TRANS_UNIT,\n          editorCtrl.filter);\n      }\n    }\n\n    function isStatusSame(statuses) {\n      return statuses.approved === statuses.translated &&\n        statuses.translated === statuses.needsWork &&\n        statuses.needsWork === statuses.untranslated;\n    }\n\n    function transitionToEditorSelectedView() {\n      if (isDocumentAndLocaleSelected()) {\n        $state.go('editor.selectedContext', {\n          'docId': editorCtrl.context.docId,\n          'localeId': editorCtrl.context.localeId\n        });\n      }\n    }\n\n    function isDocumentAndLocaleSelected() {\n      return editorCtrl.context.docId && editorCtrl.context.localeId;\n    }\n\n    /**\n     * Load document statistics (word and message)\n     *\n     * @param projectSlug\n     * @param versionSlug\n     * @param docId\n     * @param localeId\n     */\n    function loadStatistic(projectSlug, versionSlug, docId, localeId) {\n      DocumentService.getStatistics(projectSlug, versionSlug, docId, localeId)\n        .then(function(statistics) {\n            editorCtrl.wordStatistic = StatisticUtil\n              .getWordStatistic(statistics);\n            editorCtrl.messageStatistic = StatisticUtil\n              .getMsgStatistic(statistics);\n          },\n          function(error) {\n            MessageHandler.displayError('Error loading statistic: ' + error);\n          });\n    }\n\n    this.settings = UserService.settings.editor;\n\n    EditorShortcuts.enableEditorKeys();\n  }\n\n  angular\n    .module('app')\n    .controller('EditorCtrl', EditorCtrl);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * EditorDetailsCtrl.js\n   * @ngInject\n   */\n  function EditorDetailsCtrl() {\n    var editorDetailsCtrl = this;\n\n    return editorDetailsCtrl;\n  }\n\n  angular\n    .module('app')\n    .controller('EditorDetailsCtrl', EditorDetailsCtrl);\n})();\n","(function () {\n  'use strict';\n\n  /**\n   * EditorService.js\n   * //TODO: parse editorContext in functions\n   * @ngInject\n   */\n  function EditorService($rootScope, $resource, _, UrlService,\n    EventService, PhraseService, PhraseUtil, DocumentService, MessageHandler,\n    TransStatusService) {\n    var editorService = this,\n        queue = {};\n\n    editorService.context = {};\n\n    editorService.currentPageIndex = 0;\n    editorService.maxPageIndex = 0;\n\n    editorService.initContext =\n      function (projectSlug, versionSlug, docId, srcLocale, localeId, mode) {\n        editorService.context = {\n          projectSlug: projectSlug,\n          versionSlug: versionSlug,\n          docId: docId,\n          srcLocale: srcLocale,\n          localeId: localeId,\n          mode: mode // READ_WRITE, READ_ONLY, REVIEW\n        };\n        return editorService.context;\n      };\n\n    editorService.updateContext = function(projectSlug, versionSlug, docId,\n                                           localeId) {\n      if(editorService.context.projectSlug !== projectSlug) {\n        editorService.context.projectSlug = projectSlug;\n      }\n      if(editorService.context.versionSlug !== versionSlug) {\n        editorService.context.versionSlug = versionSlug;\n      }\n      if(editorService.context.docId !== docId) {\n        editorService.context.docId = docId;\n      }\n      if(editorService.context.localeId !== localeId) {\n        editorService.context.localeId = localeId;\n      }\n    };\n\n    /**\n     * EventService.EVENT.SAVE_TRANSLATION listener\n     * Perform save translation with given status\n     *\n     * - queue save translation request (1 global queue, 1 for each TU)\n     * - if queue contains request id, replace old request with new request\n     */\n    $rootScope.$on(EventService.EVENT.SAVE_TRANSLATION,\n      function (event, data) {\n        var phrase = data.phrase,\n            status = data.status;\n        if (!needToSavePhrase(phrase, status)) {\n          // nothing has changed\n          return;\n        }\n\n        //update pending queue if contains\n        if (_.has(queue, phrase.id)) {\n          var pendingRequest = queue[phrase.id];\n          pendingRequest.phrase = phrase;\n          pendingRequest.status = status;\n        } else {\n          status = resolveTranslationState(phrase, status);\n          queue[phrase.id] = {\n            'phrase': phrase,\n            'status': status,\n            'locale': data.locale,\n            'docId': data.docId\n          };\n        }\n        EventService.emitEvent(EventService.EVENT.SAVE_INITIATED, data);\n        processSaveRequest(phrase.id);\n      });\n\n    function needToSavePhrase(phrase, status) {\n      return PhraseUtil.hasTranslationChanged(phrase) ||\n        phrase.status !== status;\n    }\n\n    // Process save translation request\n    function processSaveRequest(id) {\n      var context = _.cloneDeep(editorService.context);\n\n      var request = queue[id];\n\n      var Translation = $resource(UrlService.TRANSLATION_URL, {}, {\n        update: {\n          method: 'PUT',\n          params: {\n            localeId: request.locale\n          }\n        }\n      });\n      var data = {\n        id: request.phrase.id,\n        revision: request.phrase.revision || 0,\n        content: request.phrase.newTranslations[0],\n        contents: request.phrase.newTranslations,\n        // Return status object to PascalCase Id for the server\n        status: TransStatusService.getServerId(request.status.ID),\n        plural: request.phrase.plural\n      };\n\n      Translation.update(data).$promise.then(\n        function(response) {\n          var oldStatus =  request.phrase.status.ID;\n\n          PhraseService.onTransUnitUpdated(context, data.id, request.locale,\n            response.revision, response.status, request.phrase);\n\n          DocumentService.updateStatistic(context.projectSlug,\n            context.versionSlug, request.docId, request.locale,\n            oldStatus, TransStatusService.getId(response.status),\n            request.phrase.wordCount);\n\n          EventService.emitEvent(EventService.EVENT.SAVE_COMPLETED,\n            request.phrase);\n        },\n        function(response) {\n          MessageHandler.displayWarning('Update translation failed for ' +\n            data.id + ' -' + response);\n          PhraseService.onTransUnitUpdateFailed(data.id);\n          EventService.emitEvent(EventService.EVENT.SAVE_COMPLETED,\n            request.phrase);\n        });\n      delete queue[id];\n    }\n\n    function resolveTranslationState(phrase, requestStatus) {\n      if (_.isEmpty(_.compact(phrase.newTranslations))) {\n        return TransStatusService.getStatusInfo('UNTRANSLATED');\n      }\n      return requestStatus;\n    }\n\n    return editorService;\n  }\n\n  angular\n    .module('app')\n    .factory('EditorService', EditorService);\n\n})();\n\n","(function () {\n  'use strict';\n\n  /**\n   * @name EditorShortcuts\n   * @description service for editor keyboard shortcuts\n   * @ngInject\n   */\n  function EditorShortcuts(EventService, $stateParams, _, hotkeys, PhraseUtil,\n                           TransStatusService, Mousetrap, str, $window) {\n    var editorShortcuts = this,\n      inSaveAsMode = false;\n\n    // this will be set by TransUnitService\n    // on EVENT.SELECT_TRANS_UNIT and unset on EVENT.CANCEL_EDIT\n    editorShortcuts.selectedTUCtrl = null;\n\n    function copySourceCallback(event) {\n      if (editorShortcuts.selectedTUCtrl) {\n        event.preventDefault();\n        EventService.emitEvent(EventService.EVENT.COPY_FROM_SOURCE,\n          {'phrase': editorShortcuts.selectedTUCtrl.getPhrase()});\n      }\n    }\n\n    function gotoNextRowCallback(event) {\n      if (editorShortcuts.selectedTUCtrl) {\n        event.preventDefault();\n        event.stopPropagation();\n        EventService.emitEvent(EventService.EVENT.GOTO_NEXT_ROW,\n          currentContext());\n      }\n    }\n\n    function gotoPreviousRowCallback(event) {\n      if (editorShortcuts.selectedTUCtrl) {\n        event.preventDefault();\n        event.stopPropagation();\n        EventService.emitEvent(EventService.EVENT.GOTO_PREVIOUS_ROW,\n          currentContext());\n      }\n    }\n\n    function cancelEditCallback(event) {\n      event.preventDefault();\n      event.stopPropagation();\n      if (inSaveAsMode) {\n        editorShortcuts.cancelSaveAsModeIfOn();\n        if (editorShortcuts.selectedTUCtrl) {\n          editorShortcuts.selectedTUCtrl.focusTranslation();\n        }\n      } else if (editorShortcuts.selectedTUCtrl) {\n        var phrase = editorShortcuts.selectedTUCtrl.getPhrase();\n        if (PhraseUtil.hasTranslationChanged(phrase)) {\n          // if it has changed translation, undo edit\n          EventService.emitEvent(EventService.EVENT.UNDO_EDIT,\n            phrase);\n        } else {\n          // otherwise cancel edit\n          EventService.emitEvent(EventService.EVENT.CANCEL_EDIT,\n            phrase);\n        }\n      }\n    }\n\n    function saveAsCurrentButtonOptionCallback(event) {\n      if (editorShortcuts.selectedTUCtrl) {\n        event.preventDefault();\n        var phrase = editorShortcuts.selectedTUCtrl.getPhrase();\n        EventService.emitEvent(EventService.EVENT.SAVE_TRANSLATION,\n          {\n            'phrase': phrase,\n            'status': PhraseUtil.getSaveButtonStatus(phrase),\n            'locale': $stateParams.localeId,\n            'docId': $stateParams.docId\n          });\n      }\n    }\n\n    /**\n     * This is to mimic sequence shortcut.\n     * e.g. press ctlr-shift-s then press 'n' to save as\n     * 'needs work'.\n     */\n    function saveAsModeCallback(event) {\n      event.preventDefault();\n      editorShortcuts.cancelSaveAsModeIfOn();\n      var phrase = editorShortcuts.selectedTUCtrl.getPhrase();\n      if (phrase) {\n        EventService.emitEvent(EventService.EVENT.TOGGLE_SAVE_OPTIONS,\n          {\n            'id': phrase.id,\n            'open': true\n          });\n\n        addSaveAsModeExtensionKey(phrase, 'n', 'needsWork');\n        addSaveAsModeExtensionKey(phrase, 't', 'translated');\n        addSaveAsModeExtensionKey(phrase, 'a', 'approved');\n      }\n    }\n\n    /**\n     * Generate a callback that will copy one of the suggestions to the editor.\n     *\n     * @param {number} oneBasedIndex the 1-based index of the suggestion that\n     *                               this callback will copy\n     * @return {function} callback that will copy the nth suggestion.\n     */\n    function copySuggestionCallback(oneBasedIndex) {\n      return (function (event) {\n        event.preventDefault();\n        EventService.emitEvent(EventService.EVENT.COPY_FROM_SUGGESTION_N,\n          oneBasedIndex-1);\n      });\n    }\n\n    /**\n     * mod will be replaced by ctrl if on windows/linux or cmd if on mac.\n     * By default it listens on keydown event.\n     */\n    editorShortcuts.SHORTCUTS = {\n      COPY_SOURCE: new ShortcutInfo(\n        'alt+c', copySourceCallback, 'Copy source as translation', 'alt+g'),\n\n      COPY_SUGGESTION_1: new ShortcutInfo(\n        'mod+alt+1', copySuggestionCallback(1),\n        'Copy first suggestion as translation'),\n\n      COPY_SUGGESTION_2: new ShortcutInfo(\n        'mod+alt+2', copySuggestionCallback(2),\n        'Copy second suggestion as translation'),\n\n      COPY_SUGGESTION_3: new ShortcutInfo(\n        'mod+alt+3', copySuggestionCallback(3),\n        'Copy third suggestion as translation'),\n\n      COPY_SUGGESTION_4: new ShortcutInfo(\n        'mod+alt+4', copySuggestionCallback(4),\n        'Copy fourth suggestion as translation'),\n\n      CANCEL_EDIT: new ShortcutInfo('esc', cancelEditCallback, 'Cancel edit'),\n\n      SAVE_AS_CURRENT_BUTTON_OPTION: new ShortcutInfo(\n        'mod+s', saveAsCurrentButtonOptionCallback, 'Save'),\n\n      SAVE_AS_MODE: new ShortcutInfo(\n        'mod+shift+s', saveAsModeCallback, 'Save as…'),\n\n      // this is just so we can show it in cheatsheet.\n      // see app/editor/EditorCtrl.shortcuts\n      SAVE_AS_NEEDSWORK: {\n        keyCombos: [{combo: 'mod+shift+s n', description: 'Save as needs work'}]\n      },\n\n      SAVE_AS_TRANSLATED: {\n        keyCombos: [{combo: 'mod+shift+s t', description: 'Save as translated'}]\n      },\n\n      SAVE_AS_APPROVED: {\n        keyCombos: [{combo: 'mod+shift+s a', description: 'Save as approved'}]\n      },\n\n      GOTO_NEXT_ROW_FAST: new ShortcutInfo(\n        'mod+enter', gotoNextRowCallback,\n        'Save (if changed) and go to next string',\n        ['alt+k', 'alt+down']),\n\n      GOTO_PREVIOUS_ROW: new ShortcutInfo(\n        'mod+shift+enter', gotoPreviousRowCallback,\n        'Save (if changed) and go to previous string',\n        ['alt+j', 'alt+up'])\n        /*\n         Disable for now until status navigation implementation\n         GOTO_NEXT_UNTRANSLATED: new ShortcutInfo(\n        'tab+u', gotoToNextUntranslatedCallback)\n        */\n    };\n\n    /*\n     Disable for now until status navigation implementation\n\n     function gotoToNextUntranslatedCallback(event) {\n     event.preventDefault();\n     event.stopPropagation();\n     if (editorShortcuts.selectedTUCtrl) {\n     EventService.emitEvent(EventService.EVENT.GOTO_NEXT_UNTRANSLATED,\n     currentContext());\n     }\n     // the shortcut is a tab + u combination\n     // we don't want other tab event to trigger\n     tabCombinationPressed = true;\n     }\n     */\n\n    /**\n     *\n     * @param {string} defaultKey default key combo for a shortcut\n     * @param {function} callback callback to execute\n     * @param {string} [description]\n     *  optional. If not empty will apply to default key (shows in cheatsheet)\n     * @param {(string|string[])} [otherKeys]\n     *  optional other keys that will do the same (won't show in cheatsheet)\n     * @param {string} [action] optional event to listen to. e.g. 'keyup'\n     * @returns {EditorShortcuts.ShortcutInfo}\n     * @constructor\n     */\n    function ShortcutInfo(defaultKey, callback, description, otherKeys, action)\n    {\n      this.defaultKey = defaultKey;\n      this.keyCombos = [\n        singleKeyConfig(defaultKey, description, action, callback)\n      ];\n      if (otherKeys) {\n        this.otherKeys = otherKeys instanceof Array ? otherKeys : [otherKeys];\n        this.keyCombos.push(\n          singleKeyConfig(this.otherKeys, '', action, callback));\n      }\n      return this;\n    }\n\n    function singleKeyConfig(combo, description, action, callback) {\n      var keyConfig = {\n        allowIn: ['TEXTAREA'],\n        callback: callback\n      };\n      keyConfig.combo = combo;\n      if (description) {\n        keyConfig.description = description;\n      }\n      if (action) {\n        keyConfig.action = action;\n      }\n      return keyConfig;\n    }\n\n    editorShortcuts.enableEditorKeys = function () {\n      // here we only check copy source shortcut since we always enable keys in\n      // bundle.\n      if (!hotkeys.get(editorShortcuts.SHORTCUTS.COPY_SOURCE.defaultKey)) {\n        _.forOwn(editorShortcuts.SHORTCUTS, function(value) {\n          if (value instanceof ShortcutInfo) { // a hack to handle sequence keys\n            enableShortcut(value);\n          }\n        });\n      }\n    };\n\n    editorShortcuts.disableEditorKeys = function () {\n      _.forOwn(editorShortcuts.SHORTCUTS, function(value) {\n        _.forEach(value.keyCombos, function(hotkey) {\n          editorShortcuts.deleteKeys(hotkey.combo, hotkey.action);\n        });\n      });\n    };\n\n    function enableShortcut(shortcutInfo) {\n      if (!hotkeys.get(shortcutInfo.defaultKey)) {\n        _.forEach(shortcutInfo.keyCombos,\n          function(combo) {\n            hotkeys.add(combo);\n          });\n      }\n    }\n\n    function currentContext() {\n      return {\n        'currentId': editorShortcuts.selectedTUCtrl.getPhrase().id\n      };\n    }\n\n    function addSaveAsModeExtensionKey(phrase, combo, status) {\n      var statusInfo = TransStatusService.getStatusInfo(status);\n      return hotkeys.add({\n        combo: combo,\n        description: str.sprintf('Save as %s', status),\n        allowIn: ['INPUT', 'TEXTAREA'],\n        action: 'keydown',\n        callback: function (event) {\n          editorShortcuts.saveTranslationCallBack(event, phrase, statusInfo);\n        }\n      });\n    }\n\n    editorShortcuts.saveTranslationCallBack = function(event, phrase,\n                                                       statusInfo) {\n      inSaveAsMode = true;\n\n      event.preventDefault();\n      event.stopPropagation();\n\n      EventService.emitEvent(EventService.EVENT.SAVE_TRANSLATION,\n        {\n          'phrase': phrase,\n          'status': statusInfo,\n          'locale': $stateParams.localeId,\n          'docId': $stateParams.docId\n        });\n      editorShortcuts.cancelSaveAsModeIfOn();\n    };\n\n    editorShortcuts.cancelSaveAsModeIfOn = function() {\n      if (inSaveAsMode && editorShortcuts.selectedTUCtrl) {\n        inSaveAsMode = false;\n        editorShortcuts.deleteKeys(['n', 't', 'a']);\n        EventService.emitEvent(EventService.EVENT.TOGGLE_SAVE_OPTIONS,\n          {\n            'id': editorShortcuts.selectedTUCtrl.getPhrase().id,\n            'open': false\n          });\n      }\n    };\n\n    /**\n     * This is a workaround for augular-hotkeys not being able to delete hotkey.\n     * @see https://github.com/chieffancypants/angular-hotkeys/issues/100\n     *\n     * @param {(string|string[])} keys single key or array of keys to be deleted\n     * @param {string} [action='keydown'] 'keyup' or 'keydown' etc.\n     */\n    editorShortcuts.deleteKeys = function(keys, action) {\n      var keysToDelete = keys instanceof Array ? keys : [keys];\n      action = action || 'keydown';\n      _.forEach(keysToDelete, function(key) {\n        hotkeys.del(key);\n        Mousetrap.unbind(key, action);\n      });\n    };\n\n    /**\n     * Copied from angular-hotkeys.\n     * Convert strings like cmd into symbols like ⌘\n     * @param  {String} combo Key combination, e.g. 'mod+f'\n     * @return {String} The key combination with symbols\n     */\n    editorShortcuts.symbolizeKey = function (combo) {\n      var map = {\n        command: '⌘',\n        shift: '⇧',\n        left: '←',\n        right: '→',\n        up: '↑',\n        down: '↓',\n        'return': '↩',\n        backspace: '⌫'\n      };\n      combo = combo.split('+');\n\n      for (var i = 0; i < combo.length; i++) {\n        // try to resolve command / ctrl based on OS:\n        if (combo[i] === 'mod') {\n          if ($window.navigator &&\n            $window.navigator.platform.indexOf('Mac') >= 0) {\n            combo[i] = 'command';\n          } else {\n            combo[i] = 'ctrl';\n          }\n        }\n\n        combo[i] = map[combo[i]] || combo[i];\n      }\n\n      return combo.join(' + ');\n    };\n\n    return editorShortcuts;\n  }\n\n  angular\n    .module('app')\n    .factory('EditorShortcuts', EditorShortcuts);\n})();\n\n","(function() {\n  'use strict';\n\n  /**\n   * EditorSuggestionsCtrl.js\n   * @ngInject\n   */\n  function EditorSuggestionsCtrl($scope, _, SettingsService,\n      PhraseSuggestionsService, TextSuggestionsService, EventService,\n      $rootScope, $timeout, focus) {\n    var SHOW_SUGGESTIONS_SETTING = SettingsService.SETTING.SHOW_SUGGESTIONS;\n    var SUGGESTIONS_SHOW_DIFFERENCE_SETTING =\n      SettingsService.SETTING.SUGGESTIONS_SHOW_DIFFERENCE;\n\n    var editorSuggestionsCtrl = this;\n\n    $scope.suggestions = [];\n    $scope.hasSuggestions = false;\n    $scope.$watch('suggestions.length', function (length) {\n      $scope.hasSuggestions = length !== 0;\n    });\n\n    /* @type {string[]} */\n    $scope.searchStrings = [];\n    $scope.hasSearch = false;\n    $scope.$watch('searchStrings.length', function (length) {\n      $scope.hasSearch = length !== 0;\n    });\n\n    // TODO initialize with current trans unit selection state.\n    $scope.isTransUnitSelected = false;\n\n    // These must always be opposites. Probably change to an enum.\n    $scope.isTextSearch = false;\n    $scope.isPhraseSearch = true;\n\n    function setTextSearch(active) {\n      $scope.isTextSearch = active;\n      $scope.isPhraseSearch = !active;\n    }\n\n    $scope.search = {\n      isVisible: false,\n      isLoading: false,\n      input: {\n        text: '',\n        focused: false\n      }\n    };\n\n    $scope.$watch('search.input.text', function () {\n      editorSuggestionsCtrl.searchForText();\n    });\n\n    $scope.show = SettingsService.subscribe(SHOW_SUGGESTIONS_SETTING,\n      function (show) {\n        $scope.show = show;\n\n        if (show) {\n          if ($scope.isTransUnitSelected) {\n            updatePhraseDisplay();\n          } else {\n            if (!$scope.search.isVisible) {\n              showSearch(null, true);\n            }\n          }\n        }\n\n      });\n\n    $scope.diff = SettingsService.subscribe(SUGGESTIONS_SHOW_DIFFERENCE_SETTING,\n      function (diff) {\n        $scope.diff = diff;\n      });\n\n    $scope.focusSearch = function($event) {\n      if ($event) {\n        $event.preventDefault();\n      }\n      focus('searchSugInput');\n    };\n\n    editorSuggestionsCtrl.closeSuggestions = function () {\n      SettingsService.update(SHOW_SUGGESTIONS_SETTING, false);\n      EventService.emitEvent(EventService.EVENT.SUGGESTIONS_SEARCH_TOGGLE,\n        false);\n    };\n\n    editorSuggestionsCtrl.clearSearchResults =\n      function($event, dontFocusInput) {\n        // just remove the text, service will handle updating to empty results.\n        $scope.search.input.text = '';\n\n        if (!dontFocusInput && $event) {\n          $scope.focusSearch($event);\n        }\n      };\n\n    editorSuggestionsCtrl.searchForText = function () {\n      var newText = $scope.search.input.text;\n      if (newText.length > 0) {\n        $scope.search.isLoading = true;\n      }\n      setTextSearch(true);\n      EventService.emitEvent(EventService.EVENT.REQUEST_TEXT_SUGGESTIONS,\n        newText);\n    };\n\n    editorSuggestionsCtrl.toggleSearch = function() {\n      if ($scope.search.isVisible) {\n        EventService.emitEvent(EventService.EVENT.SUGGESTIONS_SEARCH_TOGGLE,\n          false);\n      }\n      else {\n        EventService.emitEvent(EventService.EVENT.SUGGESTIONS_SEARCH_TOGGLE,\n          true);\n      }\n    };\n\n    // Init\n    if ($scope.show && !$scope.isTransUnitSelected) {\n      showSearch();\n    }\n\n    // TODO inline this\n    function displaySuggestions(suggestions) {\n      $scope.suggestions = suggestions;\n    }\n\n    function hideSearch() {\n      $scope.search.isVisible = false;\n      setTextSearch(false);\n      updatePhraseDisplay();\n    }\n\n    function showSearch($event, dontFocusInput) {\n      $scope.search.input.text = '';\n      $scope.search.isVisible = true;\n      if (!dontFocusInput && $event) {\n        $scope.focusSearch($event);\n      }\n      editorSuggestionsCtrl.searchForText();\n      updateTextDisplay();\n    }\n\n    $rootScope.$on(EventService.EVENT.SELECT_TRANS_UNIT,\n      function () {\n        // Automatically switch back to phrase search when no search is entered\n        if ($scope.search.input.text === '' && $scope.search.isVisible) {\n          EventService.emitEvent(EventService.EVENT.SUGGESTIONS_SEARCH_TOGGLE,\n           false);\n        }\n        $scope.isTransUnitSelected = true;\n      });\n\n    $rootScope.$on(EventService.EVENT.CANCEL_EDIT,\n      function () {\n        $scope.isTransUnitSelected = false;\n        if ($scope.show && !$scope.search.isVisible) {\n          showSearch(null, true);\n        }\n      });\n\n    $rootScope.$on(EventService.EVENT.SUGGESTIONS_SEARCH_TOGGLE,\n    function(event, activate) {\n      if (activate) {\n        showSearch(event);\n      }\n      else {\n        hideSearch(event);\n      }\n    });\n\n    // Automatic suggestions search on row select\n    $rootScope.$on('PhraseSuggestionsService:updated', function () {\n      if ($scope.isPhraseSearch) {\n        updatePhraseDisplay();\n      }\n    });\n\n    /**\n     * Update all the state to match the latest from the phrase search.\n     */\n    function updatePhraseDisplay() {\n      $scope.searchStrings = PhraseSuggestionsService.getSearchStrings();\n      $scope.search.isLoading = PhraseSuggestionsService.isLoading();\n      displaySuggestions(PhraseSuggestionsService.getResults());\n    }\n\n\n    // Manual suggestions search\n    $rootScope.$on('TextSuggestionsService:updated', function () {\n      if ($scope.isTextSearch) {\n        updateTextDisplay();\n      }\n    });\n\n    /**\n     * Update all the state to match the latest from the text search service.\n     */\n    function updateTextDisplay() {\n      $scope.searchStrings = TextSuggestionsService.getSearchStrings();\n      $scope.search.isLoading = TextSuggestionsService.isLoading();\n      displaySuggestions(TextSuggestionsService.getResults());\n    }\n\n    $rootScope.$on(EventService.EVENT.COPY_FROM_SUGGESTION_N,\n      function (event, matchIndex) {\n\n        if ($scope.show) {\n          // copy visible suggestion with that index\n          copySuggestion($scope.suggestions[matchIndex]);\n\n          // event for copy button on suggestion to display 'copied'\n          $scope.$broadcast('EditorSuggestionsCtrl:nth-suggestion-copied',\n                            matchIndex);\n\n        } else {\n          // copy suggestion from background phrase search\n          copySuggestion(PhraseSuggestionsService.getResults()[matchIndex]);\n        }\n\n      });\n\n\n    function copySuggestion(suggestion) {\n      if (suggestion) {\n        EventService.emitEvent(EventService.EVENT.COPY_FROM_SUGGESTION,\n          { suggestion: suggestion });\n      }\n    }\n\n    return editorSuggestionsCtrl;\n  }\n\n  angular\n    .module('app')\n    .controller('EditorSuggestionsCtrl', EditorSuggestionsCtrl);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name blur-on\n   * @description When you put attribute 'blur-on=\"something\"',\n   * you can then blur this element. It works the same way as focus-on library.\n   */\n  function blurOn() {\n    return {\n      restrict: 'A',\n      link: function(scope, elem, attr) {\n        return scope.$on('blurOn', function (e, name) {\n          if (name === attr.blurOn) {\n              return elem[0].blur();\n            }\n          });\n        }\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('blurOn', blurOn);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name clickElsewhere\n   * @description Initiate expression when clicking somewhere else\n   * @ngInject\n   */\n  function clickElsewhere($document) {\n    return {\n      restrict: 'A',\n      scope: {\n        callback: '&clickElsewhere'\n      },\n      link: function(scope, element) {\n        var handler = function(e) {\n          if (!element[0].contains(e.target)) {\n            scope.$apply(scope.callback(e));\n          }\n        };\n\n        $document.on('click', handler);\n\n        scope.$on('$destroy', function() {\n          $document.off('click', handler);\n        });\n      }\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('clickElsewhere', clickElsewhere);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * Handle server communication on document related\n   * information in project-version.\n   *\n   * DocumentService.js\n   * @ngInject\n   */\n  function DocumentService($q, $resource, UrlService, StringUtil,\n                           StatisticUtil, EventService, _, TransStatusService) {\n    var documentService = this,\n        statisticMap = {};\n\n    /**\n     * Finds all documents in given project version\n     *\n     * @param _projectSlug\n     * @param _versionSlug\n     * @returns {$promise|*|N.$promise}\n     */\n    documentService.findAll = function findAll(_projectSlug, _versionSlug) {\n      var Documents = $resource(UrlService.DOCUMENT_LIST_URL, {}, {\n        query: {\n          method: 'GET',\n          params: {\n            projectSlug: _projectSlug,\n            versionSlug: _versionSlug\n          },\n          isArray: true\n        }\n      });\n      return Documents.query().$promise;\n    };\n\n    /**\n     * Get statistic of document in locale (word and message)\n     *\n     * @param _projectSlug\n     * @param _versionSlug\n     * @param _docId\n     * @param _localeId\n     * @returns {*}\n     */\n    documentService.getStatistics = function (_projectSlug, _versionSlug,\n      _docId, _localeId) {\n      if (_docId && _localeId) {\n        var key = generateStatisticKey(_docId,  _localeId);\n        if (_.has(statisticMap, key)) {\n          return $q.when(statisticMap[key]);\n        } else {\n          var encodedDocId = documentService.encodeDocId(_docId);\n          var Statistics = $resource(UrlService.DOC_STATISTIC_URL, {}, {\n            query: {\n              method: 'GET',\n              params: {\n                projectSlug: _projectSlug,\n                versionSlug: _versionSlug,\n                docId: encodedDocId,\n                localeId: _localeId\n              },\n              isArray: true\n            }\n          });\n          return Statistics.query().$promise.then(function(statistics) {\n\n            // Make needReview(server) available to needswork\n            _.forEach(statistics, function(statistic) {\n              statistic[TransStatusService.getId('needswork')] =\n                statistic.needReview || 0;\n            });\n\n            statisticMap[key] = statistics;\n            return statisticMap[key];\n          });\n        }\n      }\n    };\n\n    /**\n     * Encode docId, replace '/' with ',' when REST call\n     * @param docId\n     * @returns {*}\n     */\n    documentService.encodeDocId = function(docId) {\n      return docId ? docId.replace(/\\//g, ',') : docId;\n    };\n\n    /**\n     * Encode docId, replace ',' with '/' when REST call\n     * @param docId\n     * @returns {*}\n     */\n    documentService.decodeDocId = function(docId) {\n      return docId ? docId.replace(/\\,/g, '/') : docId;\n    };\n\n    documentService.containsDoc = function (documents, docId) {\n      return _.any(documents, function(document) {\n         return StringUtil.equals(document.name, docId, true);\n      });\n    };\n\n    documentService.updateStatistic = function(projectSlug, versionSlug, docId,\n                                               localeId, oldState,\n                                               newState, wordCount) {\n      var key = generateStatisticKey(docId, localeId);\n      if(_.has(statisticMap, key)) {\n        adjustStatistic(statisticMap[key], oldState, newState,\n          wordCount);\n\n        EventService.emitEvent(EventService.EVENT.REFRESH_STATISTIC,\n          {\n            projectSlug: projectSlug,\n            versionSlug: versionSlug,\n            docId: docId,\n            localeId: localeId\n          }\n        );\n      }\n    };\n\n    //Generate unique key from docId and localeId for statistic cache\n    function generateStatisticKey(docId, localeId) {\n      return docId + '-' + localeId;\n    }\n\n    /**\n     * Adjust statistic based on translation change of state\n     * word - -wordCount of oldState, +wordCount of newState\n     * msg - -1 of oldState, +1 of newState\n     */\n    function adjustStatistic(statistics, oldState, newState, wordCount) {\n\n      var wordStatistic = StatisticUtil.getWordStatistic(statistics),\n        msgStatistic = StatisticUtil.getMsgStatistic(statistics);\n\n      if(wordStatistic) {\n        wordCount = parseInt(wordCount);\n        var wordOldState = parseInt(wordStatistic[oldState]) - wordCount;\n        wordStatistic[oldState] = wordOldState < 0 ? 0 : wordOldState;\n        wordStatistic[newState] = parseInt(wordStatistic[newState]) + wordCount;\n      }\n\n      if(msgStatistic) {\n        var msgOldState = parseInt(msgStatistic[oldState]) - 1;\n        msgStatistic[oldState] = msgOldState < 0 ? 0 : msgOldState;\n        msgStatistic[newState] = parseInt(msgStatistic[newState]) + 1;\n      }\n    }\n\n    return documentService;\n  }\n\n  angular\n    .module('app')\n    .factory('DocumentService', DocumentService);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name DropdownCtrl\n   *\n   * @description\n   * Handle dropdown events between directives\n   *\n   * @ngInject\n   */\n  function DropdownCtrl($scope, $attrs, $parse, dropdownConfig,\n    DropdownService, $animate, $timeout) {\n    var dropdownCtrl = this,\n        // create a child scope so we are not polluting original one\n        scope = $scope.$new(),\n        openClass = dropdownConfig.openClass,\n        getIsOpen,\n        setIsOpen = angular.noop,\n        toggleInvoker = $attrs.onToggle ?\n          $parse($attrs.onToggle) : angular.noop;\n\n    this.init = function(element) {\n      dropdownCtrl.$element = element;\n\n      if ($attrs.isOpen) {\n        getIsOpen = $parse($attrs.isOpen);\n        setIsOpen = getIsOpen.assign;\n\n        $scope.$watch(getIsOpen, function(value) {\n          scope.isOpen = !!value;\n        });\n      }\n    };\n\n    this.toggle = function(open) {\n      scope.isOpen = arguments.length ? !!open : !scope.isOpen;\n      return scope.isOpen;\n    };\n\n    // Allow other directives to watch status\n    this.isOpen = function() {\n      return scope.isOpen;\n    };\n\n    scope.getToggleElement = function() {\n      return dropdownCtrl.toggleElement;\n    };\n\n    scope.focusToggleElement = function() {\n      if (dropdownCtrl.toggleElement) {\n        dropdownCtrl.toggleElement[0].focus();\n      }\n    };\n\n    scope.$watch('isOpen', function(isOpen, wasOpen) {\n      $animate[isOpen ? 'addClass' : 'removeClass']\n        (dropdownCtrl.$element, openClass);\n\n      if (isOpen) {\n        // need to wrap it in a timeout\n        // see http://stackoverflow.com/questions/12729122/\n        // prevent-error-digest-already-in-progress-when-calling-scope-apply\n        $timeout(function() {\n          scope.focusToggleElement();\n        });\n        DropdownService.open(scope);\n      } else {\n        DropdownService.close(scope);\n      }\n\n      setIsOpen($scope, isOpen);\n      if (angular.isDefined(isOpen) && isOpen !== wasOpen) {\n        toggleInvoker($scope, {\n          open: !!isOpen\n        });\n      }\n    });\n\n    $scope.$on('$locationChangeSuccess', function() {\n      scope.isOpen = false;\n    });\n\n    $scope.$on('$destroy', function() {\n      scope.$destroy();\n    });\n\n    $scope.$on('openDropdown', function() {\n      scope.isOpen = true;\n    });\n\n    $scope.$on('closeDropdown', function() {\n      scope.isOpen = false;\n    });\n  }\n\n  angular\n    .module('app')\n    .controller('DropdownCtrl', DropdownCtrl);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name dropdownService\n   *\n   * @description\n   * Handle dropdown events between directives\n   *\n   * @ngInject\n   */\n\n  function DropdownService($document) {\n    var openScope = null,\n        dropdownService = this;\n\n    dropdownService.open = function(dropdownScope) {\n      if (!openScope) {\n        $document.bind('click', closeDropdown);\n        $document.bind('keydown', escapeKeyBind);\n      }\n\n      if (openScope && openScope !== dropdownScope) {\n        openScope.isOpen = false;\n      }\n\n      openScope = dropdownScope;\n    };\n\n    dropdownService.close = function(dropdownScope) {\n      if (openScope === dropdownScope) {\n        openScope = null;\n        $document.unbind('click', closeDropdown);\n        $document.unbind('keydown', escapeKeyBind);\n      }\n    };\n\n    var closeDropdown = function(evt) {\n      if (!openScope) {\n        return;\n      }\n      var toggleElement = openScope.getToggleElement();\n      if (evt && toggleElement && toggleElement[0].contains(evt.target)) {\n        return;\n      }\n\n      openScope.$apply(function() {\n        openScope.isOpen = false;\n      });\n    };\n\n    var escapeKeyBind = function(evt) {\n      if (evt.which === 27) {\n        openScope.focusToggleElement();\n        closeDropdown();\n      }\n    };\n  }\n\n  angular\n    .module('app')\n    .service('DropdownService', DropdownService);\n\n})();\n\n","(function() {\n  'use strict';\n\n  /**\n   * @name Dropdown\n   *\n   * @description\n   * Custom module for dropdowns\n   *\n   */\n  var dropdownConfig = {\n    openClass: 'is-active'\n  };\n\n  angular\n    .module('app')\n    .constant('dropdownConfig', dropdownConfig);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name dropdown\n   *\n   * @description\n   * Main dropdown container\n   *\n   */\n\n  function dropdown() {\n    return {\n      restrict: 'EA',\n      controller: 'DropdownCtrl',\n      link: function(scope, element, attrs, dropdownCtrl) {\n        dropdownCtrl.init(element);\n      }\n    };\n  }\n\n  function onCloseDropdown() {\n    return {\n      restrict: 'A',\n      require: '?^dropdown',\n      scope: {\n        callback: '&onCloseDropdown'\n      },\n      link: function(scope, elem, attrs, dropdownCtrl) {\n        dropdownCtrl.onCloseDropdown = scope.callback;\n      }\n    };\n  }\n\n  /**\n   * @name dropdown-toggle\n   *\n   * @description\n   * Main dropdown toggle\n   *\n   */\n\n  function dropdownToggle() {\n    return {\n      restrict: 'EA',\n      require: '?^dropdown',\n      link: function(scope, element, attrs, dropdownCtrl) {\n        if (!dropdownCtrl) {\n          return;\n        }\n\n        dropdownCtrl.toggleElement = element;\n\n        var toggleDropdown = function(event) {\n          event.preventDefault();\n          event.stopPropagation();\n\n          if (!element.hasClass('disabled') && !attrs.disabled) {\n            scope.$apply(function() {\n              dropdownCtrl.toggle();\n            });\n          }\n        };\n\n        element.bind('click', toggleDropdown);\n\n        // WAI-ARIA\n        element.attr({\n          'aria-haspopup': true,\n          'aria-expanded': false\n        });\n        scope.$watch(dropdownCtrl.isOpen, function(isOpen) {\n          element.attr('aria-expanded', !!isOpen);\n          if (dropdownCtrl.onCloseDropdown && !isOpen) {\n            scope.$applyAsync(dropdownCtrl.onCloseDropdown);\n          }\n        });\n\n        scope.$on('$destroy', function() {\n          element.unbind('click', toggleDropdown);\n        });\n      }\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('dropdown', dropdown)\n    .directive('onCloseDropdown', onCloseDropdown)\n    .directive('dropdownToggle', dropdownToggle);\n\n})();\n\n","(function () {\n  'use strict';\n\n  /**\n   * EventService.js\n   * Broadcast events service in app.\n   * Usage: EventService.emitEvent( event,  data, scope)\n   * See EventService.emitEvent\n   *\n   * @ngInject\n   */\n  function EventService($rootScope) {\n    var eventService = this;\n\n    /**\n     * @enum {string}\n     */\n    eventService.EVENT = {\n      /**\n       * Loading Events\n       *\n       * Broadcast from AppConfig\n       */\n      LOADING_START: 'loadingStart',\n      LOADING_STOP: 'loadingStop',\n\n      /**\n       * scroll to trans unit\n       * data: {id: number, updateURL: boolean, focus: boolean}\n       * id: (transunit id),\n       * updateURL: (flag on whether to update url with trans unit id)\n       * focus: flag on whether to have row in view and focused\n       */\n      SELECT_TRANS_UNIT: 'selectTransUnit',\n\n      //data: {phrase: Phrase, sourceIndex:sourceIndex}\n      COPY_FROM_SOURCE: 'copyFromSource',\n\n      // data: { suggestion: Suggestion }\n      COPY_FROM_SUGGESTION: 'copyFromSuggestion',\n\n      /**\n       * Emit this to trigger copying of the nth suggestion to the selected row.\n       *\n       * data: number (zero-based index of suggestion to copy)\n       */\n      COPY_FROM_SUGGESTION_N: 'copyFromSuggestionN',\n\n      //data: {phrase: Phrase}\n      UNDO_EDIT: 'undoEdit',\n\n      //data: {phrase: Phrase}\n      CANCEL_EDIT: 'cancelEdit',\n\n      //data:phrase\n      FOCUS_TRANSLATION: 'focusTranslation',\n\n      /**\n       * data: {\n       *  phrase: Phrase, status: StatusInfo, locale: string, docId: string\n       * }\n       * phrase:\n       * status: Object. Request save state\n       * locale: target locale\n       * docId: docId\n       */\n      SAVE_TRANSLATION: 'saveTranslation',\n\n      /**\n       * Translation save in this editor is being sent to the server and\n       * is waiting on a response.\n       */\n      SAVE_INITIATED: 'saveInitiated',\n\n      /**\n       * Translation save in this editor has been completed\n       * (Server has responded with a success or error).\n       */\n      SAVE_COMPLETED: 'saveCompleted',\n\n      /**\n       * The text in the translation editor textbox has been edited and\n       * not yet saved.\n       */\n      TRANSLATION_TEXT_MODIFIED: 'translationTextModified',\n\n      /**\n       * refresh ui statistic - changes in doc or locale\n       *\n       * data: {projectSlug: string, versionSlug: string,\n       *  docId: string, localeId: string}\n       */\n      REFRESH_STATISTIC: 'refreshStatistic',\n\n      GOTO_PREV_PAGE: 'gotoPreviousPage',\n\n      GOTO_NEXT_PAGE: 'gotoNextPage',\n\n      GOTO_FIRST_PAGE: 'gotoFirstPage',\n\n      GOTO_LAST_PAGE: 'gotoLastPage',\n\n      /**\n       * data: { currentId: number }\n       */\n      GOTO_NEXT_ROW: 'gotoNextRow',\n      GOTO_PREVIOUS_ROW: 'gotoPreviousRow',\n      GOTO_NEXT_UNTRANSLATED: 'gotoNextUntranslated',\n\n      /**\n       * Toggle save as options dropdown.\n       * data: {id: number, open: boolean}\n       */\n      TOGGLE_SAVE_OPTIONS: 'openSaveOptions',\n\n\n      /**\n       * data: {filter: refer to editorCtrl.filter}\n       */\n      FILTER_TRANS_UNIT: 'filterTransUnit',\n\n      /**\n       * Reports the number of suggestions that are available for a phrase.\n       *\n       * data: { id: number, count: number }\n       */\n      PHRASE_SUGGESTION_COUNT: 'phraseSuggestionCount',\n\n      /**\n       * Fire to request suggestions from translation memory, etc.\n       *\n       * data: { phrase: Phrase }\n       */\n      REQUEST_PHRASE_SUGGESTIONS: 'requestPhraseSuggestions',\n\n      /**\n       * Fire for manual suggestions search using a single string.\n       *\n       * data: string\n       */\n      REQUEST_TEXT_SUGGESTIONS: 'requestTextSuggestions',\n\n      /**\n       * Fired every time search is toggled\n       *\n       * @type {Boolean}\n       */\n      SUGGESTIONS_SEARCH_TOGGLE: 'suggestionsSearchToggle',\n\n      /**\n       * Indicates a single user setting has changed.\n       *\n       * Event handlers should switch on the setting name to determine whether\n       * it is a setting they are interested in.\n       *\n       * data: { setting: string, value: boolean|number|string }\n       */\n      USER_SETTING_CHANGED: 'userSettingChanged'\n    };\n\n    /**\n     * Firing an event downwards of scope\n     *\n     * @param event - eventService.EVENT type\n     * @param data - data for the event\n     * @param scope - scope of event to to fire, $rootScope if empty\n     */\n    eventService.broadcastEvent = function(event, data, scope) {\n      scope = scope || $rootScope;\n      scope.$broadcast(event, data);\n    };\n\n    /**\n     * Firing an event upwards of scope\n     *\n     * @param event - eventService.EVENT types\n     * @param data - data for the event\n     * @param scope - scope of event to to fire, $rootScope if empty\n     */\n    eventService.emitEvent = function(event, data, scope) {\n      scope = scope || $rootScope;\n      scope.$emit(event, data);\n    };\n\n    return eventService;\n  }\n\n  angular\n    .module('app')\n    .factory('EventService', EventService);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name icon\n   * @description declarative svg icons\n   * @ngInject\n   */\n  function icon($sce) {\n    return {\n      restrict: 'E',\n      required: ['name'],\n      scope: {\n        name: '@',\n        title: '@',\n        size: '@'\n      },\n      // templateUrl: 'components/icon/icon.html',\n      link: function(scope, element) {\n        var svg = '',\n            loader = '',\n            titleHtml = '';\n\n        element.addClass('Icon');\n\n        if (scope.title) {\n          titleHtml = '' + scope.title + '';\n        }\n\n        if (scope.name === 'loader') {\n          // Can't seem to animate svg symbols\n          element.addClass('Icon--loader');\n          loader = '' +\n            '' +\n              '' +\n              '' +\n              '' +\n            '';\n          element.html($sce.trustAsHtml(loader));\n        }\n        else {\n          // Stupid hack to make svg work\n          svg = '' +\n            '' +\n              '' +\n              titleHtml +\n            '';\n          element.html($sce.trustAsHtml(svg));\n        }\n      }\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('icon', icon);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * Handle locales related information.\n   *\n   * LocaleService.js\n   * @ngInject\n   */\n  function LocaleService(UrlService, StringUtil, FilterUtil, $resource, _) {\n\n    var locales = [];\n\n    /**\n     * Get project-version supported locales\n     * @param projectSlug\n     * @param versionSlug\n     * @returns {$promise|*}\n     */\n    function getSupportedLocales(projectSlug, versionSlug) {\n\n      var Locales = $resource(UrlService.LOCALE_LIST_URL, {}, {\n        query: {\n          method: 'GET',\n          params: {\n            projectSlug: projectSlug,\n            versionSlug: versionSlug\n          },\n          isArray: true\n        }\n      });\n\n      return Locales.query().$promise;\n    }\n\n    //Returns all locales supported in Zanata instance\n    function getAllLocales() {\n      var Locales = $resource(UrlService.ALL_LOCALE_URL, {}, {\n        query: {\n          method: 'GET',\n          isArray: true\n        }\n      });\n      return Locales.query().$promise.then(function(results) {\n        locales = FilterUtil.cleanResourceList(results);\n      });\n    }\n\n    function getUILocaleList() {\n      var list = $resource(UrlService.uiTranslationListURL, {}, {\n        query: {\n          method: 'GET'\n        }\n      });\n\n      return list.query().$promise;\n    }\n\n    function getLocaleByLocaleId(locales, localeId) {\n      if(locales) {\n        return _.find(locales, function(locale) {\n          return StringUtil.equals(locale.localeId, localeId, true);\n        });\n      }\n    }\n\n    function containsLocale (locales, localeId) {\n      return _.any(locales, function(locale) {\n        return StringUtil.equals(locale.localeId, localeId, true);\n      });\n    }\n\n    function getName(localeId) {\n      var locale = getLocaleByLocaleId(locales, localeId);\n      if(locale) {\n        return locale.name;\n      }\n      return localeId;\n    }\n\n    return {\n      getSupportedLocales : getSupportedLocales,\n      getUILocaleList     : getUILocaleList,\n      getLocaleByLocaleId : getLocaleByLocaleId,\n      getAllLocales : getAllLocales,\n      containsLocale : containsLocale,\n      getName : getName,\n      DEFAULT_LOCALE: {\n        'localeId' : 'en-US',\n        'name' : 'English'\n      }\n    };\n  }\n\n  angular\n    .module('app')\n    .factory('LocaleService', LocaleService);\n})();\n","(function() {\n\n  'use strict';\n\n  /**\n   * @name logoLoader\n   *\n   * @description\n   * Logo that is activated on global loading state\n   *\n   * @ngInject\n   */\n  function logoLoader(EventService) {\n    return {\n      restrict: 'EA',\n      scope: {\n        loading: '=',\n        inverted: '='\n      },\n      link: function(scope) {\n        scope.classes = '';\n\n        scope.$on(EventService.EVENT.LOADING_START, function() {\n          scope.classes += ' is-loading';\n        });\n\n        scope.$on(EventService.EVENT.LOADING_STOP, function() {\n          scope.classes = scope.classes.replace('is-loading', '');\n        });\n\n        scope.$watch('inverted', function(newInverted) {\n          if (newInverted) {\n            scope.classes += ' LogoLoader--inverted';\n          } else {\n            scope.classes = scope.classes.replace('LogoLoader--inverted', '');\n          }\n        });\n      },\n      templateUrl: 'components/logo-loader/logo-loader.html'\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('logoLoader', logoLoader);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * MessageHandler.js\n   * @ngInject\n   */\n  function MessageHandler() {\n    return {\n      displayError: function(msg) {\n        console.error(msg);\n      },\n      displayWarning: function(msg) {\n        console.warn(msg);\n      },\n      displayInfo: function(msg) {\n        console.info(msg);\n      }\n    };\n  }\n\n  angular\n    .module('app')\n    .factory('MessageHandler', MessageHandler);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * Handle notification in editor\n   *\n   * NotificationService.js\n   * @ngInject\n   */\n  function NotificationService() {\n\n  }\n\n  angular\n    .module('app')\n    .factory('NotificationService', NotificationService);\n\n})();\n","(function () {\n  'use strict';\n\n  /**\n   * PhraseCache.js\n   * Stores textflow, states in local cache.\n   * TODO: use angular-data for storage\n   * @ngInject\n   */\n  function PhraseCache($q, $resource, FilterUtil, UrlService, DocumentService,\n                       _) {\n    var phraseCache = this,\n      states = {}, //ids and states of all tu in order\n      transUnits = {};\n\n    phraseCache.getStates =\n      function (projectSlug, versionSlug, documentId, localeId) {\n        var key = generateKey(projectSlug, versionSlug, documentId, localeId);\n        if (_.has(states, key)) {\n          return $q.when(states[key]);\n        } else {\n          var encodedDocId = DocumentService.encodeDocId(documentId);\n          var methods = {\n              query: {\n                method: 'GET',\n                params: {\n                  projectSlug: projectSlug,\n                  versionSlug: versionSlug,\n                  docId: encodedDocId,\n                  localeId: localeId\n                },\n                isArray: true\n              }\n            },\n            States = $resource(UrlService.TRANSLATION_STATUS_URL, {}, methods);\n          return States.query().$promise.then(function (state) {\n            state = FilterUtil.cleanResourceList(state);\n            states[key] = state;\n            return states[key];\n          });\n        }\n      };\n\n    phraseCache.getTransUnits = function (ids, localeId) {\n      var results = {},\n        missingTUId = [],\n        missingLocaleTUId = [];\n      ids.forEach(function (id) {\n        if (_.has(transUnits, id)) {\n          if(transUnits[id][localeId]) {\n            results[id] = transUnits[id];\n          } else {\n            missingLocaleTUId.push(id);\n          }\n        } else {\n          missingTUId.push(id);\n        }\n      });\n      if (_.isEmpty(missingTUId) && _.isEmpty(missingLocaleTUId)) {\n        return $q.when(results);\n      }\n      else {\n        var TextFlows, Translations;\n        if(!_.isEmpty(missingTUId)) {\n          TextFlows = $resource(UrlService.TEXT_FLOWS_URL, {}, {\n            query: {\n              method: 'GET',\n              params: {\n                localeId: localeId,\n                ids: missingTUId.join(',')\n              }\n            }\n          });\n        }\n        if(!_.isEmpty(missingLocaleTUId)) {\n          Translations = $resource(UrlService.TRANSLATION_URL, {}, {\n            query: {\n              method: 'GET',\n              params: {\n                localeId: localeId,\n                ids: missingLocaleTUId.join(',')\n              }\n            }\n          });\n        }\n\n        //need to create chain of promises\n        if(TextFlows && Translations) {\n          return TextFlows.query().$promise.then(updateCacheWithNewTU).\n            then(Translations.query().$promise.then(updateCacheWithExistingTU));\n        } else if(TextFlows) {\n          return TextFlows.query().$promise.then(updateCacheWithNewTU);\n        } else if(Translations) {\n          return Translations.query().$promise.then(updateCacheWithExistingTU);\n        }\n      }\n\n      function updateCacheWithExistingTU(newTransUnits) {\n        newTransUnits = FilterUtil.cleanResourceMap(newTransUnits);\n        for (var key in newTransUnits) {\n          //push to cache\n          transUnits[key][localeId] = newTransUnits[key][localeId];\n          results[key] = transUnits[key]; //merge with results\n        }\n        return results;\n      }\n\n      function updateCacheWithNewTU(newTransUnits) {\n        newTransUnits = FilterUtil.cleanResourceMap(newTransUnits);\n        for (var key in newTransUnits) {\n          transUnits[key] = newTransUnits[key]; //push to cache\n          results[key] = transUnits[key]; //merge with results\n        }\n        return results;\n      }\n    };\n\n    /**\n     * On translation updated from server\n     * @param id\n     * @param localeId\n     * @param revision\n     * @param state\n     * @param content\n     * @param contents\n     */\n    phraseCache.onTransUnitUpdated =\n      function (context, id, localeId, revision, status, phrase) {\n\n        var key = generateKey(context.projectSlug, context.versionSlug,\n          context.docId, localeId);\n\n        var stateEntry = _.find(states[key], function(stateEntry) {\n          return stateEntry.id === id;\n        });\n        //Update states cache\n        if(stateEntry) {\n          stateEntry.state = status;\n        }\n\n        //Update transUnits cache\n        var translation = transUnits[id][localeId];\n        if (!translation) {\n          translation = {};\n        }\n        translation.revision = parseInt(revision);\n        translation.state = status;\n        translation.contents = phrase.newTranslations.slice();\n      };\n\n    function generateKey(projectId, versionId, documentId, localeId) {\n      return projectId + '-' + versionId + '-' +\n        documentId + '-' + localeId;\n    }\n\n    return phraseCache;\n  }\n\n  angular\n    .module('app')\n    .factory('PhraseCache', PhraseCache);\n\n})();\n","(function () {\n  'use strict';\n\n  /**\n   * @typedef {Object} Phrase\n   * @property {number} id text flow id\n   * @property {string[]} sources source contents\n   * @property {string[]} translations original translation\n   * @property {string[]} newTranslations translations in the editor\n   * @property {boolean} plural whether it's in plural form\n   * @property {StatusInfo} status information about this phrase\n   * @property {number} revision translation revision number\n   * @property {number} wordCount source word count\n   */\n  /**\n   * @name PhraseService\n   * @description Provides a list of phrases for the current document(s)\n   *\n   * @ngInject\n   */\n  function PhraseService(FilterUtil, PhraseCache, TransStatusService, _,\n                         $stateParams) {\n    var phraseService = {};\n\n    phraseService.phrases = []; //current displayed phrases\n\n    // FIXME use an object for all the ID arguments - in general we will only\n    // need to modify such an object sporadically when switching document\n    // or locale, and it is neater than passing them all\n    // around separately.\n\n    phraseService.getPhraseCount = function(context, filter) {\n      return PhraseCache.getStates(context.projectSlug, context.versionSlug,\n        context.docId, context.localeId).then(function(states) {\n          var ids = getIds(states, filter.status);\n          return ids.length;\n        });\n    };\n\n    /**\n     * Fetch each of the text flows appearing in the given states data.\n     */\n    phraseService.fetchAllPhrase = function (context, filter,\n                                             offset, maxResult) {\n\n      var localeId = context.localeId;\n\n      return PhraseCache.getStates(context.projectSlug, context.versionSlug,\n        context.docId, localeId).then(getTransUnits);\n\n      function getTransUnits(states) {\n        var ids = getIds(states, filter.status);\n        if (!isNaN(offset)) {\n          if(!isNaN(maxResult)) {\n            ids = ids.slice(offset, offset + maxResult);\n          } else {\n            ids = ids.slice(offset);\n          }\n        }\n        // Reading for chaining promises https://github.com/kriskowal/q\n        // (particularly \"Sequences\").\n        return PhraseCache.getTransUnits(ids, localeId).\n          then(transformToPhrases).then(sortPhrases);\n      }\n\n      /**\n       * Converts text flow data from the API into the form expected in the\n       * editor.\n       *\n       * @returns {Phrase[]}\n       */\n      function transformToPhrases(transUnits) {\n        return _.map(transUnits, function(transUnit, id) {\n          var source = transUnit.source,\n              trans = transUnit[localeId];\n          return {\n            id: parseInt(id),\n            sources: source.plural ? source.contents : [source.content],\n            // Original translation\n            translations: extractTranslations(source, trans),\n            // Translation from editor\n            newTranslations: extractTranslations(source, trans),\n            plural: source.plural,\n            // Conform the status from the server, return an object\n            status: trans ? TransStatusService.getStatusInfo(trans.state) :\n              TransStatusService.getStatusInfo('untranslated'),\n            revision: trans ? parseInt(trans.revision) : 0,\n            wordCount: parseInt(source.wordCount)\n          };\n        });\n      }\n\n      function extractTranslations(source, trans) {\n        if(source.plural) {\n          return trans && trans.contents ? trans.contents.slice() : [];\n        }\n        return trans ? [trans.content] : [];\n      }\n\n      function sortPhrases(phrases) {\n        return PhraseCache.getStates(context.projectSlug, context.versionSlug,\n          context.docId, localeId).then(function(states) {\n            phraseService.phrases = _.sortBy(phrases, function(phrase) {\n              var index = _.findIndex(states, function(state) {\n                return state.id === phrase.id;\n              });\n              return index >= 0 ? index : phrases.length;\n            });\n            return phraseService.phrases;\n          });\n      }\n    };\n\n    //update phrase,statuses and textFlows with given tu id\n    phraseService.onTransUnitUpdated = function(context, id, localeId, revision,\n      status, phrase) {\n\n      PhraseCache.onTransUnitUpdated(context, id, localeId, revision, status,\n        phrase);\n\n      var cachedPhrase = findPhrase(id, phraseService.phrases);\n      //update phrase if found\n      if(cachedPhrase) {\n        cachedPhrase.translations = phrase.newTranslations.slice();\n        cachedPhrase.revision = revision;\n        cachedPhrase.status = TransStatusService.getStatusInfo(status);\n      }\n    };\n\n    //rollback content of phrase\n    phraseService.onTransUnitUpdateFailed = function(id) {\n      var phrase = findPhrase(id, phraseService.phrases);\n      if(phrase) {\n        phrase.newTranslations = phrase.translations.slice();\n      }\n    };\n\n    // find next Id from phrases states\n    phraseService.findNextId = function(currentId) {\n      return PhraseCache.getStates($stateParams.projectSlug,\n                                   $stateParams.versionSlug, $stateParams.docId,\n                                   $stateParams.localeId)\n        .then(function (states) {\n          var currentIndex,\n            nextIndex;\n          currentIndex = _.findIndex(states, function (state) {\n            return state.id === currentId;\n          });\n          nextIndex = currentIndex + 1 < states.length ?\n            currentIndex + 1 : states.length - 1;\n          return states[nextIndex].id;\n        });\n    };\n\n    // find previous id from phrases states\n    phraseService.findPreviousId = function(currentId) {\n      return PhraseCache.getStates($stateParams.projectSlug,\n                                   $stateParams.versionSlug, $stateParams.docId,\n                                   $stateParams.localeId)\n        .then(function (states) {\n          var currentIndex,\n            previousIndex;\n          currentIndex = _.findIndex(states, function (state) {\n            return state.id === currentId;\n          });\n          previousIndex = currentIndex - 1 >= 0 ? currentIndex - 1 : 0;\n          return states[previousIndex].id;\n        });\n    };\n\n    // find next phrase with requested status\n    phraseService.findNextStatus = function(currentId, status) {\n      return PhraseCache.getStates($stateParams.projectSlug,\n                                   $stateParams.versionSlug, $stateParams.docId,\n                                   $stateParams.localeId)\n        .then(function (statusList) {\n          var currentIndex,\n            nextStatusInfo,\n            requestStatus = TransStatusService.getStatusInfo(status);\n\n          currentIndex = _.findIndex(statusList, function (state) {\n            return state.id === currentId;\n          });\n\n          for (var i = currentIndex + 1; i < statusList.length; i++) {\n            nextStatusInfo = TransStatusService.getStatusInfo(\n              statusList[i].state);\n            if (nextStatusInfo.ID === requestStatus.ID) {\n              return statusList[i].id;\n            }\n          }\n          return currentId;\n        });\n    };\n\n    function findPhrase(id, phrases) {\n      return _.find(phrases, function(phrase) {\n        return phrase.id === id;\n      });\n    }\n\n    function getIds(resources, states) {\n      if(states) {\n        resources = FilterUtil.filterResources(resources, ['status'], states);\n      }\n      return _.map(resources, function (item) {\n        return item.id;\n      });\n    }\n\n    // Does not appear to be used anywhere. Removing until phrase-caching code\n    // is added.\n    // phraseService.findById = function(phraseId) {\n    //   var deferred = $q.defer();\n    //   var phrase = phrases[phraseId];\n    //   deferred.resolve(phrase);\n    //   return deferred.promise;\n    // };\n\n    return phraseService;\n  }\n\n  angular\n    .module('app')\n    .factory('PhraseService', PhraseService);\n\n})();\n\n","(function() {\n  'use strict';\n\n  /**\n   * @name progressbar\n   * @description progressbar container\n   * @ngInject\n   */\n  function progressbar() {\n    return {\n      restrict: 'E',\n      required: 'progressbarStatistic',\n      scope: {\n        statistic: '=progressbarStatistic',\n        size: '@' //large, full, or empty\n      },\n      templateUrl: 'components/progressbar/progressbar.html',\n      controller: function($scope) {\n        /**\n         * Need to set to true for complex object watch. Performance issue.\n         * https://docs.angularjs.org/api/ng/type/$rootScope.Scope\n         */\n        $scope.$watch('statistic', function(statistic) {\n          if (statistic) {\n            $scope.style = getStyle(statistic);\n          }\n        }, true);\n      }\n    };\n  }\n\n  function getStyle(statistic) {\n    var total = statistic.total,\n        widthApproved = getWidthPercent(statistic.approved, total),\n        widthTranslated = getWidthPercent(statistic.translated, total),\n        marginLeftTranslated = widthApproved,\n        widthNeedsWork = getWidthPercent(statistic.needswork, total),\n        marginLeftNeedsWork = widthApproved + widthTranslated,\n        widthUntranslated = getWidthPercent(statistic.untranslated, total),\n        marginLeftUntranslated = widthApproved +\n          widthTranslated + widthNeedsWork,\n        style = {};\n\n    style.approved = {\n      'width': widthApproved + '%',\n      'marginLeft': 0\n    };\n    style.translated = {\n      'width': widthTranslated + '%',\n      'marginLeft': marginLeftTranslated + '%'\n    };\n    style.needsWork = {\n      'width': widthNeedsWork + '%',\n      'marginLeft': marginLeftNeedsWork + '%'\n    };\n    style.untranslated = {\n      'width': widthUntranslated + '%',\n      'marginLeft': marginLeftUntranslated + '%'\n    };\n    return style;\n  }\n\n  function getWidthPercent(value, total) {\n    var percent = 0;\n    if (value) {\n      percent = value / total * 100;\n    }\n    return percent;\n  }\n\n  angular\n    .module('app')\n    .directive('progressbar', progressbar);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * Handle communication with server on Project related information.\n   * ProjectService.js\n   * @ngInject\n   */\n\n  function ProjectService(UrlService, $resource) {\n\n    /**\n     * Get project's information\n     *\n     * @param projectSlug\n     * @returns {$promise|*|N.$promise}\n     */\n    function getProjectInfo(projectSlug) {\n      var methods = {\n          query: {\n            method: 'GET',\n            params: {\n              projectSlug: projectSlug\n            }\n          }\n        };\n\n      var Locales = $resource(UrlService.PROJECT_URL, {}, methods);\n      return Locales.query().$promise;\n    }\n\n    return {\n      getProjectInfo: getProjectInfo\n    };\n  }\n  angular\n    .module('app')\n    .factory('ProjectService', ProjectService);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name display-character\n   * @description display whitespace character with symbol(HTML),\n   *              *NOTE*, need to wrap around 
 tag\n   * @ngInject\n   */\n  function renderWhitespaceCharacters() {\n    var WHITESPACES = {\n      'space' : {\n        'regex' : / /g,\n        'template' : ' '\n      },\n      'newline' : {\n        'regex' : /\\n/g,\n        'template' : '\\n'\n      },\n      'tab' : {\n        'regex' : /\\t/g,\n        'template' : '\\t'\n      }\n    };\n\n    return {\n      restrict: 'A',\n      required: ['ngBind'],\n      scope: {\n        ngBind: '='\n      },\n\n      link: function compile(scope, element) {\n        scope.$watch('ngBind', function (value) {\n          value = replaceChar(value, WHITESPACES.space);\n          value = replaceChar(value, WHITESPACES.newline);\n          value = replaceChar(value, WHITESPACES.tab);\n          element.html(value);\n        });\n      }\n    };\n\n    function replaceChar(value, whitespaceChar) {\n      return value.replace(whitespaceChar.regex, whitespaceChar.template);\n    }\n  }\n\n  angular\n    .module('app')\n    .directive('renderWhitespaceCharacters', renderWhitespaceCharacters);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * Represents a draggable resizer.\n   *\n   * @param $window\n   * @param $document\n   * @param $timeout\n   * @returns {Function}\n   */\n  function resizer(SettingsService, $window, $document, $timeout) {\n\n    function link(scope, element, attrs) {\n\n      /**\n       * The height to use for the resizer when it is visible.\n       *\n       * @type {Number}\n       */\n      scope.height = parseInt(attrs.resizerHeight);\n\n      /**\n       * The current height of the resizer to display.\n       *\n       * @type {Number}\n       */\n      scope.actualHeight = scope.height;\n\n      scope.position = normalisePercentage(SettingsService.get(\n        SettingsService.SETTING.SUGGESTIONS_PANEL_HEIGHT), $window.innerHeight);\n      scope.actualPosition = scope.position;\n\n      scope.show =\n        SettingsService.subscribe(SettingsService.SETTING.SHOW_SUGGESTIONS,\n        function (show) {\n          scope.show = show;\n          setBottomPanelVisibility(show);\n        });\n\n      /**\n       * Persist the current size as a setting.\n       */\n      function saveCurrentSize() {\n        SettingsService.update(SettingsService.SETTING.SUGGESTIONS_PANEL_HEIGHT,\n          scope.actualPosition);\n      }\n\n      function setBottomPanelVisibility(showing) {\n        if (showing) {\n          scope.actualPosition = scope.position;\n          scope.actualHeight = scope.height;\n        } else {\n          // save resizer position so it can be restored\n          // does not appear to set properly without an intermediate variable\n          var currentPos = scope.actualPosition;\n          scope.position = currentPos;\n          scope.actualPosition = 0;\n          scope.actualHeight = 0;\n        }\n\n        // Panel only renders properly if resizer is adjusted in a later frame\n        setTimeout(adjustResizer);\n      }\n\n      setBottomPanelVisibility(scope.show);\n\n      element.addClass('Resizer');\n\n      // Initial Resize\n      if (attrs.resizer === 'vertical') {\n        element.addClass('Resizer--vertical');\n        $timeout(function (){\n          adjustVerticalPanel(scope.actualPosition);\n        });\n      }\n      else {\n        element.addClass('Resizer--horizontal');\n        $timeout(function (){\n          adjustHorizontalPanel(scope.actualPosition);\n        });\n      }\n\n      element.on('mousedown', function(event) {\n        event.preventDefault();\n        $document.on('mousemove', mousemove);\n        $document.on('mouseup', mouseup);\n      });\n\n      angular.element($window).bind('resize', function() {\n        $timeout.cancel(scope.resizing);\n        scope.resizing = $timeout(adjustResizer);\n      });\n\n      function mousemove(event) {\n        if (attrs.resizer === 'vertical') {\n          adjustVerticalPanel(event.pageX);\n        } else {\n          adjustHorizontalPanel($window.innerHeight - event.pageY);\n        }\n      }\n\n      function adjustVerticalPanel(resizerPositionX) {\n        var x = resizerPositionX,\n            leftPanel = angular.element(document\n              .querySelector(attrs.resizerLeft)),\n            rightPanel = angular.element(document\n              .querySelector(attrs.resizerRight)),\n            maximumPanelSize =\n              normalisePercentage(attrs.resizerMax, $window.innerHeight),\n            minimumPanelSize = attrs.resizerMin ||\n              parseInt(attrs.resizerWidth);\n\n        scope.actualPosition = x;\n        x = restrictMinOrMax(x, maximumPanelSize, minimumPanelSize);\n\n        element.css({\n          left: (x - (scope.actualHeight / 2))  + 'px'\n        });\n\n        leftPanel.css({\n          width: x + 'px'\n        });\n\n        rightPanel.css({\n          left: x + 'px'\n        });\n      }\n\n      function adjustHorizontalPanel(resizerPositionY) {\n        var y = resizerPositionY,\n            topPanel = angular.element(document\n              .querySelector(attrs.resizerTop)),\n            bottomPanel = angular.element(document\n              .querySelector(attrs.resizerBottom)),\n            maximumPanelSize =\n              normalisePercentage(attrs.resizerMax, $window.innerHeight),\n            minimumPanelSize = attrs.resizerMin || scope.actualHeight;\n\n        scope.actualPosition = y;\n        y = restrictMinOrMax(y, maximumPanelSize, minimumPanelSize);\n\n        element.css({\n          bottom: (y - (scope.actualHeight / 2))  + 'px'\n        });\n\n        topPanel.css({\n          bottom: y + 'px'\n        });\n\n        bottomPanel.css({\n          height: y + 'px'\n        });\n      }\n\n      function mouseup() {\n        $document.unbind('mousemove', mousemove);\n        $document.unbind('mouseup', mouseup);\n\n        // Now that a new value has stopped rapidly changing, persist it.\n        saveCurrentSize();\n      }\n\n      function adjustResizer() {\n        if (attrs.resizer === 'vertical') {\n          adjustVerticalPanel(scope.actualPosition);\n        }\n        else {\n          adjustHorizontalPanel(scope.actualPosition);\n        }\n      }\n\n      function restrictMinOrMax(currentSize, maxSize, minSize) {\n        // Maximum\n        if (maxSize && currentSize > maxSize) {\n          return maxSize;\n        }\n        // Minimum\n        else if (currentSize < minSize) {\n          return minSize;\n        }\n        else {\n          return currentSize;\n        }\n      }\n\n      function normalisePercentage(fraction, whole) {\n        if ((/[0-9]*\\.?[0-9]+%/).test(fraction)) {\n          return Math.round(whole * (parseInt(fraction.replace('%','')) / 100));\n        }\n        else {\n          return parseInt(fraction);\n        }\n      }\n\n    }\n\n    return {\n      link: link\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('resizer', resizer);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name ScrollbarWidthCtrl\n   *\n   * @description\n   * Handle dropdown events between directives\n   *\n   * @ngInject\n   */\n  function ScrollbarWidthCtrl() {\n    var scrollbarWidthCtrl = this;\n\n    scrollbarWidthCtrl.init = function() {\n      var container = scrollbarWidthCtrl.container[0],\n          child = scrollbarWidthCtrl.child[0],\n          scrollbarWidth = child.offsetWidth - container.offsetWidth;\n\n      scrollbarWidthCtrl.width = scrollbarWidth / 2;\n    };\n\n  }\n\n  angular\n    .module('app')\n    .controller('ScrollbarWidthCtrl', ScrollbarWidthCtrl);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name scrollbarWidth\n   *\n   * @description\n   * Scrollbar width container\n   * Needed for the controller to reference all properties\n   */\n  function scrollbarWidth() {\n    return {\n      restrict: 'A',\n      controller: 'ScrollbarWidthCtrl as scrollbarWidthCtrl',\n      link: function(scope, element, attrs, scrollbarWidthCtrl) {\n        scrollbarWidthCtrl.init(element);\n      }\n    };\n  }\n\n  /**\n   * @name scrollbarWidthElement\n   *\n   * @description\n   * The element to add the scrollbar width to\n   */\n  function scrollbarWidthElement() {\n    return {\n      restrict: 'A',\n      require: '?^scrollbarWidth',\n      link: function(scope, element, attrs, scrollbarWidthCtrl) {\n        if (!scrollbarWidthCtrl) {\n          return;\n        }\n        // Use the attribute to decide which property to set\n        element.css(attrs.scrollbarWidthElement, scrollbarWidthCtrl.width);\n      }\n    };\n  }\n\n  /**\n   * @name scrollbarWidthContainer\n   *\n   * @description\n   * Get the scrollbar container width\n   */\n  function scrollbarWidthContainer() {\n    return {\n      restrict: 'A',\n      require: '?^scrollbarWidth',\n      link: function(scope, element, attrs, scrollbarWidthCtrl) {\n        if (!scrollbarWidthCtrl) {\n          return;\n        }\n        scrollbarWidthCtrl.container = element;\n      }\n    };\n  }\n\n  /**\n   * @name scrollbarWidthChild\n   *\n   * @description\n   * Get the scrollbar child width\n   */\n  function scrollbarWidthChild() {\n    return {\n      restrict: 'A',\n      require: '?^scrollbarWidth',\n      link: function(scope, element, attrs, scrollbarWidthCtrl) {\n        if (!scrollbarWidthCtrl) {\n          return;\n        }\n        scrollbarWidthCtrl.child = element;\n      }\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('scrollbarWidth', scrollbarWidth)\n    .directive('scrollbarWidthElement', scrollbarWidthElement)\n    .directive('scrollbarWidthContainer', scrollbarWidthContainer)\n    .directive('scrollbarWidthChild', scrollbarWidthChild);\n\n})();\n","(function() {\n  'use strict';\n\n\n  /**\n   * The name of a setting, used as a unique key for lookup and storage.\n   * @typedef {string} SettingKey\n   */\n\n  /**\n   * The value for a setting.\n   *\n   * @typedef {(string|number|boolean)} SettingValue\n   */\n\n  /**\n   * Service for persisted user settings.\n   *\n   * @constructor\n   */\n  function SettingsService(EventService, $q, $rootScope, _) {\n    var settingsService = this;\n\n    /**\n     * All valid settings keys.\n     *\n     * These enum constants should be used for all settings operations.\n     *\n     * @type {Object<*, SettingKey>}\n     */\n    settingsService.SETTING = {\n      SUGGESTIONS_AUTOFILL_ON_ROW_SELECT: 'suggestionsAutofillOnRowSelect',\n      SUGGESTIONS_SHOW_DIFFERENCE: 'suggestionsShowDifference',\n      SHOW_SUGGESTIONS: 'showSuggestions',\n      SUGGESTIONS_PANEL_HEIGHT: 'suggestionsPanelHeight'\n    };\n\n    var SETTING = settingsService.SETTING;\n\n    /**\n     * Settings enum, with default values that indicate the type\n     * @enum {SettingValue}\n     */\n    var defaultSettings = {};\n    defaultSettings[SETTING.SUGGESTIONS_AUTOFILL_ON_ROW_SELECT] = true;\n    defaultSettings[SETTING.SUGGESTIONS_SHOW_DIFFERENCE] = false;\n    defaultSettings[SETTING.SHOW_SUGGESTIONS] = true;\n    defaultSettings[SETTING.SUGGESTIONS_PANEL_HEIGHT] = '30%';\n\n    /**\n     * Local settings cache.\n     *\n     * @type {Object}\n     */\n    var settings = _.clone(defaultSettings);\n\n\n    /*\n\n     TODO save settings to the server, prefer sending as a batch if possible\n     (i.e. when updateAll is used, and future option to ensure only one save\n      request at a time and use _.extend to combine all the queued settings\n      while waiting).\n\n    */\n\n    /**\n     * Update a single setting to have the given value.\n     *\n     * This will trigger a user setting update event.\n     *\n     * @param {SettingKey} setting the name of the setting to update\n     * @param {SettingValue} value the new value for the setting\n     */\n    function update(setting, value) {\n      validateSettingValue(value);\n      var settingObj = {};\n      settingObj[setting] = value;\n      _.extend(settings, settingObj);\n\n      EventService.emitEvent(EventService.EVENT.USER_SETTING_CHANGED, {\n        setting: setting,\n        value: value\n      });\n    }\n\n    /**\n     * Update multiple settings from a map of setting names and values.\n     *\n     * An event is triggered for each setting.\n     *\n     * @param {Object} settings\n     */\n    function updateAll(settings) {\n      _.each(settings, function (value, key) {\n        update(key, value);\n      });\n    }\n\n    /**\n     * Get the currently stored value for a setting.\n     *\n     * This should only be used to fetch the initial value or when a setting\n     * is used once. To track changes to a setting, subscribe to the\n     * USER_SETTING_CHANGED event and check the setting property of the event\n     * payload.\n     *\n     * @param {SettingKey} setting name of the setting to look up\n     */\n    function get(setting) {\n      if (_.has(settings, setting)) {\n        return settings[setting];\n      }\n      // Incorrect key is a programmer error - default should be set for all\n      // user settings that are used.\n      console.error('Tried to look up setting with unrecognized key: %s',\n        setting);\n    }\n\n    /**\n     * Register an action to perform when a user setting value changes, and get\n     * the current value.\n     *\n     * @param {SettingKey} setting the setting to get and subscribe to\n     * @param {function} callback called with the new value\n     * @return {SettingValue} the current value of the setting\n     */\n    function subscribe(setting, callback) {\n      $rootScope.$on(EventService.EVENT.USER_SETTING_CHANGED,\n        function (event, data) {\n          if (data.setting === setting) {\n            callback(data.value);\n          }\n        });\n      return get(setting);\n    }\n\n    /**\n     * Throw an error if the value is not the correct type for the setting.\n     *\n     * @param {SettingValue} value\n     */\n    function validateSettingValue(value) {\n      switch (typeof value) {\n        case 'boolean':\n        case 'number':\n        case 'string':\n          break;\n        default:\n          throw new Error('Invalid type for setting value: \"' + typeof value +\n            '\".');\n      }\n    }\n\n\n\n    return {\n      SETTING: SETTING,\n      update: update,\n      updateAll: updateAll,\n      get: get,\n      subscribe: subscribe\n    };\n  }\n\n  angular\n    .module('app')\n    .factory('SettingsService', SettingsService);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * PhraseSuggestionsService.js\n   * @ngInject\n   */\n  function PhraseSuggestionsService(_, EventService, SuggestionsService,\n                                    $timeout, $rootScope) {\n    // TODO extract common code from TextSuggestionsService and here\n\n    /* Minimum time in milliseconds to wait between requesting results */\n    var DELAY = 300;\n    var MAX_ACTIVE_REQUESTS = 3;\n\n    /* @type {boolean} */\n    var loading = false;\n\n    /* @type {Phrase} */\n    var searchPhrase = null;\n\n    /* @type {Array} */\n    var results = [];\n\n    /**\n     * @return {boolean} true if results have been requested and not delivered\n     */\n    function isLoading() {\n      return loading;\n    }\n\n    /**\n     *\n     * @return {string[]} strings that were used to search, or null if no search\n     *                    has been performed.\n     */\n    function getSearchStrings() {\n      return searchPhrase ? searchPhrase.sources : [];\n    }\n\n    /**\n     * Get results for the current search\n     * @return {Array} results for the current search. Empty if\n     *                             no search has been performed.\n     */\n    function getResults() {\n      return results;\n    }\n\n\n\n\n    var pendingSearchHandle = null;\n\n    /* Number of requests that are in progress */\n    var activeRequests = 0;\n    /* Time that most recent search was started */\n    var latestSearchTimestamp = Date.now();\n    var latestResultsTimestamp = Date.now();\n\n    /* Search data for a pending search. Will be overwritten whenever a new\n     * search is queued */\n    var pendingSearch = null;\n\n    /**\n     * Make this the next search that will occur when a search is eligible, and\n     * ensure that an appropriate timer is running to initiate the pending\n     * search.\n     *\n     * @param {Phrase} searchPhrase\n     */\n    function deferSearch(searchPhrase) {\n      pendingSearch = searchPhrase;\n      if (pendingSearchHandle) {\n        // timer is already running, no need to start\n        return;\n      }\n\n      // no timer yet, start one\n      waitToRunPendingSearch();\n    }\n\n    function waitToRunPendingSearch() {\n      var eligibleSearchTime = latestSearchTimestamp + DELAY;\n      var timeUntilCanSearch = eligibleSearchTime - Date.now();\n\n      var delay = timeUntilCanSearch > 0 ? timeUntilCanSearch : DELAY;\n\n      pendingSearchHandle = $timeout(function () {\n        pendingSearchHandle = null;\n\n        if (activeRequests >= MAX_ACTIVE_REQUESTS) {\n          // too many requests, keep waiting\n          waitToRunPendingSearch();\n          return;\n        }\n\n        // run the actual search\n        runPendingSearch();\n      }, delay);\n    }\n\n    /**\n     * Initiate the pending search, and set appropriate variables.\n     */\n    function runPendingSearch() {\n      if (pendingSearch === null) {\n        // no pending search, skip\n        return;\n      }\n\n      var search = pendingSearch;\n      pendingSearch = null;\n      $timeout.cancel(pendingSearchHandle);\n      pendingSearchHandle = null;\n\n      searchByPhrase(search);\n    }\n\n    /**\n     * Perform a search, and set appropriate variables.\n     *\n     * @param {Phrase} phrase\n     */\n    function searchByPhrase(phrase) {\n      searchPhrase = phrase;\n      var timestamp = Date.now();\n      latestSearchTimestamp = timestamp;\n      activeRequests++;\n\n      // Run the search and notify listeners when it is done\n      SuggestionsService.getSuggestionsForPhrase(phrase).then(\n        function (suggestions) {\n          // Only update results if this search is more recent than the\n          // current results.\n          if (timestamp > latestResultsTimestamp) {\n            latestResultsTimestamp = timestamp;\n            results = suggestions;\n          }\n        },\n        function (error) {\n          console.error('Error searching for phrase ', error);\n        }).finally(function () {\n          activeRequests--;\n          $rootScope.$broadcast('PhraseSuggestionsService:updated');\n          if (activeRequests < MAX_ACTIVE_REQUESTS) {\n            runPendingSearch();\n          }\n        });\n    }\n\n\n    $rootScope.$on(EventService.EVENT.REQUEST_PHRASE_SUGGESTIONS,\n      function (event, wrapper) {\n        /* @type {Phrase} */\n        var data = wrapper.phrase;\n\n        if (pendingSearch && pendingSearch.id === data.id) {\n          // search already pending\n          return;\n        }\n\n        if (!pendingSearch && activeRequests === 0 && searchPhrase &&\n            searchPhrase.id === data.id) {\n          // search is identical and there are no other searches to replace it\n          return;\n        }\n\n        if (activeRequests >= MAX_ACTIVE_REQUESTS) {\n          // too many requests, queue this one instead\n          deferSearch(data);\n          return;\n        }\n\n        var eligibleSearchTime = latestSearchTimestamp + DELAY;\n\n        if (Date.now() < eligibleSearchTime) {\n          // Too early to search, defer the search\n          deferSearch(data);\n          return;\n        }\n\n        results = [];\n        $rootScope.$broadcast('PhraseSuggestionsService:updated');\n        searchByPhrase(data);\n      });\n\n    return {\n      isLoading: isLoading,\n      getSearchStrings: getSearchStrings,\n      getResults: getResults\n    };\n  }\n\n  angular\n    .module('app')\n    .factory('PhraseSuggestionsService', PhraseSuggestionsService);\n})();\n","(function () {\n  'use strict';\n\n  /**\n   * SuggestionCtrl.js\n   * @ngInject\n   */\n  function SuggestionCtrl(EventService, $rootScope, $scope, _, $timeout) {\n    var suggestionCtrl = this;\n\n    suggestionCtrl.copyButtonText = 'Copy Translation';\n\n    while ($scope.search.length < $scope.suggestion.sourceContents.length) {\n      $scope.search.push('');\n    }\n\n    /**\n     * Get a modifier for the row class that will determine display colours.\n     *\n     * Intended to be used to generate css class for the row:\n     *\n     *     TransUnit--{{suggestionCtrl.rowDisplayType()}}\n     *\n     * @return {string} modifier to append to the TransUnit-- css class\n     */\n\n    suggestionCtrl.rowDisplayType = function () {\n      /* @type {MatchDetail} */\n      var topMatch = suggestionCtrl.topMatch();\n\n      if (topMatch.type === 'IMPORTED_TM') {\n        return 'secondary';\n      }\n      if (topMatch.type === 'LOCAL_PROJECT') {\n        if (topMatch.contentState === 'Translated') {\n          return 'success';\n        }\n        if (topMatch.contentState === 'Approved') {\n          return 'highlight';\n        }\n      }\n      console.error('Unable to generate row display type for top match');\n    };\n\n    /**\n     *\n     * @returns {string}\n     */\n    suggestionCtrl.percentDisplayType = function () {\n      var type = suggestionCtrl.rowDisplayType();\n      return type.charAt(0).toUpperCase() + type.substring(1);\n    };\n\n    /**\n     * Return correct percentage to display.\n     *\n     * I am using this instead of Angular's number display because the number\n     * display forces a particular number of decimal places rather than just\n     * limiting to the specified number, and because we should never show 100%\n     * unless it is exactly 100%.\n     */\n    suggestionCtrl.percent = function () {\n      var percent = $scope.suggestion.similarityPercent;\n\n      // Prevent very high percentages displaying as 100%\n      if (percent > 99.99 && percent < 100) {\n        return '99.99';\n      }\n      if (percent >= 99.90 && percent < 100) {\n        return '99.9';\n      }\n\n      // Limit any inexact percentages to a single decimal place\n      if (Math.round(percent) !== percent) {\n        return percent.toFixed(1);\n      }\n\n      return percent;\n    };\n\n    /**\n     * Return the details for the best match according to the following\n     * criteria:\n     *\n     *  - Content state and type: Approved > Translated > Imported\n     *  - Last modified: older modifications take higher priority.\n     *\n     * @return {MatchDetail} the best match\n     */\n    suggestionCtrl.topMatch = function () {\n      return $scope.suggestion.matchDetails[0];\n    };\n\n    suggestionCtrl.showSuggestionCopied = function () {\n      suggestionCtrl.copyButtonText = 'Copied';\n      suggestionCtrl.copyButtonDisabled = true;\n      $timeout(function() {\n        suggestionCtrl.copyButtonDisabled = false;\n        suggestionCtrl.copyButtonText = 'Copy Translation';\n      }, 500);\n    };\n\n    /**\n     * Request this suggestion to be copied to the selected translation field.\n     *\n     * Generates a COPY_FROM_SUGGESTION event.\n     */\n    suggestionCtrl.copySuggestion = function () {\n      suggestionCtrl.showSuggestionCopied();\n      EventService.emitEvent(EventService.EVENT.COPY_FROM_SUGGESTION,\n        { suggestion: $scope.suggestion });\n    };\n\n    $scope.$on('EditorSuggestionsCtrl:nth-suggestion-copied',\n      function (event, index) {\n        if (index === $scope.index) {\n          suggestionCtrl.showSuggestionCopied();\n        }\n    });\n\n    $scope.detail = suggestionCtrl.topMatch();\n    // Will be undefined for imported matches\n    $scope.user = $scope.detail.lastModifiedBy || 'Annoymous';\n    $scope.remaining = $scope.suggestion.matchDetails.length - 1;\n    $scope.isTextFlow = $scope.detail.type === 'LOCAL_PROJECT';\n\n    return suggestionCtrl;\n  }\n\n  angular\n    .module('app')\n    .controller('SuggestionCtrl', SuggestionCtrl);\n})();\n\n","(function() {\n  'use strict';\n\n  /**\n   * @typedef {Object} ImportedMatchDetail\n   * @param {string} type - 'IMPORTED_TM'\n   * @param {number} transMemoryUnitId - numeric identifier for this translation\n   *                         memory unit on the server\n   * @param {string} transMemorySlug - identifier for the translation memory\n   *                         that contains this translation unit\n   * @param {string} transUnitId - optional identifier for this translation unit\n   * @param {string} lastChanged - date that this text flow was last changed, in\n   *                         ISO-8601 format\n   */\n\n  /**\n   * @typedef {Object} LocalMatchDetail\n   * @param {string} type - 'LOCAL_PROJECT'\n   * @param {number} textFlowId - numeric identifier for this text flow on the\n   *                         server\n   * @param {string} contentState - 'Translated' or 'Approved'\n   * @param {string} projectId - identifier for the project that this text flow\n   *                         is in\n   * @param {string} projectName - display name for the project that this text\n   *                         flow is in\n   * @param {string} version - identifier for the version that this text flow is\n   *                         in\n   * @param {string} documentPath - file path of the document that contains this\n   *                         text flow.\n   * @param {string} documentName - file name of the document that contains this\n   *                         text flow, without the file path\n   * @param {string} resId - natural id for this text flow within the document\n   * @param {string} lastModifiedDate - date that this text flow was last\n   *                         changed, in ISO-8601 format\n   * @param {string} lastModifiedBy - username of the user who last modified\n   *                         this text flow\n   */\n\n  /**\n   * @typedef {(ImportedMatchDetail|LocalMatchDetail)} MatchDetail\n   */\n\n  /**\n   * @typedef {Object} Suggestion\n   * @param {number} relevanceScore - score from the search engine indicating\n   *                         how close a match it considers this to the query.\n   *                         It is sensible to compare scores within a query,\n   *                         but not between queries.\n   * @param {number} similarityPercent - proportion of the characters in\n   *                         sourceContents that match the query\n   * @param {Array} sourceContents - suggested source text that is\n   *                                similar to the search\n   * @param {Array} targetContents - translations of the suggested\n   *                                source text\n   * @param {Array} matchDetails - summary of all the sources with\n   *                                     the same source and target contents\n   */\n\n  /**\n   * Provide suggestions based on given source text.\n   *\n   * SuggestionsService.js\n   * @ngInject\n   */\n  function SuggestionsService(EditorService, EventService, UrlService, _,\n                              $resource) {\n\n    /**\n     * Get a list of suggestions for how to translate a piece of text.\n     *\n     * @param {string} searchText\n     * @return {Promise>} suggestions for translating the\n     *                                      given text\n     */\n    function getSuggestionsForText(searchText) {\n      return getSuggestionsForContents([searchText]);\n    }\n\n    /**\n     * Get a list of suggestions for how to translate a phrase.\n     *\n     * @param {Phrase} phrase the source text to find suggestions for\n     * @returns {Promise>} suggestions for translating the\n     *                                       given phrase\n     */\n    function getSuggestionsForPhrase(phrase) {\n      return getSuggestionsForContents(phrase.sources)\n        .then(function (suggestions) {\n          EventService.emitEvent(EventService.EVENT.PHRASE_SUGGESTION_COUNT,\n            { id: phrase.id, count: suggestions.length });\n          return suggestions;\n        });\n    }\n\n    /**\n     * Get a list of suggestions for how to translate a list of strings.\n     *\n     * @param contents {Array} source strings to find matches for\n     * @returns {Promise>}\n     */\n    function getSuggestionsForContents(contents) {\n      var sourceLocale = EditorService.context.srcLocale.localeId;\n      var transLocale = EditorService.context.localeId;\n\n      var postQuery = {\n        query: {\n          method: 'POST',\n          params: {\n            from: sourceLocale,\n            to: transLocale,\n            searchType: 'FUZZY_PLURAL'\n          },\n          isArray: true\n        }\n      };\n\n      var Suggestions = $resource(UrlService.SUGGESTIONS_URL, {}, postQuery);\n      return Suggestions.query({}, contents).$promise.then(sortSuggestions);\n    }\n\n    /**\n     * Sort suggestions so better matches are at the top, and details are in\n     * order from most to least relevant.\n     *\n     * @param {Suggestion[]} suggestions\n     * @return {Suggestion[]} the given suggestions in order.\n     */\n    function sortSuggestions(suggestions) {\n      return _.chain(suggestions)\n        .map(sortDetails)\n        .map(addBestMatchScores)\n        .sortBy(['similarityPercent', 'bestMatchScore',\n                 'bestMatchModificationDate', 'relevanceScore'])\n        .reverse()\n        .value();\n    }\n\n    /**\n     * Add properties 'bestMatchScore' and 'bestMatchModificationDate' to a\n     * suggestion to help with sorting.\n     *\n     * Higher scores are considered better, since the final results are in\n     * descending order.\n     *\n     * @param {Suggestion} suggestion\n     * @return {Suggestion}\n     */\n    function addBestMatchScores (suggestion) {\n      var date, score;\n      var topMatch = suggestion.matchDetails[0];\n\n      if (topMatch.type === 'LOCAL_PROJECT') {\n        date = topMatch.lastModifiedDate;\n        score = topMatch.contentState === 'Translated' ? 0 : 1;\n      }\n\n      if (topMatch.type === 'IMPORTED_TM') {\n        date = topMatch.lastChanged;\n        score = 2;\n      }\n\n      return _.assign({}, suggestion, {\n        bestMatchScore: score,\n        bestMatchModificationDate: date\n      });\n    }\n\n    /**\n     * Sort the match details of a suggestion by type and date.\n     *\n     * @param {Suggestion} suggestion to sort details\n     * @return {Suggestion} the given suggestion with details in correct order\n     */\n    function sortDetails (suggestion) {\n      var sortedDetails = _.sortBy(suggestion.matchDetails, typeAndDateSort);\n      return _.assign({}, suggestion, { matchDetails: sortedDetails });\n    }\n\n    // TODO use sortByAll when lodash version is increased\n    /**\n     * Return a string that will naturally sort local project details before\n     * imported TM details, approved state above translated state, and older\n     * modification dates first, in that priority order.\n     *\n     * @param {MatchDetail} detail\n     * @return {string} representation of order that will sort appropriately.\n     */\n    function typeAndDateSort (detail) {\n\n      if (detail.type === 'IMPORTED_TM') {\n        return '3' + detail.lastChanged;\n      }\n      if (detail.type === 'LOCAL_PROJECT') {\n        if (detail.contentState === 'Translated') {\n          return '2' + detail.lastModifiedDate;\n        }\n        if (detail.contentState === 'Approved') {\n          return '1' + detail.lastModifiedDate;\n        }\n      }\n      // Unrecognized, sort last\n      return '9';\n    }\n\n\n\n    return {\n      getSuggestionsForPhrase: getSuggestionsForPhrase,\n      getSuggestionsForText: getSuggestionsForText\n    };\n  }\n\n  angular\n    .module('app')\n    .factory('SuggestionsService', SuggestionsService);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * TextSuggestionsService.js\n   * @ngInject\n   */\n  function TextSuggestionsService(_, EventService, SuggestionsService,\n                                    $rootScope, $timeout) {\n\n    /* Minimum time in milliseconds to wait between requesting results */\n    var DELAY = 300;\n    var MAX_ACTIVE_REQUESTS = 3;\n\n    /* @type {string} */\n    var searchText = null;\n\n    /* @type {Array} */\n    var results = [];\n\n    /**\n     * @return {boolean} true if results have been requested and not delivered\n     */\n    function isLoading() {\n      return activeRequests > 0;\n    }\n\n    /**\n     *\n     * @return {string[]} strings that were used to search, or null if no search\n     *                    has been performed.\n     */\n    function getSearchStrings() {\n      return searchText ? [searchText] : [];\n    }\n\n    /**\n     * Get results for the current search\n     * @return {Array} results for the current search. Empty if\n     *                             no search has been performed.\n     */\n    function getResults() {\n      return results;\n    }\n\n\n    var pendingSearchHandle = null;\n\n    /* Number of requests that are in progress */\n    var activeRequests = 0;\n    /* Time that most recent search was started */\n    var latestSearchTimestamp = Date.now();\n    var latestResultsTimestamp = Date.now();\n\n    /* Search text for a pending search. Will be overwritten whenever a new\n     * search is queued */\n    var pendingSearch = null;\n\n    /**\n     * Make this the next search that will occur when a search is eligible, and\n     * ensure that an appropriate timer is running to initiate the pending\n     * search.\n     *\n     * @param {string} searchText\n     */\n    function deferSearch(searchText) {\n      pendingSearch = searchText;\n      if (pendingSearchHandle) {\n        // timer is already running, no need to start\n        return;\n      }\n\n      // no timer yet, start one\n      waitToRunPendingSearch();\n    }\n\n    function waitToRunPendingSearch() {\n      var eligibleSearchTime = latestSearchTimestamp + DELAY;\n      var timeUntilCanSearch = eligibleSearchTime - Date.now();\n\n      var delay = timeUntilCanSearch > 0 ? timeUntilCanSearch : DELAY;\n\n      pendingSearchHandle = $timeout(function () {\n        pendingSearchHandle = null;\n\n        if (activeRequests >= MAX_ACTIVE_REQUESTS) {\n          // too many requests, keep waiting\n          waitToRunPendingSearch();\n          return;\n        }\n\n        // run the actual search\n        runPendingSearch();\n      }, delay);\n    }\n\n    /**\n     * Initiate the pending search, and set appropriate variables.\n     */\n    function runPendingSearch() {\n      if (pendingSearch === null) {\n        // no pending search, skip\n        return;\n      }\n\n      var search = pendingSearch;\n      pendingSearch = null;\n      $timeout.cancel(pendingSearchHandle);\n      pendingSearchHandle = null;\n\n      searchByText(search);\n    }\n\n    /**\n     * Perform a search, and set appropriate variables.\n     *\n     * @param {string} text\n     */\n    function searchByText(text) {\n      searchText = text;\n      var timestamp = Date.now();\n      latestSearchTimestamp = timestamp;\n      activeRequests++;\n\n      // Run the search and notify listeners when it is done\n      SuggestionsService.getSuggestionsForText(text).then(\n        function (suggestions) {\n          // Only update results if this search is more recent than the\n          // current results.\n          if (timestamp > latestResultsTimestamp) {\n            latestResultsTimestamp = timestamp;\n            results = suggestions;\n          }\n        },\n        function (error) {\n          console.error('Error searching for text ', error);\n        }).finally(function () {\n          activeRequests--;\n          $rootScope.$broadcast('TextSuggestionsService:updated');\n          if (activeRequests < MAX_ACTIVE_REQUESTS) {\n            runPendingSearch();\n          }\n        });\n    }\n\n\n    $rootScope.$on(EventService.EVENT.REQUEST_TEXT_SUGGESTIONS,\n      function (event, data) {\n\n        if (pendingSearch && pendingSearch === data) {\n          // search already pending\n          return;\n        }\n\n        if (!pendingSearch && activeRequests === 0 && searchText === data) {\n          // search is identical and there are no other searches to replace it\n          return;\n        }\n\n        // Empty search can update immediately\n        if (data === '') {\n          searchText = data;\n          //loading = false;\n          results = [];\n\n          // Ensure that earlier active searches will not overwrite results.\n          pendingSearch = null;\n          $timeout.cancel(pendingSearchHandle);\n          pendingSearchHandle = null;\n          latestSearchTimestamp = Date.now;\n          latestResultsTimestamp = Date.now();\n\n          $rootScope.$broadcast('TextSuggestionsService:updated');\n          return;\n        }\n\n        if (activeRequests >= MAX_ACTIVE_REQUESTS) {\n          // too many requests, queue this one instead\n          deferSearch(data);\n          return;\n        }\n\n        var eligibleSearchTime = latestSearchTimestamp + DELAY;\n\n        if (Date.now() < eligibleSearchTime) {\n          // Too early to search, defer the search\n          deferSearch(data);\n          return;\n        }\n\n        results = [];\n        $rootScope.$broadcast('TextSuggestionsService:updated');\n        searchByText(data);\n      });\n\n    return {\n      isLoading: isLoading,\n      getSearchStrings: getSearchStrings,\n      getResults: getResults\n    };\n  }\n\n  angular\n    .module('app')\n    .factory('TextSuggestionsService', TextSuggestionsService);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name suggestion\n   * @description suggestion container\n   * @ngInject\n   */\n  function suggestion() {\n    return {\n      // Only use the template on elements with this name (not on things that\n      // have an attribute or class called 'suggestion'.\n      restrict: 'E',\n      //required: ['suggestion'],\n\n      // Specify an isolated scope for the suggestion component.\n      scope: {\n        // make variable 'suggestion' available in the template's scope, and\n        // bind its value from the attribute with the same name.\n        // (a different name for the attribute can be specified after the =\n        suggestion: '=',\n        index: '=',\n        search: '=',\n        diffEnabled: '='\n\n        // If I put & instead of = in front of a name, it will run it in the\n        // parent scope instead of this directive's isolated scope. Good for\n        // callbacks.\n      },\n      controller: 'SuggestionCtrl as suggestionCtrl',\n      templateUrl: 'components/suggestions/suggestion.html'\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('suggestion', suggestion);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name toggle-checkbox\n   * @description Add an extra element to a checkbox to\n   * so we can style it differently\n   * @ngInject\n   */\n  function toggleCheckbox() {\n    return {\n      restrict: 'A',\n      link: function(scope, element) {\n        element.after('');\n      }\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('toggleCheckbox', toggleCheckbox);\n\n})();\n","(function () {\n  'use strict';\n\n  /**\n   * @typedef {Object} StatusInfo\n   * @property {string} ID lower case translation status (content state)\n   * @property {string} NAME capitalized representation\n   * @property {string} CSSCLASS css class to use for this status\n   *\n   */\n  /**\n   * TransStatusService.js\n   *\n   * @ngInject\n   */\n  function TransStatusService(_) {\n    var transStatusService = this,\n        STATUSES = {\n          'UNTRANSLATED': {\n            'ID': 'untranslated',\n            'NAME': 'Untranslated',\n            'CSSCLASS': 'neutral'\n          },\n          'NEEDSWORK': {\n            'ID': 'needswork',\n            'NAME': 'Needs Work',\n            'CSSCLASS': 'unsure'\n          },\n          'TRANSLATED' : {\n            'ID': 'translated',\n            'NAME': 'Translated',\n            'CSSCLASS': 'success'\n          },\n          'APPROVED': {\n            'ID': 'approved',\n            'NAME': 'Approved',\n            'CSSCLASS': 'highlight'\n          }\n        };\n\n    transStatusService.getAll = function() {\n      return STATUSES;\n    };\n\n    transStatusService.getAllAsArray = function() {\n      return _.values(STATUSES);\n    };\n\n    /**\n     *\n     * @param {string} statusKey string representation of the status.\n     * @returns {StatusInfo}\n     */\n    transStatusService.getStatusInfo = function(statusKey) {\n      return STATUSES[conformStatus(statusKey)];\n    };\n\n    transStatusService.getId = function(statusKey) {\n      return STATUSES[conformStatus(statusKey)].ID;\n    };\n\n    transStatusService.getServerId = function(statusId) {\n      return serverStatusId(statusId);\n    };\n\n    transStatusService.getName = function(statusKey) {\n      return STATUSES[conformStatus(statusKey)].NAME;\n    };\n\n    transStatusService.getCSSClass = function(statusKey) {\n      return STATUSES[conformStatus(statusKey)].CSSCLASS;\n    };\n\n    /**\n     * Conform it to uppercase for lookups and\n     * temporary fix for server sending \"needReview\"\n     * instead of needswork status\n     * @param  {string} status\n     * @return {string}        new value to use\n     */\n    function conformStatus(statusKey) {\n      statusKey = angular.uppercase(statusKey);\n      if (!statusKey || statusKey === 'NEW') {\n        statusKey = 'UNTRANSLATED';\n      } else if (statusKey === 'NEEDREVIEW') {\n        statusKey = 'NEEDSWORK';\n      }\n      return statusKey;\n    }\n\n    /**\n     * Conform it to PascalCase for lookups and\n     * temporary fix for server receiving \"needReview\"\n     * instead of needswork status\n     * @param  {string} status\n     * @return {string}        new value to use\n     */\n    function serverStatusId(statusId) {\n      statusId = angular.lowercase(statusId);\n      if (!statusId || statusId === 'untranslated') {\n        return 'New';\n      } else if (statusId === 'needswork') {\n        return 'NeedReview';\n      }\n      return statusId.charAt(0).toUpperCase() + statusId.slice(1).toLowerCase();\n    }\n\n    return transStatusService;\n  }\n\n  angular\n    .module('app')\n    .factory('TransStatusService', TransStatusService);\n})();\n\n","(function () {\n  'use strict';\n\n  /**\n   * TransUnitCtrl.js\n   * @ngInject\n   */\n  function TransUnitCtrl($rootScope, $scope, $element, $stateParams, _,\n                         TransUnitService, EventService, LocaleService, focus,\n                         EditorShortcuts, PhraseUtil, SettingsService) {\n\n    var transUnitCtrl = this;\n\n    transUnitCtrl.selected = false;\n    transUnitCtrl.focused = false;\n    transUnitCtrl.focusedTranslationIndex = 0;\n\n    transUnitCtrl.hasTranslationChanged =\n      PhraseUtil.hasTranslationChanged;\n\n    transUnitCtrl.focusTranslation = function() {\n      if(transUnitCtrl.selected) {\n        focus('phrase-' + $scope.phrase.id + '-' +\n        transUnitCtrl.focusedTranslationIndex);\n      }\n    };\n\n    // when user clicked on TU or using tab to nav\n    transUnitCtrl.onTextAreaFocus = function(phrase, index) {\n      transUnitCtrl.focused = true;\n      if (!_.isUndefined(index)) {\n        transUnitCtrl.focusedTranslationIndex = index;\n      }\n      if(!transUnitCtrl.selected) {\n        EventService.emitEvent(EventService.EVENT.SELECT_TRANS_UNIT,\n          {'id': phrase.id,\n            'updateURL': true,\n            'focus': true\n          }, $scope);\n      }\n    };\n\n    transUnitCtrl.translationTextModified = function(phrase) {\n      EventService.emitEvent(EventService.EVENT.TRANSLATION_TEXT_MODIFIED,\n          phrase);\n    };\n\n    transUnitCtrl.getPhrase = function() {\n      return $scope.phrase;\n    };\n\n    transUnitCtrl.init = function() {\n      TransUnitService.addController($scope.phrase.id, transUnitCtrl);\n      if($stateParams.id && parseInt($stateParams.id) === $scope.phrase.id) {\n        EventService.emitEvent(EventService.EVENT.SELECT_TRANS_UNIT,\n          {'id': $stateParams.id,\n            'updateURL': false,\n            'focus' : $stateParams.selected});\n      }\n    };\n\n    transUnitCtrl.copySource = function($event, phrase, sourceIndex) {\n      $event.stopPropagation(); //prevent click event of TU\n      EventService.emitEvent(EventService.EVENT.COPY_FROM_SOURCE,\n        {'phrase': phrase, 'sourceIndex': sourceIndex}, $scope);\n    };\n\n    transUnitCtrl.undoEdit = function($event, phrase) {\n      $event.stopPropagation(); //prevent click event of TU\n      EventService.emitEvent(EventService.EVENT.UNDO_EDIT,\n        phrase, $scope);\n    };\n\n    transUnitCtrl.cancelEdit = function($event, phrase) {\n      $event.stopPropagation(); //prevent click event of TU\n      EventService.emitEvent(EventService.EVENT.CANCEL_EDIT,\n        phrase, $scope);\n    };\n\n    transUnitCtrl.saveAs = function($event, phrase, status) {\n      EditorShortcuts.saveTranslationCallBack($event, phrase, status);\n    };\n\n    transUnitCtrl.getLocaleName = function(localeId) {\n      return LocaleService.getName(localeId);\n    };\n\n    transUnitCtrl.toggleSaveAsOptions = function(open) {\n      EventService.broadcastEvent( open ? 'openDropdown': 'closeDropdown',\n        {}, $scope);\n      if (open) {\n        // focus on the first dropdown option\n        focus($scope.phrase.id + '-saveAsOption-0');\n      }\n    };\n\n    var SHOW_SUGGESTIONS = SettingsService.SETTING.SHOW_SUGGESTIONS;\n    $scope.showSuggestions = SettingsService.subscribe(SHOW_SUGGESTIONS,\n      function (show) {\n        $scope.showSuggestions = show;\n      });\n\n    $rootScope.$on(EventService.EVENT.SUGGESTIONS_SEARCH_TOGGLE,\n      function(event, data) {\n        transUnitCtrl.suggestionsSearchIsActive = data;\n      });\n\n    transUnitCtrl.toggleSuggestionPanel = function () {\n      if (transUnitCtrl.suggestionsSearchIsActive) {\n        EventService.emitEvent(EventService.EVENT.SUGGESTIONS_SEARCH_TOGGLE,\n          false);\n      }\n      else {\n        SettingsService.update(SHOW_SUGGESTIONS, !$scope.showSuggestions);\n      }\n    };\n\n    $scope.suggestionCount = 0;\n    $rootScope.$on(EventService.EVENT.PHRASE_SUGGESTION_COUNT,\n      function (event, data) {\n        if (data.id === $scope.phrase.id) {\n          $scope.suggestionCount = data.count;\n        }\n      });\n\n    transUnitCtrl.cancelSaveAsMode = function() {\n      EditorShortcuts.cancelSaveAsModeIfOn();\n    };\n\n    $scope.$on('$destroy', function () {\n      $element.unbind('click', onTransUnitClick);\n      $element.unbind('focus', onTransUnitClick);\n    });\n\n    transUnitCtrl.updateSaveButton = function (phrase) {\n      transUnitCtrl.saveButtonStatus =\n        PhraseUtil.getSaveButtonStatus($scope.phrase);\n      transUnitCtrl.saveButtonOptions =\n        TransUnitService.getSaveButtonOptions(transUnitCtrl.saveButtonStatus,\n          $scope.phrase);\n      transUnitCtrl.saveButtonText = transUnitCtrl.saveButtonStatus.NAME;\n      transUnitCtrl.saveButtonDisabled =\n        !PhraseUtil.hasTranslationChanged(phrase);\n      transUnitCtrl.loadingClass = '';\n      transUnitCtrl.savingStatus = '';\n    };\n\n    transUnitCtrl.phraseSaving = function (data) {\n      transUnitCtrl.loadingClass = 'is-loading';\n      transUnitCtrl.saveButtonStatus =\n        transUnitCtrl.savingStatus = data.status;\n      transUnitCtrl.saveButtonOptions =\n        TransUnitService.getSaveButtonOptions(transUnitCtrl.saveButtonStatus,\n          data.phrase);\n      transUnitCtrl.saveButtonText = 'Saving…';\n      transUnitCtrl.saveButtonDisabled = true;\n    };\n\n    transUnitCtrl.saveButtonOptionsAvailable = function() {\n      return !_.isEmpty(transUnitCtrl.saveButtonOptions);\n    };\n\n    transUnitCtrl.selectTransUnit = function(phrase) {\n      if (!transUnitCtrl.selected) {\n        EventService.emitEvent(EventService.EVENT.SELECT_TRANS_UNIT,\n                               {'id': phrase.id,\n                                 'updateURL': true,\n                                 'focus': true\n                               }, $scope);\n      }\n    };\n\n    function onTransUnitClick() {\n      if(!transUnitCtrl.selected) {\n        $scope.$apply(function () {\n          EventService.emitEvent(EventService.EVENT.SELECT_TRANS_UNIT,\n            {'id': $scope.phrase.id,\n              'updateURL': true,\n              'focus': true}, $scope);\n        });\n      }\n    }\n\n    return transUnitCtrl;\n  }\n\n  angular\n    .module('app')\n    .controller('TransUnitCtrl', TransUnitCtrl);\n})();\n\n","(function () {\n  'use strict';\n\n  /**\n   * TransUnitService\n   *\n   * See PhraseService.transformToPhrases function for phrase definition.\n   *\n   * @ngInject\n   */\n  function TransUnitService(_, $location, $rootScope, $state, $stateParams,\n    $filter, MessageHandler, EventService, TransStatusService, PRODUCTION,\n    EditorShortcuts, PhraseUtil, $timeout) {\n    var transUnitService = this,\n        controllerList = {},\n        selectedTUId;\n\n    transUnitService.addController = function(id, controller) {\n      controllerList[id] = controller;\n    };\n\n    transUnitService.getSaveButtonOptions = function(saveButtonStatus, phrase) {\n      return filterSaveButtonOptions(saveButtonStatus, phrase);\n    };\n\n    $rootScope.$on(EventService.EVENT.TOGGLE_SAVE_OPTIONS,\n      function(event, data) {\n        var transUnitCtrl = controllerList[data.id];\n        if (transUnitCtrl) {\n          transUnitCtrl.toggleSaveAsOptions(data.open);\n        }\n    });\n\n    /**\n     * EventService.EVENT.SELECT_TRANS_UNIT listener\n     * - Select and focus a trans-unit.\n     * - Perform implicit save on previous selected TU if changed\n     * - Update url with TU id without reload state\n     */\n    $rootScope.$on(EventService.EVENT.SELECT_TRANS_UNIT,\n      function (event, data) {\n        var newTuController = controllerList[data.id],\n            oldTUController = controllerList[selectedTUId],\n            updateURL = data.updateURL;\n\n        EventService.emitEvent(EventService.EVENT.REQUEST_PHRASE_SUGGESTIONS,\n          {\n            'phrase' : newTuController.getPhrase()\n          });\n\n        if(newTuController) {\n          EditorShortcuts.selectedTUCtrl = newTuController;\n\n          if (selectedTUId && selectedTUId !== data.id) {\n            setSelected(oldTUController, false);\n\n            //perform implicit save if changed\n            if(PhraseUtil.hasTranslationChanged(\n              oldTUController.getPhrase())) {\n              EventService.emitEvent(EventService.EVENT.SAVE_TRANSLATION,\n                {\n                  'phrase' : oldTUController.getPhrase(),\n                  'status' : TransStatusService.getStatusInfo('TRANSLATED'),\n                  'locale' : $stateParams.localeId,\n                  'docId'  : $stateParams.docId\n                });\n            }\n          }\n\n          updateSaveButton(event, newTuController.getPhrase());\n          selectedTUId = data.id;\n          setSelected(newTuController, true);\n\n          EventService.emitEvent(EventService.EVENT.FOCUS_TRANSLATION, data);\n\n          //Update url without reload state\n          if(updateURL) {\n            if($state.current.name !== 'editor.selectedContext.tu') {\n              $state.go('editor.selectedContext.tu', {\n                'id': data.id,\n                'selected': data.focus.toString()\n              });\n            } else {\n              $location.search('id', data.id);\n              $location.search('selected', data.focus.toString());\n            }\n          }\n        } else {\n          MessageHandler.displayWarning('Trans-unit not found:' + data.id);\n        }\n      });\n\n    /**\n     * EventService.EVENT.COPY_FROM_SOURCE listener\n     * Copy translation from source\n     */\n    $rootScope.$on(EventService.EVENT.COPY_FROM_SOURCE,\n      function (event, data) {\n        var sourceIndex = 0;\n        if(data.phrase.plural) {\n          //clicked copy source button\n          sourceIndex = data.sourceIndex;\n          if(_.isUndefined(sourceIndex)) {\n            //copy source key shortcut, copy corresponding source to target\n            var transUnitCtrl = controllerList[data.phrase.id];\n            sourceIndex = transUnitCtrl.focusedTranslationIndex;\n            if(data.phrase.sources.length <\n              transUnitCtrl.focusedTranslationIndex + 1) {\n              sourceIndex = data.phrase.sources.length - 1;\n            }\n          }\n        }\n        setTranslationText(data.phrase, data.phrase.sources[sourceIndex]);\n      });\n\n    $rootScope.$on(EventService.EVENT.COPY_FROM_SUGGESTION,\n      function (event, data) {\n        if (selectedTUId) {\n          var transUnitCtrl = controllerList[selectedTUId];\n          var phrase = transUnitCtrl.getPhrase();\n\n          var suggestion = data.suggestion;\n          var targets = suggestion.targetContents;\n\n          var copyAsPlurals = phrase.plural && targets.length > 1;\n\n\n          if (copyAsPlurals) {\n            var pluralCount = phrase.translations.length;\n\n            if (targets.length < pluralCount) {\n              var lastSuggestion = _.last(targets);\n              // pad suggestions with last suggestion, but only when there are\n              // no translations entered for the extra plural forms.\n              targets = _.assign(phrase.translations.slice(), targets,\n                function (current, suggested) {\n                  if (suggested) return suggested;\n                  if (current) return current;\n                  return lastSuggestion;\n                });\n            }\n            if (targets.length > pluralCount) {\n              targets = _.first(targets, pluralCount);\n            }\n\n            setAllTranslations(phrase, targets);\n          } else {\n            setTranslationText(phrase, targets[0]);\n          }\n        }\n      });\n\n    /**\n     * EventService.EVENT.UNDO_EDIT listener\n     * Cancel edit and restore translation\n     */\n    $rootScope.$on(EventService.EVENT.UNDO_EDIT,\n      function (event, phrase) {\n        if (PhraseUtil.hasTranslationChanged(phrase)) {\n          setAllTranslations(phrase, phrase.translations);\n        }\n      });\n\n    /**\n     * EventService.EVENT.CANCEL_EDIT listener\n     * Cancel edit and restore translation\n     */\n    $rootScope.$on(EventService.EVENT.CANCEL_EDIT,\n      function (event, phrase) {\n        if(selectedTUId) {\n          setSelected(controllerList[selectedTUId], false);\n          selectedTUId = false;\n          EditorShortcuts.selectedTUCtrl = null;\n        }\n\n        $location.search('selected', null);\n        if(!phrase) {\n          $location.search('id', null);\n        }\n\n        // EditorContentCtrl#changePage doesn't provide a phrase object\n        if (phrase) {\n          $timeout(function() {\n            return $rootScope.$broadcast('blurOn', 'phrase-' + phrase.id);\n          });\n        }\n      });\n\n    /**\n     * EventService.EVENT.TRANSLATION_TEXT_MODIFIED listener\n     *\n     */\n    $rootScope.$on(EventService.EVENT.TRANSLATION_TEXT_MODIFIED,\n       updateSaveButton);\n\n    /**\n     * EventService.EVENT.FOCUS_TRANSLATION listener\n     *\n     */\n    $rootScope.$on(EventService.EVENT.FOCUS_TRANSLATION,\n       setFocus);\n\n    /**\n      * EventService.EVENT.SAVE_COMPLETED listener\n      *\n      */\n    $rootScope.$on(EventService.EVENT.SAVE_INITIATED,\n       phraseSaving);\n\n    /**\n      * EventService.EVENT.SAVE_COMPLETED listener\n      *\n      */\n    $rootScope.$on(EventService.EVENT.SAVE_COMPLETED,\n       updateSaveButton);\n\n    function setTranslationText(phrase, newText) {\n      var index = 0;\n      if (phrase.plural) {\n        var transUnitCtrl = controllerList[phrase.id];\n        index = transUnitCtrl.focusedTranslationIndex;\n      }\n      phrase.newTranslations[index] = newText;\n      EventService.emitEvent(EventService.EVENT.TRANSLATION_TEXT_MODIFIED,\n        phrase);\n      EventService.emitEvent(EventService.EVENT.FOCUS_TRANSLATION,\n        phrase);\n    }\n\n    function setAllTranslations(phrase, newTexts) {\n      //need slice() for new instance of array\n      phrase.newTranslations = newTexts.slice();\n\n      EventService.emitEvent(EventService.EVENT.TRANSLATION_TEXT_MODIFIED,\n        phrase);\n      EventService.emitEvent(EventService.EVENT.FOCUS_TRANSLATION,\n        phrase);\n    }\n\n    function updateSaveButton(event, phrase) {\n       var transUnitCtrl = controllerList[phrase.id];\n       transUnitCtrl.updateSaveButton(phrase);\n    }\n\n    function phraseSaving(event, data) {\n      var transUnitCtrl = controllerList[data.phrase.id];\n      transUnitCtrl.phraseSaving(data);\n      EventService.emitEvent(EventService.EVENT.FOCUS_TRANSLATION,\n        data.phrase);\n    }\n\n    function setSelected(transUnitCtrl, isSelected) {\n      //This check is to prevent selected event being triggered repeatedly.\n      if(transUnitCtrl.selected !== isSelected) {\n        transUnitCtrl.selected = isSelected || false;\n      }\n    }\n\n    function setFocus(event, phrase) {\n      var transUnitCtrl = controllerList[phrase.id];\n      transUnitCtrl.focusTranslation();\n    }\n\n    /**\n     * Filters the dropdown options for saving a translation\n     * Unless the translation is empty, remove untranslated as an option\n     * Filter the current default save state out of the list and show remaining\n     *\n     * @param  {Object} saveStatus The current default translation *save* status\n     * @return {Array}             Is used to construct the dropdown list\n     */\n    function filterSaveButtonOptions(saveStatus, phrase) {\n      var filteredOptions = [];\n      if (saveStatus.ID === 'untranslated') {\n        return filteredOptions;\n      }\n      filteredOptions = $filter('filter')\n      (TransStatusService.getAllAsArray(), {ID: '!untranslated'});\n\n      if(phrase.plural) {\n        if(PhraseUtil.hasNoTranslation(phrase)) {\n          filteredOptions = $filter('filter')\n          (filteredOptions, {ID: '!needswork'});\n        } else if(PhraseUtil.hasEmptyTranslation(phrase)) {\n            filteredOptions = $filter('filter')\n            (filteredOptions, {ID: '!translated'});\n        }\n      }\n\n      if (PRODUCTION) {\n        filteredOptions = $filter('filter')\n        (filteredOptions, {ID: '!approved'});\n      }\n\n      return $filter('filter')(filteredOptions, {ID: '!'+saveStatus.ID});\n    }\n\n    return transUnitService;\n  }\n\n  angular\n    .module('app')\n    .factory('TransUnitService', TransUnitService);\n})();\n\n\n","(function() {\n  'use strict';\n\n  /**\n   * @name trans-unit\n   * @description transUnit container\n   * @ngInject\n   */\n  function transUnit() {\n    return {\n      restrict: 'E',\n      required: ['phrase', 'editorContext'],\n      scope: {\n        phrase: '=',\n        firstPhrase: '=',\n        editorContext: '='\n      },\n      controller: 'TransUnitCtrl as transUnitCtrl',\n      templateUrl: 'components/transUnit/trans-unit.html',\n      link: function(scope, element, attr, TransUnitCtrl) {\n        TransUnitCtrl.init();\n      }\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('transUnit', transUnit);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * @name trans-unit\n   * @description transUnit container\n   * @ngInject\n   */\n  function transUnitFilter() {\n    return {\n      restrict: 'E',\n      required: ['editor'],\n      scope: {\n        editor: '='\n      },\n      templateUrl: 'components/transUnitFilter/trans-unit-filter.html'\n    };\n  }\n\n  angular\n    .module('app')\n    .directive('transUnitFilter', transUnitFilter);\n\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * UserService.js\n   *\n   * @ngInject\n   */\n  function UserService($resource, UrlService) {\n\n    function getUserInfo(username) {\n      var UserInfo = $resource(UrlService.USER_INFO_URL, {}, {\n        query: {\n          method: 'GET',\n          params: {\n            username: username\n          }\n        }\n      });\n      return UserInfo.query().$promise;\n    }\n\n    function getMyInfo() {\n      var MyInfo = $resource(UrlService.MY_INFO_URL, {}, {\n        query: {\n          method: 'GET'\n        }\n      });\n      return MyInfo.query().$promise;\n    }\n\n    return {\n      settings: {\n        editor: {\n          hideMainNav: false\n        }\n      },\n      getUserInfo: getUserInfo,\n      getMyInfo: getMyInfo\n    };\n  }\n  angular\n    .module('app')\n    .factory('UserService', UserService);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * FilterUtil.js\n   *\n   * @ngInject\n   */\n  function FilterUtil(StringUtil, _) {\n\n    /**\n     * Filter in resources on given fields with matched terms\n     *\n     * @param resources - list of resources\n     * @param fields - list of fields to check\n     * @param terms - list of term to check\n     * @returns {*}\n     */\n    function filterResources(resources, fields, terms) {\n      if(!resources || !fields || !terms) {\n        return resources;\n      }\n      return _.filter(resources, function (resource) {\n        return isInclude(resource, fields, terms);\n      });\n    }\n\n    /**\n     * Filter out properties starting with $ (added by promise)\n     * @param resources\n     */\n    function cleanResourceMap(resources) {\n      var filteredList = {};\n      var ids = Object.keys(resources).filter(function (id) {\n        return id.indexOf('$') === -1;\n      });\n      ids.forEach(function(id) {\n        filteredList[id] = (resources[id]);\n      });\n      return filteredList;\n    }\n\n    function cleanResourceList(resources) {\n      var filteredList = [];\n      var ids = Object.keys(resources).filter(function (id) {\n        return id.indexOf('$') === -1;\n      });\n      ids.forEach(function(id) {\n        filteredList.push(resources[id]);\n      });\n      return filteredList;\n    }\n\n\n    function isInclude(resource, fields, terms) {\n      if(!resource || !fields || !terms) {\n        return false;\n      }\n      return _.any(fields, function(field) {\n        return _.any(terms, function(term) {\n          return StringUtil.equals(resource[field], term, true);\n        });\n      });\n    }\n\n    return {\n      filterResources  : filterResources,\n      cleanResourceList:cleanResourceList,\n      cleanResourceMap   : cleanResourceMap\n    };\n  }\n  angular\n    .module('app')\n    .factory('FilterUtil', FilterUtil);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * PhraseUtil.js\n   *\n   * @ngInject\n   */\n  function PhraseUtil(TransStatusService, _) {\n\n    function getSaveButtonStatus(phrase) {\n      if (hasNoTranslation(phrase)) {\n        return TransStatusService.getStatusInfo('untranslated');\n      }\n      else if (hasEmptyTranslation(phrase)) {\n        return TransStatusService.getStatusInfo('needswork');\n      }\n      else if (hasTranslationChanged(phrase)) {\n        return TransStatusService.getStatusInfo('translated');\n      }\n      else {\n        return phrase.status;\n      }\n    }\n\n    function hasTranslationChanged(phrase) {\n      // on Firefox with input method turned on,\n      // when hitting tab it seems to turn undefined value into ''\n      var allSame = _.every(phrase.translations,\n        function(translation, index) {\n          return nullToEmpty(translation) ===\n            nullToEmpty(phrase.newTranslations[index]);\n        });\n      return !allSame;\n    }\n\n    function hasNoTranslation(phrase) {\n      return _.isEmpty(_.compact(phrase.newTranslations));\n    }\n\n    function hasEmptyTranslation(phrase) {\n      return _.compact(phrase.newTranslations).length !==\n        phrase.newTranslations.length;\n    }\n\n    function nullToEmpty(value) {\n      return value || '';\n    }\n\n    return {\n      getSaveButtonStatus  : getSaveButtonStatus,\n      hasTranslationChanged : hasTranslationChanged,\n      hasNoTranslation : hasNoTranslation,\n      hasEmptyTranslation : hasEmptyTranslation\n    };\n  }\n  angular\n    .module('app')\n    .factory('PhraseUtil', PhraseUtil);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * Utility method for handling $resource.statistic\n   *\n   * StatisticUtil.js\n   * @ngInject\n   *\n   */\n\n  function StatisticUtil() {\n    return {\n      getWordStatistic: function(statistics) {\n        return statistics[0].unit === 'WORD' ? statistics[0] : statistics[1];\n      },\n      getMsgStatistic: function(statistics) {\n        return statistics[0].unit === 'MESSAGE' ? statistics[0] : statistics[1];\n      }\n    };\n  }\n  angular\n    .module('app')\n    .factory('StatisticUtil', StatisticUtil);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * StringUtil\n   *\n   * @ngInject\n   */\n\n  function StringUtil() {\n    function startsWith(str, prefix, ignoreCase) {\n      if (ignoreCase && str && prefix) {\n        str = str.toUpperCase();\n        prefix = prefix.toUpperCase();\n      }\n      return str.lastIndexOf(prefix, 0) === 0;\n    }\n\n    function endsWith(str, suffix, ignoreCase) {\n      if (ignoreCase && str && suffix) {\n        str = str.toUpperCase();\n        suffix = suffix.toUpperCase();\n      }\n      return str.indexOf(suffix, str.length - suffix.length) !== -1;\n    }\n\n    function equals(from, to, ignoreCase) {\n      if (ignoreCase && from && to) {\n        from = from.toUpperCase();\n        to = to.toUpperCase();\n      }\n      return from === to;\n    }\n\n    return {\n      startsWith : startsWith,\n      endsWith   : endsWith,\n      equals     : equals\n    };\n  }\n  angular\n    .module('app')\n    .factory('StringUtil', StringUtil);\n})();\n","(function() {\n  'use strict';\n\n  /**\n   * Utility to handles URL related request.\n   *\n   * UrlService.js\n   * @ngInject\n   */\n  function UrlService($location, $http, $q, $stateParams, _) {\n    //IE doesn't support location.origin\n    if (!location.origin) {\n      location.origin =\n        window.location.protocol + '//' + window.location.hostname +\n        (window.location.port ? (':' + window.location.port) : '');\n    }\n\n    var urlService = this,\n      gravatarBaseUrl = 'http://www.gravatar.com/avatar',\n      configFile = 'config.json',\n      baseUrl = '',\n      urls = {},\n      uiTranslationsURL = location.origin + location.pathname +\n        'translations';\n\n    urlService.serverContextPath = '';\n\n    urlService.init = function () {\n      if (baseUrl) {\n        return $q.when(baseUrl);\n      }\n      else {\n        /**\n         * Temporary solution to handle dynamic context path deployed for\n         * Zanata server in JBOSS (/ or /zanata).\n         *\n         * If config.baseUrl exist and not empty,\n         * baseUrl = config.baseUrl\n         *\n         * ELSE\n         * baseUrl = full.url - appPath onwards\n         */\n        return $http.get(configFile).then(function (response) {\n          var config = response.data;\n          if (config.baseUrl) {\n            baseUrl = config.baseUrl;\n          } else {\n            var deployPath = config.appPath.replace(/^\\//g, ''),\n                index = location.href.indexOf(deployPath);\n\n            urlService.serverContextPath = location.origin + location.pathname;\n            if(index >= 0) {\n              urlService.serverContextPath = location.href.substring(0, index);\n            }\n            urlService.serverContextPath = urlService.serverContextPath.\n              replace(/\\/?$/, '/');\n            baseUrl = urlService.serverContextPath + 'rest';\n          }\n\n          /* jshint -W101 */\n          // URLs over multiple lines are hard to read, allowing long lines here.\n          // Warnings for jshint are turned off/on with -/+ before the warning code.\n          // See: https://github.com/jshint/jshint/blob/2.1.4/src/shared/messages.js\n          urls = _.mapValues({\n            project: '/project/:projectSlug',\n            docs: '/project/:projectSlug/version/:versionSlug/docs',\n            locales: '/project/:projectSlug/version/:versionSlug/locales',\n            status: '/project/:projectSlug/version/:versionSlug/doc/:docId/status/:localeId',\n            textFlows: '/source+trans/:localeId',\n            docStats: '/stats/project/:projectSlug/version/:versionSlug/doc/:docId/locale/:localeId',\n            myInfo: '/user',\n            userInfo: '/user/:username',\n            translation: '/trans/:localeId',\n            allLocales: '/locales',\n            suggestions: '/suggestions'\n          }, unary(restUrl));\n          /* jshint +W101 */\n\n          urlService.PROJECT_URL = urls.project;\n          urlService.LOCALE_LIST_URL = urls.locales;\n          urlService.DOCUMENT_LIST_URL = urls.docs;\n          urlService.TRANSLATION_STATUS_URL = urls.status;\n          urlService.TEXT_FLOWS_URL = urls.textFlows;\n          urlService.DOC_STATISTIC_URL = urls.docStats;\n          urlService.MY_INFO_URL = urls.myInfo;\n          urlService.USER_INFO_URL = urls.userInfo;\n          urlService.TRANSLATION_URL = urls.translation;\n          urlService.ALL_LOCALE_URL = urls.allLocales;\n          urlService.SUGGESTIONS_URL = urls.suggestions;\n\n          urlService.PROJECT_PAGE = function(projectSlug, versionSlug) {\n            return urlService.serverContextPath + 'iteration/view/' +\n              projectSlug + '/' +  versionSlug;\n          };\n\n          urlService.DASHBOARD_PAGE = urlService.serverContextPath +\n            'dashboard';\n        });\n      }\n    };\n\n    /**\n     * Get the value of a query string parameter.\n     */\n    urlService.readValue = function (key) {\n      return $location.search()[key];\n    };\n\n    urlService.gravatarUrl = function (gravatarHash, size) {\n      return gravatarBaseUrl + '/' + gravatarHash +\n        '?d=mm&r=g&s=' + size;\n    };\n\n    urlService.uiTranslationURL = function (locale) {\n      return uiTranslationsURL + '/' + locale + '.json';\n    };\n\n    urlService.uiTranslationListURL = uiTranslationsURL + '/locales';\n\n    return urlService;\n\n    /**\n     * Create a REST URL by appending all the given URL part arguments to the\n     * base URL.\n     *\n     * No separators will be added or removed, so all parts should include\n     * leading / and exclude trailing / to avoid problems.\n     */\n    function restUrl() {\n      return baseUrl + Array.prototype.join.call(arguments, '');\n    }\n\n    /**\n     * Decorate a function to ignore all but the first argument.\n     */\n    function unary(fun) {\n      return function(arg) {\n        return fun(arg);\n      };\n    }\n  }\n\n  angular\n    .module('app')\n    .factory('UrlService', UrlService);\n})();\n"],"sourceRoot":"/source/"}
\ No newline at end of file