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:
claire bontempo
2022-12-09 15:21:42 -08:00
committed by GitHub
parent 835e3ed78d
commit cff1918b5f
9 changed files with 74 additions and 95 deletions

View File

@@ -1,2 +0,0 @@
{{@actionText}}
<Chevron @isButton={{true}} />

View File

@@ -90,11 +90,11 @@
</div> </div>
{{/if}} {{/if}}
<DownloadButton <DownloadButton
class="button is-ghost"
@data={{this.keyData}} @data={{this.keyData}}
@filename={{this.keyFilename}} @filename={{this.keyFilename}}
@mime="application/json" @mime="application/json"
@extension="json" @extension="json"
@class="button is-ghost"
@stringify={{true}} @stringify={{true}}
> >
<Icon @name="download" /> <Icon @name="download" />

View File

@@ -23,12 +23,15 @@
</PageHeader> </PageHeader>
<Toolbar> <Toolbar>
<ToolbarActions> <ToolbarActions>
<ToolbarDownloadButton <DownloadButton
@actionText="Download policy" class="toolbar-link"
@extension={{if (eq this.policyType "acl") this.model.format "sentinel"}} @extension={{if (eq this.policyType "acl") this.model.format "sentinel"}}
@filename={{this.model.name}} @filename={{this.model.name}}
@data={{this.model.policy}} @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))}} {{#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> <ToolbarLink @route="vault.cluster.policy.edit" @model={{this.model.id}} data-test-policy-edit-toggle>
Edit policy Edit policy

View File

@@ -0,0 +1,3 @@
<button data-test-download-button type="button" {{on "click" this.handleDownload}} ...attributes>
{{yield}}
</button>

View File

@@ -1,51 +1,62 @@
import Component from '@ember/component'; import { action } from '@ember/object';
import { computed } from '@ember/object'; import Component from '@glimmer/component';
import hbs from 'htmlbars-inline-precompile'; /**
* @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({ export default class DownloadButton extends Component {
layout: hbs`{{#if (has-block)}} {{yield}} {{else}} {{actionText}} {{/if}}`, get extension() {
tagName: 'a', return this.args.extension || 'txt';
role: 'button', }
attributeBindings: ['role', 'download', 'href'],
download: computed('filename', 'extension', function () {
return `${this.filename}-${new Date().toISOString()}.${this.extension}`;
}),
fileLike: computed('data', 'mime', 'stringify', 'download', function () { get mime() {
let file; return this.args.mime || 'text/plain';
let data = this.data; }
const filename = this.download;
const mime = this.mime; get filename() {
if (this.stringify) { const defaultFilename = `${new Date().toISOString()}.${this.extension}`;
data = JSON.stringify(data, null, 2); 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) { return this.args.data;
file = new Blob([data], { type: mime }); }
file.name = filename;
} else {
file = new File([data], filename, { type: mime });
}
return file;
}),
href: computed('fileLike', function () { // TODO refactor and call service instead
return window.URL.createObjectURL(this.fileLike); @action
}), handleDownload() {
const { document, URL } = window;
click(event) { const downloadElement = document.createElement('a');
if (!window.navigator.msSaveOrOpenBlob) { const content = new File([this.data], this.filename, { type: this.mime });
return; downloadElement.download = this.filename;
} downloadElement.href = URL.createObjectURL(content);
event.preventDefault(); document.body.appendChild(downloadElement);
const file = this.fileLike; downloadElement.click();
//lol whyyyy URL.revokeObjectURL(downloadElement.href);
window.navigator.msSaveOrOpenBlob(file, file.name); downloadElement.remove();
}, }
}
actionText: 'Download',
data: null,
filename: null,
mime: 'text/plain',
extension: 'txt',
stringify: false,
});

View File

@@ -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'],
});

View File

@@ -1 +0,0 @@
export { default } from 'core/components/toolbar-download-button';

View File

@@ -2,12 +2,15 @@
<Toolbar> <Toolbar>
<ToolbarActions> <ToolbarActions>
{{#if this.model}} {{#if this.model}}
<ToolbarDownloadButton <DownloadButton
@actionText="Download CA cert" class="toolbar-link"
@extension="pem" @extension="pem"
@filename={{concat this.model.ca.id "-ca"}} @filename={{concat this.model.ca.id "-ca"}}
@data={{this.model.ca.caPem}} @data={{this.model.ca.caPem}}
/> >
Download CA cert
<Chevron @isButton={{true}} />
</DownloadButton>
{{/if}} {{/if}}
<ToolbarLink @route="configure" data-test-kmip-link-configure> <ToolbarLink @route="configure" data-test-kmip-link-configure>
Configure Configure

View File

@@ -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'));
});
});