mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 02:28:09 +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}`; | ||||
|   }), | ||||
|  | ||||
|   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); | ||||
| export default class DownloadButton extends Component { | ||||
|   get extension() { | ||||
|     return this.args.extension || 'txt'; | ||||
|   } | ||||
|     if (window.navigator.msSaveOrOpenBlob) { | ||||
|       file = new Blob([data], { type: mime }); | ||||
|       file.name = filename; | ||||
|     } else { | ||||
|       file = new File([data], filename, { type: mime }); | ||||
|  | ||||
|   get mime() { | ||||
|     return this.args.mime || 'text/plain'; | ||||
|   } | ||||
|     return file; | ||||
|   }), | ||||
|  | ||||
|   href: computed('fileLike', function () { | ||||
|     return window.URL.createObjectURL(this.fileLike); | ||||
|   }), | ||||
|  | ||||
|   click(event) { | ||||
|     if (!window.navigator.msSaveOrOpenBlob) { | ||||
|       return; | ||||
|   get filename() { | ||||
|     const defaultFilename = `${new Date().toISOString()}.${this.extension}`; | ||||
|     return this.args.filename ? this.args.filename + '-' + defaultFilename : defaultFilename; | ||||
|   } | ||||
|     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, | ||||
| }); | ||||
|   get data() { | ||||
|     if (this.args.stringify) { | ||||
|       return JSON.stringify(this.args.data, null, 2); | ||||
|     } | ||||
|     return this.args.data; | ||||
|   } | ||||
|  | ||||
|   // 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
	 claire bontempo
					claire bontempo