UNPKG

@carbon/ibm-cloud-cognitive-cdai

Version:
576 lines (574 loc) 23.7 kB
import _extends from "@babel/runtime/helpers/extends"; import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; import _classCallCheck from "@babel/runtime/helpers/classCallCheck"; import _createClass from "@babel/runtime/helpers/createClass"; import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn"; import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf"; import _inherits from "@babel/runtime/helpers/inherits"; import _regeneratorRuntime from "@babel/runtime/regenerator"; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } // // Copyright IBM Corp. 2020, 2020 // // This source code is licensed under the Apache-2.0 license found in the // LICENSE file in the root directory of this source tree. // import React from 'react'; import PropTypes from 'prop-types'; import { FileUploaderDropContainer, FileUploaderItem, FormItem, TextInput, Button } from 'carbon-components-react'; import { parseFileFromUrl } from '../../component_helpers/FileHelper'; import { countFiles as _countFiles, sortFiles, uuid, validateFileAdded as _validateFileAdded, FILE_UPLOAD_STATUS } from './helpers'; import { idePrefix } from '../../globals/js/settings'; // TODO(ritch): move to cosntants file var IdeImporting = /*#__PURE__*/function (_React$Component) { function IdeImporting(props) { var _this; _classCallCheck(this, IdeImporting); _this = _callSuper(this, IdeImporting, [props]); _this.currentIndex = -1; _this.state = { open: props.open, urlInput: '', urlInputIsValid: false, filesToUpload: props.initialFiles, finished: false }; _this.handleFilesAdded = _this.handleFilesAdded.bind(_this); return _this; } _inherits(IdeImporting, _React$Component); return _createClass(IdeImporting, [{ key: "componentDidMount", value: function componentDidMount() { this.mounted = true; } }, { key: "componentWillUnmount", value: function componentWillUnmount() { this.mounted = false; } }, { key: "countFiles", value: function countFiles() { return _countFiles(this.state.filesToUpload); } }, { key: "getVerbLabel", value: function getVerbLabel() { var _this$props = this.props, enableUpload = _this$props.enableUpload, verbLabel = _this$props.verbLabel; if (verbLabel) { return verbLabel; } else if (enableUpload) { return 'uploaded'; } return 'imported'; } }, { key: "getDescription", value: function getDescription() { if (this.props.enableUpload) { return this.props.uploadDescription; } return this.props.importDescription; } }, { key: "updateFileToUploadState", value: function updateFileToUploadState(uuid, update) { this.setState(function (state) { var updatedFiles = []; var _iterator = _createForOfIteratorHelper(state.filesToUpload), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var fileInfo = _step.value; if (fileInfo.uuid === uuid) { updatedFiles.push(_objectSpread(_objectSpread({}, fileInfo), update)); } else { updatedFiles.push(fileInfo); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return _objectSpread(_objectSpread({}, state), {}, { filesToUpload: updatedFiles }); }); } }, { key: "isValidUrl", value: function isValidUrl(url) { var onValidateUrl = this.props.onValidateUrl; if (typeof onValidateUrl === 'function') { return onValidateUrl(url); } var re = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/; return !!re.exec(url); } }, { key: "getInvalidExtensionText", value: function getInvalidExtensionText() { var validExtensionsText = this.props.mustBeExtensionTextSingular; if (this.props.validExtensions.length > 1) { validExtensionsText = this.props.mustBeExtensionTextPlural; } validExtensionsText = validExtensionsText.replace('$EXT', this.props.validExtensions.join(', ')); return "".concat(this.props.extensionIsInvalidText, " ").concat(validExtensionsText); } }, { key: "validateFileAdded", value: function validateFileAdded(fileToUpload) { return _validateFileAdded(fileToUpload, this.props, this.getInvalidExtensionText.bind(this)); } }, { key: "handleFileAdded", value: function () { var _handleFileAdded = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(fileToUpload) { var _e$message$split, _e$message$split2, errorSubject, errorBody; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: if (this.mounted) { _context.next = 2; break; } return _context.abrupt("return"); case 2: if (!fileToUpload.invalid) { _context.next = 4; break; } return _context.abrupt("return"); case 4: _context.prev = 4; this.updateFileToUploadState(fileToUpload.uuid, { status: FILE_UPLOAD_STATUS.UPLOADING }); _context.next = 8; return this.props.onFileAdded(fileToUpload); case 8: if (this.mounted) { _context.next = 10; break; } return _context.abrupt("return"); case 10: if (this.props.allowValidFileEditing || this.props.enableUpload === false) { this.updateFileToUploadState(fileToUpload.uuid, { status: FILE_UPLOAD_STATUS.EDIT, invalid: false }); } else { this.updateFileToUploadState(fileToUpload.uuid, { status: FILE_UPLOAD_STATUS.COMPLETE, invalid: false }); } _context.next = 18; break; case 13: _context.prev = 13; _context.t0 = _context["catch"](4); _e$message$split = _context.t0.message.split(':'), _e$message$split2 = _slicedToArray(_e$message$split, 2), errorSubject = _e$message$split2[0], errorBody = _e$message$split2[1]; this.updateFileToUploadState(fileToUpload.uuid, { status: FILE_UPLOAD_STATUS.EDIT, invalid: true, errorSubject: errorSubject, errorBody: errorBody }); throw _context.t0; case 18: case "end": return _context.stop(); } }, _callee, this, [[4, 13]]); })); function handleFileAdded(_x) { return _handleFileAdded.apply(this, arguments); } return handleFileAdded; }() }, { key: "getNextIndex", value: function getNextIndex() { this.currentIndex++; return this.currentIndex; } }, { key: "createFileToUpload", value: function createFileToUpload(info) { var file = info.file, url = info.url; if (url) { file = { name: parseFileFromUrl(url) }; } var validation = this.validateFileAdded({ file: file, url: url }); return _objectSpread({ index: this.getNextIndex(), file: file, url: url, uuid: uuid(), status: FILE_UPLOAD_STATUS.EDIT }, validation); } }, { key: "handleFilesAdded", value: function handleFilesAdded(e, _ref) { var _this2 = this; var addedFiles = _ref.addedFiles; e.stopPropagation(); if (!this.props.multiple) { addedFiles = [addedFiles[0]]; } var mappedFiles = addedFiles.map(function (file) { return _this2.createFileToUpload({ file: file }); }); this.setState(function (state) { return { filesToUpload: [].concat(_toConsumableArray(state.filesToUpload), _toConsumableArray(mappedFiles)) }; }); var _iterator2 = _createForOfIteratorHelper(mappedFiles), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var fileToUpload = _step2.value; this.handleFileAdded(fileToUpload).catch(function (err) { console.warn(err); }); } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } } }, { key: "handleUrlAdded", value: function handleUrlAdded(addedFiles) { var _this3 = this; var mappedFiles = addedFiles.map(function (url) { return _this3.createFileToUpload({ url: url }); }); this.setState(function (state) { return { filesToUpload: [].concat(_toConsumableArray(state.filesToUpload), _toConsumableArray(mappedFiles)) }; }); var _iterator3 = _createForOfIteratorHelper(mappedFiles), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { var fileToUpload = _step3.value; this.handleFileAdded(fileToUpload); } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } } }, { key: "handleRemoveFile", value: function handleRemoveFile(clickedUuid) { var _this4 = this, _this$props$onFileRem, _this$props2; this.setState(function (state) { var filesToUpload = _this4.state.filesToUpload; return _objectSpread(_objectSpread({}, state), {}, { filesToUpload: filesToUpload.filter(function (_ref2) { var uuid = _ref2.uuid; return clickedUuid !== uuid; }) }); }); (_this$props$onFileRem = (_this$props2 = this.props).onFileRemoved) === null || _this$props$onFileRem === void 0 || _this$props$onFileRem.call(_this$props2, clickedUuid); } }, { key: "getSortedFiles", value: function getSortedFiles() { var filesToUpload = this.state.filesToUpload; // ensure files are sorted in groups and by order added (index) // also ensures that the import status files are at the top // eg. errors should show at the top, followed by pending, // then finally completed files return filesToUpload.sort(function (a, b) { return sortFiles(a, b, filesToUpload.length); }); } }, { key: "renderFilesToUpload", value: function renderFilesToUpload(counts) { var _this5 = this; var _this$props3 = this.props, multiple = _this$props3.multiple, singleFileLabel = _this$props3.singleFileLabel, fileDropHeader = _this$props3.fileDropHeader, hideImport = _this$props3.hideImport; return /*#__PURE__*/React.createElement("div", { className: "".concat(idePrefix, "--file-status"), style: { width: '100%' } }, /*#__PURE__*/React.createElement("div", { className: "".concat(idePrefix, "--file-list ").concat(idePrefix, "-hide-import") }, /*#__PURE__*/React.createElement("h6", { className: "".concat(idePrefix, "--file-list-status") }, multiple && /*#__PURE__*/React.createElement("span", null, counts.finished, " / ", counts.total, ' '), !hideImport && !multiple && /*#__PURE__*/React.createElement("span", null, singleFileLabel), !hideImport && this.getVerbLabel()), hideImport && /*#__PURE__*/React.createElement("div", { className: "".concat(idePrefix, "--file-header-label") }, fileDropHeader), this.getSortedFiles().map(function (_ref3) { var file = _ref3.file, uuid = _ref3.uuid, status = _ref3.status, invalid = _ref3.invalid, errorSubject = _ref3.errorSubject, errorBody = _ref3.errorBody; return /*#__PURE__*/React.createElement(FileUploaderItem, { key: uuid, uuid: uuid, name: file.name, status: status, invalid: invalid, errorSubject: errorSubject, errorBody: errorBody, onDelete: _this5.handleRemoveFile.bind(_this5, uuid) }); }))); } }, { key: "shouldDisableInput", value: function shouldDisableInput() { var multiple = this.props.multiple; var single = !multiple; var counts = this.countFiles(); if (single && counts.total > 0 || single && this.state.urlInput) { // disable inputs in single mode // when a file has been selected // or any characters are entered into the url input return true; } if (counts.uploading > 0) { // disable inputs during upload return true; } return false; } }, { key: "renderFileMode", value: function renderFileMode() { var _this$props4 = this.props, multiple = _this$props4.multiple, enableFileDrop = _this$props4.enableFileDrop, hideImport = _this$props4.hideImport, fileDropHeader = _this$props4.fileDropHeader; if (!enableFileDrop) { return null; } var disabled = this.shouldDisableInput(); var fileUploaderProps = { multiple: multiple, disabled: disabled, labelText: multiple ? this.props.fileDropLabelPlural : this.props.fileDropLabelSingular, name: 'name', accept: [].concat(_toConsumableArray(this.props.validExtensions.map(function (ext) { return ".".concat(ext); })), ['*']) }; return hideImport && disabled ? null : /*#__PURE__*/React.createElement(FormItem, null, hideImport ? /*#__PURE__*/React.createElement("div", { className: "".concat(idePrefix, "--file-header-label") }, fileDropHeader) : /*#__PURE__*/React.createElement("h5", null, fileDropHeader), /*#__PURE__*/React.createElement(FileUploaderDropContainer, _extends({}, fileUploaderProps, { onAddFiles: this.handleFilesAdded }))); } }, { key: "handleUrlChanged", value: function handleUrlChanged(e) { this.setState({ urlInput: e.target.value, urlInputIsValid: this.isValidUrl(e.target.value) }); } }, { key: "renderUrlMode", value: function renderUrlMode() { var _this6 = this; var _this$props5 = this.props, multiple = _this$props5.multiple, enableUrlInput = _this$props5.enableUrlInput; var urlInputIsValid = this.state.urlInputIsValid; if (!enableUrlInput) { return null; } var inputProps = { key: 'importing-input', id: 'ide-input-modal-url-input', labelText: this.props.urlInputLabel, value: this.state.urlInput, disabled: !multiple && this.state.filesToUpload.length > 0, invalid: !!(this.state.urlInput && !urlInputIsValid), invalidText: this.props.invalidUrlText, className: "".concat(idePrefix, "-importing-url-input-field"), onChange: function onChange(e) { e.stopPropagation(); _this6.handleUrlChanged(e); } }; var buttonProps = { disabled: !urlInputIsValid || !this.state.urlInput, size: 'field', onClick: function onClick() { /* istanbul ignore else */ if (_this6.state.urlInput) { _this6.handleUrlAdded([_this6.state.urlInput]); _this6.setState({ urlInput: '' }); } } }; return /*#__PURE__*/React.createElement(FormItem, { className: "".concat(idePrefix, "-file-by-url") }, /*#__PURE__*/React.createElement("h5", null, this.props.urlInputHeader), /*#__PURE__*/React.createElement("div", { className: "".concat(idePrefix, "-importing-flex-input") }, /*#__PURE__*/React.createElement(TextInput, inputProps), /*#__PURE__*/React.createElement("div", { className: "".concat(idePrefix, "-importing-flex-button") }, /*#__PURE__*/React.createElement(Button, buttonProps, this.props.addUrlBttonLabel)))); } }, { key: "renderText", value: function renderText() { return /*#__PURE__*/React.createElement("p", { className: "".concat(idePrefix, "-importing-description") }, this.getDescription()); } }, { key: "render", value: function render() { var counts = this.countFiles(); return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { className: "".concat(idePrefix, "-import-container") }, this.renderText(), this.renderFileMode(), this.renderUrlMode(), counts.total > 0 ? this.renderFilesToUpload(counts) : null)); } }]); }(React.Component); export { IdeImporting as default }; IdeImporting.propTypes = { addUrlBttonLabel: PropTypes.string, allowInvalidFilenameInUrl: PropTypes.bool, allowValidFileEditing: PropTypes.bool, autoCloseDelay: PropTypes.number, defaultUncaughtErrorBody: PropTypes.string, defaultUncaughtErrorSubject: PropTypes.string, dropDescription: PropTypes.string, enableFileDrop: PropTypes.bool, enableUpload: PropTypes.bool, enableUrlInput: PropTypes.bool, extensionIsInvalidText: PropTypes.string, extensionIsRequiredText: PropTypes.string, fileDropHeader: PropTypes.string, /** Max file size in bytes. Defaults to `Infinity`. */ fileDropLabel: PropTypes.string, fileDropLabelPlural: PropTypes.string, fileDropLabelSingular: PropTypes.string, /** The file tab label. Defaults to "File" */ fileTabLabel: PropTypes.string, filesToUploadText: PropTypes.string, filesToUploadTextPlural: PropTypes.string, hideImport: PropTypes.bool, importDescription: PropTypes.string, initialFiles: PropTypes.array, invalidExtensionText: PropTypes.string, invalidFileNameText: PropTypes.string, invalidUrlText: PropTypes.string, maxFileSize: PropTypes.number, maxFileSizeMessage: PropTypes.string, multiple: PropTypes.bool, mustBeExtensionTextPlural: PropTypes.string, mustBeExtensionTextSingular: PropTypes.string, onFileAdded: PropTypes.func, onFileRemoved: PropTypes.func, /** Called when the entire form is submitted. See README for examples. */ onImport: PropTypes.func, onValidateUrl: PropTypes.func, /** Defaults to `true`. Set to false to hide/close the modal. */ open: PropTypes.bool, singleFileLabel: PropTypes.string, sync: PropTypes.bool, uploadDescription: PropTypes.string, urlInputHeader: PropTypes.string, urlInputLabel: PropTypes.string, /** The file tab label. Defaults to "URL" */ urlTabLabel: PropTypes.string, /** Defaults to `['*']`. Specify valid file extensions. */ validExtensions: PropTypes.arrayOf(PropTypes.string).isRequired, verbLabel: PropTypes.string }; IdeImporting.defaultProps = { uploadDescription: 'Use the inputs below to select file(s) to be uploaded.', importDescription: 'Use the inputs below to select file(s) to be imported.', open: true, sync: false, headingPlural: 'Select Files to import', headingSingular: 'Select a File import', fileTabLabel: 'File', hideImport: false, urlTabLabel: 'URL', invalidFileNameText: 'You must provide a valid file name.', validExtensions: ['*'], multiple: true, fileDropLabelSingular: 'Drag and drop a single file here or click to import', fileDropLabelPlural: 'Drag and drop files here or click to import', filenameRequiredText: 'A filename is required.', urlInputLabel: '', invalidUrlText: 'Enter a valid URL', maxFileSize: Infinity, maxFileSizeSubject: 'File size exceeds limit', maxFileSizeMessage: 'File is larger than the max file size.', addUrlBttonLabel: 'Add File', extensionIsRequiredText: 'File must have a valid extension.', extensionIsInvalidText: 'Extension is not valid.', errorTextSingular: 'Failed to import file.', errorTextPlural: 'Failed to import files.', successTextSingular: 'Your file has been imported.', successTextPlural: 'Your files have been imported.', extensionRequired: true, autoCloseDelay: 2, enableFileDrop: true, enableUrlInput: true, invalidFileText: 'Invalid File', initialFiles: [], mustBeExtensionTextSingular: 'Must be a $EXT file.', mustBeExtensionTextPlural: 'Must be one of: $EXT.', allowInvalidFilenameInUrl: false, defaultUncaughtErrorSubject: 'Import Failed', defaultUncaughtErrorBody: 'Failed to import file.', filesToUploadTextPlural: 'Files to import', enableUpload: true, allowValidFileEditing: false, fileDropHeader: 'Add by File', urlInputHeader: 'Add by URL', singleFileLabel: 'File' };