浏览代码

[frontend] Add UI analytics events

[frontend] Add Editor analytics events
[frontend] Add Right-assist analytics events
[frontend] Add Left-assist analytics events
[frontend] Add filebrowser analytics events
[frontend] Add importer analytics events
[frontend] Add filechooser analytics events
Björn Alm 2 年之前
父节点
当前提交
06bf10a67b

+ 11 - 11
apps/filebrowser/src/filebrowser/templates/display.mako

@@ -52,46 +52,46 @@ ${ fb_components.menubar() }
         <!-- ko if: $root.file -->
         <ul class="nav nav-list">
           <!-- ko if: $root.isViewing -->
-            <li><a  data-bind="click: goToParentDirectory" href=""><i class="fa fa-reply"></i> ${_('Back')}</a></li>
+            <li><a data-hue-analytics="filebrowser:back-btn-click" data-bind="click: goToParentDirectory" href=""><i class="fa fa-reply"></i> ${_('Back')}</a></li>
 
             <!-- ko if: $root.file().view.compression() && $root.file().view.compression() === "none" && $root.file().editable -->
-              <li><a class="pointer" data-bind="click: $root.editFile"><i class="fa fa-pencil"></i> ${_('Edit file')}</a></li>
+              <li><a data-hue-analytics="filebrowser:edit-file-btn-click"class="pointer" data-bind="click: $root.editFile"><i class="fa fa-pencil"></i> ${_('Edit file')}</a></li>
             <!-- /ko -->
 
-            <li><a class="pointer" data-bind="click: changePage"><i class="fa fa-refresh"></i> ${_('Refresh')}</a></li>
+            <li><a data-hue-analytics="filebrowser:refresh-btn-click" class="pointer" data-bind="click: changePage"><i class="fa fa-refresh"></i> ${_('Refresh')}</a></li>
 
             <!-- ko if: $root.file().view.mode() === 'binary' -->
-            <li><a class="pointer" data-bind="click: function(){ switchMode('text'); }"><i class="fa fa-font"></i> ${_('View as text')}</a></li>
+            <li><a data-hue-analytics="filebrowser:view-text-btn-click" class="pointer" data-bind="click: function(){ switchMode('text'); }"><i class="fa fa-font"></i> ${_('View as text')}</a></li>
             <!-- /ko -->
 
             <!-- ko if: $root.file().view.mode() === 'text' -->
-              <li><a class="pointer" data-bind="click: function(){ switchMode('binary'); }"><i class="fa fa-barcode"></i> ${_('View as binary')}</a></li>
+              <li><a data-hue-analytics="filebrowser:view-binary-btn-click" class="pointer" data-bind="click: function(){ switchMode('binary'); }"><i class="fa fa-barcode"></i> ${_('View as binary')}</a></li>
             <!-- /ko -->
 
             <!-- ko if: $root.file().view.compression() !== "gzip" && $root.file().path().toLowerCase().endsWith('.gz') -->
-              <li><a class="pointer" data-bind="click: function(){ switchCompression('gzip'); }"><i class="fa fa-youtube-play"></i> ${_('Preview as Gzip')}</a></li>
+              <li><a data-hue-analytics="filebrowser:preview-gzip--btn-click" class="pointer" data-bind="click: function(){ switchCompression('gzip'); }"><i class="fa fa-youtube-play"></i> ${_('Preview as Gzip')}</a></li>
             <!-- /ko -->
 
             <!-- ko if: $root.file().view.compression() !== "bz2" && ($root.file().path().toLowerCase().endsWith('.bz2') || $root.file().path().toLowerCase().endsWith('.bzip2'))-->
-              <li><a class="pointer" data-bind="click: function(){ switchCompression('bz2'); }"><i class="fa fa-youtube-play"></i> ${_('Preview as Bzip2')}</a></li>
+              <li><a data-hue-analytics="filebrowser:preview-bz2--btn-click" class="pointer" data-bind="click: function(){ switchCompression('bz2'); }"><i class="fa fa-youtube-play"></i> ${_('Preview as Bzip2')}</a></li>
             <!-- /ko -->
 
             <!-- ko if: $root.file().view.compression() !== "avro" && $root.file().view.compression() !== "snappy_avro" && $root.file().path().toLowerCase().endsWith('.avro') -->
-              <li><a class="pointer" data-bind="click: function(){ switchCompression('avro'); }"><i class="fa fa-youtube-play"></i> ${_('Preview as Avro')}</a></li>
+              <li><a data-hue-analytics="filebrowser:preview-avro--btn-click" class="pointer" data-bind="click: function(){ switchCompression('avro'); }"><i class="fa fa-youtube-play"></i> ${_('Preview as Avro')}</a></li>
             <!-- /ko -->
 
             <!-- ko if: $root.file().view.compression() && $root.file().view.compression() !== "none" -->
-              <li><a class="pointer" data-bind="click: function(){ switchCompression('none'); }"><i class="fa fa-times-circle"></i> ${_('Stop preview')}</a></li>
+              <li><a data-hue-analytics="filebrowser:stop-preview--btn-click" class="pointer" data-bind="click: function(){ switchCompression('none'); }"><i class="fa fa-times-circle"></i> ${_('Stop preview')}</a></li>
             <!-- /ko -->
           <!-- /ko -->
 
           <!-- ko ifnot: $root.isViewing -->
-            <li><a class="pointer" data-bind="click: $root.viewFile"><i class="fa fa-reply"></i> ${_('View file')}</a></li>
+            <li><a data-hue-analytics="filebrowser:view-file-btn-click" class="pointer" data-bind="click: $root.viewFile"><i class="fa fa-reply"></i> ${_('View file')}</a></li>
           <!-- /ko -->
 
           <!-- ko if: $root.isViewing -->
             <!-- ko if: $root.file().show_download_button -->
-              <li><a class="pointer" data-bind="click: $root.downloadFile"><i class="fa fa-download"></i> ${_('Download')}</a></li>
+              <li><a data-hue-analytics="filebrowser:download-btn-click" class="pointer" data-bind="click: $root.downloadFile"><i class="fa fa-download"></i> ${_('Download')}</a></li>
             <!-- /ko -->
           <!-- /ko -->
 

+ 6 - 2
apps/filebrowser/src/filebrowser/templates/fb_components.mako

@@ -91,10 +91,14 @@ else:
             <% label, f_url = breadcrumb_item['label'], breadcrumb_item['url'] %>
             %if label[-1] == '/':
             <li><a href="javascript: void(0)" data-bind="click: ()=> {
-              huePubSub.publish('open.filebrowserlink', { pathPrefix: '/filebrowser/view=', decodedPath: `${f_url | n}` });}"><span class="divider">${label}</span></a></li>
+              huePubSub.publish('open.filebrowserlink', { pathPrefix: '/filebrowser/view=', decodedPath: `${f_url | n}` });
+              window.hueAnalytics.log('filebrowser', 'file-breadcrumb-navigation');
+              }"><span class="divider">${label}</span></a></li>              
             %else:
             <li><a href="javascript: void(0)" data-bind="click: ()=> {
-              huePubSub.publish('open.filebrowserlink', { pathPrefix: '/filebrowser/view=', decodedPath: `${f_url | n}` });}">${label}</a><span class="divider">/</span></li>
+              huePubSub.publish('open.filebrowserlink', { pathPrefix: '/filebrowser/view=', decodedPath: `${f_url | n}` });
+              window.hueAnalytics.log('filebrowser', 'file-breadcrumb-navigation');
+              }">${label}</a><span class="divider">/</span></li>              
             %endif
           % endfor
           </ul>

+ 14 - 14
apps/filebrowser/src/filebrowser/templates/listdir.mako

@@ -66,17 +66,17 @@ ${ fb_components.menubar() }
               <span class="caret" style="line-height: 15px"></span>
             </button>
             <ul class="dropdown-menu" style="top: auto">
-              <li><a href="javascript: void(0)" title="${_('Rename')}" data-bind="visible: !inTrash() && selectedFiles().length == 1, click: renameFile,
+              <li><a data-hue-analytics="filebrowser:actions-menu/rename-click" href="javascript: void(0)" title="${_('Rename')}" data-bind="visible: !inTrash() && selectedFiles().length == 1, click: renameFile,
               enable: selectedFiles().length == 1 && isCurrentDirSelected().length == 0"><i class="fa fa-fw fa-font"></i>
               ${_('Rename')}</a></li>
-              <li><a href="javascript: void(0)" title="${_('Move')}" data-bind="click: move, enable: selectedFiles().length > 0 &&
+              <li><a data-hue-analytics="filebrowser:actions-menu/move-click" href="javascript: void(0)" title="${_('Move')}" data-bind="click: move, enable: selectedFiles().length > 0 &&
               isCurrentDirSelected().length == 0"><i class="fa fa-fw fa-random"></i> ${_('Move')}</a></li>
               <li data-bind="css: {'disabled': $root.selectedFiles().length == 0 || isCurrentDirSelected().length > 0}">
-              <a href="javascript: void(0)" title="${_('Copy')}" data-bind="click: ($root.selectedFiles().length > 0 && isCurrentDirSelected().length == 0) ? $root.copy: void(0), enable: selectedFiles().length > 0 &&
+              <a data-hue-analytics="filebrowser:actions-menu/copy-click" href="javascript: void(0)" title="${_('Copy')}" data-bind="click: ($root.selectedFiles().length > 0 && isCurrentDirSelected().length == 0) ? $root.copy: void(0), enable: selectedFiles().length > 0 &&
               isCurrentDirSelected().length == 0"><i class="fa fa-fw fa-files-o"></i> ${_('Copy')}</a></li>
               % if show_download_button:
               <li>
-                <a href="javascript: void(0)" title="${_('Download')}" data-bind="visible: !inTrash() && selectedFiles().length == 1 && selectedFile().type == 'file', click: downloadFile">
+                <a data-hue-analytics="filebrowser:actions-menu/download-click" href="javascript: void(0)" title="${_('Download')}" data-bind="visible: !inTrash() && selectedFiles().length == 1 && selectedFile().type == 'file', click: downloadFile">
                   <i class="fa fa-fw fa-arrow-circle-o-down"></i> ${_('Download')}
                 </a>
               </li>
@@ -96,35 +96,35 @@ ${ fb_components.menubar() }
               </li>
               <li class="divider" data-bind="visible: isCompressEnabled() || isReplicationEnabled() || isSummaryEnabled()"></li>
               <li data-bind="css: {'disabled': inTrash() || selectedFiles().length > 1 }, visible: isSummaryEnabled()">
-                <a class="pointer" data-bind="click: function(){ selectedFiles().length == 1 ? showSummary(): void(0)}">
+                <a data-hue-analytics="filebrowser:actions-menu/show-summary-click" class="pointer" data-bind="click: function(){ selectedFiles().length == 1 ? showSummary(): void(0)}">
                   <i class="fa fa-fw fa-pie-chart"></i> ${_('Summary')}
                 </a>
               </li>
               <li>
-                <a href="javascript: void(0)" title="${_('Set Replication')}" data-bind="visible: !inTrash() && isReplicationEnabled() && selectedFiles().length == 1 && selectedFile().type == 'file', click: setReplicationFactor">
+                <a data-hue-analytics="filebrowser:actions-menu/set-replication-click"href="javascript: void(0)" title="${_('Set Replication')}" data-bind="visible: !inTrash() && isReplicationEnabled() && selectedFiles().length == 1 && selectedFile().type == 'file', click: setReplicationFactor">
                   <i class="fa fa-fw fa-hdd-o"></i> ${_('Set replication')}
                 </a>
               </li>
               % if not is_trash_enabled:
               <li>
-                <a href="javascript: void(0)" title="${_('Delete')}" data-bind="visible: !inTrash() && selectedFiles().length > 0 && isCurrentDirSelected().length == 0, click: deleteSelected">
+                <a data-hue-analytics="filebrowser:actions-menu/delete-click" href="javascript: void(0)" title="${_('Delete')}" data-bind="visible: !inTrash() && selectedFiles().length > 0 && isCurrentDirSelected().length == 0, click: deleteSelected">
                   <i class="fa fa-fw fa-bolt"></i> ${_('Delete')}
                 </a>
               </li>
               % endif
               % if ENABLE_EXTRACT_UPLOADED_ARCHIVE.get():
-                <li><a href="javascript: void(0)" title="${_('Compress selection into a single archive')}" data-bind="click: function() { setCompressArchiveDefault(); confirmCompressFiles();}, visible: showCompressButton">
+                <li><a data-hue-analytics="filebrowser:actions-menu/compress-click" href="javascript: void(0)" title="${_('Compress selection into a single archive')}" data-bind="click: function() { setCompressArchiveDefault(); confirmCompressFiles();}, visible: showCompressButton">
                   <i class="fa fa-fw fa-file-archive-o"></i> ${_('Compress')}</a>
                 </li>
-                <li><a href="javascript: void(0)" title="${_('Extract selected archive')}" data-bind="visible: selectedFiles().length == 1 && isArchive(selectedFile().name) && isCompressEnabled(), click: confirmExtractArchive">
+                <li><a data-hue-analytics="filebrowser:actions-menu/extract-click" href="javascript: void(0)" title="${_('Extract selected archive')}" data-bind="visible: selectedFiles().length == 1 && isArchive(selectedFile().name) && isCompressEnabled(), click: confirmExtractArchive">
                   <i class="fa fa-fw fa-file-archive-o"></i> ${_('Extract')}</a>
                 </li>
               % endif
             </ul>
           </div>
-          <button class="btn fileToolbarBtn" title="${_('Copy Path')}" data-bind="enable: selectedFiles().length == 1 && isCurrentDirSelected().length == 0, click: copyPath"><i class="fa fa-fw fa-files-o"></i> ${_('Copy Path')}</button>
-          <button class="btn fileToolbarBtn" title="${_('Open in Importer')}" data-bind="enable: selectedFiles().length == 1 && isCurrentDirSelected().length == 0 && selectedFile().type == 'file', click: openInImporter"><i class="fa fa-fw fa-database"></i> ${_('Open in Importer')}</button>
-          <button class="btn fileToolbarBtn" title="${_('Restore from trash')}" data-bind="visible: inRestorableTrash(), click: restoreTrashSelected, enable: selectedFiles().length > 0 && isCurrentDirSelected().length == 0"><i class="fa fa-cloud-upload"></i> ${_('Restore')}</button>
+          <button data-hue-analytics="filebrowser:copy-path-btn-click" class="btn fileToolbarBtn" title="${_('Copy Path')}" data-bind="enable: selectedFiles().length == 1 && isCurrentDirSelected().length == 0, click: copyPath"><i class="fa fa-fw fa-files-o"></i> ${_('Copy Path')}</button>
+          <button data-hue-analytics="filebrowser:open-in-importer-btn-click" class="btn fileToolbarBtn" title="${_('Open in Importer')}" data-bind="enable: selectedFiles().length == 1 && isCurrentDirSelected().length == 0 && selectedFile().type == 'file', click: openInImporter"><i class="fa fa-fw fa-database"></i> ${_('Open in Importer')}</button>
+          <button data-hue-analytics="filebrowser:restore-btn-click" class="btn fileToolbarBtn" title="${_('Restore from trash')}" data-bind="visible: inRestorableTrash(), click: restoreTrashSelected, enable: selectedFiles().length > 0 && isCurrentDirSelected().length == 0"><i class="fa fa-cloud-upload"></i> ${_('Restore')}</button>
           <!-- ko ifnot: inTrash -->
           % if is_trash_enabled:
           <div id="delete-dropdown" class="btn-group" style="vertical-align: middle">
@@ -171,7 +171,7 @@ ${ fb_components.menubar() }
           <!-- /ko -->
           <!-- ko ifnot: isS3() || isABFS() -->
           <div id="upload-dropdown" class="btn-group" style="vertical-align: middle">
-            <a href="javascript: void(0)" class="btn upload-link dropdown-toggle" title="${_('Upload')}" data-bind="click: uploadFile, visible: !inTrash(), css: {'disabled': isS3() && isS3Root() || isABFS() && isABFSRoot()}">
+            <a data-hue-analytics="filebrowser:upload-btn-click" href="javascript: void(0)" class="btn upload-link dropdown-toggle" title="${_('Upload')}" data-bind="click: uploadFile, visible: !inTrash(), css: {'disabled': isS3() && isS3Root() || isABFS() && isABFSRoot()}">
               <i class="fa fa-arrow-circle-o-up"></i> ${_('Upload')}
             </a>
           </div>
@@ -183,7 +183,7 @@ ${ fb_components.menubar() }
               <span class="caret"></span>
             </a>
             <ul class="dropdown-menu pull-right" style="top: auto">
-              <li data-bind="visible: !isS3() && !isABFS() || isS3() && !isS3Root() || isABFS() && !isABFSRoot()"><a href="javascript: void(0)" class="create-file-link" title="${_('File')}"><i class="fa fa-file-o"></i> ${_('File')}</a></li>
+              <li data-bind="visible: !isS3() && !isABFS() || isS3() && !isS3Root() || isABFS() && !isABFSRoot()"><a data-hue-analytics="filebrowser:new-file-btn-click" href="javascript: void(0)" class="create-file-link" title="${_('File')}"><i class="fa fa-file-o"></i> ${_('File')}</a></li>
               <li><a href="javascript: void(0)" class="create-directory-link" title="${_('Directory')}">
                 <i class="fa fa-folder"></i>
                 <span data-bind="visible: !isS3() && !isABFS() || isS3() && !isS3Root() || isABFS() && !isABFSRoot()">${_('Directory')}</span>

+ 7 - 1
apps/filebrowser/src/filebrowser/templates/listdir_components.mako

@@ -909,7 +909,8 @@ else:
               }              
               fileBrowserViewModel.targetPageNum(1);              
               const pathPrefix = "${url('filebrowser:filebrowser.views.view', path='')}";
-              huePubSub.publish('open.filebrowserlink', { pathPrefix, decodedPath: this.url, fileBrowserModel: fileBrowserViewModel});              
+              huePubSub.publish('open.filebrowserlink', { pathPrefix, decodedPath: this.url, fileBrowserModel: fileBrowserViewModel});
+              window.hueAnalytics.log('filebrowser', 'directory-breadcrumb-navigation');             
             }
             else {
               window.open($(e.target).attr('href'));
@@ -1312,6 +1313,7 @@ else:
 
       self.searchQuery.subscribe(function (newValue) {
         if (newValue !== '' || self.enableFilterAfterSearch) {
+          window.hueAnalytics.log('filebrowser', newValue === '' ? 'search-file-name-clear' : 'search-file-name');
           self.filter();
         }
         self.enableFilterAfterSearch = true;
@@ -1340,6 +1342,7 @@ else:
 
       self.openHome = function (vm, e) {
         self.openDefaultFolder(vm, e, 'default_to_home');
+        window.hueAnalytics.log('filebrowser', 'home-btn-click');
       }
 
       self.openTrash = function (vm, e) {
@@ -1582,6 +1585,7 @@ else:
       };
 
       self.changePermissions = function (data, event) {
+        window.hueAnalytics.log('filebrowser', 'actions-menu/change-permissions-click');
         if (!self.isCurrentDirSentryManaged()) {
           var paths = [];
 
@@ -2391,6 +2395,7 @@ else:
       huePubSub.publish('update.autocompleters');
 
       $(".create-directory-link").click(function () {
+        window.hueAnalytics.log('filebrowser', 'new-directory-btn-click');
         $("#newDirectoryNameInput").val('');
         $("#createDirectoryModal").modal({
           keyboard:true,
@@ -2445,6 +2450,7 @@ else:
           $(this).hide();
           $(".hue-breadcrumbs").hide();
           $("#hueBreadcrumbText").show().focus();
+          window.hueAnalytics.log('filebrowser', 'edit-breadcrumb-click');
         }
       });
 

+ 2 - 0
desktop/core/src/desktop/js/apps/editor/components/ExecutableActionsKoBridge.vue

@@ -33,6 +33,7 @@
   import ExecutableActions from './ExecutableActions.vue';
   import SqlExecutable from 'apps/editor/execution/sqlExecutable';
   import SubscriptionTracker from 'components/utils/SubscriptionTracker';
+  import hueAnalytics from '../../../../js/utils/hueAnalytics';
 
   import { wrap } from 'vue/webComponentWrap';
 
@@ -66,6 +67,7 @@
     },
     methods: {
       limitChanged(limit: number): void {
+        hueAnalytics.log('editor', 'limit-changed/' + limit);
         if (this.executable && this.executable.executor.defaultLimit) {
           this.executable.executor.defaultLimit(limit);
         }

+ 1 - 0
desktop/core/src/desktop/js/apps/editor/components/ExecuteLimitInput.vue

@@ -20,6 +20,7 @@
   <form autocomplete="off" class="inline-block margin-left-10">
     <input
       v-model="limit"
+      data-hue-analytics="editor:limit-input-click"
       class="input-small limit-input"
       type="number"
       autocorrect="off"

+ 17 - 3
desktop/core/src/desktop/js/apps/editor/components/QueryHistoryTable.vue

@@ -34,17 +34,31 @@
         <SearchInput v-model="searchFilter" :show-magnify="false" :small="true" />
       </div>
       <div class="query-history-actions">
-        <HueButton :small="true" :disabled="!history.length" @click="onClearClick">
+        <HueButton
+          data-hue-analytics="editor:clear-query-history-btn-click"
+          :small="true"
+          :disabled="!history.length"
+          @click="onClearClick"
+        >
           <i class="fa fa-fw fa-calendar-times-o" /> {{ I18n('Clear') }}
         </HueButton>
-        <HueButton :small="true" :disabled="!history.length" @click="onExportClick">
+        <HueButton
+          data-hue-analytics="editor:export-query-history-btn-click"
+          :small="true"
+          :disabled="!history.length"
+          @click="onExportClick"
+        >
           <i
             class="fa fa-fw"
             :class="{ 'fa-download': !exportingHistory, 'fa-spinner fa-spin': exportingHistory }"
           />
           {{ I18n('Export') }}
         </HueButton>
-        <HueButton :small="true" @click="onImportClick">
+        <HueButton
+          data-hue-analytics="editor:import-query-history-btn-click"
+          :small="true"
+          @click="onImportClick"
+        >
           <i class="fa fa-fw fa-upload" /> {{ I18n('import') }}
         </HueButton>
       </div>

+ 5 - 5
desktop/core/src/desktop/js/apps/editor/components/ko.snippetEditorActions.js

@@ -36,7 +36,7 @@ const TEMPLATE = `
     </button>
     <ul class="dropdown-menu pull-right" style="position: fixed !important; transform: translateX(-143px); left: initial; right: initial; top: initial; bottom: initial;">
       <li>
-        <a href="javascript:void(0)" data-bind="click: explain, css: {'disabled': !explainEnabled() }" title="${I18n(
+        <a data-hue-analytics="editor:more-menu-selection/explain-btn-click" href="javascript:void(0)" data-bind="click: explain, css: {'disabled': !explainEnabled() }" title="${I18n(
           'Explain the current SQL query'
         )}">
           <i class="fa fa-fw fa-map-o"></i> ${I18n('Explain')}
@@ -44,7 +44,7 @@ const TEMPLATE = `
       </li>
       <!-- ko if: window.HAS_GIST -->
       <li>
-        <a href="javascript:void(0)" data-bind="click: createGist, css: { 'disabled': !createGistEnabled() }" title="${I18n(
+        <a data-hue-analytics="editor:more-menu-selection/sharable-link" href="javascript:void(0)" data-bind="click: createGist, css: { 'disabled': !createGistEnabled() }" title="${I18n(
           'Share the query selection via a link'
         )}">
           <i class="fa fa-fw fa-link"></i> ${I18n('Shareable link')}
@@ -52,21 +52,21 @@ const TEMPLATE = `
       </li>
       <!-- /ko -->
       <li>
-        <a href="javascript:void(0)" data-bind="click: format, css: { 'disabled': !formatEnabled() }" title="${I18n(
+        <a data-hue-analytics="editor:more-menu-selection/format" href="javascript:void(0)" data-bind="click: format, css: { 'disabled': !formatEnabled() }" title="${I18n(
           'Format the current SQL query'
         )}">
           <i class="fa fa-fw fa-indent"></i> ${I18n('Format')}
         </a>
       </li>
       <li>
-        <a href="javascript:void(0)" data-bind="click: clear, css: {'disabled': !clearEnabled() }" title="${I18n(
+        <a data-hue-analytics="editor:more-menu-selection/clear" href="javascript:void(0)" data-bind="click: clear, css: {'disabled': !clearEnabled() }" title="${I18n(
           'Clear the current editor'
         )}">
           <i class="fa fa-fw fa-eraser"></i> ${I18n('Clear')}
         </a>
       </li>
       <li>
-        <a href="javascript:void(0)" data-bind="toggle: snippet.settingsVisible, visible: snippet.hasProperties" title="${I18n(
+        <a data-hue-analytics="editor:more-menu-selection/settings" href="javascript:void(0)" data-bind="toggle: snippet.settingsVisible, visible: snippet.hasProperties" title="${I18n(
           'Query settings'
         )}">
           <i class="fa fa-fw fa-cog"></i> ${I18n('Settings')}

+ 4 - 2
desktop/core/src/desktop/js/apps/editor/components/resultChart/ko.resultChart.js

@@ -863,8 +863,10 @@ class ResultChart extends DisposableComponent {
   }
 
   prepopulateChart() {
-    const type = this.chartType();
-    hueAnalytics.log('notebook', 'chart/' + type);
+    if (!window.ENABLE_NOTEBOOK_2) {
+      const type = this.chartType();
+      hueAnalytics.log('notebook', 'chart/' + type);
+    }
 
     if (this.isMapChart() && this.cleanedNumericMeta().length >= 2) {
       if (this.chartX() === null || typeof this.chartX() === 'undefined') {

+ 9 - 0
desktop/core/src/desktop/js/jquery/plugins/jquery.filechooser.js

@@ -424,6 +424,7 @@ Plugin.prototype.navigateTo = function (path) {
       }
 
       $search.find('.fa-search').on('click', () => {
+        window.hueAnalytics.log('filechooser', 'show-search-btn-click');
         if ($searchInput.is(':visible')) {
           slideOutInput();
         } else {
@@ -442,6 +443,7 @@ Plugin.prototype.navigateTo = function (path) {
 
       $search.find('.fa-refresh').on('click', () => {
         _parent.navigateTo(path);
+        window.hueAnalytics.log('filechooser', 'refresh-btn-click');
       });
 
       $search.appendTo($(_parent.element).find('.filechooser-tree'));
@@ -491,6 +493,7 @@ Plugin.prototype.navigateTo = function (path) {
         if ($(e.target).is('ul') || $(e.target).hasClass('spacer')) {
           $(this).hide();
           $hdfsAutocomplete.show().focus();
+          window.hueAnalytics.log('filechooser', 'show-edit-breadcrumbs-path');
         }
       });
 
@@ -516,6 +519,7 @@ Plugin.prototype.navigateTo = function (path) {
             const _url = crumb.url != null && crumb.url != '' ? crumb.url : '/';
             _parent.options.onFolderChange(_url);
             _parent.navigateTo(_url);
+            window.hueAnalytics.log('filechooser', 'breadcrumb-navigation-click');
           });
           _crumb.appendTo($scrollingBreadcrumbs);
         });
@@ -533,6 +537,7 @@ Plugin.prototype.navigateTo = function (path) {
           _parent.options.onFolderChange(_url);
           _parent.navigateTo(_url);
           $('#jHueHdfsAutocomplete').hide();
+          window.hueAnalytics.log('filechooser', 'confirm-edit-breadcrumbs-path');
         },
         onBlur: function () {
           $hdfsAutocomplete.hide();
@@ -694,12 +699,14 @@ Plugin.prototype.navigateTo = function (path) {
         _folderCancel.click(() => {
           if (_uploadFileBtn) {
             _uploadFileBtn.removeClass('disabled');
+            window.hueAnalytics.log('filechooser', 'create-folder-cancel-btn-click');
           }
           _createFolderBtn.removeClass('disabled');
           _createFolderDetails.slideUp();
         });
         _folderBtn.click(() => {
           if (_folderName.val().length > 0) {
+            window.hueAnalytics.log('filechooser', 'create-folder-btn-2-click');
             $.ajax({
               type: 'POST',
               url: '/filebrowser/mkdir',
@@ -728,6 +735,7 @@ Plugin.prototype.navigateTo = function (path) {
 
         _createFolderBtn.click(() => {
           if (_uploadFileBtn) {
+            window.hueAnalytics.log('filechooser', 'create-folder-btn-1-click');
             _uploadFileBtn.addClass('disabled');
           }
           _createFolderBtn.addClass('disabled');
@@ -783,6 +791,7 @@ function initUploader(path, _parent, el, labels) {
     },
     onSubmit: function (id, fileName) {
       num_of_pending_uploads++;
+      window.hueAnalytics.log('filechooser', 'uploading-file');
     },
     template:
       '<div class="qq-uploader">' +

+ 4 - 0
desktop/core/src/desktop/js/ko/components/assist/ko.assistPanel.js

@@ -27,6 +27,7 @@ import { GET_KNOWN_CONFIG_TOPIC } from 'config/events';
 import AssistInnerPanel from 'ko/components/assist/assistInnerPanel';
 import componentUtils from 'ko/components/componentUtils';
 import huePubSub from 'utils/huePubSub';
+import hueAnalytics from 'utils/hueAnalytics';
 import I18n from 'utils/i18n';
 import { withLocalStorage } from 'utils/storageUtils';
 
@@ -283,6 +284,9 @@ class AssistPanel {
       });
 
       self.visiblePanel.subscribe(newValue => {
+        if (self.lastOpenPanelType() !== newValue?.type) {
+          hueAnalytics.log('left-assist-panel', 'panel-selection/' + newValue?.type);
+        }
         self.lastOpenPanelType(newValue.type);
       });
 

+ 2 - 0
desktop/core/src/desktop/js/ko/components/assist/ko.rightAssistPanel.js

@@ -24,6 +24,7 @@ import {
 import { ACTIVE_SNIPPET_CONNECTOR_CHANGED_EVENT } from 'apps/editor/events';
 import componentUtils from 'ko/components/componentUtils';
 import huePubSub from 'utils/huePubSub';
+import hueAnalytics from 'utils/hueAnalytics';
 import I18n from 'utils/i18n';
 import { withLocalStorage } from 'utils/storageUtils';
 
@@ -216,6 +217,7 @@ class RightAssistPanel {
   }
 
   switchTab(tabName) {
+    hueAnalytics.log('right-assist-panel', 'tab-click/' + tabName);
     if (this.activeTab() === tabName) {
       this.visible(false);
       this.activeTab(undefined);

+ 1 - 0
desktop/core/src/desktop/js/sidePanelViewModel.js

@@ -40,6 +40,7 @@ class SidePanelViewModel {
         setInLocalStorage('assist.left_assist_panel_visible', val);
       }
       hueAnalytics.convert('hue', 'leftAssistVisible/' + val);
+      hueAnalytics.log('left-assist-panel', 'show-assist-toggle/' + val);
       window.setTimeout(() => {
         huePubSub.publish('split.panel.resized');
         $(window).trigger('resize');

+ 3 - 0
desktop/core/src/desktop/templates/config_ko_components.mako

@@ -480,6 +480,7 @@ else:
       }
 
       KeyValueListInputViewModel.prototype.addValue = function () {
+        window.hueAnalytics.log('editor', 'settings/add-settings-value');
         var self = this;
         var newValue = {
           key: ko.observable(''),
@@ -610,6 +611,7 @@ else:
       }
 
       FunctionListInputViewModel.prototype.addValue = function () {
+        window.hueAnalytics.log('editor', 'settings/add-function');
         var self = this;
         var newValue = {
           name: ko.observable(''),
@@ -683,6 +685,7 @@ else:
       }
 
       HdfsFileListInputViewModel.prototype.addValue = function () {
+        window.hueAnalytics.log('editor', 'settings/add-file-path');
         var self = this;
         var newValue = {
           path: ko.observable(''),

+ 41 - 17
desktop/libs/indexer/src/indexer/templates/importer.mako

@@ -229,7 +229,7 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
             </label>
             <!-- ko if: createWizard.source.path().length > 0 -->
               <a data-bind="storageContextPopover: { path: createWizard.source.path(), offset: { right: 5 } }" title="${ _('Preview') }" style="font-size: 14px" class="margin-left-10">
-                <i class="fa fa-fw fa-info"></i>
+                <i data-hue-analytics="importer:preview-path-btn-click" class="fa fa-fw fa-info"></i>
               </a>
             <!-- /ko -->
           </div>
@@ -652,7 +652,7 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
             <div class="control-group">
               <label class="control-label"><div>${ _('Extras') }</div>
                 <a href="javascript:void(0)" data-bind="css: { 'inactive-action': !showProperties() }, toggle: showProperties" title="${ _('Show extra properties') }">
-                  <i class="fa fa-sliders fa-padding-top"></i>
+                  <i data-hue-analytics="importer:show-extras-btn-click" class="fa fa-sliders fa-padding-top"></i>
                 </a>
               </label>
             </div>
@@ -660,12 +660,12 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
             <span data-bind="visible: showProperties">
               <div class="control-group">
                 <label class="checkbox inline-block" data-bind="visible: tableFormat() != 'kudu'">
-                  <input type="checkbox" data-bind="checked: useDefaultLocation, disable: isIceberg"> ${_('Store in Default location')}
+                  <input data-hue-analytics="importer:store-in-default-localtion-checkbox-interaction" type="checkbox" data-bind="checked: useDefaultLocation, disable: isIceberg"> ${_('Store in Default location')}
                 </label>
               </div>
               <div class="control-group" data-bind="visible: isTransactionalVisible">
                 <label class="checkbox inline-block">
-                  <input type="checkbox" data-bind="checked: isTransactional, disable: isIceberg"> ${_('Transactional table')}
+                  <input type="checkbox" data-hue-analytics="importer:is-transactional-checkbox-interaction" data-bind="checked: isTransactional, disable: isIceberg"> ${_('Transactional table')}
                 </label>
                 <label class="checkbox inline-block" title="${_('Full transactional support available in Hive with ORC')}">
                   <input type="checkbox" data-bind="checked: isInsertOnly, enable: isTransactionalUpdateEnabled"> ${_('Insert only')}
@@ -680,13 +680,13 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
 
               <div class="control-group">
                 <label class="checkbox inline-block" data-bind="visible: $root.createWizard.source.inputFormat() != 'manual'">
-                  <input type="checkbox" data-bind="checked: importData, disable: !useDefaultLocation() && $parent.createWizard.source.path() == nonDefaultLocation();"> ${_('Import data')}
+                  <input data-hue-analytics="importer:import-data-checkbox-interaction" type="checkbox" data-bind="checked: importData, disable: !useDefaultLocation() && $parent.createWizard.source.path() == nonDefaultLocation();"> ${_('Import data')}
                 </label>
               </div>
 
               <div class="control-group" data-bind="visible: icebergEnabled">
                 <label class="checkbox inline-block">
-                  <input type="checkbox" data-bind="checked: isIceberg"> ${_('Iceberg table')}
+                  <input data-hue-analytics="importer:is-iceberg-checkbox-interaction" type="checkbox" data-bind="checked: isIceberg"> ${_('Iceberg table')}
                 </label>
               </div>
 
@@ -697,7 +697,7 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
               </div>
               <div class="control-group" data-bind="visible: $root.createWizard.source.inputFormat() == 'file'">
                 <label class="checkbox inline-block">
-                  <input type="checkbox" data-bind="checked: hasHeader"> ${_('Use first row as header')}
+                  <input data-hue-analytics="importer:use-first-row-as-header-interaction" type="checkbox" data-bind="checked: hasHeader"> ${_('Use first row as header')}
                 </label>
               </div>
               <div class="control-group" data-bind="visible: tableFormat() == 'text'">
@@ -735,11 +735,14 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
               <!-- ko if: tableFormat() != 'kudu' && $root.createWizard.source.inputFormat() != 'rdbms' -->
               <div class="inline-table">
                 <div class="form-inline" data-bind="foreach: partitionColumns">
-                  <a class="pointer pull-right margin-top-20" data-bind="click: function() { $parent.partitionColumns.remove($data); }"><i class="fa fa-minus"></i></a>
+                  <a class="pointer pull-right margin-top-20" data-bind="click: function() { 
+                    $parent.partitionColumns.remove($data);
+                    window.hueAnalytics.log('importer', 'remove-partiction-btn-click');
+                  }"><i class="fa fa-minus"></i></a>
                   <div data-bind="template: { name: 'table-field-template', data: $data }" class="margin-top-10 field inline-block"></div>
                   <div class="clearfix"></div>
                 </div>
-                <a data-bind="click: function() { partitionColumns.push($root.loadDefaultField({isPartition: true})); }" class="pointer" title="${_('Add Partition')}"><i class="fa fa-plus fa-padding-top"></i> ${_('Add partition')}</a>
+                <a data-hue-analytics="importer:add-partiction-btn-click" data-bind="click: function() { partitionColumns.push($root.loadDefaultField({isPartition: true})); }" class="pointer" title="${_('Add Partition')}"><i class="fa fa-plus fa-padding-top"></i> ${_('Add partition')}</a>
               </div>
               <!-- /ko -->
 
@@ -997,7 +1000,7 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
               <!-- ko ifnot: fieldEditorEnabled -->
                 ${_('Fields')} <!-- ko if: $root.createWizard.isGuessingFieldTypes --><i class="fa fa-spinner fa-spin"></i><!-- /ko -->
                 <a class="inactive-action pointer" data-bind="visible: columns().length > 0, publish: 'importer.show.bulkeditor'" href="javascript:void(0)">
-                  <i class="fa fa-edit"></i>
+                  <i data-hue-analytics="importer:bulk-field-editor-show" class="fa fa-edit"></i>
                 </a>
               <!-- /ko -->
             </h4>
@@ -1107,13 +1110,16 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
       <!-- /ko -->
 
       <!-- ko if: currentStep() == 1 -->
-      <button class="btn" data-bind="enable: !createWizard.isGuessingFormat() && createWizard.source.show(), click: function() { currentStep(2); }">
+      <button class="btn" data-bind="enable: !createWizard.isGuessingFormat() && createWizard.source.show(), click: function() { 
+        currentStep(2);
+        window.hueAnalytics.log('importer', 'next-btn-click/' +  createWizard?.source?.inputFormat());
+        }">
         ${_('Next')}
       </button>
       <!-- /ko -->
 
       <!-- ko if: currentStep() == 2 -->
-        <button class="btn btn-primary disable-feedback" data-bind="click: function() { createWizard.indexFile(); }, enable: createWizard.readyToIndex() && !createWizard.indexingStarted()">
+        <button data-hue-analytics="importer:submit-btn-click" class="btn btn-primary disable-feedback" data-bind="click: function() { createWizard.indexFile(); }, enable: createWizard.readyToIndex() && !createWizard.indexingStarted()">
           ${ _('Submit') } <i class="fa fa-spinner fa-spin" data-bind="visible: createWizard.indexingStarted"></i>
         </button>
 
@@ -1146,8 +1152,8 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
       <input type="text" class="input-xxlarge" placeholder="${ _('e.g. id, name, salary') }" data-bind="textInput: createWizard.destination.bulkColumnNames">
     </div>
     <div class="modal-footer">
-      <button class="btn" data-dismiss="modal" aria-hidden="true">${ _('Cancel') }</button>
-      <button class="btn btn-primary" data-bind="click: createWizard.destination.processBulkColumnNames">${ _('Change field names') }</button>
+      <button data-hue-analytics="importer:bulk-field-editor-cancel" class="btn" data-dismiss="modal" aria-hidden="true">${ _('Cancel') }</button>
+      <button data-hue-analytics="importer:bulk-field-editor-change" class="btn btn-primary" data-bind="click: createWizard.destination.processBulkColumnNames">${ _('Change field names') }</button>
     </div>
   </div>
 
@@ -1157,7 +1163,7 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
 <script type="text/html" id="table-field-template">
   <div>
     <label data-bind="visible: level() == 0 || ($parent.type() != 'array' && $parent.type() != 'map')">${ _('Name') }&nbsp;
-      <input type="text" class="input-large" placeholder="${ _('Field name') }" required data-bind="textInput: name" pattern="[a-zA-Z0-9_]+$" title="${ _('Only alphanumeric and underscore characters') }">
+      <input data-hue-analytics="importer:field-name-click" type="text" class="input-large" placeholder="${ _('Field name') }" required data-bind="textInput: name" pattern="[a-zA-Z0-9_]+$" title="${ _('Only alphanumeric and underscore characters') }">
     </label>
 
     <label class="margin-left-5">${ _('Type') }&nbsp;
@@ -1183,7 +1189,7 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
     <!-- /ko -->
 
     <span data-bind="visible: level() == 0 || ($parent.type() != 'array' && $parent.type() != 'map')">
-      <a href="javascript:void(0)" title="${ _('Show field properties') }" data-bind="css: {'inactive-action': !showProperties()}, click: function() {showProperties(!showProperties()) }"><i class="fa fa-sliders"></i></a>
+      <a href="javascript:void(0)" title="${ _('Show field properties') }" data-bind="css: {'inactive-action': !showProperties()}, click: function() {showProperties(!showProperties()) }"><i data-hue-analytics="importer:toggle-field-properties" class="fa fa-sliders"></i></a>
 
       <span data-bind="visible: showProperties">
         <input type="text" class="input-medium margin-left-5" placeholder="${ _('Field comment') }" data-bind="value: comment">
@@ -1781,6 +1787,7 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
       % endif
 
       self.inputFormat.subscribe(function(val) {
+        window.hueAnalytics.log('importer', 'source-type-selection/' + val);
         wizard.destination.columns.removeAll();
         if (self.sample()) {
           self.sample.removeAll();
@@ -2345,6 +2352,7 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
           wizard.guessFieldTypes();
           resizeElements();
         }
+        window.hueAnalytics.log('importer', 'destination-type-selection/' + newValue);
       });
       self.outputFormatsList = ko.observableArray([
           {'name': '${ _("Table") }', 'value': 'table'},
@@ -2557,6 +2565,9 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
         return self.outputFormat() === 'database' ? self.name() : (self.outputFormat() === 'table' && self.name().indexOf('.') > 0 ? self.name().split('.', 2)[0] : 'default');
       });
       self.tableFormat = ko.observable('text');
+      self.tableFormat.subscribe(function(value) {
+        window.hueAnalytics.log('importer', 'table-format-selection/' + value);
+      })
       self.KUDU_DEFAULT_RANGE_PARTITION_COLUMN = {values: [{value: ''}], name: 'VALUES', lower_val: 0, include_lower_val: '<=', upper_val: 1, include_upper_val: '<='};
       self.KUDU_DEFAULT_PARTITION_COLUMN = {columns: [], range_partitions: [self.KUDU_DEFAULT_RANGE_PARTITION_COLUMN], name: 'HASH', int_val: 16};
 
@@ -2606,7 +2617,13 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
       });
 
       self.importData = ko.observable(true);
+      self.importData.subscribe(function(val) {
+        window.hueAnalytics.log('importer', 'import-data/' + val);
+      })      
       self.useDefaultLocation = ko.observable(true);
+      self.useDefaultLocation.subscribe(function(val) {
+        window.hueAnalytics.log('importer', 'default-location/' + val);
+      })
       self.nonDefaultLocation = ko.observable('');
 
       var isTransactionalVisibleImpala = '${ impala_flags.is_transactional() }'.toLowerCase() == 'true';
@@ -2615,6 +2632,9 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
 
       self.isTransactionalVisible = ko.observable((vm.sourceType == 'impala' && isTransactionalVisibleImpala) || (vm.sourceType == 'hive' && isTransactionalVisibleHive));
       self.isTransactional = ko.observable(self.isTransactionalVisible());
+      self.isTransactional.subscribe(function(val) {
+        window.hueAnalytics.log('importer', 'is-transactional/' + val);
+      })   
       self.isInsertOnly = ko.observable(true); // Impala doesn't have yet full support.
       self.isTransactionalUpdateEnabled = ko.pureComputed(function() {
         var enabled = self.tableFormat() == 'orc' && (vm.sourceType == 'hive' || (vm.sourceType == 'impala' && transactionalDefaultType.length && transactionalDefaultType != 'insert_only'));
@@ -2636,6 +2656,7 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
           self.isTransactional(self.isTransactionalVisible());
           self.tableFormat('text');
         }
+        window.hueAnalytics.log('importer', 'is-iceberg/' + val);
       });
 
       self.hasHeader = ko.observable(false);
@@ -2743,6 +2764,9 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
       self.fileType = ko.observable();
       self.fileType.subscribe(function (newType) {
         if (self.source.format()) {
+          if(self.source.format()?.type() !== newType?.name) {
+            window.hueAnalytics.log('importer', 'file-type-selected/' + newType?.name);
+          }
           self.source.format().type(newType.name);
         }
       });
@@ -3219,7 +3243,7 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode }
       self.previousStep = function () {
         if (self.previousStepVisible()) {
           self.currentStep(self.currentStep() - 1);
-          hueAnalytics.log('importer', 'step/' + self.currentStep());
+          window.hueAnalytics.log('importer', 'back-btn-click/' +  self.createWizard?.source?.inputFormat() );
         }
       };
 

+ 16 - 16
desktop/libs/notebook/src/notebook/templates/editor2.mako

@@ -74,7 +74,7 @@ There is no bridge to KO for components using this integration. Example using in
 % if ENABLE_PRESENTATION.get():
     <!-- ko with: selectedNotebook() -->
     <div class="btn-group">
-      <a class="btn" data-bind="click: function() { isPresentationMode(!isPresentationMode()); },
+      <a class="btn" data-bind="click: function() { isPresentationMode(!isPresentationMode()); hueAnalytics.log('editor', 'view-as-presentation');},
       css: {'btn-inverse': $root.isPresentationMode()}, attr: {title: isPresentationMode() ? '${ _ko('Exit presentation') }' : '${ _ko('View as a presentation') }'}">
         <i class="fa fa-line-chart"></i>
       </a>
@@ -94,7 +94,7 @@ There is no bridge to KO for components using this integration. Example using in
 % endif
 
     <div class="btn-group">
-      <a class="btn" rel="tooltip" data-placement="bottom" data-loading-text="${ _("Saving...") }" data-bind="click: function() { if ($root.canSave() ) { saveNotebook() } else { $('#editorSaveAsModal').modal('show');} }, attr: { title: $root.canSave() ? '${ _ko('Save') }' : '${ _ko('Save As') }' }">
+      <a data-hue-analytics="editor:save-query-as-click" class="btn" rel="tooltip" data-placement="bottom" data-loading-text="${ _("Saving...") }" data-bind="click: function() { if ($root.canSave() ) { saveNotebook() } else { $('#editorSaveAsModal').modal('show');} }, attr: { title: $root.canSave() ? '${ _ko('Save') }' : '${ _ko('Save As') }' }">
         <i class="fa fa-save"></i>
       </a>
 
@@ -120,7 +120,7 @@ There is no bridge to KO for components using this integration. Example using in
       <ul class="dropdown-menu pull-right">
         <li>
           <!-- ko if: editorMode -->
-          <a href="javascript:void(0)" data-bind="click: function() { hueUtils.removeURLParameter('editor'); newNotebook($root.editorType(), null, selectedNotebook() ? $root.selectedNotebook().snippets()[0].currentQueryTab() : null, 'blank'); }, attr: { 'title': '${ _('New ') }' +  editorTitle() + '${ _(' Query') }' }">
+          <a data-hue-analytics="editor:new-query-button-click" href="javascript:void(0)" data-bind="click: function() { hueUtils.removeURLParameter('editor'); newNotebook($root.editorType(), null, selectedNotebook() ? $root.selectedNotebook().snippets()[0].currentQueryTab() : null, 'blank'); }, attr: { 'title': '${ _('New ') }' +  editorTitle() + '${ _(' Query') }' }">
             <i class="fa fa-fw fa-file-o"></i> ${ _('New') }
           </a>
           <!-- /ko -->
@@ -131,12 +131,12 @@ There is no bridge to KO for components using this integration. Example using in
           <!-- /ko -->
         </li>
         <li>
-          <a href="javascript:void(0)" data-bind="publish: { 'assist.show.documents': editorMode() ? 'query-' + editorType() : editorType() }">
+          <a data-hue-analytics="editor:queries-button-click" href="javascript:void(0)" data-bind="publish: { 'assist.show.documents': editorMode() ? 'query-' + editorType() : editorType() }">
             <svg class="hi hi-fw hi-bigger"><use xlink:href="#hi-documents"></use></svg> <span data-bind="text: editorMode() ? '${ _ko('Queries') }' : '${ _ko('Notebooks') }'"></span>
           </a>
         </li>
         <li>
-          <a href="javascript:void(0)" title="${ _('Show Editor Help') }" data-toggle="modal" data-target="#editorHelpModal">
+          <a data-hue-analytics="editor:show-help-button-click" href="javascript:void(0)" title="${ _('Show Editor Help') }" data-toggle="modal" data-target="#editorHelpModal">
             <i class="fa fa-fw fa-question"></i>  ${ _('Help') }
           </a>
         </li>
@@ -152,7 +152,7 @@ There is no bridge to KO for components using this integration. Example using in
         <!-- /ko -->
         <!-- /ko -->
         <li>
-          <a href="javascript:void(0)" data-bind="click: showSessionPanel">
+          <a data-hue-analytics="editor:show-sessions-button-click" href="javascript:void(0)" data-bind="click: showSessionPanel">
             <i class="fa fa-fw fa-cogs"></i> ${ _('Sessions') }
           </a>
         </li>
@@ -839,12 +839,12 @@ There is no bridge to KO for components using this integration. Example using in
             </li>
             <li class="query-name no-horiz-padding skip-width-calculation">
               <a href="javascript:void(0)">
-                <div class="notebook-name-desc" data-bind="editable: name, editableOptions: { inputclass: 'notebook-name-input', enabled: true, placement: 'bottom', emptytext: '${_ko('Add a name...')}', tpl: '<input type=\'text\' maxlength=\'255\'>' }"></div>
+                <div data-hue-analytics="editor:add-name-click" class="notebook-name-desc" data-bind="editable: name, editableOptions: { inputclass: 'notebook-name-input', enabled: true, placement: 'bottom', emptytext: '${_ko('Add a name...')}', tpl: '<input type=\'text\' maxlength=\'255\'>' }"></div>
               </a>
             </li>
             <li class="skip-width-calculation" data-bind="tooltip: { placement: 'bottom', title: description }">
               <a href="javascript:void(0)">
-                <div class="notebook-name-desc" data-bind="editable: description, editableOptions: { type: 'textarea', enabled: true, placement: 'bottom', emptytext: '${_ko('Add a description...')}' }"></div>
+                <div data-hue-analytics="editor:add-description-click" class="notebook-name-desc" data-bind="editable: description, editableOptions: { type: 'textarea', enabled: true, placement: 'bottom', emptytext: '${_ko('Add a description...')}' }"></div>
               </a>
             </li>
             <!-- /ko -->
@@ -891,7 +891,7 @@ There is no bridge to KO for components using this integration. Example using in
           <div class="editor-top-right-actions">
             <!-- ko template: { name: 'snippet-header-database-selection' } --><!-- /ko -->
             <button title="${ _('Expand editor') }" data-bind="toggle: $root.topExpanded">
-              <i class="fa" data-bind="css: { 'fa-expand': !$root.topExpanded(), 'fa-compress': $root.topExpanded() }"></i>
+              <i data-hue-analytics="editor:expand-editor-click" class="fa" data-bind="css: { 'fa-expand': !$root.topExpanded(), 'fa-compress': $root.topExpanded() }"></i>
             </button>
           </div>
         </div>
@@ -930,23 +930,23 @@ There is no bridge to KO for components using this integration. Example using in
       <div class="editor-bottom">
         <ul class="editor-bottom-tabs nav nav-tabs">
           <li data-bind="click: function() { currentQueryTab('queryHistory'); }, css: { 'active': currentQueryTab() == 'queryHistory' }">
-            <a class="inactive-action" style="display:inline-block" href="#queryHistory" data-toggle="tab">${_('Query History')}</a>
+            <a data-hue-analytics="editor:bottom-tab-click/query-history" class="inactive-action" style="display:inline-block" href="#queryHistory" data-toggle="tab">${_('Query History')}</a>
           </li>
           <li data-bind="click: function(){ currentQueryTab('savedQueries'); }, css: { 'active': currentQueryTab() == 'savedQueries' }">
-            <a class="inactive-action" style="display:inline-block" href="#savedQueries" data-toggle="tab">${_('Saved Queries')}</a>
+            <a data-hue-analytics="editor:bottom-tab-click/saved-queries" class="inactive-action" style="display:inline-block" href="#savedQueries" data-toggle="tab">${_('Saved Queries')}</a>
           </li>
           <li data-bind="click: function() { currentQueryTab('queryResults'); }, css: {'active': currentQueryTab() == 'queryResults'}">
-            <a class="inactive-action" style="display:inline-block" href="#queryResults" data-toggle="tab">${_('Results')}
+            <a data-hue-analytics="editor:bottom-tab-click/query-result" class="inactive-action" style="display:inline-block" href="#queryResults" data-toggle="tab">${_('Results')}
   ##          <!-- ko if: result.rows() != null  -->
   ##          (<span data-bind="text: result.rows().toLocaleString() + (dialect() == 'impala' && result.rows() == 1024 ? '+' : '')" title="${ _('Number of rows') }"></span>)
   ##          <!-- /ko -->
             </a>
           </li>
           <li data-bind="click: function() { currentQueryTab('queryChart'); }, css: {'active': currentQueryTab() == 'queryChart'}">
-            <a class="inactive-action" style="display:inline-block" href="#queryChart" data-toggle="tab">${_('Chart')}</a>
+            <a data-hue-analytics="editor:bottom-tab-click/query-chart" class="inactive-action" style="display:inline-block" href="#queryChart" data-toggle="tab">${_('Chart')}</a>
           </li>
           <!-- ko if: explanation -->
-          <li data-bind="click: function() { currentQueryTab('queryExplain'); }, css: {'active': currentQueryTab() == 'queryExplain'}"><a class="inactive-action" href="#queryExplain" data-toggle="tab">${_('Explain')}</a></li>
+          <li data-hue-analytics="editor:bottom-tab-click/query-explain" data-bind="click: function() { currentQueryTab('queryExplain'); }, css: {'active': currentQueryTab() == 'queryExplain'}"><a class="inactive-action" href="#queryExplain" data-toggle="tab">${_('Explain')}</a></li>
           <!-- /ko -->
           <!-- ko foreach: pinnedContextTabs -->
           <li data-bind="click: function() { $parent.currentQueryTab(tabId) }, css: { 'active': $parent.currentQueryTab() === tabId }">
@@ -960,12 +960,12 @@ There is no bridge to KO for components using this integration. Example using in
           <!-- /ko -->
 
           <li data-bind="click: function(){ currentQueryTab('executionAnalysis'); }, css: {'active': currentQueryTab() == 'executionAnalysis'}">
-            <a class="inactive-action" href="#executionAnalysis" data-toggle="tab">${_('Execution Analysis')}</a>
+            <a data-hue-analytics="editor:bottom-tab-click/execution-analysis" class="inactive-action" href="#executionAnalysis" data-toggle="tab">${_('Execution Analysis')}</a>
           </li>
 
           <li class="editor-bottom-tab-actions">
             <button data-bind="toggle: $root.bottomExpanded">
-              <i class="fa" data-bind="css: { 'fa-expand': !$root.bottomExpanded(), 'fa-compress': $root.bottomExpanded() }"></i>
+              <i data-hue-analytics="editor:expand-result-click" class="fa" data-bind="css: { 'fa-expand': !$root.bottomExpanded(), 'fa-compress': $root.bottomExpanded() }"></i>
             </button>
           </li>
         </ul>