UNPKG

gov-gui

Version:

Gov UI Component Library Typscript Build

384 lines (383 loc) 14.6 kB
import { h } from "@stencil/core"; import { getGlobalPropsClasses } from "../../global/global-styles-helper"; import { getAnimationClasses } from "../../global/animation-helpers"; export class FileUpload { constructor() { this.fileNames = []; this.status = null; this.failedStatus = ''; this.allowedFileTypes = ['pdf', 'xls', 'png', 'jpeg']; this.fileNameValue = ''; // Value to return when filename is identified this.required = false; // New required prop this.animationDelay = '2s'; this.allClasses = ''; this.uploadUrl = ''; // Private property for the upload URL } get allowedTypesString() { // Handle both string and array formats if (Array.isArray(this.allowedFileTypes)) { return this.allowedFileTypes.join(', '); } return this.allowedFileTypes; } //watching for any change in animations to trigger them watchAnimations() { this.provideClass(); } watchAnimationsDelay() { this.provideClass(); } watchAnimationsSpeed() { this.provideClass(); } componentWillLoad() { if (typeof this.allowedFileTypes === 'string') { try { this.allowedFileTypes = JSON.parse(this.allowedFileTypes); } catch (e) { console.error('Invalid allowedFileTypes format'); this.allowedFileTypes = ['pdf', 'xls', 'png', 'jpeg']; } } const animationClasses = getAnimationClasses({ animation: this.animation, animationDelay: this.animationDelay, animationSpeed: this.animationSpeed }); this.allClasses = getGlobalPropsClasses({ classes: ' ' + animationClasses, }); } handleFileUpload(event) { const input = event.target; // Access the file input element const files = Array.from(input.files || []); // Get the selected files this.processFiles(files); } handleFileDrop(event) { var _a; event.preventDefault(); const files = Array.from(((_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.files) || []); this.processFiles(files); } processFiles(files) { // If no files are provided and the upload is required, set an error. if (files.length === 0) { if (this.required) { this.status = 'failed'; this.failedStatus = 'File upload is required.'; } return; } // Filter valid files first const validFiles = files.filter(file => { var _a; const fileExtension = (_a = file.name.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase(); return this.allowedFileTypes.includes(fileExtension || ''); }); if (validFiles.length > 0) { this.fileNames = validFiles.map(file => file.name); this.fileNameValue = String(this.fileNames); this.fileUpload(validFiles); } else { this.fileNames = []; this.status = 'failed'; this.failedStatus = 'Uploaded files have unsupported formats.'; } } async fileUpload(files) { this.status = 'loading'; const formData = new FormData(); files.forEach(file => { formData.append('files', file); }); try { const response = await fetch(this.uploadUrl || '/', { method: 'POST', body: formData, }); if (!response.ok) { throw new Error('Upload failed'); } const contentType = response.headers.get('Content-Type'); if (contentType && contentType.includes('application/json')) { const result = await response.json(); if (result && typeof result === 'object' && result['success']) { this.status = 'done'; } else { this.status = 'failed'; this.failedStatus = `Failed: False success response.`; } } else if (contentType && contentType.includes('text/html')) { const result = await response.text(); if (result && result.includes('success')) { this.status = 'done'; } else { this.status = 'failed'; this.failedStatus = `Failed: False success response.`; } } else if (!contentType) { this.status = 'done'; } else { this.failedStatus = `Failed: Unexpected response format.`; throw new Error('Unexpected response format'); } } catch (error) { console.error('Upload error:', error); this.status = 'failed'; this.failedStatus = `Failed: Failed to upload.`; } } triggerFileUpload() { this.fileInput.click(); } preventDefaults(event) { event.preventDefault(); event.stopPropagation(); } getStatusClass() { return this.status ? this.status : ''; } /** * Public getter returns a comma‑separated list of file names. * If no files have been uploaded, it returns "No files uploaded". */ get value() { return this.fileNames.length > 0 ? this.fileNames.join(', ') : 'No files uploaded'; } /** * Public method to set the upload URL through script. */ async setUploadUrl(url) { this.uploadUrl = url; } /** * Public method to validate that a file has been uploaded when required. * Returns true if valid; otherwise, sets an error status and returns false. */ async validate() { if (this.required && this.fileNames.length === 0) { this.status = 'failed'; this.failedStatus = 'File upload is required.'; return false; } return true; } //Called on change of any animation related property to trigger change provideClass() { const animationClasses = getAnimationClasses({ animation: this.animation, animationDelay: this.animationDelay, animationSpeed: this.animationSpeed }); this.allClasses = getGlobalPropsClasses({ classes: ' ' + animationClasses, }); } render() { return (h("div", { key: '350c9421b4001c4d30f92d747db7ccc21d242aa2', class: `upload-container ${this.getStatusClass()} ${this.allClasses}`, onDragOver: this.preventDefaults, onDragEnter: this.preventDefaults, onDrop: event => this.handleFileDrop(event) }, h("div", { key: '408e9f484aa0b67bff2d53902de04b72e0bfd6ba', class: `upload-field ${this.getStatusClass()}` }, h("input", { key: '78b6b3e17341fe11025f6a1fe2ee20c3113ecbcc', type: "file", id: "file-input", class: "file-input", multiple: true, required: this.required, ref: el => (this.fileInput = el), onChange: event => this.handleFileUpload(event) }), h("label", { key: 'd332ee6838b8a91c1cbed50774cd450dece0b3b6', htmlFor: "file-input", class: "file-label" }, this.fileNames.length > 0 ? this.fileNames.join(', ') : `Drop files here (${this.allowedTypesString})`), h("button", { key: '2aa61dd6ee70f443fecd3c87ed22a67526f57dff', class: `upload-button ${this.getStatusClass()}`, type: "button", onClick: () => this.triggerFileUpload() }, "Upload Files")), this.status && (h("div", { key: 'c800cc5034cef35ff18054d8f5149f939c11bc1c', class: `upload-status ${this.getStatusClass()}` }, this.status === 'loading' && 'Loading...', this.status === 'done' && 'Files uploaded successfully!', this.status === 'warning' && 'Warning: Uploaded file is too large.', this.status === 'failed' && (this.failedStatus !== '' ? this.failedStatus : 'Failed: Uploaded files have unsupported formats.'))))); } static get is() { return "gov-upload"; } static get encapsulation() { return "shadow"; } static get originalStyleUrls() { return { "$": ["gov-upload.css"] }; } static get styleUrls() { return { "$": ["gov-upload.css"] }; } static get properties() { return { "allowedFileTypes": { "type": "string", "mutable": false, "complexType": { "original": "string | string[]", "resolved": "string | string[]", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "getter": false, "setter": false, "attribute": "allowed-file-types", "reflect": false, "defaultValue": "['pdf', 'xls', 'png', 'jpeg']" }, "fileNameValue": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "getter": false, "setter": false, "attribute": "file-name-value", "reflect": false, "defaultValue": "''" }, "required": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "getter": false, "setter": false, "attribute": "required", "reflect": false, "defaultValue": "false" }, "animation": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "" }, "getter": false, "setter": false, "attribute": "animation", "reflect": false }, "animationDelay": { "type": "string", "mutable": false, "complexType": { "original": "'2s' | '3s' | '4s' | '5s'", "resolved": "\"2s\" | \"3s\" | \"4s\" | \"5s\"", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "" }, "getter": false, "setter": false, "attribute": "animation-delay", "reflect": false, "defaultValue": "'2s'" }, "animationSpeed": { "type": "string", "mutable": false, "complexType": { "original": "'slow' | 'slower' | 'fast' | 'faster'", "resolved": "\"fast\" | \"faster\" | \"slow\" | \"slower\"", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "" }, "getter": false, "setter": false, "attribute": "animation-speed", "reflect": false } }; } static get states() { return { "fileNames": {}, "status": {}, "failedStatus": {} }; } static get methods() { return { "setUploadUrl": { "complexType": { "signature": "(url: string) => Promise<void>", "parameters": [{ "name": "url", "type": "string", "docs": "" }], "references": { "Promise": { "location": "global", "id": "global::Promise" } }, "return": "Promise<void>" }, "docs": { "text": "Public method to set the upload URL through script.", "tags": [] } }, "validate": { "complexType": { "signature": "() => Promise<boolean>", "parameters": [], "references": { "Promise": { "location": "global", "id": "global::Promise" } }, "return": "Promise<boolean>" }, "docs": { "text": "Public method to validate that a file has been uploaded when required.\r\nReturns true if valid; otherwise, sets an error status and returns false.", "tags": [] } } }; } static get watchers() { return [{ "propName": "animation", "methodName": "watchAnimations" }, { "propName": "animationDelay", "methodName": "watchAnimationsDelay" }, { "propName": "animationSpeed", "methodName": "watchAnimationsSpeed" }]; } } //# sourceMappingURL=gov-upload.js.map