]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5114 Modify client side application to support App WS
authorStas Vilchik <vilchiks@gmail.com>
Wed, 5 Mar 2014 17:16:25 +0000 (18:16 +0100)
committerStas Vilchik <vilchiks@gmail.com>
Wed, 5 Mar 2014 17:16:31 +0000 (18:16 +0100)
Also add translation module

34 files changed:
plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties
sonar-server/karma.conf.js
sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QgateAppHandler.java
sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_head.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/measures/search.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/index.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_actions_template.hbs.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_condition_template.hbs.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_conditions_empty_template.hbs.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_conditions_template.hbs.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_header_template.hbs.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_projects_template.hbs.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_edit_template.hbs.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_sidebar_list_empty_template.hbs.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_sidebar_list_item_template.hbs.erb
sonar-server/src/main/webapp/javascripts/common/handlebars-extensions.js
sonar-server/src/main/webapp/javascripts/common/inputs.coffee
sonar-server/src/main/webapp/javascripts/common/inputs.js
sonar-server/src/main/webapp/javascripts/quality-gate/app.coffee
sonar-server/src/main/webapp/javascripts/quality-gate/app.js
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-condition-view.coffee
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-condition-view.js
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-conditions-view.coffee
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-conditions-view.js
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-header-view.coffee
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-header-view.js
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-projects-view.coffee
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-projects-view.js
sonar-server/src/main/webapp/javascripts/tests/common/inputsSpec.coffee
sonar-server/src/main/webapp/javascripts/tests/common/inputsSpec.js
sonar-server/src/main/webapp/javascripts/tests/translateSpec.coffee [new file with mode: 0644]
sonar-server/src/main/webapp/javascripts/tests/translateSpec.js [new file with mode: 0644]
sonar-server/src/main/webapp/javascripts/translate.js [new file with mode: 0644]
sonar-server/wro.xml

index de3fc835737a60e1cbe47688f7b943aa39cb31cc..a03ed679bf6d4c591c68e1ad0f14eac3ea99beae 100644 (file)
@@ -1655,6 +1655,10 @@ quality_gates.projects.all=All
 quality_gates.projects.noResults=No Projects
 quality_gates.projects.select_hint=Click to associate this project with the quality gate
 quality_gates.projects.deselect_hint=Click to remove association between this project and the quality gate
+quality_gates.operator.LT=is less than
+quality_gates.operator.GT=is greater than
+quality_gates.operator.EQ=equals
+quality_gates.operator.NE=is not
 
 #------------------------------------------------------------------------------
 #
index 6b69e1acd6cec7b38f3625c0dca6d3f6cacf3e00..09d37706938f50635b224060b7c5b045c2a02f4e 100644 (file)
@@ -27,6 +27,7 @@ module.exports = function(config) {
         'third-party/jquery.js',
         'third-party/underscore.js',
         'third-party/require.js',
+        'translate.js',
         'common/inputs.js',
 
         // libs
@@ -57,7 +58,8 @@ module.exports = function(config) {
 
     preprocessors: {
       'navigator/**/*.js': 'coverage',
-      'common/inputs.js': 'coverage'
+      'common/inputs.js': 'coverage',
+      'translate.js': 'coverage'
     },
 
 
index 7da851cab3958ca99b5d84b46695e8bb63802c5b..a9e1286173c161346c855fd37ec64b5e61d89bc2 100644 (file)
@@ -38,10 +38,6 @@ public class QgateAppHandler implements RequestHandler {
       "alerts.notes.error",
       "alerts.notes.ok",
       "alerts.notes.warn",
-      "alerts.operator.!=",
-      "alerts.operator.<",
-      "alerts.operator.=",
-      "alerts.operator.>",
       "alerts.select_metric",
       "alerts.warn_tooltip",
       "are_you_sure",
@@ -54,11 +50,16 @@ public class QgateAppHandler implements RequestHandler {
       "name",
       "quality_gates.add",
       "quality_gates.add_condition",
+      "quality_gates.conditions",
       "quality_gates.copy",
       "quality_gates.health_icons",
       "quality_gates.introduction",
       "quality_gates.no_conditions",
       "quality_gates.noQualityGates",
+      "quality_gates.operator.LT",
+      "quality_gates.operator.GT",
+      "quality_gates.operator.EQ",
+      "quality_gates.operator.NE",
       "quality_gates.page",
       "quality_gates.projects",
       "quality_gates.projects.all",
index c569bfe5a2d2433a38ea076135c8d15973e45510..f1dc7f7d8bec8946a13a7da12a693fb95e010227 100644 (file)
@@ -45,6 +45,8 @@
     <%= javascript_include_tag 'third-party/select2' %>
     <%= javascript_include_tag 'select2-jquery-ui-fix' %>
 
+    <%= javascript_include_tag 'translate' %>
+
     <%= javascript_include_tag 'widgets/widget' %>
     <%= javascript_include_tag 'widgets/bubble-chart' %>
     <%= javascript_include_tag 'widgets/timeline' %>
index c8a91047d5bcda9f1aea8c6e914b62fd168b12d3..d056480a983d611804fc6df92976458305f882ca 100644 (file)
       'warning':        '<%= escape_javascript message('measure_filter.criteria.alert.warn') -%>',
       'ok':             '<%= escape_javascript message('measure_filter.criteria.alert.ok') -%>',
       'days':           '<%= escape_javascript message('measure_filter.criteria.age.days') -%>',
-      'filtersList':    '<%= escape_javascript message('measure_filter.filter_list') -%>'
+      'filtersList':    '<%= escape_javascript message('measure_filter.filter_list') -%>',
+
+      'work_duration': {
+        'x_days': '<%= escape_javascript message('work_duration.x_days') -%>',
+        'x_hours': '<%= escape_javascript message('work_duration.x_hours') -%>',
+        'x_minutes': '<%= escape_javascript message('work_duration.x_minutes') -%>'
+      }
     }
   });
 
index ff814fc9ccb4888acf5f0dbf171fda8d2964f070..5402dcae379e4701a3e8b75605e3477459f46477 100644 (file)
 
 <script>
   window.SS = {
-    metricPeriods: [
-      { key: '1', text: '<%= Api::Utils.period_label(1) -%>' },
-      { key: '2', text: '<%= Api::Utils.period_label(2) -%>' },
-      { key: '3', text: '<%= Api::Utils.period_label(3) -%>' }
-    ],
-
     workDuration: {
       days: '<%= message('work_duration.x_days') -%>',
       hours: '<%= message('work_duration.x_hours') -%>',
       minutes: '<%= message('work_duration.x_minutes') -%>'
-    },
-
-    phrases: {
-      areYouSure: '<%= message('are_you_sure') -%>',
-      alerts: {
-        operator: {
-          'LT': '<%= message('alerts.operator.<') -%>',
-          'GT': '<%= message('alerts.operator.>') -%>',
-          'EQ': '<%= message('alerts.operator.=') -%>',
-          'NE': '<%= message('alerts.operator.!=') -%>'
-        },
-        select_metric: '<%= message('alerts.select_metric') -%>'
-      },
-      projects: {
-        'with': '<%= message('quality_gates.projects.with') -%>',
-        without: '<%= message('quality_gates.projects.without') -%>',
-        all: '<%= message('quality_gates.projects.all') -%>',
-        select_hint: '<%= message('quality_gates.projects.select_hint') -%>',
-        deselect_hint: '<%= message('quality_gates.projects.deselect_hint') -%>',
-        noResults: '<%= message('quality_gates.projects.noResults') -%>'
-      }
     }
   };
 </script>
index 1b27f7dcc56786e3ae234b4d52fb0dfa2df02e10..083091f5e25d20773a9882fce2511eeb99dfce4b 100644 (file)
@@ -1,8 +1,8 @@
 <script id="quality-gate-actions-template" type="text/x-handlebars-template">
-  <h1 class="navigator-header-title"><%= message('quality_gates.page') -%></h1>
+  <h1 class="navigator-header-title">{{t 'quality_gates.page'}}</h1>
   {{#if canEdit}}
     <div class="navigator-header-actions button-group">
-      <button id="quality-gate-add"><%= message('add_verb') -%></button>
+      <button id="quality-gate-add">{{t 'add_verb'}}</button>
     </div>
   {{/if}}
 </script>
index 0458e7e3571ab73e428a2aca21bea79a9c762cb8..cbc78673732237cd845b782031e851c946502a8b 100644 (file)
@@ -5,7 +5,7 @@
   <td width="10%" nowrap>
     {{#if canEdit}}
       <select name="period">
-        <option value="0"><%= message('value') -%></option>
+        <option value="0">{{t 'value'}}</option>
         {{#each periods}}<option value="{{key}}">{{text}}</option>{{/each}}
       </select>
     {{else}}
     {{#if canEdit}}
       <select name="operator">
         {{#operators metric.type}}
-          <option value="{{this}}">{{translate 'alerts.operator' this}}</option>
+          <option value="{{this}}">{{t 'quality_gates.operator' this}}</option>
         {{/operators}}
       </select>
     {{else}}
-      {{translate 'alerts.operator' op}}
+      {{t 'quality_gates.operator' op}}
     {{/if}}
   </td>
   <td width="15%">
-    <i class="icon-alert-warn" title="<%= message('alerts.warn_tooltip') -%>"></i>
+    <i class="icon-alert-warn" title="{{t 'alerts.warn_tooltip'}}"></i>
     {{#if canEdit}}
       <input name="warning" class="measure-input" data-type="{{metric.type}}" type="text">
     {{else}}
@@ -32,7 +32,7 @@
     {{/if}}
   </td>
   <td width="15%">
-    <i class="icon-alert-error" title="<%= message('alerts.error_tooltip') -%>"></i>
+    <i class="icon-alert-error" title="{{t 'alerts.error_tooltip'}}"></i>
     {{#if canEdit}}
       <input name="error" class="measure-input" data-type="{{metric.type}}" type="text">
     {{else}}
     {{#if canEdit}}
       {{#if id}}
         <div class="button-group">
-          <button class="update-condition" disabled><%= message('update_verb') -%></button>
-          <button class="button-red delete-condition"><%= message('delete') -%></button>
+          <button class="update-condition" disabled>{{t 'update_verb'}}</button>
+          <button class="button-red delete-condition">{{t 'delete'}}</button>
         </div>
       {{else}}
         <div class="button-group">
-          <button class="add-condition"><%= message('add_verb') -%></button>
-          <a class="action cancel-add-condition"><%= message('cancel') -%></a>
+          <button class="add-condition">{{t 'add_verb'}}</button>
+          <a class="action cancel-add-condition">{{t 'cancel'}}</a>
         </div>
       {{/if}}
     {{/if}}
index 29e5ecd845fb9a16667842f592b6678950933117..038e0786fb599772e1d98e8d70463c9688848014 100644 (file)
@@ -1,5 +1,5 @@
 <script id="quality-gate-detail-conditions-empty-template" type="text/x-handlebars-template">
   <td colspan="6">
-    <%= message('quality_gates.no_conditions') -%>
+    {{t 'quality_gates.no_conditions'}}
   </td>
 </script>
index 047d12c147a94020eb906d72b8b0468d4e80591c..1ff680bc484e711c6331e8f5a1423432cb038a90 100644 (file)
@@ -1,12 +1,12 @@
 <script id="quality-gate-detail-conditions-template" type="text/x-handlebars-template">
-  <div class="quality-gate-section-name"><%= message('quality_gates.conditions') -%></div>
+  <div class="quality-gate-section-name">{{t 'quality_gates.conditions'}}</div>
 
   <div class="quality-gate-introduction">
-    <p><%= message('quality_gates.introduction') -%>
-      <a class="link-action quality-gate-introduction-show-more"><%= message('more') -%></a>
+    <p>{{t 'quality_gates.introduction'}}
+      <a class="link-action quality-gate-introduction-show-more">{{t 'more'}}</a>
     </p>
     <div class="quality-gate-introduction-more">
-      <%= message('quality_gates.health_icons') -%>
+      {{t 'quality_gates.health_icons'}}
       <table class="data">
         <thead>
         <tr>
         <tbody>
         <tr class="even">
           <td><i class="icon-alert-ok"></i></td>
-          <td><%= message('alerts.notes.ok') -%></td>
+          <td>{{t 'alerts.notes.ok'}}</td>
         </tr>
         <tr class="odd">
           <td><i class="icon-alert-warn"></i></td>
-          <td><%= message('alerts.notes.warn') -%></td>
+          <td>{{t 'alerts.notes.warn'}}</td>
         </tr>
         <tr class="even">
           <td><i class="icon-alert-error"></i></td>
-          <td><%= message('alerts.notes.error') -%></td>
+          <td>{{t 'alerts.notes.error'}}</td>
         </tr>
         </tbody>
       </table>
@@ -33,7 +33,7 @@
 
   {{#if canEdit}}
     <div class="quality-gate-new-condition">
-      <label for="quality-gate-new-condition-metric"><%= message('quality_gates.add_condition') -%>:</label>
+      <label for="quality-gate-new-condition-metric">{{t 'quality_gates.add_condition'}}:</label>
       <select id="quality-gate-new-condition-metric">
         <option></option>
         {{#each metricGroups}}
index 151c9f1ad036d712200f6c60b4fa63a7ec6e4b68..7d4274c9de825d699bfc8651c83a0f68cdef7179 100644 (file)
@@ -3,14 +3,14 @@
 
   {{#if canEdit}}
     <div class="navigator-header-actions button-group">
-      <button id="quality-gate-rename"><%= message('rename') -%></button>
-      <button id="quality-gate-copy"><%= message('copy') -%></button>
+      <button id="quality-gate-rename">{{t 'rename'}}</button>
+      <button id="quality-gate-copy">{{t 'copy'}}</button>
       {{#if default}}
-        <button id="quality-gate-unset-as-default"><%= message('unset_as_default') -%></button>
+        <button id="quality-gate-unset-as-default">{{t 'unset_as_default'}}</button>
       {{else}}
-        <button id="quality-gate-set-as-default"><%= message('set_as_default') -%></button>
+        <button id="quality-gate-set-as-default">{{t 'set_as_default'}}</button>
       {{/if}}
-      <button id="quality-gate-delete" class="button-red"><%= message('delete') -%></button>
+      <button id="quality-gate-delete" class="button-red">{{t 'delete'}}</button>
     </div>
   {{/if}}
 </script>
index 64e599cdb4c6924166b2cea78dddfb22e36e27a1..9f107237684aececd3761fb12870d1d281fa8ef3 100644 (file)
@@ -1,8 +1,8 @@
 <script id="quality-gate-detail-projects-template" type="text/x-handlebars-template">
-  <div class="quality-gate-section-name"><%= message('quality_gates.projects') -%></div>
+  <div class="quality-gate-section-name">{{t 'quality_gates.projects'}}</div>
 
   {{#if default}}
-    <p><%= message('quality_gates.projects_for_default') -%></p>
+    <p>{{t 'quality_gates.projects_for_default'}}</p>
   {{else}}
     <div id="select-list-projects"></div>
   {{/if}}
index 34b12f6ebef5c97f553148616f6b76c375748d1f..592da39d1bcc05e13f745f43a846f515e0bac303 100644 (file)
@@ -1,24 +1,24 @@
 <script id="quality-gate-edit-template" type="text/x-handlebars-template">
   <form>
     <div class="modal-head">
-      {{#eq method "rename"}}<h2><%= message('quality_gates.rename') -%> {{name}}</h2>{{/eq}}
-      {{#eq method "copy"}}<h2><%= message('quality_gates.copy') -%> {{name}}</h2>{{/eq}}
-      {{#eq method "create"}}<h2><%= message('quality_gates.add') -%></h2>{{/eq}}
+      {{#eq method "rename"}}<h2>{{t 'quality_gates.rename'}} {{name}}</h2>{{/eq}}
+      {{#eq method "copy"}}<h2>{{t 'quality_gates.copy'}} {{name}}</h2>{{/eq}}
+      {{#eq method "create"}}<h2>{{t 'quality_gates.add'}}</h2>{{/eq}}
     </div>
 
     <div class="modal-body">
       <div class="modal-error"></div>
       <div class="modal-field">
-        <label for="quality-gate-edit-name"><%= message('name') -%> <em class="mandatory">*</em></label>
+        <label for="quality-gate-edit-name">{{t 'name'}} <em class="mandatory">*</em></label>
         <input id="quality-gate-edit-name" type="text" size="50" maxlength="100">
       </div>
     </div>
 
     <div class="modal-foot">
-      {{#eq method "rename"}}<button><%= message('save') -%></button>{{/eq}}
-      {{#eq method "copy"}}<button><%= message('copy') -%></button>{{/eq}}
-      {{#eq method "create"}}<button><%= message('create') -%></button>{{/eq}}
-      <a id="quality-gate-cancel-create" class="action"><%= message('cancel') -%></a>
+      {{#eq method "rename"}}<button>{{t 'save'}}</button>{{/eq}}
+      {{#eq method "copy"}}<button>{{t 'copy'}}</button>{{/eq}}
+      {{#eq method "create"}}<button>{{t 'create'}}</button>{{/eq}}
+      <a id="quality-gate-cancel-create" class="action">{{t 'cancel'}}</a>
     </div>
   </form>
 </script>
index 5fe429c3f24fe06ccff0274537b30db806000d90..9daa6f315a917c360b0903eed1072c4d69074c9b 100644 (file)
@@ -1,3 +1,3 @@
 <script id="quality-gate-sidebar-list-empty-template" type="text/x-handlebars-template">
-  <div class="line line-nowrap"><%= message('quality_gates.noQualityGates') -%></div>
+  <div class="line line-nowrap">{{t 'quality_gates.noQualityGates'}}</div>
 </script>
index 262c0be59567652b56d587fed209706c98228cf1..7d75b457ec4f8397858c0f3ae522bdc435c0146b 100644 (file)
@@ -1,3 +1,3 @@
 <script id="quality-gate-sidebar-list-item-template" type="text/x-handlebars-template">
-  <div class="line line-nowrap">{{name}} {{#if default}}<span class="subtitle">(<%= message('default') -%>)</span>{{/if}}</div>
+  <div class="line line-nowrap">{{name}} {{#if default}}<span class="subtitle">({{t 'default'}})</span>{{/if}}</div>
 </script>
index 87b650dbe28b642eadab55d37ba7a07ca66aca7e..74d02784d0689762ac72da51aac52b5b2dbbb29d 100644 (file)
@@ -82,16 +82,14 @@ define(['handlebars'], function (Handlebars) {
     return url;
   });
 
-  Handlebars.registerHelper('translate', function(key, prefix) {
-    var args = Array.prototype.slice.call(arguments, 0, -1),
-        tokens = args.reduce(function(prev, current) {
-          return prev.concat(current.split('.'));
-        }, []),
-        start = window.SS.phrases;
-
-    return tokens.reduce(function(prev, current) {
-      return current ? prev[current] : prev;
-    }, start);
+  Handlebars.registerHelper('translate', function() {
+    var args = Array.prototype.slice.call(arguments, 0, -1);
+    return window.translate.apply(this, args);
+  });
+
+  Handlebars.registerHelper('t', function() {
+    var args = Array.prototype.slice.call(arguments, 0, -1);
+    return window.t.apply(this, args);
   });
 
   Handlebars.registerHelper('pluginActions', function(actions, options) {
index c914068b9e4d22c2bcd6c5d0b9f4d5e187664b5d..4352040b021dae6e697a8d0cc8c91ea3873c7be1 100644 (file)
@@ -5,9 +5,9 @@ transformPattern = (pattern) ->
 
 
 convertWorkDuration = (value) ->
-  daysPattern = transformPattern window.SS.workDuration.days
-  hoursPattern = transformPattern window.SS.workDuration.hours
-  minutesPattern = transformPattern window.SS.workDuration.minutes
+  daysPattern = transformPattern t('work_duration.x_days')
+  hoursPattern = transformPattern t('work_duration.x_hours')
+  minutesPattern = transformPattern t('work_duration.x_minutes')
 
   days = value.match daysPattern
   hours = value.match hoursPattern
@@ -29,9 +29,9 @@ restoreWorkDuration = (value) ->
   hours = Math.floor((value - days * 8 * 60) / 60)
   minutes = value % 60
   result = []
-  result.push window.SS.workDuration.days.replace('{0}', days) if days > 0
-  result.push window.SS.workDuration.hours.replace('{0}', hours) if hours > 0
-  result.push window.SS.workDuration.minutes.replace('{0}', minutes) if minutes > 0
+  result.push t('work_duration.x_days').replace('{0}', days) if days > 0
+  result.push t('work_duration.x_hours').replace('{0}', hours) if hours > 0
+  result.push t('work_duration.x_minutes').replace('{0}', minutes) if minutes > 0
   result.join ' '
 
 
index 093116c9a57993139b01d6a4480a6df42ea9d491..d4c3b61fc8481ccde87c08507aa3ec8f52543ca3 100644 (file)
@@ -10,9 +10,9 @@
 
   convertWorkDuration = function(value) {
     var days, daysPattern, hours, hoursPattern, minutes, minutesPattern;
-    daysPattern = transformPattern(window.SS.workDuration.days);
-    hoursPattern = transformPattern(window.SS.workDuration.hours);
-    minutesPattern = transformPattern(window.SS.workDuration.minutes);
+    daysPattern = transformPattern(t('work_duration.x_days'));
+    hoursPattern = transformPattern(t('work_duration.x_hours'));
+    minutesPattern = transformPattern(t('work_duration.x_minutes'));
     days = value.match(daysPattern);
     hours = value.match(hoursPattern);
     minutes = value.match(minutesPattern);
     minutes = value % 60;
     result = [];
     if (days > 0) {
-      result.push(window.SS.workDuration.days.replace('{0}', days));
+      result.push(t('work_duration.x_days').replace('{0}', days));
     }
     if (hours > 0) {
-      result.push(window.SS.workDuration.hours.replace('{0}', hours));
+      result.push(t('work_duration.x_hours').replace('{0}', hours));
     }
     if (minutes > 0) {
-      result.push(window.SS.workDuration.minutes.replace('{0}', minutes));
+      result.push(t('work_duration.x_minutes').replace('{0}', minutes));
     }
     return result.join(' ');
   };
index 346636af8a775b73af6cd790590eb0e0ce851868..6c119104c12a4a774974e735592cf59102047ac7 100644 (file)
@@ -125,13 +125,18 @@ requirejs [
     App.openFirstQualityGate() if initial
 
 
-  # Load metrics and the list of quality gates before start the application
+  # Call app, Load metrics and the list of quality gates before start the application
+  appXHR = jQuery.ajax
+    url: "#{baseUrl}/api/qualitygates/app"
+  .done (r) =>
+      App.canEdit = r.edit
+      App.periods = r.periods
+      window.messages = r.messages
+
   qualityGatesXHR = App.qualityGates.fetch()
-  jQuery.when(App.metrics.fetch(), qualityGatesXHR)
-    .done ->
-      # Set permissions
-      App.canEdit = qualityGatesXHR.responseJSON.edit
 
+  jQuery.when(App.metrics.fetch(), qualityGatesXHR, appXHR)
+    .done ->
       # Remove the initial spinner
       jQuery('.quality-gate-page-loader').remove()
 
index de8c167eb714387565ca309f5b0844ed5a6821d5..b72dfa17020346fc8e73101e40d3adadc097f354 100644 (file)
@@ -31,7 +31,8 @@
   });
 
   requirejs(['backbone', 'backbone.marionette', 'handlebars', 'quality-gate/collections/quality-gates', 'quality-gate/collections/metrics', 'quality-gate/views/quality-gate-sidebar-list-view', 'quality-gate/views/quality-gate-actions-view', 'quality-gate/views/quality-gate-edit-view', 'quality-gate/router', 'quality-gate/layout', 'common/handlebars-extensions'], function(Backbone, Marionette, Handlebars, QualityGates, Metrics, QualityGateSidebarListItemView, QualityGateActionsView, QualityGateEditView, QualityGateRouter, QualityGateLayout) {
-    var App, qualityGatesXHR;
+    var App, appXHR, qualityGatesXHR,
+      _this = this;
     jQuery.ajaxSetup({
       error: function(jqXHR) {
         var errorBox, text, _ref;
         return App.openFirstQualityGate();
       }
     });
+    appXHR = jQuery.ajax({
+      url: "" + baseUrl + "/api/qualitygates/app"
+    }).done(function(r) {
+      App.canEdit = r.edit;
+      App.periods = r.periods;
+      return window.messages = r.messages;
+    });
     qualityGatesXHR = App.qualityGates.fetch();
-    return jQuery.when(App.metrics.fetch(), qualityGatesXHR).done(function() {
-      App.canEdit = qualityGatesXHR.responseJSON.edit;
+    return jQuery.when(App.metrics.fetch(), qualityGatesXHR, appXHR).done(function() {
       jQuery('.quality-gate-page-loader').remove();
       return App.start();
     });
index f60bd4439a1d5ed28d7b375a71db90a3e2de72c5..bae22f95073cb20cbbd75257ce33f3caf58b7054 100644 (file)
@@ -89,7 +89,7 @@ define [
 
 
     deleteCondition: ->
-      if confirm window.SS.phrases.areYouSure
+      if confirm t('are_you_sure')
         @showSpinner()
         @model.delete().done =>
           @options.collectionView.updateConditions()
@@ -105,8 +105,8 @@ define [
 
 
     serializeData: ->
-      period = _.findWhere(window.SS.metricPeriods, key: '' + this.model.get('period'))
+      period = _.findWhere(@options.app.periods, key: '' + this.model.get('period'))
       _.extend super,
         canEdit: @options.app.canEdit
-        periods: window.SS.metricPeriods
+        periods: @options.app.periods
         periodText: period?.text
index 6e29ecc2db13f11f9d7c764e2d5003524052b0c1..ddd499d7f646cdd8322e60c6649fb1c8ec88204d 100644 (file)
 
       QualityGateDetailConditionView.prototype.deleteCondition = function() {
         var _this = this;
-        if (confirm(window.SS.phrases.areYouSure)) {
+        if (confirm(t('are_you_sure'))) {
           this.showSpinner();
           return this.model["delete"]().done(function() {
             _this.options.collectionView.updateConditions();
 
       QualityGateDetailConditionView.prototype.serializeData = function() {
         var period;
-        period = _.findWhere(window.SS.metricPeriods, {
+        period = _.findWhere(this.options.app.periods, {
           key: '' + this.model.get('period')
         });
         return _.extend(QualityGateDetailConditionView.__super__.serializeData.apply(this, arguments), {
           canEdit: this.options.app.canEdit,
-          periods: window.SS.metricPeriods,
+          periods: this.options.app.periods,
           periodText: period != null ? period.text : void 0
         });
       };
index 9e88a74ee9f1c07dca12eb08c4f0bc6afaf0e941..8fc8054abcd7e3f99693a60a23c865274f68255d 100644 (file)
@@ -49,7 +49,7 @@ define [
       @ui.metricSelect.select2
         allowClear: false,
         width: '250px',
-        placeholder: window.SS.phrases.alerts.select_metric
+        placeholder: t('alerts.select_metric')
 
 
     groupedMetrics: ->
index a6a26c583fcc20b40db8d5d22e516dc6f08c0681..7a145e44594eae6f001cd023aa7f2ed18058535d 100644 (file)
@@ -55,7 +55,7 @@
         return this.ui.metricSelect.select2({
           allowClear: false,
           width: '250px',
-          placeholder: window.SS.phrases.alerts.select_metric
+          placeholder: t('alerts.select_metric')
         });
       };
 
index b5be79800a118a0722b17aae4936d432083b94aa..932de7a1e332a6923bd23cd01f4d7dfc03e8fed2 100644 (file)
@@ -39,7 +39,7 @@ define [
 
 
     deleteQualityGate: ->
-      if confirm window.SS.phrases.areYouSure
+      if confirm t('are_you_sure')
         @showSpinner()
         jQuery.ajax
           type: 'POST'
index d3dcdd9359104bb08b7dd96f2e0439a913c82643..1ec05e1ea63b4885ecb32fc602c21542949f198c 100644 (file)
@@ -45,7 +45,7 @@
 
       QualityGateDetailHeaderView.prototype.deleteQualityGate = function() {
         var _this = this;
-        if (confirm(window.SS.phrases.areYouSure)) {
+        if (confirm(t('are_you_sure'))) {
           this.showSpinner();
           return jQuery.ajax({
             type: 'POST',
index 0d02f0bf29882b89d1ecdd1e323bcddb7eb05b52..70fbe8f261e08f9aef49308b93185de19f3c07ff 100644 (file)
@@ -26,10 +26,10 @@ define [
           selectParameter: 'projectId'
           selectParameterValue: 'id'
           labels:
-            selected: window.SS.phrases.projects.with
-            deselected: window.SS.phrases.projects.without
-            all: window.SS.phrases.projects.all
-            noResults: window.SS.phrases.projects.noResults
+            selected: t('quality_gates.projects.with')
+            deselected: t('quality_gates.projects.without')
+            all: t('quality_gates.projects.all')
+            noResults: t('quality_gates.projects.noResults')
           tooltips:
-            select: window.SS.phrases.projects.select_hint
-            deselect: window.SS.phrases.projects.deselect_hint
+            select: t('quality_gates.projects.select_hint')
+            deselect: t('quality_gates.projects.deselect_hint')
index 2da6868f81e8ebe0b59357b7103eacc243a0e0d6..3c647112f037e63fe82fbd733bca0284e841eb4a 100644 (file)
             selectParameter: 'projectId',
             selectParameterValue: 'id',
             labels: {
-              selected: window.SS.phrases.projects["with"],
-              deselected: window.SS.phrases.projects.without,
-              all: window.SS.phrases.projects.all,
-              noResults: window.SS.phrases.projects.noResults
+              selected: t('quality_gates.projects.with'),
+              deselected: t('quality_gates.projects.without'),
+              all: t('quality_gates.projects.all'),
+              noResults: t('quality_gates.projects.noResults')
             },
             tooltips: {
-              select: window.SS.phrases.projects.select_hint,
-              deselect: window.SS.phrases.projects.deselect_hint
+              select: t('quality_gates.projects.select_hint'),
+              deselect: t('quality_gates.projects.deselect_hint')
             }
           });
         }
index 335d26b190bd665bb3cebe759acf1a7a1d0ab22d..d20983d9c65155a1c15ec520ee47ca8fb905cd0b 100644 (file)
@@ -3,9 +3,10 @@ $ = jQuery
 describe 'WORK_DUR suite', ->
 
   beforeEach ->
-    window.SS =
-      workDuration:
-        days: '{0}d', hours: '{0}h', minutes: '{0}min'
+    window.SS = {}
+    window.SS.phrases =
+      'work_duration':
+        'x_days': '{0}d', 'x_hours': '{0}h', 'x_minutes': '{0}min'
 
     @input = $('<input type="text">')
     @input.appendTo $('body')
index 8d83eb5bfc873b253340b303ce21b6fd373ef6c1..2278db2d672b0ade87970c021cd6dd1aff7b0fb2 100644 (file)
@@ -6,11 +6,12 @@
 
   describe('WORK_DUR suite', function() {
     beforeEach(function() {
-      window.SS = {
-        workDuration: {
-          days: '{0}d',
-          hours: '{0}h',
-          minutes: '{0}min'
+      window.SS = {};
+      window.SS.phrases = {
+        'work_duration': {
+          'x_days': '{0}d',
+          'x_hours': '{0}h',
+          'x_minutes': '{0}min'
         }
       };
       this.input = $('<input type="text">');
diff --git a/sonar-server/src/main/webapp/javascripts/tests/translateSpec.coffee b/sonar-server/src/main/webapp/javascripts/tests/translateSpec.coffee
new file mode 100644 (file)
index 0000000..2418518
--- /dev/null
@@ -0,0 +1,70 @@
+$ = jQuery
+
+describe 'translation "t" suite', ->
+
+  beforeEach ->
+    window.messages =
+      'something': 'SOMETHING'
+      'something_with_underscore': 'SOMETHING_WITH_UNDERSCORE'
+      'something_with{braces}': 'SOMETHING_WITH{braces}'
+
+    window.SS =
+      phrases:
+        'something': 'SOMETHING ANOTHER'
+
+
+  afterEach ->
+    window.messages = window.SS = undefined
+
+
+  it 'translates', ->
+    expect(t('something')).toBe 'SOMETHING'
+
+
+  it 'translates with underscore', ->
+    expect(t('something_with_underscore')).toBe 'SOMETHING_WITH_UNDERSCORE'
+
+
+  it 'translates with braces', ->
+    expect(t('something_with{braces}')).toBe 'SOMETHING_WITH{braces}'
+
+
+  it 'fallbacks to "translate"', ->
+    window.messages = undefined
+    expect(t('something')).toBe 'SOMETHING ANOTHER'
+
+
+  it 'returns the key when no translation', ->
+    expect(t('something_another')).toBe 'something_another'
+
+
+
+describe 'translation "translate" suite', ->
+
+  beforeEach ->
+    window.SS =
+      phrases:
+        'something': 'SOMETHING'
+        'something_with_underscore': 'SOMETHING_WITH_UNDERSCORE'
+        'something_with{braces}': 'SOMETHING_WITH{braces}'
+
+
+  afterEach ->
+    window.messages = window.SS = undefined
+
+
+  it 'translates', ->
+    expect(translate('something')).toBe 'SOMETHING'
+
+
+  it 'translates with underscore', ->
+    expect(translate('something_with_underscore')).toBe 'SOMETHING_WITH_UNDERSCORE'
+
+
+  it 'translates with braces', ->
+    expect(translate('something_with{braces}')).toBe 'SOMETHING_WITH{braces}'
+
+
+  it 'returns the key when no translation', ->
+    expect(translate('something_another')).toBe 'something_another'
+
diff --git a/sonar-server/src/main/webapp/javascripts/tests/translateSpec.js b/sonar-server/src/main/webapp/javascripts/tests/translateSpec.js
new file mode 100644 (file)
index 0000000..b634742
--- /dev/null
@@ -0,0 +1,68 @@
+// Generated by CoffeeScript 1.6.3
+(function() {
+  var $;
+
+  $ = jQuery;
+
+  describe('translation "t" suite', function() {
+    beforeEach(function() {
+      window.messages = {
+        'something': 'SOMETHING',
+        'something_with_underscore': 'SOMETHING_WITH_UNDERSCORE',
+        'something_with{braces}': 'SOMETHING_WITH{braces}'
+      };
+      return window.SS = {
+        phrases: {
+          'something': 'SOMETHING ANOTHER'
+        }
+      };
+    });
+    afterEach(function() {
+      return window.messages = window.SS = void 0;
+    });
+    it('translates', function() {
+      return expect(t('something')).toBe('SOMETHING');
+    });
+    it('translates with underscore', function() {
+      return expect(t('something_with_underscore')).toBe('SOMETHING_WITH_UNDERSCORE');
+    });
+    it('translates with braces', function() {
+      return expect(t('something_with{braces}')).toBe('SOMETHING_WITH{braces}');
+    });
+    it('fallbacks to "translate"', function() {
+      window.messages = void 0;
+      return expect(t('something')).toBe('SOMETHING ANOTHER');
+    });
+    return it('returns the key when no translation', function() {
+      return expect(t('something_another')).toBe('something_another');
+    });
+  });
+
+  describe('translation "translate" suite', function() {
+    beforeEach(function() {
+      return window.SS = {
+        phrases: {
+          'something': 'SOMETHING',
+          'something_with_underscore': 'SOMETHING_WITH_UNDERSCORE',
+          'something_with{braces}': 'SOMETHING_WITH{braces}'
+        }
+      };
+    });
+    afterEach(function() {
+      return window.messages = window.SS = void 0;
+    });
+    it('translates', function() {
+      return expect(translate('something')).toBe('SOMETHING');
+    });
+    it('translates with underscore', function() {
+      return expect(translate('something_with_underscore')).toBe('SOMETHING_WITH_UNDERSCORE');
+    });
+    it('translates with braces', function() {
+      return expect(translate('something_with{braces}')).toBe('SOMETHING_WITH{braces}');
+    });
+    return it('returns the key when no translation', function() {
+      return expect(translate('something_another')).toBe('something_another');
+    });
+  });
+
+}).call(this);
diff --git a/sonar-server/src/main/webapp/javascripts/translate.js b/sonar-server/src/main/webapp/javascripts/translate.js
new file mode 100644 (file)
index 0000000..3803a03
--- /dev/null
@@ -0,0 +1,42 @@
+(function() {
+  var warn = function(message) {
+    if (console != null && typeof console.warn === 'function') {
+      console.warn(message);
+    }
+  };
+
+  window.t = function() {
+    if (!window.messages) {
+      return window.translate.apply(this, arguments);
+    }
+
+    var args = Array.prototype.slice.call(arguments, 0),
+        key = args.join('.');
+    if (!window.messages[key]) {
+      warn('No translation for "' + key + '"');
+    }
+    return (window.messages && window.messages[key]) || key;
+  };
+
+
+  window.translate = function() {
+    var args = Array.prototype.slice.call(arguments, 0),
+        tokens = args.reduce(function(prev, current) {
+          return prev.concat(current.split('.'));
+        }, []),
+        key = tokens.join('.'),
+        start = window.SS.phrases,
+        found = true;
+
+    var result = tokens.reduce(function(prev, current) {
+      if (!current || !prev[current]) {
+        warn('No translation for "' + key + '"');
+        found = false;
+      }
+      return current ? prev[current] : prev;
+    }, start);
+
+    return found ? result : key;
+  };
+
+})();
index 3bcadf2a340a200507a31a28d46eae0cd89dc9ba..649e4569f879f5c45b3e982e4c9306d41e1a31b8 100644 (file)
@@ -24,6 +24,8 @@
     <js>/javascripts/third-party/select2.js</js>
     <js>/javascripts/select2-jquery-ui-fix.js</js>
 
+    <js>/javascripts/translate.js</js>
+
     <js>/javascripts/widgets/widget.js</js>
     <js>/javascripts/widgets/bubble-chart.js</js>
     <js>/javascripts/widgets/timeline.js</js>