Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dashboard - rework options #5377

Draft
wants to merge 8 commits into
base: lakesare/type-dashboard-2
Choose a base branch
from

Conversation

lakesare
Copy link
Collaborator

@lakesare lakesare commented Jul 30, 2024

UPDATE: Consider this PR on pause, I will return to it in September.


#TODO - change base back to the main branch when I'll be inviting the reviewers

This PR is a part of the "converting Dashboard to typescript" effort, however I'm PRing it separately because it involves a significant reworking of how we handle options, and we might want some discussion here.

In this PR:

  • we go from all options are optional + DefinePluginOpts makes them required => to all options are required + default typescript's Partial makes them optional

    This lets us use default typescript's functionality instead of relying on our own typescript methods, and cuts down on levels of indirection.

  • remove keyof typeof defaultOptions, make default options also typed

  • add missing option types such as onDragLeave, onDragOver, onDrop, thumbnailHeight, etc.

  • make "Dynamic default options" less confusing

Only merge after #5367

Copy link
Contributor

github-actions bot commented Jul 30, 2024

Diff output files
diff --git a/packages/@uppy/dashboard/lib/Dashboard.js b/packages/@uppy/dashboard/lib/Dashboard.js
index a4e8014..6211f92 100644
--- a/packages/@uppy/dashboard/lib/Dashboard.js
+++ b/packages/@uppy/dashboard/lib/Dashboard.js
@@ -34,12 +34,9 @@ function createPromise() {
   });
   return o;
 }
-const defaultOptions = {
+const defaultOptions = () => ({
   target: "body",
   metaFields: [],
-  inline: false,
-  width: 750,
-  height: 550,
   thumbnailWidth: 280,
   thumbnailType: "image/jpeg",
   waitForThumbnailsBeforeUpload: false,
@@ -52,28 +49,45 @@ const defaultOptions = {
   hidePauseResumeButton: false,
   hideProgressAfterFinish: false,
   note: null,
-  closeModalOnClickOutside: false,
-  closeAfterFinish: false,
   singleFileFullScreen: true,
   disableStatusBar: false,
   disableInformer: false,
   disableThumbnailGenerator: false,
-  disablePageScrollWhenModalOpen: true,
-  animateOpenClose: true,
   fileManagerSelectionType: "files",
   proudlyDisplayPoweredByUppy: true,
   showSelectedFiles: true,
   showRemoveButtonAfterComplete: false,
-  browserBackButtonClose: false,
   showNativePhotoCameraButton: false,
   showNativeVideoCameraButton: false,
   theme: "light",
   autoOpen: null,
   disabled: false,
   disableLocalFiles: false,
-  doneButtonHandler: undefined,
-  onRequestCloseModal: null,
-};
+  nativeCameraFacingMode: "",
+  doneButtonHandler: () => {},
+  onRequestCloseModal: () => {},
+  onDragLeave: () => {},
+  onDragOver: () => {},
+  onDrop: () => {},
+  thumbnailHeight: undefined,
+  plugins: [],
+});
+const defaultModalOptions = () => ({
+  ...defaultOptions(),
+  inline: false,
+  animateOpenClose: true,
+  browserBackButtonClose: false,
+  closeAfterFinish: false,
+  closeModalOnClickOutside: false,
+  disablePageScrollWhenModalOpen: true,
+  trigger: null,
+});
+const defaultInlineOptions = () => ({
+  ...defaultOptions(),
+  inline: true,
+  width: 750,
+  height: 550,
+});
 var _disabledNodes = _classPrivateFieldLooseKey("disabledNodes");
 var _generateLargeThumbnailIfSingleFile = _classPrivateFieldLooseKey("generateLargeThumbnailIfSingleFile");
 var _openFileEditorWhenFilesAdded = _classPrivateFieldLooseKey("openFileEditorWhenFilesAdded");
@@ -92,14 +106,22 @@ var _getStatusBarId = _classPrivateFieldLooseKey("getStatusBarId");
 var _getThumbnailGeneratorId = _classPrivateFieldLooseKey("getThumbnailGeneratorId");
 var _getInformerId = _classPrivateFieldLooseKey("getInformerId");
 export default class Dashboard extends UIPlugin {
-  constructor(uppy, _opts) {
-    var _opts$autoOpen, _this$opts4, _this$opts4$onRequest;
-    const autoOpen = (_opts$autoOpen = _opts == null ? void 0 : _opts.autoOpen) != null ? _opts$autoOpen : null;
-    super(uppy, {
-      ...defaultOptions,
-      ..._opts,
-      autoOpen,
-    });
+  constructor(uppy, passedOpts) {
+    if (passedOpts === void 0) {
+      passedOpts = {};
+    }
+    const options = passedOpts.inline === false || passedOpts.inline === undefined
+      ? {
+        ...defaultModalOptions(),
+        ...passedOpts,
+        inline: false,
+      }
+      : {
+        ...defaultInlineOptions(),
+        ...passedOpts,
+        inline: true,
+      };
+    super(uppy, options);
     Object.defineProperty(this, _getInformerId, {
       value: _getInformerId2,
     });
@@ -241,6 +263,7 @@ export default class Dashboard extends UIPlugin {
       this.closeFileEditor();
     };
     this.openModal = () => {
+      if (this.opts.inline) return Promise.resolve();
       const {
         promise,
         resolve,
@@ -274,6 +297,7 @@ export default class Dashboard extends UIPlugin {
     };
     this.closeModal = opts => {
       var _opts$manualClose;
+      if (this.opts.inline) return Promise.resolve();
       const manualClose = (_opts$manualClose = opts == null ? void 0 : opts.manualClose) != null
         ? _opts$manualClose
         : true;
@@ -478,6 +502,7 @@ export default class Dashboard extends UIPlugin {
       if (event.keyCode === TAB_KEY) trapFocus.forModal(event, this.getPluginState().activeOverlayType, this.el);
     };
     this.handleClickOutside = () => {
+      if (this.opts.inline) return;
       if (this.opts.closeModalOnClickOutside) this.requestCloseModal();
     };
     this.handlePaste = event => {
@@ -501,7 +526,6 @@ export default class Dashboard extends UIPlugin {
       }
     };
     this.handleDragOver = event => {
-      var _this$opts$onDragOver, _this$opts;
       event.preventDefault();
       event.stopPropagation();
       const canSomePluginHandleRootDrop = () => {
@@ -533,21 +557,17 @@ export default class Dashboard extends UIPlugin {
       this.setPluginState({
         isDraggingOver: true,
       });
-      (_this$opts$onDragOver = (_this$opts = this.opts).onDragOver) == null
-        || _this$opts$onDragOver.call(_this$opts, event);
+      this.opts.onDragOver(event);
     };
     this.handleDragLeave = event => {
-      var _this$opts$onDragLeav, _this$opts2;
       event.preventDefault();
       event.stopPropagation();
       this.setPluginState({
         isDraggingOver: false,
       });
-      (_this$opts$onDragLeav = (_this$opts2 = this.opts).onDragLeave) == null
-        || _this$opts$onDragLeav.call(_this$opts2, event);
+      this.opts.onDragLeave(event);
     };
     this.handleDrop = async event => {
-      var _this$opts$onDrop, _this$opts3;
       event.preventDefault();
       event.stopPropagation();
       this.setPluginState({
@@ -574,7 +594,7 @@ export default class Dashboard extends UIPlugin {
         this.uppy.log("[Dashboard] Files dropped");
         this.addFiles(files);
       }
-      (_this$opts$onDrop = (_this$opts3 = this.opts).onDrop) == null || _this$opts$onDrop.call(_this$opts3, event);
+      this.opts.onDrop(event);
     };
     this.handleRequestThumbnail = file => {
       if (!this.opts.waitForThumbnailsBeforeUpload) {
@@ -599,6 +619,7 @@ export default class Dashboard extends UIPlugin {
       let {
         failed,
       } = _ref;
+      if (this.opts.inline) return;
       if (this.opts.closeAfterFinish && !(failed != null && failed.length)) {
         this.requestCloseModal();
       }
@@ -648,10 +669,10 @@ export default class Dashboard extends UIPlugin {
       },
     });
     this.initEvents = () => {
-      if (this.opts.trigger && !this.opts.inline) {
-        const showModalTrigger = findAllDOMElements(this.opts.trigger);
-        if (showModalTrigger) {
-          showModalTrigger.forEach(trigger => trigger.addEventListener("click", this.openModal));
+      if (!this.opts.inline && this.opts.trigger) {
+        const triggerEls = findAllDOMElements(this.opts.trigger);
+        if (triggerEls) {
+          triggerEls.forEach(trigger => trigger.addEventListener("click", this.openModal));
         } else {
           this.uppy.log(
             "Dashboard modal trigger not found. Make sure `trigger` is set in Dashboard options, unless you are planning to call `dashboard.openModal()` method yourself",
@@ -690,9 +711,11 @@ export default class Dashboard extends UIPlugin {
       }
     };
     this.removeEvents = () => {
-      const showModalTrigger = findAllDOMElements(this.opts.trigger);
-      if (!this.opts.inline && showModalTrigger) {
-        showModalTrigger.forEach(trigger => trigger.removeEventListener("click", this.openModal));
+      if (!this.opts.inline && this.opts.trigger) {
+        const triggerEls = findAllDOMElements(this.opts.trigger);
+        if (triggerEls) {
+          triggerEls.forEach(trigger => trigger.removeEventListener("click", this.openModal));
+        }
       }
       this.stopListeningToResize();
       document.removeEventListener("paste", this.handlePasteOnBody);
@@ -859,7 +882,7 @@ export default class Dashboard extends UIPlugin {
         saveFileEditor: this.saveFileEditor,
         closeFileEditor: this.closeFileEditor,
         disableInteractiveElements: this.disableInteractiveElements,
-        animateOpenClose: this.opts.animateOpenClose,
+        animateOpenClose: !this.opts.inline && this.opts.animateOpenClose,
         isClosing: pluginState.isClosing,
         progressindicators,
         editors,
@@ -888,8 +911,8 @@ export default class Dashboard extends UIPlugin {
         saveFileCard: this.saveFileCard,
         openFileEditor: this.openFileEditor,
         canEditFile: this.canEditFile,
-        width: this.opts.width,
-        height: this.opts.height,
+        width: this.opts.inline && this.opts.width || 0,
+        height: this.opts.inline && this.opts.height || 0,
         showLinkToFileUploadResult: this.opts.showLinkToFileUploadResult,
         fileManagerSelectionType: this.opts.fileManagerSelectionType,
         proudlyDisplayPoweredByUppy: this.opts.proudlyDisplayPoweredByUppy,
@@ -921,7 +944,9 @@ export default class Dashboard extends UIPlugin {
     Object.defineProperty(this, _addSpecifiedPluginsFromOptions, {
       writable: true,
       value: () => {
-        const plugins = this.opts.plugins || [];
+        const {
+          plugins,
+        } = this.opts;
         plugins.forEach(pluginID => {
           const plugin = this.uppy.getPlugin(pluginID);
           if (plugin) {
@@ -973,20 +998,11 @@ export default class Dashboard extends UIPlugin {
         areInsidesReadyToBeVisible: false,
         isDraggingOver: false,
       });
-      const {
-        inline,
-        closeAfterFinish,
-      } = this.opts;
-      if (inline && closeAfterFinish) {
-        throw new Error(
-          "[Dashboard] `closeAfterFinish: true` cannot be used on an inline Dashboard, because an inline Dashboard cannot be closed at all. Either set `inline: false`, or disable the `closeAfterFinish` option.",
-        );
-      }
       const {
         allowMultipleUploads,
         allowMultipleUploadBatches,
       } = this.uppy.opts;
-      if ((allowMultipleUploads || allowMultipleUploadBatches) && closeAfterFinish) {
+      if ((allowMultipleUploads || allowMultipleUploadBatches) && !this.opts.inline && this.opts.closeAfterFinish) {
         this.uppy.log(
           "[Dashboard] When using `closeAfterFinish`, we recommended setting the `allowMultipleUploadBatches` option to `false` in the Uppy constructor. See https://uppy.io/docs/uppy/#allowMultipleUploads-true",
           "warning",
@@ -1046,7 +1062,9 @@ export default class Dashboard extends UIPlugin {
         const thumbnail = this.uppy.getPlugin(`${this.id}:ThumbnailGenerator`);
         if (thumbnail) this.uppy.removePlugin(thumbnail);
       }
-      const plugins = this.opts.plugins || [];
+      const {
+        plugins,
+      } = this.opts;
       plugins.forEach(pluginID => {
         const plugin = this.uppy.getPlugin(pluginID);
         if (plugin) plugin.unmount();
@@ -1056,7 +1074,7 @@ export default class Dashboard extends UIPlugin {
         (_this$darkModeMediaQu2 = this.darkModeMediaQuery) == null
           || _this$darkModeMediaQu2.removeListener(this.handleSystemDarkModeChange);
       }
-      if (this.opts.disablePageScrollWhenModalOpen) {
+      if (!this.opts.inline && this.opts.disablePageScrollWhenModalOpen) {
         document.body.classList.remove("uppy-Dashboard-isFixed");
       }
       this.unmount();
@@ -1066,15 +1084,17 @@ export default class Dashboard extends UIPlugin {
     this.title = "Dashboard";
     this.type = "orchestrator";
     this.defaultLocale = locale;
-    if (this.opts.doneButtonHandler === undefined) {
+    if (passedOpts.doneButtonHandler === undefined) {
       this.opts.doneButtonHandler = () => {
         this.uppy.clear();
         this.requestCloseModal();
       };
     }
-    (_this$opts4$onRequest = (_this$opts4 = this.opts).onRequestCloseModal) != null
-      ? _this$opts4$onRequest
-      : _this$opts4.onRequestCloseModal = () => this.closeModal();
+    if (passedOpts.onRequestCloseModal === undefined) {
+      this.opts.onRequestCloseModal = () => {
+        this.closeModal();
+      };
+    }
     this.i18nInit();
   }
   setOptions(opts) {
diff --git a/packages/@uppy/dashboard/lib/components/AddFiles.js b/packages/@uppy/dashboard/lib/components/AddFiles.js
index 07770cb..68d3ebf 100644
--- a/packages/@uppy/dashboard/lib/components/AddFiles.js
+++ b/packages/@uppy/dashboard/lib/components/AddFiles.js
@@ -2,23 +2,32 @@ import { Component, Fragment, h } from "preact";
 class AddFiles extends Component {
   constructor() {
     super(...arguments);
+    this.fileInput = null;
+    this.folderInput = null;
+    this.mobilePhotoFileInput = null;
+    this.mobileVideoFileInput = null;
     this.triggerFileInputClick = () => {
-      this.fileInput.click();
+      var _this$fileInput;
+      (_this$fileInput = this.fileInput) == null || _this$fileInput.click();
     };
     this.triggerFolderInputClick = () => {
-      this.folderInput.click();
+      var _this$folderInput;
+      (_this$folderInput = this.folderInput) == null || _this$folderInput.click();
     };
     this.triggerVideoCameraInputClick = () => {
-      this.mobileVideoFileInput.click();
+      var _this$mobileVideoFile;
+      (_this$mobileVideoFile = this.mobileVideoFileInput) == null || _this$mobileVideoFile.click();
     };
     this.triggerPhotoCameraInputClick = () => {
-      this.mobilePhotoFileInput.click();
+      var _this$mobilePhotoFile;
+      (_this$mobilePhotoFile = this.mobilePhotoFileInput) == null || _this$mobilePhotoFile.click();
     };
     this.onFileInputChange = event => {
       this.props.handleInputChange(event);
-      event.target.value = null;
+      event.target.value = "";
     };
     this.renderHiddenInput = (isFolder, refCallback) => {
+      var _this$props$allowedFi;
       return h("input", {
         className: "uppy-Dashboard-input",
         hidden: true,
@@ -29,7 +38,9 @@ class AddFiles extends Component {
         name: "files[]",
         multiple: this.props.maxNumberOfFiles !== 1,
         onChange: this.onFileInputChange,
-        accept: this.props.allowedFileTypes,
+        accept: (_this$props$allowedFi = this.props.allowedFileTypes) == null
+          ? void 0
+          : _this$props$allowedFi.join(", "),
         ref: refCallback,
       });
     };
@@ -302,16 +313,6 @@ class AddFiles extends Component {
       if (hasOnlyMyDevice) list = [];
       const listWithoutLastTwo = [...list];
       const lastTwo = listWithoutLastTwo.splice(list.length - 2, list.length);
-      const renderList = l =>
-        l.map(_ref => {
-          let {
-            key,
-            elements,
-          } = _ref;
-          return h(Fragment, {
-            key: key,
-          }, elements);
-        });
       return h(
         Fragment,
         null,
@@ -322,13 +323,33 @@ class AddFiles extends Component {
             className: "uppy-Dashboard-AddFiles-list",
             role: "tablist",
           },
-          renderList(listWithoutLastTwo),
-          h("span", {
-            role: "presentation",
-            style: {
-              "white-space": "nowrap",
+          listWithoutLastTwo.map(_ref => {
+            let {
+              key,
+              elements,
+            } = _ref;
+            return h(Fragment, {
+              key: key,
+            }, elements);
+          }),
+          h(
+            "span",
+            {
+              role: "presentation",
+              style: {
+                "white-space": "nowrap",
+              },
             },
-          }, renderList(lastTwo)),
+            lastTwo.map(_ref2 => {
+              let {
+                key,
+                elements,
+              } = _ref2;
+              return h(Fragment, {
+                key: key,
+              }, elements);
+            }),
+          ),
         ),
       );
     };
@@ -410,7 +431,7 @@ class AddFiles extends Component {
         this.props.note && h("div", {
           className: "uppy-Dashboard-note",
         }, this.props.note),
-        this.props.proudlyDisplayPoweredByUppy && this.renderPoweredByUppy(this.props),
+        this.props.proudlyDisplayPoweredByUppy && this.renderPoweredByUppy(),
       ),
     );
   }
diff --git a/packages/@uppy/dashboard/lib/components/Dashboard.js b/packages/@uppy/dashboard/lib/components/Dashboard.js
index 1fb0233..189b65d 100644
--- a/packages/@uppy/dashboard/lib/components/Dashboard.js
+++ b/packages/@uppy/dashboard/lib/components/Dashboard.js
@@ -55,7 +55,7 @@ export default function Dashboard(props) {
   const numberOfFilesForRecovery = props.recoveredState ? Object.keys(props.recoveredState.files).length : null;
   const numberOfGhosts = props.files
     ? Object.keys(props.files).filter(fileID => props.files[fileID].isGhost).length
-    : null;
+    : 0;
   const renderRestoredText = () => {
     if (numberOfGhosts > 0) {
       return props.i18n("recoveredXFiles", {
@@ -191,12 +191,23 @@ export default function Dashboard(props) {
             containerWidth: props.containerWidth,
             containerHeight: props.containerHeight,
           })
-          : h(
-            AddFiles,
-            _extends({}, props, {
-              isSizeMD: isSizeMD,
-            }),
-          ),
+          : h(AddFiles, {
+            i18n: props.i18n,
+            i18nArray: props.i18nArray,
+            acquirers: props.acquirers,
+            handleInputChange: props.handleInputChange,
+            maxNumberOfFiles: props.maxNumberOfFiles,
+            allowedFileTypes: props.allowedFileTypes,
+            showNativePhotoCameraButton: props.showNativePhotoCameraButton,
+            showNativeVideoCameraButton: props.showNativeVideoCameraButton,
+            nativeCameraFacingMode: props.nativeCameraFacingMode,
+            showPanel: props.showPanel,
+            activePickerPanel: props.activePickerPanel,
+            disableLocalFiles: props.disableLocalFiles,
+            fileManagerSelectionType: props.fileManagerSelectionType,
+            note: props.note,
+            proudlyDisplayPoweredByUppy: props.proudlyDisplayPoweredByUppy,
+          }),
         h(
           Slide,
           null,

@lakesare lakesare changed the base branch from main to lakesare/type-dashboard-2 August 2, 2024 09:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant