mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-30 02:02:43 +00:00
ui: glimmerize download button component (#18292)
* initial glimmerization, delete toolbar-download-button component * remove extra line * cleanup component file * add data getter * delete toolbar download button component * add jsdoc to component * move class att directly to component, remove arg * remove content getter
This commit is contained in:
@@ -1,2 +0,0 @@
|
||||
{{@actionText}}
|
||||
<Chevron @isButton={{true}} />
|
||||
@@ -90,11 +90,11 @@
|
||||
</div>
|
||||
{{/if}}
|
||||
<DownloadButton
|
||||
class="button is-ghost"
|
||||
@data={{this.keyData}}
|
||||
@filename={{this.keyFilename}}
|
||||
@mime="application/json"
|
||||
@extension="json"
|
||||
@class="button is-ghost"
|
||||
@stringify={{true}}
|
||||
>
|
||||
<Icon @name="download" />
|
||||
|
||||
@@ -23,12 +23,15 @@
|
||||
</PageHeader>
|
||||
<Toolbar>
|
||||
<ToolbarActions>
|
||||
<ToolbarDownloadButton
|
||||
@actionText="Download policy"
|
||||
<DownloadButton
|
||||
class="toolbar-link"
|
||||
@extension={{if (eq this.policyType "acl") this.model.format "sentinel"}}
|
||||
@filename={{this.model.name}}
|
||||
@data={{this.model.policy}}
|
||||
/>
|
||||
>
|
||||
Download policy
|
||||
<Chevron @isButton={{true}} />
|
||||
</DownloadButton>
|
||||
{{#if (and (not-eq this.model.id "root") (or this.capabilities.canUpdate this.capabilities.canDelete))}}
|
||||
<ToolbarLink @route="vault.cluster.policy.edit" @model={{this.model.id}} data-test-policy-edit-toggle>
|
||||
Edit policy
|
||||
|
||||
3
ui/lib/core/addon/components/download-button.hbs
Normal file
3
ui/lib/core/addon/components/download-button.hbs
Normal file
@@ -0,0 +1,3 @@
|
||||
<button data-test-download-button type="button" {{on "click" this.handleDownload}} ...attributes>
|
||||
{{yield}}
|
||||
</button>
|
||||
@@ -1,51 +1,62 @@
|
||||
import Component from '@ember/component';
|
||||
import { computed } from '@ember/object';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { action } from '@ember/object';
|
||||
import Component from '@glimmer/component';
|
||||
/**
|
||||
* @module DownloadButton
|
||||
* DownloadButton components are an action button used to download data. Both the action text and icon are yielded.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* <DownloadButton
|
||||
* class="button"
|
||||
* @data={{this.data}}
|
||||
* @filename={{this.filename}}
|
||||
* @mime={{this.mime}}
|
||||
* @extension={{this.extension}}
|
||||
* @stringify={{true}}
|
||||
* >
|
||||
* <Icon @name="download" />
|
||||
* Download
|
||||
* </DownloadButton>
|
||||
* ```
|
||||
* @param {string} data - data to download
|
||||
* @param {boolean} [stringify=false] - argument to stringify the data before passing to the File constructor
|
||||
* @param {string} [filename] - name of file that prefixes the ISO timestamp generated when download
|
||||
* @param {string} [mime='text/plain'] - media type to be downloaded
|
||||
* @param {string} [extension='txt'] - file extension
|
||||
*/
|
||||
|
||||
export default Component.extend({
|
||||
layout: hbs`{{#if (has-block)}} {{yield}} {{else}} {{actionText}} {{/if}}`,
|
||||
tagName: 'a',
|
||||
role: 'button',
|
||||
attributeBindings: ['role', 'download', 'href'],
|
||||
download: computed('filename', 'extension', function () {
|
||||
return `${this.filename}-${new Date().toISOString()}.${this.extension}`;
|
||||
}),
|
||||
export default class DownloadButton extends Component {
|
||||
get extension() {
|
||||
return this.args.extension || 'txt';
|
||||
}
|
||||
|
||||
fileLike: computed('data', 'mime', 'stringify', 'download', function () {
|
||||
let file;
|
||||
let data = this.data;
|
||||
const filename = this.download;
|
||||
const mime = this.mime;
|
||||
if (this.stringify) {
|
||||
data = JSON.stringify(data, null, 2);
|
||||
get mime() {
|
||||
return this.args.mime || 'text/plain';
|
||||
}
|
||||
|
||||
get filename() {
|
||||
const defaultFilename = `${new Date().toISOString()}.${this.extension}`;
|
||||
return this.args.filename ? this.args.filename + '-' + defaultFilename : defaultFilename;
|
||||
}
|
||||
|
||||
get data() {
|
||||
if (this.args.stringify) {
|
||||
return JSON.stringify(this.args.data, null, 2);
|
||||
}
|
||||
if (window.navigator.msSaveOrOpenBlob) {
|
||||
file = new Blob([data], { type: mime });
|
||||
file.name = filename;
|
||||
} else {
|
||||
file = new File([data], filename, { type: mime });
|
||||
}
|
||||
return file;
|
||||
}),
|
||||
return this.args.data;
|
||||
}
|
||||
|
||||
href: computed('fileLike', function () {
|
||||
return window.URL.createObjectURL(this.fileLike);
|
||||
}),
|
||||
|
||||
click(event) {
|
||||
if (!window.navigator.msSaveOrOpenBlob) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
const file = this.fileLike;
|
||||
//lol whyyyy
|
||||
window.navigator.msSaveOrOpenBlob(file, file.name);
|
||||
},
|
||||
|
||||
actionText: 'Download',
|
||||
data: null,
|
||||
filename: null,
|
||||
mime: 'text/plain',
|
||||
extension: 'txt',
|
||||
stringify: false,
|
||||
});
|
||||
// TODO refactor and call service instead
|
||||
@action
|
||||
handleDownload() {
|
||||
const { document, URL } = window;
|
||||
const downloadElement = document.createElement('a');
|
||||
const content = new File([this.data], this.filename, { type: this.mime });
|
||||
downloadElement.download = this.filename;
|
||||
downloadElement.href = URL.createObjectURL(content);
|
||||
document.body.appendChild(downloadElement);
|
||||
downloadElement.click();
|
||||
URL.revokeObjectURL(downloadElement.href);
|
||||
downloadElement.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* @module ToolbarSecretLink
|
||||
* `ToolbarSecretLink` styles SecretLink for the Toolbar.
|
||||
* It should only be used inside of `Toolbar`.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* <Toolbar>
|
||||
* <ToolbarActions>
|
||||
* <ToolbarDownloadButton @actionText="Download policy" @extension={{if (eq policyType "acl") model.format "sentinel"}} @filename={{model.name}} @data={{model.policy}} />
|
||||
* </ToolbarActions>
|
||||
* </Toolbar>
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
|
||||
import DownloadButton from './download-button';
|
||||
|
||||
export default DownloadButton.extend({
|
||||
classNames: ['toolbar-link'],
|
||||
});
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'core/components/toolbar-download-button';
|
||||
@@ -2,12 +2,15 @@
|
||||
<Toolbar>
|
||||
<ToolbarActions>
|
||||
{{#if this.model}}
|
||||
<ToolbarDownloadButton
|
||||
@actionText="Download CA cert"
|
||||
<DownloadButton
|
||||
class="toolbar-link"
|
||||
@extension="pem"
|
||||
@filename={{concat this.model.ca.id "-ca"}}
|
||||
@data={{this.model.ca.caPem}}
|
||||
/>
|
||||
>
|
||||
Download CA cert
|
||||
<Chevron @isButton={{true}} />
|
||||
</DownloadButton>
|
||||
{{/if}}
|
||||
<ToolbarLink @route="configure" data-test-kmip-link-configure>
|
||||
Configure
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render } from '@ember/test-helpers';
|
||||
import { isPresent } from 'ember-cli-page-object';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
|
||||
module('Integration | Component | toolbar-download-button', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it renders', async function (assert) {
|
||||
await render(hbs`<ToolbarDownloadButton @actionText="Link" />`);
|
||||
|
||||
assert.dom(this.element).hasText('Link');
|
||||
assert.ok(isPresent('.toolbar-link'));
|
||||
assert.ok(isPresent('.icon'));
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user