From 25c6627368d583e0721390e20a054b2263eb3bdb Mon Sep 17 00:00:00 2001 From: Jim Unger Date: Tue, 24 Nov 2015 13:06:50 -0600 Subject: [PATCH 1/8] [url shortener] initial prototype --- src/plugins/kibana/public/dashboard/index.js | 27 ++++--- .../public/dashboard/partials/share.html | 5 +- .../public/discover/controllers/discover.js | 3 +- src/plugins/kibana/public/discover/index.html | 10 +++ .../discover/partials/share_search.html | 22 ++++++ src/plugins/kibana/public/goto/index.js | 22 ++++++ .../kibana/public/visualize/editor/editor.js | 16 ++-- .../public/visualize/editor/panels/share.html | 5 +- src/server/http/index.js | 21 +++++ src/server/http/urlLookup.js | 77 +++++++++++++++++++ src/ui/public/directives/config.js | 2 + src/ui/public/share/index.html | 39 ++++++++++ src/ui/public/share/index.js | 57 ++++++++++++++ src/ui/public/share/url_shortener.js | 27 +++++++ 14 files changed, 310 insertions(+), 23 deletions(-) create mode 100644 src/plugins/kibana/public/discover/partials/share_search.html create mode 100644 src/plugins/kibana/public/goto/index.js create mode 100644 src/server/http/urlLookup.js create mode 100644 src/ui/public/share/index.html create mode 100644 src/ui/public/share/index.js create mode 100644 src/ui/public/share/url_shortener.js diff --git a/src/plugins/kibana/public/dashboard/index.js b/src/plugins/kibana/public/dashboard/index.js index 45e247b498755..f55e8b96371cc 100644 --- a/src/plugins/kibana/public/dashboard/index.js +++ b/src/plugins/kibana/public/dashboard/index.js @@ -10,6 +10,7 @@ define(function (require) { require('ui/config'); require('ui/notify'); require('ui/typeahead'); + require('ui/share'); require('plugins/kibana/dashboard/directives/grid'); require('plugins/kibana/dashboard/components/panel/panel'); @@ -25,7 +26,8 @@ define(function (require) { 'kibana/courier', 'kibana/config', 'kibana/notify', - 'kibana/typeahead' + 'kibana/typeahead', + 'kibana/share' ]); require('ui/routes') @@ -90,6 +92,7 @@ define(function (require) { var $uiState = $scope.uiState = $state.makeStateful('uiState'); $scope.$watchCollection('state.options', function (newVal, oldVal) { + //console.log('watch state.options'); if (!angular.equals(newVal, oldVal)) $state.save(); }); $scope.$watch('state.options.darkTheme', setDarkTheme); @@ -154,6 +157,7 @@ define(function (require) { } function setDarkTheme(enabled) { + //console.log('setDarkTheme'); var theme = Boolean(enabled) ? 'theme-dark' : 'theme-light'; chrome.removeApplicationClass(['theme-dark', 'theme-light']); chrome.addApplicationClass(theme); @@ -161,6 +165,7 @@ define(function (require) { // update root source when filters update $scope.$listen(queryFilter, 'update', function () { + //console.log('queryFilter update'); updateQueryOnRootSource(); $state.save(); }); @@ -233,15 +238,17 @@ define(function (require) { ui: $state.options, save: $scope.save, addVis: $scope.addVis, - addSearch: $scope.addSearch, - shareData: function () { - return { - link: $location.absUrl(), - // This sucks, but seems like the cleanest way. Uhg. - embed: '' - }; - } + addSearch: $scope.addSearch + // , + // shareData: function () { + // //console.log('this is being called.'); + // return { + // link: $location.absUrl(), + // // This sucks, but seems like the cleanest way. Uhg. + // embed: '' + // }; + // } }; init(); diff --git a/src/plugins/kibana/public/dashboard/partials/share.html b/src/plugins/kibana/public/dashboard/partials/share.html index bf34366604db1..79046da5db0b1 100644 --- a/src/plugins/kibana/public/dashboard/partials/share.html +++ b/src/plugins/kibana/public/dashboard/partials/share.html @@ -1,4 +1,5 @@ -
+ + diff --git a/src/plugins/kibana/public/discover/controllers/discover.js b/src/plugins/kibana/public/discover/controllers/discover.js index f144362cd7a8e..e69f9065736e2 100644 --- a/src/plugins/kibana/public/discover/controllers/discover.js +++ b/src/plugins/kibana/public/discover/controllers/discover.js @@ -91,7 +91,8 @@ define(function (require) { // config panel templates $scope.configTemplate = new ConfigTemplate({ load: require('plugins/kibana/discover/partials/load_search.html'), - save: require('plugins/kibana/discover/partials/save_search.html') + save: require('plugins/kibana/discover/partials/save_search.html'), + share: require('plugins/kibana/discover/partials/share_search.html') }); $scope.timefilter = timefilter; diff --git a/src/plugins/kibana/public/discover/index.html b/src/plugins/kibana/public/discover/index.html index ac17f7bf80d43..89099697b9338 100644 --- a/src/plugins/kibana/public/discover/index.html +++ b/src/plugins/kibana/public/discover/index.html @@ -50,6 +50,16 @@ + + + diff --git a/src/plugins/kibana/public/discover/partials/share_search.html b/src/plugins/kibana/public/discover/partials/share_search.html new file mode 100644 index 0000000000000..6b878b6c8c7f4 --- /dev/null +++ b/src/plugins/kibana/public/discover/partials/share_search.html @@ -0,0 +1,22 @@ + + diff --git a/src/plugins/kibana/public/goto/index.js b/src/plugins/kibana/public/goto/index.js new file mode 100644 index 0000000000000..9c1aea43172de --- /dev/null +++ b/src/plugins/kibana/public/goto/index.js @@ -0,0 +1,22 @@ +define(function (require) { + var angular = require('angular'); + + require('ui/routes') + .when('/goto/:id', { + template: require('plugins/kibana/dashboard/index.html'), + resolve: { + dash: function (savedDashboards, Notifier, $route, $location, courier) { + return savedDashboards.get($route.current.params.id) + .catch(courier.redirectWhenMissing({ + 'dashboard' : '/dashboard' + })); + } + } + }); + + require('ui/routes') + .when('/visualize', { + redirectTo: '/visualize/step/1' + }); + +}); diff --git a/src/plugins/kibana/public/visualize/editor/editor.js b/src/plugins/kibana/public/visualize/editor/editor.js index d37eb924345aa..92f4e2f2ea88b 100644 --- a/src/plugins/kibana/public/visualize/editor/editor.js +++ b/src/plugins/kibana/public/visualize/editor/editor.js @@ -234,14 +234,14 @@ define(function (require) { }, notify.fatal); }; - $scope.shareData = function () { - return { - link: $location.absUrl(), - // This sucks, but seems like the cleanest way. Uhg. - embed: '' - }; - }; + // $scope.shareData = function () { + // return { + // link: $location.absUrl(), + // // This sucks, but seems like the cleanest way. Uhg. + // embed: '' + // }; + // }; $scope.unlink = function () { if (!$state.linked) return; diff --git a/src/plugins/kibana/public/visualize/editor/panels/share.html b/src/plugins/kibana/public/visualize/editor/panels/share.html index a356060024e00..2292d1eb311c0 100644 --- a/src/plugins/kibana/public/visualize/editor/panels/share.html +++ b/src/plugins/kibana/public/visualize/editor/panels/share.html @@ -1,4 +1,5 @@ - + + diff --git a/src/server/http/index.js b/src/server/http/index.js index 26ecf8ed41767..9c7fcfab30f34 100644 --- a/src/server/http/index.js +++ b/src/server/http/index.js @@ -10,6 +10,8 @@ module.exports = function (kbnServer, server, config) { server = kbnServer.server = new Hapi.Server(); + const urlLookup = require('./urlLookup')(server); + // Create a new connection var connectionOptions = { host: config.get('server.host'), @@ -29,6 +31,7 @@ module.exports = function (kbnServer, server, config) { server.connection(connectionOptions); + // provide a simple way to expose static directories server.decorate('server', 'exposeStaticDir', function (routePath, dirPath) { this.route({ @@ -122,5 +125,23 @@ module.exports = function (kbnServer, server, config) { } }); + server.route({ + method: 'GET', + path: '/goto/{urlId}', + handler: async function (request, reply) { + const url = await urlLookup.getUrl(request.params.urlId); + reply().redirect(url); + } + }); + + server.route({ + method: 'POST', + path: '/shorten', + handler: async function (request, reply) { + const urlId = await urlLookup.generateUrlId(request.payload.url); + reply(urlId); + } + }); + return kbnServer.mixin(require('./xsrf')); }; diff --git a/src/server/http/urlLookup.js b/src/server/http/urlLookup.js new file mode 100644 index 0000000000000..e7c8f03931f6c --- /dev/null +++ b/src/server/http/urlLookup.js @@ -0,0 +1,77 @@ +const crypto = require('crypto'); + +export default function (server) { + async function updateMetadata(urlId, urlDoc) { + const client = server.plugins.elasticsearch.client; + + try { + await client.update({ + index: '.kibana', + type: 'url', + id: urlId, + body: { + doc: { + 'access-date': new Date(), + 'access-count': urlDoc._source['access-count'] + 1 + } + } + }); + } catch (err) { + console.log(err); + //swallow errors. We don't care if there is no update. + } + } + + return { + async generateUrlId(url) { + const urlId = await new Promise((resolve, reject) => { + const client = server.plugins.elasticsearch.client; + + // const urlId = crypto.createHash('md5') + // .update(url) + // .digest('hex'); + + client.index({ + index: '.kibana', + type: 'url', + body: { + url, + 'access-count': 0, + 'create-date': new Date(), + 'access-date': new Date() + } + }) + .then(response => { + const urlId = response._id; + resolve(urlId); + }) + .catch(err => { + reject(err); + }); + }); + + return urlId; + }, + async getUrl(urlId) { + const url = await new Promise((resolve, reject) => { + const client = server.plugins.elasticsearch.client; + + client.get({ + index: '.kibana', + type: 'url', + id: urlId + }) + .then(response => { + const url = response._source.url; + updateMetadata(urlId, response); + resolve(url); + }) + .catch(err => { + resolve('/'); + }); + }); + + return url; + } + }; +}; diff --git a/src/ui/public/directives/config.js b/src/ui/public/directives/config.js index a8f69b28ca5e7..d02e99d7d0746 100644 --- a/src/ui/public/directives/config.js +++ b/src/ui/public/directives/config.js @@ -29,6 +29,7 @@ define(function (require) { var tmpScope = $scope.$new(); $scope.$watch('configObject', function (newVal) { + console.log('config watch'); $scope[attr.configObject] = $scope.configObject; }); @@ -44,6 +45,7 @@ define(function (require) { 'configSubmit', 'configTemplate.current || configTemplate' ], function () { + console.log('config watchMulti'); var tmpl = $scope.configTemplate; if (tmpl instanceof ConfigTemplate) { tmpl = tmpl.toString(); diff --git a/src/ui/public/share/index.html b/src/ui/public/share/index.html new file mode 100644 index 0000000000000..022adc462812e --- /dev/null +++ b/src/ui/public/share/index.html @@ -0,0 +1,39 @@ + +

+ + +

+

+

+ +
+ <iframe src="{{embedUrl}}" height="600" width="800"></iframe> +
+
+ <iframe src="{{shortEmbedUrl}}" height="600" width="800"></iframe> +
+
+ Generating Short URL... +
+
+

+

+

+ +
+ {{getUrl()}} +
+
+ {{shortUrl}} +
+
+ Generating Short URL... +
+
+

+
diff --git a/src/ui/public/share/index.js b/src/ui/public/share/index.js new file mode 100644 index 0000000000000..a815bf6ee29b8 --- /dev/null +++ b/src/ui/public/share/index.js @@ -0,0 +1,57 @@ +define(function (require) { + const app = require('ui/modules').get('kibana/share'); + + app.directive('share', function (Private) { + const urlShortener = Private(require('./url_shortener')); + + return { + restrict: 'E', + scope: { objectType: '@' }, + template: require('ui/share/index.html'), + controller: function ($scope, $rootScope, $location, $http) { + $scope.shortUrlsLoading = false; + + $scope.$watch('getUrl()', function (url) { + $scope.url = url; + $scope.embedUrl = url.replace('?', '?embed&'); + + //when the url changes we want to hide any generated short urls + $scope.shortenUrls = false; + $scope.shortUrl = undefined; + }); + + $scope.$watch('shortenUrls', enabled => { + if (!!enabled) { + if ($scope.shortUrl) { + $scope.shortUrlsLoading = false; + } else { + $scope.shortUrlsLoading = true; + + const linkPromise = urlShortener.shortenUrl($scope.url) + .then(shortUrl => { + $scope.shortUrl = shortUrl; + }); + + const embedPromise = urlShortener.shortenUrl($scope.embedUrl) + .then(shortUrl => { + $scope.shortEmbedUrl = shortUrl; + }); + + Promise.all([linkPromise, embedPromise]) + .then(() => { + $scope.shortUrlsLoading = false; + }) + .catch(err => { + $scope.shortenUrls = false; + }); + } + } + }); + + $scope.getUrl = function () { + return $location.absUrl(); + }; + } + }; + }); +}); diff --git a/src/ui/public/share/url_shortener.js b/src/ui/public/share/url_shortener.js new file mode 100644 index 0000000000000..304e30b3456d0 --- /dev/null +++ b/src/ui/public/share/url_shortener.js @@ -0,0 +1,27 @@ +define(function (require) { + return function createUrlShortener(Notifier, $http, $location) { + const notify = new Notifier({ + location: 'Url Shortener' + }); + const baseUrl = `${$location.protocol()}://${$location.host()}:${$location.port()}`; + + async function shortenUrl(url) { + const relativeUrl = url.replace(baseUrl, ''); + + var formData = { url: relativeUrl }; + + try { + const result = await $http.post('/shorten', formData); + + return `${baseUrl}/goto/${result.data}`; + } catch (err) { + notify.error(err); + throw err; + } + } + + return { + shortenUrl + }; + }; +}); From 5783f3135cbe91ec0944c5f407779aa091420cb4 Mon Sep 17 00:00:00 2001 From: Jim Unger Date: Tue, 24 Nov 2015 16:35:12 -0600 Subject: [PATCH 2/8] [url shortener] modified to use hash --- src/plugins/kibana/public/dashboard/index.js | 16 +-- .../public/dashboard/partials/share.html | 21 ---- .../public/discover/controllers/discover.js | 1 + .../discover/partials/share_search.html | 21 ---- src/plugins/kibana/public/goto/index.js | 22 ---- .../kibana/public/visualize/editor/editor.js | 10 +- .../public/visualize/editor/panels/share.html | 22 ---- src/server/http/index.js | 1 - src/server/http/urlLookup.js | 112 +++++++++++------- src/ui/public/directives/config.js | 2 - src/ui/public/share/index.js | 2 +- src/ui/public/share/url_shortener.js | 3 +- 12 files changed, 72 insertions(+), 161 deletions(-) delete mode 100644 src/plugins/kibana/public/goto/index.js diff --git a/src/plugins/kibana/public/dashboard/index.js b/src/plugins/kibana/public/dashboard/index.js index f55e8b96371cc..d3464adca65be 100644 --- a/src/plugins/kibana/public/dashboard/index.js +++ b/src/plugins/kibana/public/dashboard/index.js @@ -26,8 +26,7 @@ define(function (require) { 'kibana/courier', 'kibana/config', 'kibana/notify', - 'kibana/typeahead', - 'kibana/share' + 'kibana/typeahead' ]); require('ui/routes') @@ -92,7 +91,6 @@ define(function (require) { var $uiState = $scope.uiState = $state.makeStateful('uiState'); $scope.$watchCollection('state.options', function (newVal, oldVal) { - //console.log('watch state.options'); if (!angular.equals(newVal, oldVal)) $state.save(); }); $scope.$watch('state.options.darkTheme', setDarkTheme); @@ -157,7 +155,6 @@ define(function (require) { } function setDarkTheme(enabled) { - //console.log('setDarkTheme'); var theme = Boolean(enabled) ? 'theme-dark' : 'theme-light'; chrome.removeApplicationClass(['theme-dark', 'theme-light']); chrome.addApplicationClass(theme); @@ -165,7 +162,6 @@ define(function (require) { // update root source when filters update $scope.$listen(queryFilter, 'update', function () { - //console.log('queryFilter update'); updateQueryOnRootSource(); $state.save(); }); @@ -239,16 +235,6 @@ define(function (require) { save: $scope.save, addVis: $scope.addVis, addSearch: $scope.addSearch - // , - // shareData: function () { - // //console.log('this is being called.'); - // return { - // link: $location.absUrl(), - // // This sucks, but seems like the cleanest way. Uhg. - // embed: '' - // }; - // } }; init(); diff --git a/src/plugins/kibana/public/dashboard/partials/share.html b/src/plugins/kibana/public/dashboard/partials/share.html index 79046da5db0b1..cf9fc6898b4f2 100644 --- a/src/plugins/kibana/public/dashboard/partials/share.html +++ b/src/plugins/kibana/public/dashboard/partials/share.html @@ -1,22 +1 @@ - diff --git a/src/plugins/kibana/public/discover/controllers/discover.js b/src/plugins/kibana/public/discover/controllers/discover.js index e69f9065736e2..a457131965d30 100644 --- a/src/plugins/kibana/public/discover/controllers/discover.js +++ b/src/plugins/kibana/public/discover/controllers/discover.js @@ -20,6 +20,7 @@ define(function (require) { require('ui/state_management/app_state'); require('ui/timefilter'); require('ui/highlight/highlight_tags'); + require('ui/share'); var app = require('ui/modules').get('apps/discover', [ 'kibana/notify', diff --git a/src/plugins/kibana/public/discover/partials/share_search.html b/src/plugins/kibana/public/discover/partials/share_search.html index 6b878b6c8c7f4..3870634f84832 100644 --- a/src/plugins/kibana/public/discover/partials/share_search.html +++ b/src/plugins/kibana/public/discover/partials/share_search.html @@ -1,22 +1 @@ - diff --git a/src/plugins/kibana/public/goto/index.js b/src/plugins/kibana/public/goto/index.js deleted file mode 100644 index 9c1aea43172de..0000000000000 --- a/src/plugins/kibana/public/goto/index.js +++ /dev/null @@ -1,22 +0,0 @@ -define(function (require) { - var angular = require('angular'); - - require('ui/routes') - .when('/goto/:id', { - template: require('plugins/kibana/dashboard/index.html'), - resolve: { - dash: function (savedDashboards, Notifier, $route, $location, courier) { - return savedDashboards.get($route.current.params.id) - .catch(courier.redirectWhenMissing({ - 'dashboard' : '/dashboard' - })); - } - } - }); - - require('ui/routes') - .when('/visualize', { - redirectTo: '/visualize/step/1' - }); - -}); diff --git a/src/plugins/kibana/public/visualize/editor/editor.js b/src/plugins/kibana/public/visualize/editor/editor.js index 92f4e2f2ea88b..9f7c628493c0e 100644 --- a/src/plugins/kibana/public/visualize/editor/editor.js +++ b/src/plugins/kibana/public/visualize/editor/editor.js @@ -6,6 +6,7 @@ define(function (require) { require('ui/visualize'); require('ui/collapsible_sidebar'); + require('ui/share'); require('ui/routes') .when('/visualize/create', { @@ -234,15 +235,6 @@ define(function (require) { }, notify.fatal); }; - // $scope.shareData = function () { - // return { - // link: $location.absUrl(), - // // This sucks, but seems like the cleanest way. Uhg. - // embed: '' - // }; - // }; - $scope.unlink = function () { if (!$state.linked) return; diff --git a/src/plugins/kibana/public/visualize/editor/panels/share.html b/src/plugins/kibana/public/visualize/editor/panels/share.html index 2292d1eb311c0..0a3cda5e13b24 100644 --- a/src/plugins/kibana/public/visualize/editor/panels/share.html +++ b/src/plugins/kibana/public/visualize/editor/panels/share.html @@ -1,23 +1 @@ - diff --git a/src/server/http/index.js b/src/server/http/index.js index 9c7fcfab30f34..52a79d1450584 100644 --- a/src/server/http/index.js +++ b/src/server/http/index.js @@ -31,7 +31,6 @@ module.exports = function (kbnServer, server, config) { server.connection(connectionOptions); - // provide a simple way to expose static directories server.decorate('server', 'exposeStaticDir', function (routePath, dirPath) { this.route({ diff --git a/src/server/http/urlLookup.js b/src/server/http/urlLookup.js index e7c8f03931f6c..18e094a08462a 100644 --- a/src/server/http/urlLookup.js +++ b/src/server/http/urlLookup.js @@ -17,61 +17,83 @@ export default function (server) { } }); } catch (err) { - console.log(err); - //swallow errors. We don't care if there is no update. + console.log('Error updating url metadata', err); + //swallow errors. It isn't critical if there is no update. } } - return { - async generateUrlId(url) { - const urlId = await new Promise((resolve, reject) => { - const client = server.plugins.elasticsearch.client; + async function getUrlDoc(urlId) { + const urlDoc = await new Promise((resolve, reject) => { + const client = server.plugins.elasticsearch.client; - // const urlId = crypto.createHash('md5') - // .update(url) - // .digest('hex'); + client.get({ + index: '.kibana', + type: 'url', + id: urlId + }) + .then(response => { + resolve(response); + }) + .catch(err => { + resolve(); + }); + }); - client.index({ - index: '.kibana', - type: 'url', - body: { - url, - 'access-count': 0, - 'create-date': new Date(), - 'access-date': new Date() - } - }) - .then(response => { - const urlId = response._id; - resolve(urlId); - }) - .catch(err => { - reject(err); - }); + return urlDoc; + } + + async function createUrlDoc(url, urlId) { + const newUrlId = await new Promise((resolve, reject) => { + const client = server.plugins.elasticsearch.client; + + client.index({ + index: '.kibana', + type: 'url', + id: urlId, + body: { + url, + 'access-count': 0, + 'create-date': new Date(), + 'access-date': new Date() + } + }) + .then(response => { + resolve(response._id); + }) + .catch(err => { + reject(err); }); + }); + + return newUrlId; + } + + function createUrlId(url) { + const urlId = crypto.createHash('md5') + .update(url) + .digest('hex'); + + return urlId; + } - return urlId; + return { + async generateUrlId(url) { + const urlId = createUrlId(url); + + const urlDoc = await getUrlDoc(urlId); + if (urlDoc) return urlId; + + return createUrlDoc(url, urlId); }, async getUrl(urlId) { - const url = await new Promise((resolve, reject) => { - const client = server.plugins.elasticsearch.client; - - client.get({ - index: '.kibana', - type: 'url', - id: urlId - }) - .then(response => { - const url = response._source.url; - updateMetadata(urlId, response); - resolve(url); - }) - .catch(err => { - resolve('/'); - }); - }); + try { + const urlDoc = await getUrlDoc(urlId); + updateMetadata(urlId, urlDoc); - return url; + return urlDoc._source.url; + } catch (err) { + return '/'; + } } }; }; diff --git a/src/ui/public/directives/config.js b/src/ui/public/directives/config.js index d02e99d7d0746..a8f69b28ca5e7 100644 --- a/src/ui/public/directives/config.js +++ b/src/ui/public/directives/config.js @@ -29,7 +29,6 @@ define(function (require) { var tmpScope = $scope.$new(); $scope.$watch('configObject', function (newVal) { - console.log('config watch'); $scope[attr.configObject] = $scope.configObject; }); @@ -45,7 +44,6 @@ define(function (require) { 'configSubmit', 'configTemplate.current || configTemplate' ], function () { - console.log('config watchMulti'); var tmpl = $scope.configTemplate; if (tmpl instanceof ConfigTemplate) { tmpl = tmpl.toString(); diff --git a/src/ui/public/share/index.js b/src/ui/public/share/index.js index a815bf6ee29b8..1e587a0fd7452 100644 --- a/src/ui/public/share/index.js +++ b/src/ui/public/share/index.js @@ -1,5 +1,5 @@ define(function (require) { - const app = require('ui/modules').get('kibana/share'); + const app = require('ui/modules').get('kibana'); app.directive('share', function (Private) { const urlShortener = Private(require('./url_shortener')); diff --git a/src/ui/public/share/url_shortener.js b/src/ui/public/share/url_shortener.js index 304e30b3456d0..98411fd2bcd6c 100644 --- a/src/ui/public/share/url_shortener.js +++ b/src/ui/public/share/url_shortener.js @@ -7,8 +7,7 @@ define(function (require) { async function shortenUrl(url) { const relativeUrl = url.replace(baseUrl, ''); - - var formData = { url: relativeUrl }; + const formData = { url: relativeUrl }; try { const result = await $http.post('/shorten', formData); From 7fcef6b7caac6d8fcd9cb49c83c7d8987c3ccf63 Mon Sep 17 00:00:00 2001 From: Jim Unger Date: Mon, 30 Nov 2015 14:47:20 -0600 Subject: [PATCH 3/8] Addressed how modules were defined --- src/server/http/index.js | 6 +- .../{urlLookup.js => short_url_lookup.js} | 12 +- src/ui/public/share/index.js | 106 +++++++++--------- src/ui/public/share/url_shortener.js | 38 +++---- 4 files changed, 79 insertions(+), 83 deletions(-) rename src/server/http/{urlLookup.js => short_url_lookup.js} (89%) diff --git a/src/server/http/index.js b/src/server/http/index.js index 52a79d1450584..4208d7f01eaa8 100644 --- a/src/server/http/index.js +++ b/src/server/http/index.js @@ -10,7 +10,7 @@ module.exports = function (kbnServer, server, config) { server = kbnServer.server = new Hapi.Server(); - const urlLookup = require('./urlLookup')(server); + const shortUrlLookup = require('./short_url_lookup')(server); // Create a new connection var connectionOptions = { @@ -128,7 +128,7 @@ module.exports = function (kbnServer, server, config) { method: 'GET', path: '/goto/{urlId}', handler: async function (request, reply) { - const url = await urlLookup.getUrl(request.params.urlId); + const url = await shortUrlLookup.getUrl(request.params.urlId); reply().redirect(url); } }); @@ -137,7 +137,7 @@ module.exports = function (kbnServer, server, config) { method: 'POST', path: '/shorten', handler: async function (request, reply) { - const urlId = await urlLookup.generateUrlId(request.payload.url); + const urlId = await shortUrlLookup.generateUrlId(request.payload.url); reply(urlId); } }); diff --git a/src/server/http/urlLookup.js b/src/server/http/short_url_lookup.js similarity index 89% rename from src/server/http/urlLookup.js rename to src/server/http/short_url_lookup.js index 18e094a08462a..a67accada2ca8 100644 --- a/src/server/http/urlLookup.js +++ b/src/server/http/short_url_lookup.js @@ -11,8 +11,8 @@ export default function (server) { id: urlId, body: { doc: { - 'access-date': new Date(), - 'access-count': urlDoc._source['access-count'] + 1 + 'accessDate': new Date(), + 'accessCount': urlDoc._source.accessCount + 1 } } }); @@ -35,7 +35,7 @@ export default function (server) { resolve(response); }) .catch(err => { - resolve(); + reject(); }); }); @@ -52,9 +52,9 @@ export default function (server) { id: urlId, body: { url, - 'access-count': 0, - 'create-date': new Date(), - 'access-date': new Date() + 'accessCount': 0, + 'createDate': new Date(), + 'accessDate': new Date() } }) .then(response => { diff --git a/src/ui/public/share/index.js b/src/ui/public/share/index.js index 1e587a0fd7452..5cb9cd42a81b8 100644 --- a/src/ui/public/share/index.js +++ b/src/ui/public/share/index.js @@ -1,57 +1,55 @@ -define(function (require) { - const app = require('ui/modules').get('kibana'); - - app.directive('share', function (Private) { - const urlShortener = Private(require('./url_shortener')); - - return { - restrict: 'E', - scope: { objectType: '@' }, - template: require('ui/share/index.html'), - controller: function ($scope, $rootScope, $location, $http) { - $scope.shortUrlsLoading = false; - - $scope.$watch('getUrl()', function (url) { - $scope.url = url; - $scope.embedUrl = url.replace('?', '?embed&'); - - //when the url changes we want to hide any generated short urls - $scope.shortenUrls = false; - $scope.shortUrl = undefined; - }); - - $scope.$watch('shortenUrls', enabled => { - if (!!enabled) { - if ($scope.shortUrl) { +const app = require('ui/modules').get('kibana'); + +app.directive('share', function (Private) { + const urlShortener = Private(require('./url_shortener')); + + return { + restrict: 'E', + scope: { objectType: '@' }, + template: require('ui/share/index.html'), + controller: function ($scope, $rootScope, $location, $http) { + $scope.shortUrlsLoading = false; + + $scope.$watch('getUrl()', function (url) { + $scope.url = url; + $scope.embedUrl = url.replace('?', '?embed&'); + + //when the url changes we want to hide any generated short urls + $scope.shortenUrls = false; + $scope.shortUrl = undefined; + }); + + $scope.$watch('shortenUrls', enabled => { + if (!!enabled) { + if ($scope.shortUrl) { + $scope.shortUrlsLoading = false; + } else { + $scope.shortUrlsLoading = true; + + const linkPromise = urlShortener.shortenUrl($scope.url) + .then(shortUrl => { + $scope.shortUrl = shortUrl; + }); + + const embedPromise = urlShortener.shortenUrl($scope.embedUrl) + .then(shortUrl => { + $scope.shortEmbedUrl = shortUrl; + }); + + Promise.all([linkPromise, embedPromise]) + .then(() => { $scope.shortUrlsLoading = false; - } else { - $scope.shortUrlsLoading = true; - - const linkPromise = urlShortener.shortenUrl($scope.url) - .then(shortUrl => { - $scope.shortUrl = shortUrl; - }); - - const embedPromise = urlShortener.shortenUrl($scope.embedUrl) - .then(shortUrl => { - $scope.shortEmbedUrl = shortUrl; - }); - - Promise.all([linkPromise, embedPromise]) - .then(() => { - $scope.shortUrlsLoading = false; - }) - .catch(err => { - $scope.shortenUrls = false; - }); - } + }) + .catch(err => { + $scope.shortenUrls = false; + }); } - }); - - $scope.getUrl = function () { - return $location.absUrl(); - }; - } - }; - }); + } + }); + + $scope.getUrl = function () { + return $location.absUrl(); + }; + } + }; }); diff --git a/src/ui/public/share/url_shortener.js b/src/ui/public/share/url_shortener.js index 98411fd2bcd6c..3e29500d8d2f0 100644 --- a/src/ui/public/share/url_shortener.js +++ b/src/ui/public/share/url_shortener.js @@ -1,26 +1,24 @@ -define(function (require) { - return function createUrlShortener(Notifier, $http, $location) { - const notify = new Notifier({ - location: 'Url Shortener' - }); - const baseUrl = `${$location.protocol()}://${$location.host()}:${$location.port()}`; +export default function createUrlShortener(Notifier, $http, $location) { + const notify = new Notifier({ + location: 'Url Shortener' + }); + const baseUrl = `${$location.protocol()}://${$location.host()}:${$location.port()}`; - async function shortenUrl(url) { - const relativeUrl = url.replace(baseUrl, ''); - const formData = { url: relativeUrl }; + async function shortenUrl(url) { + const relativeUrl = url.replace(baseUrl, ''); + const formData = { url: relativeUrl }; - try { - const result = await $http.post('/shorten', formData); + try { + const result = await $http.post('/shorten', formData); - return `${baseUrl}/goto/${result.data}`; - } catch (err) { - notify.error(err); - throw err; - } + return `${baseUrl}/goto/${result.data}`; + } catch (err) { + notify.error(err); + throw err; } + } - return { - shortenUrl - }; + return { + shortenUrl }; -}); +}; From cef5afd4d8cf5611f674bad4e2e1c2812b3bcc8e Mon Sep 17 00:00:00 2001 From: Jim Unger Date: Wed, 2 Dec 2015 12:05:00 -0600 Subject: [PATCH 4/8] [url shortener] Can now share urls without app state in url --- .../public/dashboard/partials/share.html | 5 +- .../discover/partials/share_search.html | 5 +- .../public/visualize/editor/panels/share.html | 5 +- src/server/http/short_url_lookup.js | 6 ++- src/ui/public/share/index.html | 9 +++- src/ui/public/share/index.js | 51 ++++++++++++++++--- 6 files changed, 68 insertions(+), 13 deletions(-) diff --git a/src/plugins/kibana/public/dashboard/partials/share.html b/src/plugins/kibana/public/dashboard/partials/share.html index cf9fc6898b4f2..046acbb5c95b8 100644 --- a/src/plugins/kibana/public/dashboard/partials/share.html +++ b/src/plugins/kibana/public/dashboard/partials/share.html @@ -1 +1,4 @@ - + + diff --git a/src/plugins/kibana/public/discover/partials/share_search.html b/src/plugins/kibana/public/discover/partials/share_search.html index 3870634f84832..8e41617ae1f07 100644 --- a/src/plugins/kibana/public/discover/partials/share_search.html +++ b/src/plugins/kibana/public/discover/partials/share_search.html @@ -1 +1,4 @@ - + + diff --git a/src/plugins/kibana/public/visualize/editor/panels/share.html b/src/plugins/kibana/public/visualize/editor/panels/share.html index 0a3cda5e13b24..016109cfff6f5 100644 --- a/src/plugins/kibana/public/visualize/editor/panels/share.html +++ b/src/plugins/kibana/public/visualize/editor/panels/share.html @@ -1 +1,4 @@ - + + diff --git a/src/server/http/short_url_lookup.js b/src/server/http/short_url_lookup.js index a67accada2ca8..d312ac12fba83 100644 --- a/src/server/http/short_url_lookup.js +++ b/src/server/http/short_url_lookup.js @@ -17,7 +17,7 @@ export default function (server) { } }); } catch (err) { - console.log('Error updating url metadata', err); + console.log('Warning: Error updating url metadata', err); //swallow errors. It isn't critical if there is no update. } } @@ -35,7 +35,7 @@ export default function (server) { resolve(response); }) .catch(err => { - reject(); + resolve(); }); }); @@ -88,6 +88,8 @@ export default function (server) { async getUrl(urlId) { try { const urlDoc = await getUrlDoc(urlId); + if (!urlDoc) throw new Error('Requested shortened url does note exist in kibana index'); + updateMetadata(urlId, urlDoc); return urlDoc._source.url; diff --git a/src/ui/public/share/index.html b/src/ui/public/share/index.html index 022adc462812e..9d920b8ec1e1c 100644 --- a/src/ui/public/share/index.html +++ b/src/ui/public/share/index.html @@ -1,4 +1,11 @@
+

+ + +

@@ -26,7 +33,7 @@ Share a link

- {{getUrl()}} + {{url}}
{{shortUrl}} diff --git a/src/ui/public/share/index.js b/src/ui/public/share/index.js index 5cb9cd42a81b8..08c06abbedae8 100644 --- a/src/ui/public/share/index.js +++ b/src/ui/public/share/index.js @@ -1,22 +1,63 @@ const app = require('ui/modules').get('kibana'); +const _ = require('lodash'); +const { parse } = require('querystring'); app.directive('share', function (Private) { const urlShortener = Private(require('./url_shortener')); return { restrict: 'E', - scope: { objectType: '@' }, + scope: { + objectType: '@', + objectId: '@' + }, template: require('ui/share/index.html'), - controller: function ($scope, $rootScope, $location, $http) { + controller: function ($scope, $rootScope, $location) { $scope.shortUrlsLoading = false; - $scope.$watch('getUrl()', function (url) { + function updateUrl(url) { $scope.url = url; $scope.embedUrl = url.replace('?', '?embed&'); //when the url changes we want to hide any generated short urls $scope.shortenUrls = false; $scope.shortUrl = undefined; + } + + function buildQueryString(data) { + var result = []; + _.forOwn(data, (value, key) => { + result.push(`${key}=${value}`); + }); + return result.join('&'); + } + + function removeAppState(url) { + let index = url.indexOf('?'); + if (index === -1) return url; + + let base = url.substring(0, index); + let qs = url.substring(index + 1); + + let qsParts = parse(qs); + delete qsParts._a; + qs = buildQueryString(qsParts); + + return `${base}?${qs}`; + } + + $scope.getUrl = function () { + return $location.absUrl(); + }; + + $scope.$watch('getUrl()', updateUrl); + + $scope.$watch('ignoreState', enabled => { + if (enabled) { + updateUrl(removeAppState($scope.url)); + } else { + updateUrl($scope.getUrl()); + } }); $scope.$watch('shortenUrls', enabled => { @@ -46,10 +87,6 @@ app.directive('share', function (Private) { } } }); - - $scope.getUrl = function () { - return $location.absUrl(); - }; } }; }); From 10492794cc71359a5d38bad98ae92f49f4154f13 Mon Sep 17 00:00:00 2001 From: Jim Unger Date: Thu, 3 Dec 2015 13:19:24 -0600 Subject: [PATCH 5/8] [url shortener] hides the embed section on the discover tab --- .../public/discover/partials/share_search.html | 3 ++- src/ui/public/share/index.html | 16 ++++++++-------- src/ui/public/share/index.js | 5 ++++- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/plugins/kibana/public/discover/partials/share_search.html b/src/plugins/kibana/public/discover/partials/share_search.html index 8e41617ae1f07..69fee7ad756d0 100644 --- a/src/plugins/kibana/public/discover/partials/share_search.html +++ b/src/plugins/kibana/public/discover/partials/share_search.html @@ -1,4 +1,5 @@ + object-id="{{opts.savedSearch.id}}" + allow-embed="false"> diff --git a/src/ui/public/share/index.html b/src/ui/public/share/index.html index 9d920b8ec1e1c..8ef8688d8b9e6 100644 --- a/src/ui/public/share/index.html +++ b/src/ui/public/share/index.html @@ -1,16 +1,16 @@ -

+

-

-

+

+
-

-

+

+
-

-

+

+
-

+
diff --git a/src/ui/public/share/index.js b/src/ui/public/share/index.js index 08c06abbedae8..254f3c9e0b1ad 100644 --- a/src/ui/public/share/index.js +++ b/src/ui/public/share/index.js @@ -1,6 +1,7 @@ const app = require('ui/modules').get('kibana'); const _ = require('lodash'); const { parse } = require('querystring'); +const angular = require('angular'); app.directive('share', function (Private) { const urlShortener = Private(require('./url_shortener')); @@ -9,10 +10,12 @@ app.directive('share', function (Private) { restrict: 'E', scope: { objectType: '@', - objectId: '@' + objectId: '@', + setAllowEmbed: '&?allowEmbed' }, template: require('ui/share/index.html'), controller: function ($scope, $rootScope, $location) { + $scope.allowEmbed = $scope.setAllowEmbed ? $scope.setAllowEmbed() : true; $scope.shortUrlsLoading = false; function updateUrl(url) { From 0fb14507740a9a3ef943eea9aa5bef7cb818b7d3 Mon Sep 17 00:00:00 2001 From: Jim Unger Date: Fri, 11 Dec 2015 09:17:54 -0600 Subject: [PATCH 6/8] [url shortener] reorganized code, added clipboard.js support --- package.json | 1 + src/ui/public/share/directives/share.js | 16 +++ .../share/directives/share_object_url.js | 86 ++++++++++++++++ src/ui/public/share/index.html | 46 --------- src/ui/public/share/index.js | 97 +------------------ src/ui/public/share/lib/build_query_string.js | 9 ++ .../share/lib/remove_query_string_value.js | 16 +++ .../public/share/{ => lib}/url_shortener.js | 0 src/ui/public/share/styles/index.less | 21 ++++ src/ui/public/share/views/share.html | 32 ++++++ .../public/share/views/share_object_url.html | 21 ++++ 11 files changed, 204 insertions(+), 141 deletions(-) create mode 100644 src/ui/public/share/directives/share.js create mode 100644 src/ui/public/share/directives/share_object_url.js delete mode 100644 src/ui/public/share/index.html create mode 100644 src/ui/public/share/lib/build_query_string.js create mode 100644 src/ui/public/share/lib/remove_query_string_value.js rename src/ui/public/share/{ => lib}/url_shortener.js (100%) create mode 100644 src/ui/public/share/styles/index.less create mode 100644 src/ui/public/share/views/share.html create mode 100644 src/ui/public/share/views/share_object_url.html diff --git a/package.json b/package.json index 82d78b0300578..d312662c5514a 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "bootstrap": "3.3.5", "brace": "0.5.1", "bunyan": "1.4.0", + "clipboard": "1.5.5", "commander": "2.8.1", "css-loader": "0.17.0", "d3": "3.5.6", diff --git a/src/ui/public/share/directives/share.js b/src/ui/public/share/directives/share.js new file mode 100644 index 0000000000000..49ebb95afba34 --- /dev/null +++ b/src/ui/public/share/directives/share.js @@ -0,0 +1,16 @@ +const app = require('ui/modules').get('kibana'); + +app.directive('share', function () { + return { + restrict: 'E', + scope: { + objectType: '@', + objectId: '@', + setAllowEmbed: '&?allowEmbed' + }, + template: require('ui/share/views/share.html'), + controller: function ($scope) { + $scope.allowEmbed = $scope.setAllowEmbed ? $scope.setAllowEmbed() : true; + } + }; +}); diff --git a/src/ui/public/share/directives/share_object_url.js b/src/ui/public/share/directives/share_object_url.js new file mode 100644 index 0000000000000..6bd0d7053820b --- /dev/null +++ b/src/ui/public/share/directives/share_object_url.js @@ -0,0 +1,86 @@ +const app = require('ui/modules').get('kibana'); +const Clipboard = require('clipboard'); +const removeQueryStringValue = require('../lib/remove_query_string_value'); + +require('../styles/index.less'); + +app.directive('shareObjectUrl', function (Private, Notifier) { + const urlShortener = Private(require('../lib/url_shortener')); + + return { + restrict: 'E', + scope: { + getShareAsEmbed: '&shareAsEmbed', + stripAppState: '=' + }, + template: require('ui/share/views/share_object_url.html'), + link: function ($scope, $el) { + const notify = new Notifier({ + location: `Share ${$scope.$parent.objectType}` + }); + + $scope.textbox = $el.find('input.url')[0]; + $scope.clipboardButton = $el.find('button.clipboard-button')[0]; + + const clipboard = new Clipboard($scope.clipboardButton, { + target: function (trigger) { + return $scope.textbox; + } + }); + + clipboard.on('success', function (e) { + notify.info('URL copied to clipboard.'); + e.clearSelection(); + }); + + clipboard.on('error', function (e) { + notify.info('URL selected. Press Ctrl+C to copy.'); + }); + + $scope.clipboard = clipboard; + }, + controller: function ($scope, $location) { + function updateUrl(url) { + $scope.url = url; + + if ($scope.shareAsEmbed) { + $scope.formattedUrl = ``; + } else { + $scope.formattedUrl = $scope.url; + } + + $scope.shortGenerated = false; + } + + $scope.shareAsEmbed = $scope.getShareAsEmbed(); + + $scope.generateShortUrl = function () { + if ($scope.shortGenerated) return; + + $scope.generating = true; + urlShortener.shortenUrl($scope.url) + .then(shortUrl => { + updateUrl(shortUrl); + $scope.shortGenerated = true; + $scope.generating = false; + }); + }; + + $scope.getUrl = function () { + return $location.absUrl(); + }; + + $scope.$watch('getUrl()', updateUrl); + + $scope.$watch('stripAppState', function (enabled) { + const currentUrl = $scope.getUrl(); + if (enabled) { + let newUrl = removeQueryStringValue(currentUrl, '_a'); + updateUrl(newUrl); + } else { + updateUrl(currentUrl); + } + }); + } + }; +}); diff --git a/src/ui/public/share/index.html b/src/ui/public/share/index.html deleted file mode 100644 index 8ef8688d8b9e6..0000000000000 --- a/src/ui/public/share/index.html +++ /dev/null @@ -1,46 +0,0 @@ -
-
- - -
-
- - -
-
-
- -
- <iframe src="{{embedUrl}}" height="600" width="800"></iframe> -
-
- <iframe src="{{shortEmbedUrl}}" height="600" width="800"></iframe> -
-
- Generating Short URL... -
-
-
-
-
- -
- {{url}} -
-
- {{shortUrl}} -
-
- Generating Short URL... -
-
-
-
diff --git a/src/ui/public/share/index.js b/src/ui/public/share/index.js index 254f3c9e0b1ad..2dec91dcc725d 100644 --- a/src/ui/public/share/index.js +++ b/src/ui/public/share/index.js @@ -1,95 +1,2 @@ -const app = require('ui/modules').get('kibana'); -const _ = require('lodash'); -const { parse } = require('querystring'); -const angular = require('angular'); - -app.directive('share', function (Private) { - const urlShortener = Private(require('./url_shortener')); - - return { - restrict: 'E', - scope: { - objectType: '@', - objectId: '@', - setAllowEmbed: '&?allowEmbed' - }, - template: require('ui/share/index.html'), - controller: function ($scope, $rootScope, $location) { - $scope.allowEmbed = $scope.setAllowEmbed ? $scope.setAllowEmbed() : true; - $scope.shortUrlsLoading = false; - - function updateUrl(url) { - $scope.url = url; - $scope.embedUrl = url.replace('?', '?embed&'); - - //when the url changes we want to hide any generated short urls - $scope.shortenUrls = false; - $scope.shortUrl = undefined; - } - - function buildQueryString(data) { - var result = []; - _.forOwn(data, (value, key) => { - result.push(`${key}=${value}`); - }); - return result.join('&'); - } - - function removeAppState(url) { - let index = url.indexOf('?'); - if (index === -1) return url; - - let base = url.substring(0, index); - let qs = url.substring(index + 1); - - let qsParts = parse(qs); - delete qsParts._a; - qs = buildQueryString(qsParts); - - return `${base}?${qs}`; - } - - $scope.getUrl = function () { - return $location.absUrl(); - }; - - $scope.$watch('getUrl()', updateUrl); - - $scope.$watch('ignoreState', enabled => { - if (enabled) { - updateUrl(removeAppState($scope.url)); - } else { - updateUrl($scope.getUrl()); - } - }); - - $scope.$watch('shortenUrls', enabled => { - if (!!enabled) { - if ($scope.shortUrl) { - $scope.shortUrlsLoading = false; - } else { - $scope.shortUrlsLoading = true; - - const linkPromise = urlShortener.shortenUrl($scope.url) - .then(shortUrl => { - $scope.shortUrl = shortUrl; - }); - - const embedPromise = urlShortener.shortenUrl($scope.embedUrl) - .then(shortUrl => { - $scope.shortEmbedUrl = shortUrl; - }); - - Promise.all([linkPromise, embedPromise]) - .then(() => { - $scope.shortUrlsLoading = false; - }) - .catch(err => { - $scope.shortenUrls = false; - }); - } - } - }); - } - }; -}); +require('./directives/share'); +require('./directives/share_object_url'); diff --git a/src/ui/public/share/lib/build_query_string.js b/src/ui/public/share/lib/build_query_string.js new file mode 100644 index 0000000000000..35c1c61055b6e --- /dev/null +++ b/src/ui/public/share/lib/build_query_string.js @@ -0,0 +1,9 @@ +const _ = require('lodash'); + +export default function buildQueryString(data) { + var result = []; + _.forOwn(data, (value, key) => { + result.push(`${key}=${value}`); + }); + return result.join('&'); +} diff --git a/src/ui/public/share/lib/remove_query_string_value.js b/src/ui/public/share/lib/remove_query_string_value.js new file mode 100644 index 0000000000000..7e9c7c2f2053f --- /dev/null +++ b/src/ui/public/share/lib/remove_query_string_value.js @@ -0,0 +1,16 @@ +const buildQueryString = require('./build_query_string'); +const { parse } = require('querystring'); + +export default function removeAppState(url, key) { + let index = url.indexOf('?'); + if (index === -1) return url; + + let base = url.substring(0, index); + let qs = url.substring(index + 1); + + let qsParts = parse(qs); + delete qsParts[key]; + qs = buildQueryString(qsParts); + + return `${base}?${qs}`; +} diff --git a/src/ui/public/share/url_shortener.js b/src/ui/public/share/lib/url_shortener.js similarity index 100% rename from src/ui/public/share/url_shortener.js rename to src/ui/public/share/lib/url_shortener.js diff --git a/src/ui/public/share/styles/index.less b/src/ui/public/share/styles/index.less new file mode 100644 index 0000000000000..5acb20bb3449a --- /dev/null +++ b/src/ui/public/share/styles/index.less @@ -0,0 +1,21 @@ +share-object-url { + .input-group { + display: flex; + + .clipboard-button { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + + .shorten-button { + border-top-right-radius: 0; + border-top-left-radius: 0; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + } + + .form-control.url { + cursor: text; + } + } +} diff --git a/src/ui/public/share/views/share.html b/src/ui/public/share/views/share.html new file mode 100644 index 0000000000000..4c57e51287d05 --- /dev/null +++ b/src/ui/public/share/views/share.html @@ -0,0 +1,32 @@ +
+
+ + +
+ By selecting this option, future changes to this saved {{objectType}} will be reflected in the shared view. Note: Shared URLs always include globally persisted state such as time picker and auto refresh. +
+
+
+ + + +
+
+ + + +
+
diff --git a/src/ui/public/share/views/share_object_url.html b/src/ui/public/share/views/share_object_url.html new file mode 100644 index 0000000000000..6c1b1438e9e90 --- /dev/null +++ b/src/ui/public/share/views/share_object_url.html @@ -0,0 +1,21 @@ +
+ + + + +
From e59750cad2de21de89f9d18b1a983022695ef9ef Mon Sep 17 00:00:00 2001 From: Jim Unger Date: Fri, 11 Dec 2015 13:44:06 -0600 Subject: [PATCH 7/8] [url shortener] removed link-to-saved-object functionality --- .../share/directives/share_object_url.js | 16 +------------- src/ui/public/share/lib/build_query_string.js | 9 -------- .../share/lib/remove_query_string_value.js | 16 -------------- src/ui/public/share/views/share.html | 21 ++----------------- 4 files changed, 3 insertions(+), 59 deletions(-) delete mode 100644 src/ui/public/share/lib/build_query_string.js delete mode 100644 src/ui/public/share/lib/remove_query_string_value.js diff --git a/src/ui/public/share/directives/share_object_url.js b/src/ui/public/share/directives/share_object_url.js index 6bd0d7053820b..93e6207293fa4 100644 --- a/src/ui/public/share/directives/share_object_url.js +++ b/src/ui/public/share/directives/share_object_url.js @@ -1,6 +1,5 @@ const app = require('ui/modules').get('kibana'); const Clipboard = require('clipboard'); -const removeQueryStringValue = require('../lib/remove_query_string_value'); require('../styles/index.less'); @@ -10,8 +9,7 @@ app.directive('shareObjectUrl', function (Private, Notifier) { return { restrict: 'E', scope: { - getShareAsEmbed: '&shareAsEmbed', - stripAppState: '=' + getShareAsEmbed: '&shareAsEmbed' }, template: require('ui/share/views/share_object_url.html'), link: function ($scope, $el) { @@ -57,12 +55,10 @@ app.directive('shareObjectUrl', function (Private, Notifier) { $scope.generateShortUrl = function () { if ($scope.shortGenerated) return; - $scope.generating = true; urlShortener.shortenUrl($scope.url) .then(shortUrl => { updateUrl(shortUrl); $scope.shortGenerated = true; - $scope.generating = false; }); }; @@ -71,16 +67,6 @@ app.directive('shareObjectUrl', function (Private, Notifier) { }; $scope.$watch('getUrl()', updateUrl); - - $scope.$watch('stripAppState', function (enabled) { - const currentUrl = $scope.getUrl(); - if (enabled) { - let newUrl = removeQueryStringValue(currentUrl, '_a'); - updateUrl(newUrl); - } else { - updateUrl(currentUrl); - } - }); } }; }); diff --git a/src/ui/public/share/lib/build_query_string.js b/src/ui/public/share/lib/build_query_string.js deleted file mode 100644 index 35c1c61055b6e..0000000000000 --- a/src/ui/public/share/lib/build_query_string.js +++ /dev/null @@ -1,9 +0,0 @@ -const _ = require('lodash'); - -export default function buildQueryString(data) { - var result = []; - _.forOwn(data, (value, key) => { - result.push(`${key}=${value}`); - }); - return result.join('&'); -} diff --git a/src/ui/public/share/lib/remove_query_string_value.js b/src/ui/public/share/lib/remove_query_string_value.js deleted file mode 100644 index 7e9c7c2f2053f..0000000000000 --- a/src/ui/public/share/lib/remove_query_string_value.js +++ /dev/null @@ -1,16 +0,0 @@ -const buildQueryString = require('./build_query_string'); -const { parse } = require('querystring'); - -export default function removeAppState(url, key) { - let index = url.indexOf('?'); - if (index === -1) return url; - - let base = url.substring(0, index); - let qs = url.substring(index + 1); - - let qsParts = parse(qs); - delete qsParts[key]; - qs = buildQueryString(qsParts); - - return `${base}?${qs}`; -} diff --git a/src/ui/public/share/views/share.html b/src/ui/public/share/views/share.html index 4c57e51287d05..5f7ffdd0a6797 100644 --- a/src/ui/public/share/views/share.html +++ b/src/ui/public/share/views/share.html @@ -1,32 +1,15 @@
-
- - -
- By selecting this option, future changes to this saved {{objectType}} will be reflected in the shared view. Note: Shared URLs always include globally persisted state such as time picker and auto refresh. -
-
- - +
- - +
From 96b74040d99e92ac80e5439795c1e13eab1ee457 Mon Sep 17 00:00:00 2001 From: Jim Unger Date: Thu, 17 Dec 2015 12:14:47 -0600 Subject: [PATCH 8/8] [url shortener] Added clipboard cleanup, fixed server logging --- src/server/http/short_url_lookup.js | 2 +- src/ui/public/share/directives/share_object_url.js | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/server/http/short_url_lookup.js b/src/server/http/short_url_lookup.js index d312ac12fba83..4ced5e5d812a9 100644 --- a/src/server/http/short_url_lookup.js +++ b/src/server/http/short_url_lookup.js @@ -17,7 +17,7 @@ export default function (server) { } }); } catch (err) { - console.log('Warning: Error updating url metadata', err); + server.log('Warning: Error updating url metadata', err); //swallow errors. It isn't critical if there is no update. } } diff --git a/src/ui/public/share/directives/share_object_url.js b/src/ui/public/share/directives/share_object_url.js index 93e6207293fa4..ee65c86345d44 100644 --- a/src/ui/public/share/directives/share_object_url.js +++ b/src/ui/public/share/directives/share_object_url.js @@ -21,20 +21,24 @@ app.directive('shareObjectUrl', function (Private, Notifier) { $scope.clipboardButton = $el.find('button.clipboard-button')[0]; const clipboard = new Clipboard($scope.clipboardButton, { - target: function (trigger) { + target(trigger) { return $scope.textbox; } }); - clipboard.on('success', function (e) { + clipboard.on('success', e => { notify.info('URL copied to clipboard.'); e.clearSelection(); }); - clipboard.on('error', function (e) { + clipboard.on('error', () => { notify.info('URL selected. Press Ctrl+C to copy.'); }); + $scope.$on('$destroy', () => { + clipboard.destroy(); + }); + $scope.clipboard = clipboard; }, controller: function ($scope, $location) {