diff --git a/.i18nrc.json b/.i18nrc.json index de532fdb60984..cfef3cf80c631 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -2,7 +2,7 @@ "paths": { "common.ui": "src/ui", "console": "src/core_plugins/console", - "inputControl":"src/core_plugins/input_control_vis", + "inputControl": "src/core_plugins/input_control_vis", "kbn": "src/core_plugins/kibana", "kbnVislibVisTypes": "src/core_plugins/kbn_vislib_vis_types", "markdownVis": "src/core_plugins/markdown_vis", @@ -12,6 +12,7 @@ "regionMap": "src/core_plugins/region_map", "statusPage": "src/core_plugins/status_page", "tileMap": "src/core_plugins/tile_map", + "timelion": "src/core_plugins/timelion", "tagCloud": "src/core_plugins/tagcloud", "xpack.grokDebugger": "x-pack/plugins/grokdebugger", "xpack.idxMgmt": "x-pack/plugins/index_management", diff --git a/src/core_plugins/timelion/index.js b/src/core_plugins/timelion/index.js index aecb3f6cbbe22..3a1284eaacf90 100644 --- a/src/core_plugins/timelion/index.js +++ b/src/core_plugins/timelion/index.js @@ -103,7 +103,8 @@ export default function (kibana) { description: `[experimental] Your API key from www.quandl.com`, category: ['timelion'], } - } + }, + translations: [], }, init: require('./init.js'), }); diff --git a/src/core_plugins/timelion/init.js b/src/core_plugins/timelion/init.js index 67c1c1f1e7a1a..eecebfb81fdf0 100644 --- a/src/core_plugins/timelion/init.js +++ b/src/core_plugins/timelion/init.js @@ -17,6 +17,7 @@ * under the License. */ +import { i18n } from '@kbn/i18n'; import _ from 'lodash'; import processFunctionDefinition from './server/lib/process_function_definition'; @@ -33,7 +34,15 @@ export default function (server) { } function getFunction(name) { - if (!functions[name]) throw new Error ('No such function: ' + name); + if (!functions[name]) { + throw new Error( + i18n.translate('timelion.noFunctionErrorMessage', { + defaultMessage: 'No such function: {name}', + values: { name }, + }) + ); + } + return functions[name]; } diff --git a/src/core_plugins/timelion/public/app.js b/src/core_plugins/timelion/public/app.js index bfc4047294cc6..036b53ad826c2 100644 --- a/src/core_plugins/timelion/public/app.js +++ b/src/core_plugins/timelion/public/app.js @@ -91,6 +91,7 @@ app.controller('timelion', function ( kbnUrl, Notifier, Private, + i18n, ) { // Keeping this at app scope allows us to keep the current page when the user @@ -114,22 +115,30 @@ app.controller('timelion', function ( $scope.topNavMenu = [{ key: 'new', - description: 'New Sheet', + description: i18n('timelion.topNavMenu.newDescription', { + defaultMessage: 'New Sheet', + }), run: function () { kbnUrl.change('/'); }, testId: 'timelionNewButton', }, { key: 'add', - description: 'Add a chart', + description: i18n('timelion.topNavMenu.addDescription', { + defaultMessage: 'Add a chart', + }), run: function () { $scope.newCell(); }, testId: 'timelionAddChartButton', }, { key: 'save', - description: 'Save Sheet', + description: i18n('timelion.topNavMenu.saveDescription', { + defaultMessage: 'Save Sheet', + }), template: require('plugins/timelion/partials/save_sheet.html'), testId: 'timelionSaveButton', }, { key: 'delete', - description: 'Delete current sheet', + description: i18n('timelion.topNavMenu.deleteDescription', { + defaultMessage: 'Delete current sheet', + }), disableButton: function () { return !savedSheet.id; }, @@ -137,32 +146,55 @@ app.controller('timelion', function ( const title = savedSheet.title; function doDelete() { savedSheet.delete().then(() => { - toastNotifications.addSuccess(`Deleted '${title}'`); + toastNotifications.addSuccess(i18n( + 'timelion.topNavMenu.delete.modal.successNotificationText', + { + defaultMessage: `Deleted '{title}'`, + values: { title }, + } + )); kbnUrl.change('/'); }).catch(error => fatalError(error, location)); } const confirmModalOptions = { onConfirm: doDelete, - confirmButtonText: 'Delete', - title: `Delete Timelion sheet '${title}'?` + confirmButtonText: i18n('timelion.topNavMenu.delete.modal.confirmButtonLabel', { + defaultMessage: 'Delete', + }), + title: i18n('timelion.topNavMenu.delete.modalTitle', { + defaultMessage: `Delete Timelion sheet '{title}'?`, + values: { title } + }), }; - confirmModal(`You can't recover deleted sheets.`, confirmModalOptions); + + confirmModal( + i18n('timelion.topNavMenu.delete.modal.warningText', { + defaultMessage: `You can't recover deleted sheets.`, + }), + confirmModalOptions + ); }, testId: 'timelionDeleteButton', }, { key: 'open', - description: 'Open Sheet', + description: i18n('timelion.topNavMenu.openDescription', { + defaultMessage: 'Open Sheet', + }), template: require('plugins/timelion/partials/load_sheet.html'), testId: 'timelionOpenButton', }, { key: 'options', - description: 'Options', + description: i18n('timelion.topNavMenu.optionsDescription', { + defaultMessage: 'Options', + }), template: require('plugins/timelion/partials/sheet_options.html'), testId: 'timelionOptionsButton', }, { key: 'help', - description: 'Help', + description: i18n('timelion.topNavMenu.helpDescription', { + defaultMessage: 'Help', + }), template: '', testId: 'timelionDocsButton', }]; @@ -289,7 +321,13 @@ app.controller('timelion', function ( savedSheet.timelion_rows = $scope.state.rows; savedSheet.save().then(function (id) { if (id) { - toastNotifications.addSuccess(`Saved sheet '${savedSheet.title}'`); + toastNotifications.addSuccess( + i18n('timelion.saveSheet.successNotificationText', { + defaultMessage: `Saved sheet '{title}'`, + values: { title: savedSheet.title }, + }) + ); + if (savedSheet.id !== $routeParams.id) { kbnUrl.change('/{{id}}', { id: savedSheet.id }); } @@ -307,7 +345,12 @@ app.controller('timelion', function ( savedExpression.visState.title = title; savedExpression.save().then(function (id) { if (id) { - toastNotifications.addSuccess(`Saved expression '${savedExpression.title}'`); + toastNotifications.addSuccess( + i18n('timelion.saveExpression.successNotificationText', { + defaultMessage: `Saved expression '{title}'`, + values: { title: savedExpression.title }, + }), + ); } }); }); diff --git a/src/core_plugins/timelion/public/directives/cells/cells.html b/src/core_plugins/timelion/public/directives/cells/cells.html index 6f74580fe3513..6be1b089d2deb 100644 --- a/src/core_plugins/timelion/public/directives/cells/cells.html +++ b/src/core_plugins/timelion/public/directives/cells/cells.html @@ -21,18 +21,18 @@ diff --git a/src/core_plugins/timelion/public/directives/chart/chart.js b/src/core_plugins/timelion/public/directives/chart/chart.js index 98269414a8b46..a7ca4c113b56a 100644 --- a/src/core_plugins/timelion/public/directives/chart/chart.js +++ b/src/core_plugins/timelion/public/directives/chart/chart.js @@ -16,12 +16,11 @@ * specific language governing permissions and limitations * under the License. */ - import panelRegistryProvider from '../../lib/panel_registry'; require('ui/modules') .get('apps/timelion', []) - .directive('chart', function (Private) { + .directive('chart', function (Private, i18n) { return { restrict: 'A', scope: { @@ -46,7 +45,12 @@ require('ui/modules') const panelSchema = panelRegistry.byName[seriesList.render.type]; if (!panelSchema) { - $elem.text('No such panel type: ' + seriesList.render.type); + $elem.text( + i18n('timelion.chart.seriesList.noSchemaWarning', { + defaultMessage: 'No such panel type: {renderType}', + values: { renderType: seriesList.render.type }, + }) + ); return; } diff --git a/src/core_plugins/timelion/public/directives/fullscreen/fullscreen.html b/src/core_plugins/timelion/public/directives/fullscreen/fullscreen.html index 9aabde9ea019e..325c7eabb2b03 100644 --- a/src/core_plugins/timelion/public/directives/fullscreen/fullscreen.html +++ b/src/core_plugins/timelion/public/directives/fullscreen/fullscreen.html @@ -4,9 +4,9 @@ diff --git a/src/core_plugins/timelion/public/directives/timelion_expression_input.html b/src/core_plugins/timelion/public/directives/timelion_expression_input.html index c05da60022bbb..d2c740400fb3e 100644 --- a/src/core_plugins/timelion/public/directives/timelion_expression_input.html +++ b/src/core_plugins/timelion/public/directives/timelion_expression_input.html @@ -13,7 +13,7 @@ role="textbox" rows="{{ rows }}" class="timExpressionInput kuiTextArea fullWidth" - placeholder="Try a query with .es(*)" + placeholder="{{ ::'timelion.expressionInputPlaceholder' | i18n: { defaultMessage: 'Try a query with {esQuery}', values: { esQuery: '.es(*)' } } }}" ng-model="sheet" ng-focus="onFocusInput()" ng-keydown="onKeyDownInput($event)" @@ -22,7 +22,7 @@ ng-mousedown="onMouseDownInput()" ng-mouseup="onMouseUpInput()" ng-click="onClickExpression()" - aria-label="Timelion expression" + aria-label="{{ ::'timelion.expressionInputAriaLabel' | i18n: { defaultMessage: 'Timelion expression' } }}" aria-multiline="false" aria-autocomplete="list" aria-controls="timelionSuggestionList" diff --git a/src/core_plugins/timelion/public/directives/timelion_expression_suggestions/timelion_expression_suggestions.html b/src/core_plugins/timelion/public/directives/timelion_expression_suggestions/timelion_expression_suggestions.html index 62cede14bb7f0..ddb9f21615aee 100644 --- a/src/core_plugins/timelion/public/directives/timelion_expression_suggestions/timelion_expression_suggestions.html +++ b/src/core_plugins/timelion/public/directives/timelion_expression_suggestions/timelion_expression_suggestions.html @@ -26,14 +26,27 @@

.{{suggestion.name}}() - {{suggestion.help}} - {{suggestion.chainable ? '(Chainable)' : '(Data Source)'}} + +

- Arguments: + {{arg.name}}=({{arg.types.join(' | ')}}) , @@ -43,9 +56,21 @@

- - - + + + diff --git a/src/core_plugins/timelion/public/directives/timelion_help/timelion_help.html b/src/core_plugins/timelion/public/directives/timelion_help/timelion_help.html index 8f2456d5e6f2e..cf136b00c9157 100644 --- a/src/core_plugins/timelion/public/directives/timelion_help/timelion_help.html +++ b/src/core_plugins/timelion/public/directives/timelion_help/timelion_help.html @@ -1,21 +1,36 @@
-

Welcome to Timelion!

+

+

- Timelion is the clawing, gnashing, zebra killing, pluggable time - series interface for everything. If your datastore can - produce a time series, then you have all of the awesome power of - Timelion at your disposal. Timelion lets you compare, combine, and - combobulate datasets across multiple datasources with one - easy-to-master expression syntax. This tutorial focuses on - Elasticsearch, but you'll quickly discover that what you learn here - applies to any datasource Timelion supports. -

-

- Ready to get started? Click Next. Want to skip the - tutorial and view the docs? - Jump to the function reference. + + .

@@ -24,7 +39,7 @@

Welcome to Timelion!

ng-click="opts.dontShowHelp()" class="kuiButton kuiButton--hollow" > - Don't show this again + {{translations.dontShowHelpButtonLabel}} @@ -32,7 +47,7 @@

Welcome to Timelion!

ng-click="setPage(page+1)" class="kuiButton kuiButton--primary" > - Next + {{translations.nextButtonLabel}}
@@ -40,20 +55,28 @@

Welcome to Timelion!

-

First time configuration

-

- If you're using Logstash, you don't need to configure anything to - start exploring your log data with Timelion. To search other - indices, go to Management / Kibana / Advanced Settings - and configure the timelion:es.default_index - and timelion:es.timefield settings to match your - indices. -

-

- You'll also see some other Timelion settings. For now, you don't need - to worry about them. Later, you'll see that you can set most of - them on the fly if you need to. -

+

+

+

@@ -61,74 +84,139 @@

First time configuration

ng-click="setPage(page-1)" class="kuiButton kuiButton--primary" > - Previous + {{translations.previousButtonLabel}} - - Could not validate Elasticsearch settings: - {{es.invalidReason}}. Check your Advanced Settings - and try again. ({{es.invalidCount}}) - + + i18n-id="timelion.help.configuration.notValid.validateButtonLabel" + i18n-default-message="Validate Config" + >
-

Good news, Elasticsearch is configured correctly!

+

- We validated your default index and your timefield and everything - looks ok. We found data from {{es.stats.min}} to - {{es.stats.max}}. You're probably all set. If this - doesn't look right, see First time - configuration for information about configuring the Elasticsearch - datasource. -

-

- You should already see one chart, but you might need to make a - couple adjustments before you see any interesting data: + + +

+

  • - Intervals +

    - The interval selector at the right of the input bar lets you - control the sampling frequency. It's currently set to - {{state.interval}}. + - You're all set! + - - Set it to auto to let Timelion choose an - appropriate interval. - - If Timelion thinks your combination of time range and interval - will produce too many data points, it throws an error. You can - adjust that limit by configuring timelion:max_buckets - in Management/Kibana/Advanced Settings. + +

  • - Time range -

    - Use the timepicker in the - Kibana toolbar to select the time period that contains the - data you want to visualize. Make sure you select a time - period that includes all or part of the time range shown - above. -

    + +

-

- Now, you should see a line chart that displays a count of your - data points over time. -

+

@@ -136,7 +224,7 @@

Good news, Elasticsearch is configured correctly!

ng-click="setPage(page-1)" class="kuiButton kuiButton--primary" > - Previous + {{translations.previousButtonLabel}} @@ -144,7 +232,7 @@

Good news, Elasticsearch is configured correctly!

ng-click="setPage(page+1)" class="kuiButton kuiButton--primary" > - Next + {{translations.nextButtonLabel}}
@@ -152,60 +240,131 @@

Good news, Elasticsearch is configured correctly!

-

Querying the Elasticsearch datasource

+

+

- Now that we've validated that you have a working Elasticsearch - datasource, you can start submitting queries. For starters, - enter .es(*) in the input bar and hit enter. -

-

- This says hey Elasticsearch, find everything in my default - index. If you want to find a subset, you could enter something - like .es(html) to count events that match html, - or .es('user:bob AND bytes:>100') to find events - that contain bob in the user field and have a - bytes field that is greater than 100. Note that this query - is enclosed in single quotes—that's because it contains - spaces. You can enter any + - Lucene query string - - as the first argument to the .es() function. + href="https://www.elastic.co/guide/en/elasticsearch/reference/5.1/query-dsl-query-string-query.html#query-string-syntax" + target="_blank" + rel="noopener noreferrer" + i18n-id="timelion.help.querying.luceneQueryLinkText" + i18n-default-message="Lucene query string" + i18n-context="Part of composite text + timelion.help.querying.paragraph2Part1 + + timelion.help.querying.luceneQueryLinkText + + timelion.help.querying.paragraph2Part2" + > +

-

Passing arguments

+

+

+

- Timelion has a number of shortcuts that make it easy to do common - things. One is that for simple arguments that don't contain spaces or - special characters, you don't need to use quotes. Many functions also - have defaults. For example, .es() and .es(*) - do the same thing. Arguments also have names, so you don't have to - specify them in a specific order. For example, you can enter - .es(index='logstash-*', q='*') to tell the - Elasticsearch datasource use * as the q (query) for the - logstash-* index. -

-

Beyond count

-

- Counting events is all well and good, but the Elasticsearch datasource - also supports any + - Elasticsearch metric aggregation - - that returns a single value. Some of the most useful are - min, max, avg, sum, - and cardinality. Let's say you want a unique count of the - src_ip field. Simply use the cardinality - metric: .es(*, metric='cardinality:src_ip'). To get the - average of the bytes field, you can use the - avg metric: .es(metric='avg:bytes'). + href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics.html" + target="_blank" + rel="noopener noreferrer" + i18n-id="timelion.help.querying.countMetricAggregationLinkText" + i18n-default-message="Elasticsearch metric aggregation" + i18n-context="Part of composite text + timelion.help.querying.countTextPart1 + + timelion.help.querying.countMetricAggregationLinkText + + timelion.help.querying.countTextPart2" + > +

@@ -214,7 +373,7 @@

Beyond count

ng-click="setPage(page-1)" class="kuiButton kuiButton--primary" > - Previous + {{translations.previousButtonLabel}} @@ -222,7 +381,7 @@

Beyond count

ng-click="setPage(page+1)" class="kuiButton kuiButton--primary" > - Next + {{translations.nextButtonLabel}}
@@ -230,60 +389,95 @@

Beyond count

-

Expressing yourself with expressions

-

- Every expression starts with a datasource function. From there, you - can append new functions to the datasource to transform and augment - it. -

-

- By the way, from here on out you probably know more about your data - than we do. Feel free to replace the sample queries with something - more meaningful! -

-

- We're going to experiment, so click Add in the Kibana - toolbar to add another chart or three. Then, select a chart, copy - one of the following expressions, paste it into the input bar, - and hit enter. Rinse, repeat to try out the other expressions. -

+

+

+

+

Argument NameAccepted TypesInformation
{{arg.name}}
- + - + - + - +
.es(*), .es(US)Double the fun. Two expressions on the same - chart.
.es(*).color(#f66), .es(US).bars(1) - Custom styling. Colorizes the first series red - and uses 1 pixel wide bars for the second series. -
.es(*).color(#f66).lines(fill=3), .es(US).bars(1).points(radius=3, weight=1) - Named arguments. Forget trying to remember what - order you need to specify arguments in, use named arguments to make - the expressions easier to read and write. -
(.es(*), .es(GB)).points() - Grouped expressions. You can also chain groups - of expressions to functions. Here, both series are shown as - points instead of lines. -

- Timelion provides additional view transformation functions you can use - to customize the appearance of your charts. For the complete list, see - the Function reference. + + .

@@ -292,7 +486,7 @@

Expressing yourself with expressions

ng-click="setPage(page-1)" class="kuiButton kuiButton--primary" > - Previous + {{translations.previousButtonLabel}} @@ -300,50 +494,93 @@

Expressing yourself with expressions

ng-click="setPage(page+1)" class="kuiButton kuiButton--primary" > - Next + {{translations.nextButtonLabel}}

-

Transforming your data: the real fun begins!

-

- Now that you've mastered the basics, it's time to unleash the power of - Timelion. Let's figure out what percentage some subset of our data - represents of the whole, over time. For example, what percentage of - our web traffic comes from the US? -

+

+

+

+

+

+

- First, we need to find all events that contain US: - .es('US'). -

-

- Next, we want to calculate the ratio of US events to the whole. To - divide 'US' by everything, we can use the - divide function: .es('US').divide(.es()). -

-

- Not bad, but this gives us a number between 0 and 1. To convert it - to a percentage, simply multiply by 100: - .es('US').divide(.es()).multiply(100). -

-

- Now we know what percentage of our traffic comes from the US, and - can see how it has changed over time! - Timelion has a number of built-in arithmetic functions, such as - sum, subtract, multiply, and - divide. Many of these can take a series or a number. - There are also other useful data transformation functions, such as - movingaverage, abs, and - derivative. -

-

Now that you're familiar with the syntax, refer to the - Function reference to see - how to use all of the available Timelion functions. You can view - the reference at any time by clicking Docs - in the Kibana toolbar. To get back to this tutorial, click the - Tutorial link at the top of the reference. + + +

@@ -352,7 +589,7 @@

Transforming your data: the real fun begins!

ng-click="setPage(page-1)" class="kuiButton kuiButton--primary" > - Previous + {{translations.previousButtonLabel}} @@ -361,29 +598,34 @@

Transforming your data: the real fun begins!

ng-click="opts.dontShowHelp()" class="kuiButton kuiButton--hollow" > - Don't show this again + {{translations.dontShowHelpButtonLabel}}
-

- Help -

+

- +
- Click any function for more information. Just getting started? + - Check out the tutorial - . + >.
@@ -409,9 +651,21 @@

ng-show="function.args.length > (function.chainable ? 1: 0)" > - Argument Name - Accepted Types - Information + + +
- - This function does not accept any arguments. - Well that's simple, isn't it? - +

@@ -436,26 +690,50 @@

- +
-
General editing
+
+
Ctrl/Cmd + Enter
-
Submit request
+
-
When auto-complete is visible
-
Down arrow
-
Switch focus to auto-complete menu. Use arrows to further select a term
+
+ +
+
+
Enter/Tab
-
Select the currently selected or the top most term in auto-complete menu
+
Esc
-
Close auto-complete menu
+
diff --git a/src/core_plugins/timelion/public/directives/timelion_help/timelion_help.js b/src/core_plugins/timelion/public/directives/timelion_help/timelion_help.js index e970bca3b49b5..f9a44fc03b6d2 100644 --- a/src/core_plugins/timelion/public/directives/timelion_help/timelion_help.js +++ b/src/core_plugins/timelion/public/directives/timelion_help/timelion_help.js @@ -24,7 +24,7 @@ import moment from 'moment'; const app = uiModules.get('apps/timelion', []); -app.directive('timelionHelp', function ($http) { +app.directive('timelionHelp', function ($http, i18n) { return { restrict: 'E', template, @@ -38,6 +38,52 @@ app.directive('timelionHelp', function ($http) { $scope.es = { invalidCount: 0 }; + + $scope.translations = { + nextButtonLabel: i18n('timelion.help.nextPageButtonLabel', { + defaultMessage: 'Next', + }), + previousButtonLabel: i18n('timelion.help.previousPageButtonLabel', { + defaultMessage: 'Previous', + }), + dontShowHelpButtonLabel: i18n('timelion.help.dontShowHelpButtonLabel', { + defaultMessage: `Don't show this again`, + }), + strongNextText: i18n('timelion.help.welcome.content.strongNextText', { + defaultMessage: 'Next', + }), + emphasizedEverythingText: i18n('timelion.help.welcome.content.emphasizedEverythingText', { + defaultMessage: 'everything', + }), + notValidAdvancedSettingsPath: i18n('timelion.help.configuration.notValid.advancedSettingsPathText', { + defaultMessage: 'Management / Kibana / Advanced Settings' + }), + validAdvancedSettingsPath: i18n('timelion.help.configuration.valid.advancedSettingsPathText', { + defaultMessage: 'Management/Kibana/Advanced Settings', + }), + esAsteriskQueryDescription: i18n('timelion.help.querying.esAsteriskQueryDescriptionText', { + defaultMessage: 'hey Elasticsearch, find everything in my default index', + }), + esIndexQueryDescription: i18n('timelion.help.querying.esIndexQueryDescriptionText', { + defaultMessage: 'use * as the q (query) for the logstash-* index', + }), + strongAddText: i18n('timelion.help.expressions.strongAddText', { + defaultMessage: 'Add', + }), + twoExpressionsDescriptionTitle: i18n('timelion.help.expressions.examples.twoExpressionsDescriptionTitle', { + defaultMessage: 'Double the fun.', + }), + customStylingDescriptionTitle: i18n('timelion.help.expressions.examples.customStylingDescriptionTitle', { + defaultMessage: 'Custom styling.', + }), + namedArgumentsDescriptionTitle: i18n('timelion.help.expressions.examples.namedArgumentsDescriptionTitle', { + defaultMessage: 'Named arguments.', + }), + groupedExpressionsDescriptionTitle: i18n('timelion.help.expressions.examples.groupedExpressionsDescriptionTitle', { + defaultMessage: 'Grouped expressions.', + }), + }; + getFunctions(); checkElasticsearch(); } @@ -73,7 +119,7 @@ app.directive('timelionHelp', function ($http) { } catch (e) { if (_.get(resp, 'data.resp.message')) return _.get(resp, 'data.resp.message'); if (_.get(resp, 'data.resp.output.payload.message')) return _.get(resp, 'data.resp.output.payload.message'); - return 'Unknown error'; + return i18n('timelion.help.unknownErrorMessage', { defaultMessage: 'Unknown error' }); } }()); } diff --git a/src/core_plugins/timelion/public/directives/timelion_interval/timelion_interval.html b/src/core_plugins/timelion/public/directives/timelion_interval/timelion_interval.html index fcac264341dee..fcc1c1f531c9e 100644 --- a/src/core_plugins/timelion/public/directives/timelion_interval/timelion_interval.html +++ b/src/core_plugins/timelion/public/directives/timelion_interval/timelion_interval.html @@ -1,13 +1,13 @@ Save entire Timelion sheet ng-disabled="!opts.savedSheet.title" type="submit" class="kuiButton kuiButton--primary kuiVerticalRhythmSmall" - > - Save - + i18n-id="timelion.topNavMenu.save.saveEntireSheet.submitButtonLabel" + i18n-default-message="Save" + >
- + {{opts.state.sheet[opts.state.selected]}}
- - + +
- +
diff --git a/src/core_plugins/timelion/public/partials/sheet_options.html b/src/core_plugins/timelion/public/partials/sheet_options.html index 3331e54129cd2..e3a9ae21c89cd 100644 --- a/src/core_plugins/timelion/public/partials/sheet_options.html +++ b/src/core_plugins/timelion/public/partials/sheet_options.html @@ -1,11 +1,17 @@
-

- Sheet options -

+

- +
- +