Skip to content

Commit

Permalink
reorganized code, added clipboard.js support
Browse files Browse the repository at this point in the history
Fixes #5497
  • Loading branch information
BigFunger authored and Jim Unger committed Dec 18, 2015
1 parent d77aafd commit 683c582
Show file tree
Hide file tree
Showing 11 changed files with 204 additions and 141 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,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",
Expand Down
16 changes: 16 additions & 0 deletions src/ui/public/share/directives/share.js
Original file line number Diff line number Diff line change
@@ -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;
}
};
});
86 changes: 86 additions & 0 deletions src/ui/public/share/directives/share_object_url.js
Original file line number Diff line number Diff line change
@@ -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 = `<iframe src="${$scope.url}" height="600" width="800"></iframe>`;
} 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);
}
});
}
};
});
46 changes: 0 additions & 46 deletions src/ui/public/share/index.html

This file was deleted.

97 changes: 2 additions & 95 deletions src/ui/public/share/index.js
Original file line number Diff line number Diff line change
@@ -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');
9 changes: 9 additions & 0 deletions src/ui/public/share/lib/build_query_string.js
Original file line number Diff line number Diff line change
@@ -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('&');
}
16 changes: 16 additions & 0 deletions src/ui/public/share/lib/remove_query_string_value.js
Original file line number Diff line number Diff line change
@@ -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}`;
}
File renamed without changes.
21 changes: 21 additions & 0 deletions src/ui/public/share/styles/index.less
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
32 changes: 32 additions & 0 deletions src/ui/public/share/views/share.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<form role="form" class="vis-share">
<div
class="form-group"
ng-show="objectId">
<input type="checkbox" ng-model="ignoreState" id="ignoreState" />
<label for="ignoreState">
Link to saved {{objectType}}
</label>
<div>
<small>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.</small>
</div>
</div>
<div class="form-group" ng-if="allowEmbed">
<label>
Embed this {{objectType}}
<small>Add to your html source. Note all clients must still be able to access kibana</small>
</label>
<share-object-url
share-as-embed="true"
strip-app-state="ignoreState">
</share-object-url>
</div>
<div class="form-group">
<label>
Share a link
</label>
<share-object-url
share-as-embed="false"
strip-app-state="ignoreState">
</share-object-url>
</div>
</form>
21 changes: 21 additions & 0 deletions src/ui/public/share/views/share_object_url.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<div class="input-group">
<input
ng-model="formattedUrl"
type="text"
readonly=""
class="form-control url">
</input>
<button
class="shorten-button"
tooltip="Generate Short URL"
ng-click="generateShortUrl()"
ng-disabled="shortGenerated">
<span aria-hidden="true" class="fa fa-compress"></span>
</button>
<button
class="clipboard-button"
tooltip="Copy to Clipboard"
ng-click="copyToClipboard()">
<span aria-hidden="true" class="fa fa-clipboard"></span>
</button>
</div>

0 comments on commit 683c582

Please sign in to comment.