diff --git a/scripts/celerity_mapper.php b/scripts/celerity_mapper.php index 1172c93a98..ab37b3482e 100755 --- a/scripts/celerity_mapper.php +++ b/scripts/celerity_mapper.php @@ -56,6 +56,7 @@ $package_spec = array( 'javelin-behavior-phabricator-remarkup-assist', 'phabricator-textareautils', 'phabricator-file-upload', + 'javelin-behavior-global-drag-and-drop', ), 'core.pkg.css' => array( 'phabricator-core-css', @@ -100,6 +101,7 @@ $package_spec = array( 'phabricator-side-menu-view-css', 'phabricator-crumbs-view-css', 'phabricator-object-item-list-view-css', + 'global-drag-and-drop-css', ), 'differential.pkg.css' => array( diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php index bcaae2417b..4392213523 100644 --- a/src/__celerity_resource_map__.php +++ b/src/__celerity_resource_map__.php @@ -478,15 +478,15 @@ celerity_register_resource_map(array( ), '/rsrc/image/sprite-apps-large-X2.png' => array( - 'hash' => 'dffe647d8d8ddfab9b2f5f870b4e40b4', - 'uri' => '/res/dffe647d/rsrc/image/sprite-apps-large-X2.png', + 'hash' => 'f1218e52784088e7aabdb2744bda2cc3', + 'uri' => '/res/f1218e52/rsrc/image/sprite-apps-large-X2.png', 'disk' => '/rsrc/image/sprite-apps-large-X2.png', 'type' => 'png', ), '/rsrc/image/sprite-apps-large.png' => array( - 'hash' => 'cc0d81cafa185c541350a9db6f3befb7', - 'uri' => '/res/cc0d81ca/rsrc/image/sprite-apps-large.png', + 'hash' => 'f19222adadaddd0dd7e12bcd1b1fdba9', + 'uri' => '/res/f19222ad/rsrc/image/sprite-apps-large.png', 'disk' => '/rsrc/image/sprite-apps-large.png', 'type' => 'png', ), @@ -513,15 +513,15 @@ celerity_register_resource_map(array( ), '/rsrc/image/sprite-icon-X2.png' => array( - 'hash' => 'd4c36b33f4961bdcf63a0cc0bb4ecb1e', - 'uri' => '/res/d4c36b33/rsrc/image/sprite-icon-X2.png', + 'hash' => 'c9fae25bc6221922ce26517e654a18e4', + 'uri' => '/res/c9fae25b/rsrc/image/sprite-icon-X2.png', 'disk' => '/rsrc/image/sprite-icon-X2.png', 'type' => 'png', ), '/rsrc/image/sprite-icon.png' => array( - 'hash' => 'b29f5d1d2781b6589946bd73734100f1', - 'uri' => '/res/b29f5d1d/rsrc/image/sprite-icon.png', + 'hash' => 'b690ea69bf5f2abe84d0a6e9ef64b03d', + 'uri' => '/res/b690ea69/rsrc/image/sprite-icon.png', 'disk' => '/rsrc/image/sprite-icon.png', 'type' => 'png', ), @@ -690,7 +690,7 @@ celerity_register_resource_map(array( ), 'aphront-table-view-css' => array( - 'uri' => '/res/732d5e1f/rsrc/css/aphront/table-view.css', + 'uri' => '/res/d2cd4818/rsrc/css/aphront/table-view.css', 'type' => 'css', 'requires' => array( @@ -760,7 +760,7 @@ celerity_register_resource_map(array( ), 'differential-local-commits-view-css' => array( - 'uri' => '/res/86432ba7/rsrc/css/application/differential/local-commits-view.css', + 'uri' => '/res/224f3703/rsrc/css/application/differential/local-commits-view.css', 'type' => 'css', 'requires' => array( @@ -805,7 +805,7 @@ celerity_register_resource_map(array( ), 'differential-revision-history-css' => array( - 'uri' => '/res/71cffe43/rsrc/css/application/differential/revision-history.css', + 'uri' => '/res/d41bc64c/rsrc/css/application/differential/revision-history.css', 'type' => 'css', 'requires' => array( @@ -857,14 +857,14 @@ celerity_register_resource_map(array( ), 'disk' => '/rsrc/css/application/diffusion/diffusion-source.css', ), - 'files-css' => + 'global-drag-and-drop-css' => array( - 'uri' => '/res/a265a77d/rsrc/css/application/files/files.css', + 'uri' => '/res/f3fb4a79/rsrc/css/application/files/global-drag-and-drop.css', 'type' => 'css', 'requires' => array( ), - 'disk' => '/rsrc/css/application/files/files.css', + 'disk' => '/rsrc/css/application/files/global-drag-and-drop.css', ), 'herald-css' => array( @@ -978,20 +978,19 @@ celerity_register_resource_map(array( ), 'javelin-behavior-aphront-drag-and-drop' => array( - 'uri' => '/res/0910fc0a/rsrc/js/application/core/behavior-drag-and-drop.js', + 'uri' => '/res/84a67d72/rsrc/js/application/core/behavior-drag-and-drop.js', 'type' => 'js', 'requires' => array( 0 => 'javelin-behavior', 1 => 'javelin-dom', - 2 => 'javelin-util', - 3 => 'phabricator-drag-and-drop-file-upload', + 2 => 'phabricator-drag-and-drop-file-upload', ), 'disk' => '/rsrc/js/application/core/behavior-drag-and-drop.js', ), 'javelin-behavior-aphront-drag-and-drop-textarea' => array( - 'uri' => '/res/ad737ce4/rsrc/js/application/core/behavior-drag-and-drop-textarea.js', + 'uri' => '/res/853e33b9/rsrc/js/application/core/behavior-drag-and-drop-textarea.js', 'type' => 'js', 'requires' => array( @@ -1363,18 +1362,19 @@ celerity_register_resource_map(array( ), 'disk' => '/rsrc/js/application/core/behavior-fancy-datepicker.js', ), - 'javelin-behavior-files-drag-and-drop' => + 'javelin-behavior-global-drag-and-drop' => array( - 'uri' => '/res/4eb2f339/rsrc/js/application/core/behavior-files-drag-and-drop.js', + 'uri' => '/res/73ae3fd1/rsrc/js/application/core/behavior-global-drag-and-drop.js', 'type' => 'js', 'requires' => array( 0 => 'javelin-behavior', 1 => 'javelin-dom', 2 => 'javelin-uri', - 3 => 'phabricator-drag-and-drop-file-upload', + 3 => 'javelin-mask', + 4 => 'phabricator-drag-and-drop-file-upload', ), - 'disk' => '/rsrc/js/application/core/behavior-files-drag-and-drop.js', + 'disk' => '/rsrc/js/application/core/behavior-global-drag-and-drop.js', ), 'javelin-behavior-herald-rule-editor' => array( @@ -2473,7 +2473,7 @@ celerity_register_resource_map(array( ), 'phabricator-drag-and-drop-file-upload' => array( - 'uri' => '/res/496110e1/rsrc/js/application/core/DragAndDropFileUpload.js', + 'uri' => '/res/ce71f19a/rsrc/js/application/core/DragAndDropFileUpload.js', 'type' => 'js', 'requires' => array( @@ -2753,7 +2753,7 @@ celerity_register_resource_map(array( ), 'phabricator-property-list-view-css' => array( - 'uri' => '/res/9f4d6640/rsrc/css/layout/phabricator-property-list-view.css', + 'uri' => '/res/cd84ee5a/rsrc/css/layout/phabricator-property-list-view.css', 'type' => 'css', 'requires' => array( @@ -2810,7 +2810,7 @@ celerity_register_resource_map(array( ), 'phabricator-source-code-view-css' => array( - 'uri' => '/res/cf0c566c/rsrc/css/layout/phabricator-source-code-view.css', + 'uri' => '/res/aa04c202/rsrc/css/layout/phabricator-source-code-view.css', 'type' => 'css', 'requires' => array( @@ -3128,7 +3128,7 @@ celerity_register_resource_map(array( ), 'sprite-apps-large-css' => array( - 'uri' => '/res/3629ff92/rsrc/css/sprite-apps-large.css', + 'uri' => '/res/250ebd13/rsrc/css/sprite-apps-large.css', 'type' => 'css', 'requires' => array( @@ -3155,7 +3155,7 @@ celerity_register_resource_map(array( ), 'sprite-icon-css' => array( - 'uri' => '/res/2e174787/rsrc/css/sprite-icon.css', + 'uri' => '/res/ff841245/rsrc/css/sprite-icon.css', 'type' => 'css', 'requires' => array( @@ -3201,7 +3201,7 @@ celerity_register_resource_map(array( ), array( 'packages' => array( - 'e6ad9cda' => + 'a5058778' => array( 'name' => 'core.pkg.css', 'symbols' => @@ -3244,11 +3244,12 @@ celerity_register_resource_map(array( 35 => 'phabricator-side-menu-view-css', 36 => 'phabricator-crumbs-view-css', 37 => 'phabricator-object-item-list-view-css', + 38 => 'global-drag-and-drop-css', ), - 'uri' => '/res/pkg/e6ad9cda/core.pkg.css', + 'uri' => '/res/pkg/a5058778/core.pkg.css', 'type' => 'css', ), - 'ba3c323b' => + '70c8162b' => array( 'name' => 'core.pkg.js', 'symbols' => @@ -3284,8 +3285,9 @@ celerity_register_resource_map(array( 28 => 'javelin-behavior-phabricator-remarkup-assist', 29 => 'phabricator-textareautils', 30 => 'phabricator-file-upload', + 31 => 'javelin-behavior-global-drag-and-drop', ), - 'uri' => '/res/pkg/ba3c323b/core.pkg.js', + 'uri' => '/res/pkg/70c8162b/core.pkg.js', 'type' => 'js', ), '8edbada5' => @@ -3300,7 +3302,7 @@ celerity_register_resource_map(array( 'uri' => '/res/pkg/8edbada5/darkconsole.pkg.js', 'type' => 'js', ), - '94cb8965' => + '380df740' => array( 'name' => 'differential.pkg.css', 'symbols' => @@ -3320,10 +3322,10 @@ celerity_register_resource_map(array( 12 => 'differential-local-commits-view-css', 13 => 'inline-comment-summary-css', ), - 'uri' => '/res/pkg/94cb8965/differential.pkg.css', + 'uri' => '/res/pkg/380df740/differential.pkg.css', 'type' => 'css', ), - '7ecd31fa' => + 'a8e8f2b7' => array( 'name' => 'differential.pkg.js', 'symbols' => @@ -3348,7 +3350,7 @@ celerity_register_resource_map(array( 17 => 'javelin-behavior-differential-toggle-files', 18 => 'javelin-behavior-differential-user-select', ), - 'uri' => '/res/pkg/7ecd31fa/differential.pkg.js', + 'uri' => '/res/pkg/a8e8f2b7/differential.pkg.js', 'type' => 'js', ), 'c8ce2d88' => @@ -3433,82 +3435,84 @@ celerity_register_resource_map(array( 'reverse' => array( 'aphront-attached-file-view-css' => '7839ae2d', - 'aphront-crumbs-view-css' => 'e6ad9cda', - 'aphront-dialog-view-css' => 'e6ad9cda', - 'aphront-error-view-css' => 'e6ad9cda', - 'aphront-form-view-css' => 'e6ad9cda', - 'aphront-headsup-action-list-view-css' => '94cb8965', - 'aphront-headsup-view-css' => 'e6ad9cda', - 'aphront-list-filter-view-css' => 'e6ad9cda', - 'aphront-pager-view-css' => 'e6ad9cda', - 'aphront-panel-view-css' => 'e6ad9cda', - 'aphront-side-nav-view-css' => 'e6ad9cda', - 'aphront-table-view-css' => 'e6ad9cda', - 'aphront-tokenizer-control-css' => 'e6ad9cda', - 'aphront-tooltip-css' => 'e6ad9cda', - 'aphront-typeahead-control-css' => 'e6ad9cda', - 'differential-changeset-view-css' => '94cb8965', - 'differential-core-view-css' => '94cb8965', - 'differential-inline-comment-editor' => '7ecd31fa', - 'differential-local-commits-view-css' => '94cb8965', - 'differential-results-table-css' => '94cb8965', - 'differential-revision-add-comment-css' => '94cb8965', - 'differential-revision-comment-css' => '94cb8965', - 'differential-revision-comment-list-css' => '94cb8965', - 'differential-revision-history-css' => '94cb8965', - 'differential-revision-list-css' => '94cb8965', - 'differential-table-of-contents-css' => '94cb8965', + 'aphront-crumbs-view-css' => 'a5058778', + 'aphront-dialog-view-css' => 'a5058778', + 'aphront-error-view-css' => 'a5058778', + 'aphront-form-view-css' => 'a5058778', + 'aphront-headsup-action-list-view-css' => '380df740', + 'aphront-headsup-view-css' => 'a5058778', + 'aphront-list-filter-view-css' => 'a5058778', + 'aphront-pager-view-css' => 'a5058778', + 'aphront-panel-view-css' => 'a5058778', + 'aphront-side-nav-view-css' => 'a5058778', + 'aphront-table-view-css' => 'a5058778', + 'aphront-tokenizer-control-css' => 'a5058778', + 'aphront-tooltip-css' => 'a5058778', + 'aphront-typeahead-control-css' => 'a5058778', + 'differential-changeset-view-css' => '380df740', + 'differential-core-view-css' => '380df740', + 'differential-inline-comment-editor' => 'a8e8f2b7', + 'differential-local-commits-view-css' => '380df740', + 'differential-results-table-css' => '380df740', + 'differential-revision-add-comment-css' => '380df740', + 'differential-revision-comment-css' => '380df740', + 'differential-revision-comment-list-css' => '380df740', + 'differential-revision-history-css' => '380df740', + 'differential-revision-list-css' => '380df740', + 'differential-table-of-contents-css' => '380df740', 'diffusion-commit-view-css' => 'c8ce2d88', 'diffusion-icons-css' => 'c8ce2d88', - 'inline-comment-summary-css' => '94cb8965', - 'javelin-aphlict' => 'ba3c323b', + 'global-drag-and-drop-css' => 'a5058778', + 'inline-comment-summary-css' => '380df740', + 'javelin-aphlict' => '70c8162b', 'javelin-behavior' => 'db6d724d', - 'javelin-behavior-aphlict-dropdown' => 'ba3c323b', - 'javelin-behavior-aphlict-listen' => 'ba3c323b', - 'javelin-behavior-aphront-basic-tokenizer' => 'ba3c323b', - 'javelin-behavior-aphront-drag-and-drop' => '7ecd31fa', - 'javelin-behavior-aphront-drag-and-drop-textarea' => '7ecd31fa', - 'javelin-behavior-aphront-form-disable-on-submit' => 'ba3c323b', + 'javelin-behavior-aphlict-dropdown' => '70c8162b', + 'javelin-behavior-aphlict-listen' => '70c8162b', + 'javelin-behavior-aphront-basic-tokenizer' => '70c8162b', + 'javelin-behavior-aphront-drag-and-drop' => 'a8e8f2b7', + 'javelin-behavior-aphront-drag-and-drop-textarea' => 'a8e8f2b7', + 'javelin-behavior-aphront-form-disable-on-submit' => '70c8162b', 'javelin-behavior-audit-preview' => '5e68be89', 'javelin-behavior-dark-console' => '8edbada5', 'javelin-behavior-dark-console-ajax' => '8edbada5', - 'javelin-behavior-device' => 'ba3c323b', - 'javelin-behavior-differential-accept-with-errors' => '7ecd31fa', - 'javelin-behavior-differential-add-reviewers-and-ccs' => '7ecd31fa', - 'javelin-behavior-differential-comment-jump' => '7ecd31fa', - 'javelin-behavior-differential-diff-radios' => '7ecd31fa', - 'javelin-behavior-differential-dropdown-menus' => '7ecd31fa', - 'javelin-behavior-differential-edit-inline-comments' => '7ecd31fa', - 'javelin-behavior-differential-feedback-preview' => '7ecd31fa', - 'javelin-behavior-differential-keyboard-navigation' => '7ecd31fa', - 'javelin-behavior-differential-populate' => '7ecd31fa', - 'javelin-behavior-differential-show-more' => '7ecd31fa', - 'javelin-behavior-differential-toggle-files' => '7ecd31fa', - 'javelin-behavior-differential-user-select' => '7ecd31fa', + 'javelin-behavior-device' => '70c8162b', + 'javelin-behavior-differential-accept-with-errors' => 'a8e8f2b7', + 'javelin-behavior-differential-add-reviewers-and-ccs' => 'a8e8f2b7', + 'javelin-behavior-differential-comment-jump' => 'a8e8f2b7', + 'javelin-behavior-differential-diff-radios' => 'a8e8f2b7', + 'javelin-behavior-differential-dropdown-menus' => 'a8e8f2b7', + 'javelin-behavior-differential-edit-inline-comments' => 'a8e8f2b7', + 'javelin-behavior-differential-feedback-preview' => 'a8e8f2b7', + 'javelin-behavior-differential-keyboard-navigation' => 'a8e8f2b7', + 'javelin-behavior-differential-populate' => 'a8e8f2b7', + 'javelin-behavior-differential-show-more' => 'a8e8f2b7', + 'javelin-behavior-differential-toggle-files' => 'a8e8f2b7', + 'javelin-behavior-differential-user-select' => 'a8e8f2b7', 'javelin-behavior-diffusion-commit-graph' => '5e68be89', 'javelin-behavior-diffusion-pull-lastmodified' => '5e68be89', 'javelin-behavior-error-log' => '8edbada5', - 'javelin-behavior-konami' => 'ba3c323b', - 'javelin-behavior-lightbox-attachments' => 'ba3c323b', + 'javelin-behavior-global-drag-and-drop' => '70c8162b', + 'javelin-behavior-konami' => '70c8162b', + 'javelin-behavior-lightbox-attachments' => '70c8162b', 'javelin-behavior-maniphest-batch-selector' => '7707de41', 'javelin-behavior-maniphest-subpriority-editor' => '7707de41', 'javelin-behavior-maniphest-transaction-controls' => '7707de41', 'javelin-behavior-maniphest-transaction-expand' => '7707de41', 'javelin-behavior-maniphest-transaction-preview' => '7707de41', - 'javelin-behavior-phabricator-active-nav' => 'ba3c323b', - 'javelin-behavior-phabricator-autofocus' => 'ba3c323b', - 'javelin-behavior-phabricator-keyboard-shortcuts' => 'ba3c323b', - 'javelin-behavior-phabricator-nav' => 'ba3c323b', - 'javelin-behavior-phabricator-object-selector' => '7ecd31fa', - 'javelin-behavior-phabricator-oncopy' => 'ba3c323b', - 'javelin-behavior-phabricator-remarkup-assist' => 'ba3c323b', - 'javelin-behavior-phabricator-search-typeahead' => 'ba3c323b', - 'javelin-behavior-phabricator-tooltips' => 'ba3c323b', - 'javelin-behavior-phabricator-watch-anchor' => 'ba3c323b', - 'javelin-behavior-refresh-csrf' => 'ba3c323b', - 'javelin-behavior-repository-crossreference' => '7ecd31fa', - 'javelin-behavior-toggle-class' => 'ba3c323b', - 'javelin-behavior-workflow' => 'ba3c323b', + 'javelin-behavior-phabricator-active-nav' => '70c8162b', + 'javelin-behavior-phabricator-autofocus' => '70c8162b', + 'javelin-behavior-phabricator-keyboard-shortcuts' => '70c8162b', + 'javelin-behavior-phabricator-nav' => '70c8162b', + 'javelin-behavior-phabricator-object-selector' => 'a8e8f2b7', + 'javelin-behavior-phabricator-oncopy' => '70c8162b', + 'javelin-behavior-phabricator-remarkup-assist' => '70c8162b', + 'javelin-behavior-phabricator-search-typeahead' => '70c8162b', + 'javelin-behavior-phabricator-tooltips' => '70c8162b', + 'javelin-behavior-phabricator-watch-anchor' => '70c8162b', + 'javelin-behavior-refresh-csrf' => '70c8162b', + 'javelin-behavior-repository-crossreference' => 'a8e8f2b7', + 'javelin-behavior-toggle-class' => '70c8162b', + 'javelin-behavior-workflow' => '70c8162b', 'javelin-dom' => 'db6d724d', 'javelin-event' => 'db6d724d', 'javelin-install' => 'db6d724d', @@ -3527,48 +3531,48 @@ celerity_register_resource_map(array( 'javelin-util' => 'db6d724d', 'javelin-vector' => 'db6d724d', 'javelin-workflow' => 'db6d724d', - 'lightbox-attachment-css' => 'e6ad9cda', + 'lightbox-attachment-css' => 'a5058778', 'maniphest-task-summary-css' => '7839ae2d', 'maniphest-transaction-detail-css' => '7839ae2d', - 'phabricator-app-buttons-css' => 'e6ad9cda', - 'phabricator-busy' => 'ba3c323b', - 'phabricator-content-source-view-css' => '94cb8965', - 'phabricator-core-buttons-css' => 'e6ad9cda', - 'phabricator-core-css' => 'e6ad9cda', - 'phabricator-crumbs-view-css' => 'e6ad9cda', - 'phabricator-directory-css' => 'e6ad9cda', - 'phabricator-drag-and-drop-file-upload' => '7ecd31fa', - 'phabricator-dropdown-menu' => 'ba3c323b', - 'phabricator-file-upload' => 'ba3c323b', - 'phabricator-filetree-view-css' => 'e6ad9cda', - 'phabricator-flag-css' => 'e6ad9cda', - 'phabricator-form-view-css' => 'e6ad9cda', - 'phabricator-header-view-css' => 'e6ad9cda', - 'phabricator-jump-nav' => 'e6ad9cda', - 'phabricator-keyboard-shortcut' => 'ba3c323b', - 'phabricator-keyboard-shortcut-manager' => 'ba3c323b', - 'phabricator-main-menu-view' => 'e6ad9cda', - 'phabricator-menu-item' => 'ba3c323b', - 'phabricator-nav-view-css' => 'e6ad9cda', - 'phabricator-notification' => 'ba3c323b', - 'phabricator-notification-css' => 'e6ad9cda', - 'phabricator-notification-menu-css' => 'e6ad9cda', - 'phabricator-object-item-list-view-css' => 'e6ad9cda', - 'phabricator-object-selector-css' => '94cb8965', - 'phabricator-paste-file-upload' => 'ba3c323b', - 'phabricator-prefab' => 'ba3c323b', + 'phabricator-app-buttons-css' => 'a5058778', + 'phabricator-busy' => '70c8162b', + 'phabricator-content-source-view-css' => '380df740', + 'phabricator-core-buttons-css' => 'a5058778', + 'phabricator-core-css' => 'a5058778', + 'phabricator-crumbs-view-css' => 'a5058778', + 'phabricator-directory-css' => 'a5058778', + 'phabricator-drag-and-drop-file-upload' => 'a8e8f2b7', + 'phabricator-dropdown-menu' => '70c8162b', + 'phabricator-file-upload' => '70c8162b', + 'phabricator-filetree-view-css' => 'a5058778', + 'phabricator-flag-css' => 'a5058778', + 'phabricator-form-view-css' => 'a5058778', + 'phabricator-header-view-css' => 'a5058778', + 'phabricator-jump-nav' => 'a5058778', + 'phabricator-keyboard-shortcut' => '70c8162b', + 'phabricator-keyboard-shortcut-manager' => '70c8162b', + 'phabricator-main-menu-view' => 'a5058778', + 'phabricator-menu-item' => '70c8162b', + 'phabricator-nav-view-css' => 'a5058778', + 'phabricator-notification' => '70c8162b', + 'phabricator-notification-css' => 'a5058778', + 'phabricator-notification-menu-css' => 'a5058778', + 'phabricator-object-item-list-view-css' => 'a5058778', + 'phabricator-object-selector-css' => '380df740', + 'phabricator-paste-file-upload' => '70c8162b', + 'phabricator-prefab' => '70c8162b', 'phabricator-project-tag-css' => '7839ae2d', - 'phabricator-remarkup-css' => 'e6ad9cda', - 'phabricator-shaped-request' => '7ecd31fa', - 'phabricator-side-menu-view-css' => 'e6ad9cda', - 'phabricator-standard-page-view' => 'e6ad9cda', - 'phabricator-textareautils' => 'ba3c323b', - 'phabricator-tooltip' => 'ba3c323b', - 'phabricator-transaction-view-css' => 'e6ad9cda', - 'sprite-apps-large-css' => 'e6ad9cda', - 'sprite-gradient-css' => 'e6ad9cda', - 'sprite-icon-css' => 'e6ad9cda', - 'sprite-menu-css' => 'e6ad9cda', - 'syntax-highlighting-css' => 'e6ad9cda', + 'phabricator-remarkup-css' => 'a5058778', + 'phabricator-shaped-request' => 'a8e8f2b7', + 'phabricator-side-menu-view-css' => 'a5058778', + 'phabricator-standard-page-view' => 'a5058778', + 'phabricator-textareautils' => '70c8162b', + 'phabricator-tooltip' => '70c8162b', + 'phabricator-transaction-view-css' => 'a5058778', + 'sprite-apps-large-css' => 'a5058778', + 'sprite-gradient-css' => 'a5058778', + 'sprite-icon-css' => 'a5058778', + 'sprite-menu-css' => 'a5058778', + 'syntax-highlighting-css' => 'a5058778', ), )); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index a2c5a03c02..1b8324a2e1 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -788,7 +788,6 @@ phutil_register_library_map(array( 'PhabricatorFileTransformController' => 'applications/files/controller/PhabricatorFileTransformController.php', 'PhabricatorFileUploadController' => 'applications/files/controller/PhabricatorFileUploadController.php', 'PhabricatorFileUploadException' => 'applications/files/exception/PhabricatorFileUploadException.php', - 'PhabricatorFileUploadView' => 'applications/files/view/PhabricatorFileUploadView.php', 'PhabricatorFilesManagementEnginesWorkflow' => 'applications/files/management/PhabricatorFilesManagementEnginesWorkflow.php', 'PhabricatorFilesManagementMigrateWorkflow' => 'applications/files/management/PhabricatorFilesManagementMigrateWorkflow.php', 'PhabricatorFilesManagementWorkflow' => 'applications/files/management/PhabricatorFilesManagementWorkflow.php', @@ -807,6 +806,7 @@ phutil_register_library_map(array( 'PhabricatorGarbageCollectorDaemon' => 'infrastructure/daemon/PhabricatorGarbageCollectorDaemon.php', 'PhabricatorGitGraphStream' => 'applications/repository/daemon/PhabricatorGitGraphStream.php', 'PhabricatorGlobalLock' => 'infrastructure/util/PhabricatorGlobalLock.php', + 'PhabricatorGlobalUploadTargetView' => 'applications/files/view/PhabricatorGlobalUploadTargetView.php', 'PhabricatorHandleObjectSelectorDataView' => 'applications/phid/handle/view/PhabricatorHandleObjectSelectorDataView.php', 'PhabricatorHash' => 'infrastructure/util/PhabricatorHash.php', 'PhabricatorHeaderView' => 'view/layout/PhabricatorHeaderView.php', @@ -2070,7 +2070,6 @@ phutil_register_library_map(array( 'PhabricatorFileTransformController' => 'PhabricatorFileController', 'PhabricatorFileUploadController' => 'PhabricatorFileController', 'PhabricatorFileUploadException' => 'Exception', - 'PhabricatorFileUploadView' => 'AphrontView', 'PhabricatorFilesManagementEnginesWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementMigrateWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementWorkflow' => 'PhutilArgumentWorkflow', @@ -2086,6 +2085,7 @@ phutil_register_library_map(array( 'PhabricatorFormExample' => 'PhabricatorUIExample', 'PhabricatorGarbageCollectorDaemon' => 'PhabricatorDaemon', 'PhabricatorGlobalLock' => 'PhutilLock', + 'PhabricatorGlobalUploadTargetView' => 'AphrontView', 'PhabricatorHeaderView' => 'AphrontView', 'PhabricatorHelpController' => 'PhabricatorController', 'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController', diff --git a/src/applications/directory/controller/PhabricatorDirectoryMainController.php b/src/applications/directory/controller/PhabricatorDirectoryMainController.php index 1aa2a86819..b5a5d53b51 100644 --- a/src/applications/directory/controller/PhabricatorDirectoryMainController.php +++ b/src/applications/directory/controller/PhabricatorDirectoryMainController.php @@ -76,6 +76,7 @@ final class PhabricatorDirectoryMainController ); $nav->appendChild($content); + $nav->appendChild(new PhabricatorGlobalUploadTargetView()); return $this->buildStandardPageResponse( $nav, @@ -491,7 +492,7 @@ final class PhabricatorDirectoryMainController $nav_buttons[] = array( 'Upload File', - '/file/', + '/file/upload/', 'upload-file', 'Share Files'); $nav_buttons[] = array( diff --git a/src/applications/files/controller/PhabricatorFileController.php b/src/applications/files/controller/PhabricatorFileController.php index a850f8c847..9c6a1a68b1 100644 --- a/src/applications/files/controller/PhabricatorFileController.php +++ b/src/applications/files/controller/PhabricatorFileController.php @@ -2,17 +2,43 @@ abstract class PhabricatorFileController extends PhabricatorController { - public function buildStandardPageResponse($view, array $data) { - $page = $this->buildStandardPageView(); + public function buildApplicationCrumbs() { + $crumbs = parent::buildApplicationCrumbs(); + $crumbs->addAction( + id(new PhabricatorMenuItemView()) + ->setName(pht('Upload File')) + ->setIcon('create') // TODO: Get @chad to build an "upload" icon. + ->setHref($this->getApplicationURI('/upload/'))); - $page->setApplicationName('Files'); - $page->setBaseURI('/file/'); - $page->setTitle(idx($data, 'title')); - $page->setGlyph("\xE2\x87\xAA"); - $page->appendChild($view); - - $response = new AphrontWebpageResponse(); - return $response->setContent($page->render()); + return $crumbs; } + protected function buildSideNavView() { + $menu = $this->buildMenu($for_devices = false); + return AphrontSideNavFilterView::newFromMenu($menu); + } + + protected function buildApplicationMenu() { + return $this->buildMenu($for_devices = true); + } + + private function buildMenu($for_devices) { + $menu = new PhabricatorMenuView(); + + if ($for_devices) { + $menu->newLink(pht('Upload File'), $this->getApplicationURI('/upload/')); + } + + $menu->newLabel(pht('Filters')); + + $menu->newLink(pht('My Files'), $this->getApplicationURI('filter/my/')) + ->setKey('my'); + + $menu->newLink(pht('All Files'), $this->getApplicationURI('filter/all/')) + ->setKey('all'); + + return $menu; + } + + } diff --git a/src/applications/files/controller/PhabricatorFileListController.php b/src/applications/files/controller/PhabricatorFileListController.php index c88c9a06aa..ecdaba4d6b 100644 --- a/src/applications/files/controller/PhabricatorFileListController.php +++ b/src/applications/files/controller/PhabricatorFileListController.php @@ -1,35 +1,20 @@ filter = $filter; return $this; } + private function getFilter() { return $this->filter; } - private function useBasicUploader() { - return $this->getUseBasicUploader(); - } - private function getUseBasicUploader() { - return $this->useBasicUploader; - } - private function setUseBasicUploader($use_basic_uploader) { - $this->useBasicUploader = $use_basic_uploader; - return $this; - } - public function willProcessRequest(array $data) { - $this->setFilter(idx($data, 'filter', 'upload')); + $this->setFilter(idx($data, 'filter', 'my')); } public function processRequest() { @@ -42,26 +27,13 @@ final class PhabricatorFileListController extends PhabricatorFileController { $query = id(new PhabricatorFileQuery()) ->setViewer($user); - $show_pager = true; - $show_upload = false; - switch ($this->getFilter()) { - case 'upload': - default: - $this->setUseBasicUploader($request->getExists('basic_uploader')); - - $query->withAuthorPHIDs(array($user->getPHID())); - $pager->setPageSize(10); - - $header = pht('Recently Uploaded Files'); - $show_pager = false; - $show_upload = true; - break; case 'my': $query->withAuthorPHIDs(array($user->getPHID())); $header = pht('Files You Uploaded'); break; case 'all': + default: $header = pht('All Files'); break; } @@ -74,9 +46,6 @@ final class PhabricatorFileListController extends PhabricatorFileController { $side_nav = $this->buildSideNavView(); $side_nav->selectFilter($this->getFilter()); - if ($show_upload) { - $side_nav->appendChild($this->renderUploadPanel()); - } $header_view = id(new PhabricatorHeaderView()) ->setHeader($header); @@ -85,13 +54,23 @@ final class PhabricatorFileListController extends PhabricatorFileController { array( $header_view, $file_list, - $show_pager ? $pager : null, + $pager, + new PhabricatorGlobalUploadTargetView(), )); + $side_nav->setCrumbs( + $this + ->buildApplicationCrumbs() + ->addCrumb( + id(new PhabricatorCrumbView()) + ->setName($header) + ->setHref($request->getRequestURI()))); + return $this->buildApplicationPage( $side_nav, array( 'title' => 'Files', + 'device' => true, )); } @@ -141,66 +120,4 @@ final class PhabricatorFileListController extends PhabricatorFileController { return $list_view; } - private function buildSideNavView() { - $view = new AphrontSideNavFilterView(); - $view->setBaseURI(new PhutilURI($this->getApplicationURI('/filter/'))); - - $view->addLabel('Files'); - $view->addFilter('upload', 'Upload File'); - $view->addFilter('my', 'My Files'); - $view->addFilter('all', 'All Files'); - - return $view; - } - - private function renderUploadPanel() { - $request = $this->getRequest(); - $user = $request->getUser(); - - $limit_text = PhabricatorFileUploadView::renderUploadLimit(); - - if ($this->useBasicUploader()) { - - $upload_panel = new PhabricatorFileUploadView(); - $upload_panel->setUser($user); - - } else { - - require_celerity_resource('files-css'); - $upload_id = celerity_generate_unique_node_id(); - $panel_id = celerity_generate_unique_node_id(); - - $upload_panel = new AphrontPanelView(); - $upload_panel->setHeader('Upload Files'); - $upload_panel->setCaption($limit_text); - $upload_panel->setCreateButton('Basic Uploader', - $request->getRequestURI()->setQueryParam('basic_uploader', true) - ); - - $upload_panel->setWidth(AphrontPanelView::WIDTH_FULL); - $upload_panel->setID($panel_id); - - $upload_panel->appendChild( - phutil_render_tag( - 'div', - array( - 'id' => $upload_id, - 'style' => 'display: none;', - 'class' => 'files-drag-and-drop', - ), - '')); - - Javelin::initBehavior( - 'files-drag-and-drop', - array( - 'uri' => '/file/dropupload/', - 'browseURI' => '/file/filter/my/', - 'control' => $upload_id, - 'target' => $panel_id, - 'activatedClass' => 'aphront-panel-view-drag-and-drop', - )); - } - - return $upload_panel; - } } diff --git a/src/applications/files/controller/PhabricatorFileUploadController.php b/src/applications/files/controller/PhabricatorFileUploadController.php index 8055211119..f94e587a19 100644 --- a/src/applications/files/controller/PhabricatorFileUploadController.php +++ b/src/applications/files/controller/PhabricatorFileUploadController.php @@ -3,28 +3,114 @@ final class PhabricatorFileUploadController extends PhabricatorFileController { public function processRequest() { - $request = $this->getRequest(); $user = $request->getUser(); + $e_file = true; + $errors = array(); if ($request->isFormPost()) { - $file = PhabricatorFile::newFromPHPUpload( - idx($_FILES, 'file'), - array( - 'name' => $request->getStr('name'), - 'authorPHID' => $user->getPHID(), - )); + if (!$request->getFileExists('file')) { + $e_file = pht('Required'); + $errors[] = pht('You must select a file to upload.'); + } else { + $file = PhabricatorFile::newFromPHPUpload( + idx($_FILES, 'file'), + array( + 'name' => $request->getStr('name'), + 'authorPHID' => $user->getPHID(), + )); + } - return id(new AphrontRedirectResponse())->setURI($file->getBestURI()); + if (!$errors) { + return id(new AphrontRedirectResponse())->setURI($file->getViewURI()); + } } - $panel = new PhabricatorFileUploadView(); - $panel->setUser($user); + $support_id = celerity_generate_unique_node_id(); + $instructions = id(new AphrontFormMarkupControl()) + ->setControlID($support_id) + ->setControlStyle('display: none') + ->setValue( + '

'. + pht( + 'Drag and Drop: You can also upload files by '. + 'dragging and dropping them from your desktop onto this page or '. + 'the Phabricator home page.'). + '

'); - return $this->buildStandardPageResponse( - array($panel), + $form = id(new AphrontFormView()) + ->setFlexible(true) + ->setUser($user) + ->setEncType('multipart/form-data') + ->appendChild( + id(new AphrontFormFileControl()) + ->setLabel(pht('File')) + ->setName('file') + ->setError($e_file) + ->setCaption($this->renderUploadLimit())) + ->appendChild( + id(new AphrontFormTextControl()) + ->setLabel(pht('Name')) + ->setName('name') + ->setValue($request->getStr('name')) + ->setCaption('Optional file display name.')) + ->appendChild( + id(new AphrontFormSubmitControl()) + ->setValue(pht('Upload')) + ->addCancelButton('/file/')) + ->appendChild($instructions); + + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addCrumb( + id(new PhabricatorCrumbView()) + ->setName(pht('Upload')) + ->setHref($request->getRequestURI())); + + $header = id(new PhabricatorHeaderView()) + ->setHeader(pht('Upload File')); + + if ($errors) { + $errors = id(new AphrontErrorView()) + ->setTitle('Form Errors') + ->setErrors($errors); + } + + $global_upload = id(new PhabricatorGlobalUploadTargetView()) + ->setShowIfSupportedID($support_id); + + return $this->buildApplicationPage( + array( + $crumbs, + $header, + $errors, + $form, + $global_upload, + ), array( 'title' => 'Upload File', + 'device' => true, )); } + + private function renderUploadLimit() { + $limit = PhabricatorEnv::getEnvConfig('storage.upload-size-limit'); + $limit = phabricator_parse_bytes($limit); + if ($limit) { + $formatted = phabricator_format_bytes($limit); + return 'Maximum file size: '.phutil_escape_html($formatted); + } + + $doc_href = PhabricatorEnv::getDocLink( + 'article/Configuring_File_Upload_Limits.html'); + $doc_link = phutil_render_tag( + 'a', + array( + 'href' => $doc_href, + 'target' => '_blank', + ), + 'Configuring File Upload Limits'); + + return 'Upload limit is not configured, see '.$doc_link.'.'; + } + } diff --git a/src/applications/files/view/PhabricatorFileUploadView.php b/src/applications/files/view/PhabricatorFileUploadView.php deleted file mode 100644 index b9160bf278..0000000000 --- a/src/applications/files/view/PhabricatorFileUploadView.php +++ /dev/null @@ -1,73 +0,0 @@ -user; - } - public function setUser(PhabricatorUser $user) { - $this->user = $user; - return $this; - } - - public function render() { - $user = $this->getUser(); - if (!$user) { - throw new Exception("Call setUser() before render()!"); - } - - $form = new AphrontFormView(); - $form->setAction('/file/upload/'); - $form->setUser($user); - - $form - ->setEncType('multipart/form-data') - ->appendChild( - id(new AphrontFormFileControl()) - ->setLabel('File') - ->setName('file') - ->setError(true) - ->setCaption(self::renderUploadLimit())) - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel('Name') - ->setName('name') - ->setCaption('Optional file display name.')) - ->appendChild( - id(new AphrontFormSubmitControl()) - ->setValue('Upload') - ->addCancelButton('/file/')); - - $panel = new AphrontPanelView(); - $panel->setHeader('Upload File'); - - $panel->appendChild($form); - $panel->setWidth(AphrontPanelView::WIDTH_FULL); - - return $panel->render(); - } - - public static function renderUploadLimit() { - $limit = PhabricatorEnv::getEnvConfig('storage.upload-size-limit'); - $limit = phabricator_parse_bytes($limit); - if ($limit) { - $formatted = phabricator_format_bytes($limit); - return 'Maximum file size: '.phutil_escape_html($formatted); - } - - $doc_href = PhabricatorEnv::getDocLink( - 'article/Configuring_File_Upload_Limits.html'); - $doc_link = phutil_render_tag( - 'a', - array( - 'href' => $doc_href, - 'target' => '_blank', - ), - 'Configuring File Upload Limits'); - - return 'Upload limit is not configured, see '.$doc_link.'.'; - } -} - diff --git a/src/applications/files/view/PhabricatorGlobalUploadTargetView.php b/src/applications/files/view/PhabricatorGlobalUploadTargetView.php new file mode 100644 index 0000000000..6b8a0f566a --- /dev/null +++ b/src/applications/files/view/PhabricatorGlobalUploadTargetView.php @@ -0,0 +1,37 @@ +showIfSupportedID = $show_if_supported_id; + return $this; + } + + public function getShowIfSupportedID() { + return $this->showIfSupportedID; + } + + public function render() { + $instructions_id = celerity_generate_unique_node_id(); + + require_celerity_resource('global-drag-and-drop-css'); + + Javelin::initBehavior('global-drag-and-drop', array( + 'ifSupported' => $this->showIfSupportedID, + 'instructions' => $instructions_id, + 'uploadURI' => '/file/dropupload/', + 'browseURI' => '/file/filter/my/', + )); + + return phutil_render_tag( + 'div', + array( + 'id' => $instructions_id, + 'class' => 'phabricator-global-upload-instructions', + 'style' => 'display: none;', + ), + pht("\xE2\x87\xAA Drop Files to Upload")); + } +} diff --git a/src/view/form/control/AphrontFormTextAreaControl.php b/src/view/form/control/AphrontFormTextAreaControl.php index 378fa5e8bf..55327e40cd 100644 --- a/src/view/form/control/AphrontFormTextAreaControl.php +++ b/src/view/form/control/AphrontFormTextAreaControl.php @@ -11,7 +11,6 @@ class AphrontFormTextAreaControl extends AphrontFormControl { private $height; private $readOnly; - private $enableDragAndDropFileUploads; private $customClass; public function setHeight($height) { diff --git a/src/view/layout/AphrontSideNavFilterView.php b/src/view/layout/AphrontSideNavFilterView.php index 3d7629a200..574f9f31ef 100644 --- a/src/view/layout/AphrontSideNavFilterView.php +++ b/src/view/layout/AphrontSideNavFilterView.php @@ -32,6 +32,13 @@ final class AphrontSideNavFilterView extends AphrontView { $this->menu = new PhabricatorMenuView(); } + public static function newFromMenu(PhabricatorMenuView $menu) { + $object = new AphrontSideNavFilterView(); + $object->setBaseURI(new PhutilURI('/')); + $object->menu = $menu; + return $object; + } + public function setCrumbs(PhabricatorCrumbsView $crumbs) { $this->crumbs = $crumbs; return $this; @@ -128,7 +135,7 @@ final class AphrontSideNavFilterView extends AphrontView { public function selectFilter($key, $default = null) { $this->selectedFilter = $default; - if ($this->menu->getItem($key)) { + if ($this->menu->getItem($key) && strlen($key)) { $this->selectedFilter = $key; } return $this->selectedFilter; diff --git a/src/view/layout/PhabricatorMenuView.php b/src/view/layout/PhabricatorMenuView.php index eaaa04520c..5bd799db0a 100644 --- a/src/view/layout/PhabricatorMenuView.php +++ b/src/view/layout/PhabricatorMenuView.php @@ -3,7 +3,6 @@ final class PhabricatorMenuView extends AphrontView { private $items = array(); - private $map = array(); private $classes = array(); public function addClass($class) { @@ -34,14 +33,6 @@ final class PhabricatorMenuView extends AphrontView { public function addMenuItem(PhabricatorMenuItemView $item) { $key = $item->getKey(); - if ($key !== null) { - if (isset($this->map[$key])) { - throw new Exception( - "Menu contains duplicate items with key '{$key}'!"); - } - $this->map[$key] = $item; - } - $this->items[] = $item; $this->appendChild($item); @@ -49,7 +40,19 @@ final class PhabricatorMenuView extends AphrontView { } public function getItem($key) { - return idx($this->map, (string)$key); + $key = (string)$key; + + // NOTE: We could optimize this, but need to update any map when items have + // their keys change. Since that's moderately complex, wait for a profile + // or use case. + + foreach ($this->items as $item) { + if ($item->getKey() == $key) { + return $item; + } + } + + return null; } public function getItems() { @@ -57,6 +60,18 @@ final class PhabricatorMenuView extends AphrontView { } public function render() { + $key_map = array(); + foreach ($this->items as $item) { + $key = $item->getKey(); + if ($key !== null) { + if (isset($key_map[$key])) { + throw new Exception( + "Menu contains duplicate items with key '{$key}'!"); + } + $key_map[$key] = $item; + } + } + $classes = $this->classes; $classes[] = 'phabricator-menu-view'; diff --git a/webroot/rsrc/css/application/files/files.css b/webroot/rsrc/css/application/files/files.css deleted file mode 100644 index beaff56c38..0000000000 --- a/webroot/rsrc/css/application/files/files.css +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @provides files-css - */ - -.files-drag-and-drop { - text-align: center; - padding: 0em 1em .5em; - font-size: 15px; - color: #666666; -} diff --git a/webroot/rsrc/css/application/files/global-drag-and-drop.css b/webroot/rsrc/css/application/files/global-drag-and-drop.css new file mode 100644 index 0000000000..d4c5af095f --- /dev/null +++ b/webroot/rsrc/css/application/files/global-drag-and-drop.css @@ -0,0 +1,22 @@ +/** + * @provides global-drag-and-drop-css + */ + +.phabricator-global-upload-instructions { + text-align: center; + position: fixed; + font-size: 36px; + font-weight: bold; + + margin: 0 10%; + width: 80%; + left: 0; + top: 30%; + padding: 18px 0; + + color: #ffffff; + background: rgba(0, 0, 0, 0.8); + z-index: 8; + border-radius: 18px; + +} diff --git a/webroot/rsrc/js/application/core/DragAndDropFileUpload.js b/webroot/rsrc/js/application/core/DragAndDropFileUpload.js index d77e7c2986..e3e3b69706 100644 --- a/webroot/rsrc/js/application/core/DragAndDropFileUpload.js +++ b/webroot/rsrc/js/application/core/DragAndDropFileUpload.js @@ -15,12 +15,19 @@ JX.install('PhabricatorDragAndDropFileUpload', { this._node = node; }, - events : ['willUpload', 'progress', 'didUpload', 'didError'], + events : [ + 'didBeginDrag', + 'didEndDrag', + 'willUpload', + 'progress', + 'didUpload', + 'didError'], statics : { isSupported : function() { // TODO: Is there a better capability test for this? This seems okay in // Safari, Firefox and Chrome. + return !!window.FileList; } }, @@ -29,11 +36,17 @@ JX.install('PhabricatorDragAndDropFileUpload', { _node : null, _depth : 0, _updateDepth : function(delta) { + if (this._depth == 0 && delta > 0) { + JX.log('begin: ' + this._depth + ' @ ' + delta); + this.invoke('didBeginDrag'); + } + this._depth += delta; - JX.DOM.alterClass( - this._node, - this.getActivatedClass(), - (this._depth > 0)); + + if (this._depth == 0 && delta < 0) { + JX.log('end: ' + this._depth + ' @ ' + delta); + this.invoke('didEndDrag'); + } }, start : function() { diff --git a/webroot/rsrc/js/application/core/behavior-drag-and-drop-textarea.js b/webroot/rsrc/js/application/core/behavior-drag-and-drop-textarea.js index 9ad1cd11fb..0deff3dda7 100644 --- a/webroot/rsrc/js/application/core/behavior-drag-and-drop-textarea.js +++ b/webroot/rsrc/js/application/core/behavior-drag-and-drop-textarea.js @@ -12,13 +12,29 @@ JX.behavior('aphront-drag-and-drop-textarea', function(config) { var target = JX.$(config.target); function onupload(f) { - JX.TextAreaUtils.setSelectionText(target, '{F' + f.getID() + '}'); + var text = JX.TextAreaUtils.getSelectionText(target); + var ref = '{F' + f.getID() + '}'; + + // If the user has dragged and dropped multiple files, we'll get an event + // each time an upload completes. Rather than overwriting the first + // reference, append the new reference if the selected text looks like an + // existing file reference. + if (text.match(/^\{F/)) { + ref = text + "\n\n" + ref; + } + + JX.TextAreaUtils.setSelectionText(target, ref); } if (JX.PhabricatorDragAndDropFileUpload.isSupported()) { var drop = new JX.PhabricatorDragAndDropFileUpload(target) - .setActivatedClass(config.activatedClass) .setURI(config.uri); + drop.listen('didBeginDrag', function(e) { + JX.DOM.alterClass(target, config.activatedClass, true); + }); + drop.listen('didEndDrag', function(e) { + JX.DOM.alterClass(target, config.activatedClass, false); + }); drop.listen('didUpload', onupload); drop.start(); } diff --git a/webroot/rsrc/js/application/core/behavior-drag-and-drop.js b/webroot/rsrc/js/application/core/behavior-drag-and-drop.js index 6788f38d0e..4e115e1826 100644 --- a/webroot/rsrc/js/application/core/behavior-drag-and-drop.js +++ b/webroot/rsrc/js/application/core/behavior-drag-and-drop.js @@ -2,7 +2,6 @@ * @provides javelin-behavior-aphront-drag-and-drop * @requires javelin-behavior * javelin-dom - * javelin-util * phabricator-drag-and-drop-file-upload */ @@ -23,9 +22,16 @@ JX.behavior('aphront-drag-and-drop', function(config) { var list = JX.$(config.list); var drop = new JX.PhabricatorDragAndDropFileUpload(JX.$(config.list)) - .setActivatedClass(config.activatedClass) .setURI(config.uri); + drop.listen('didBeginDrag', function(e) { + JX.DOM.alterClass(list, config.activatedClass, true); + }); + + drop.listen('didEndDrag', function(e) { + JX.DOM.alterClass(list, config.activatedClass, false); + }); + drop.listen('willUpload', function(f) { pending++; redraw(); diff --git a/webroot/rsrc/js/application/core/behavior-files-drag-and-drop.js b/webroot/rsrc/js/application/core/behavior-files-drag-and-drop.js deleted file mode 100644 index b2da9efa01..0000000000 --- a/webroot/rsrc/js/application/core/behavior-files-drag-and-drop.js +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @provides javelin-behavior-files-drag-and-drop - * @requires javelin-behavior - * javelin-dom - * javelin-uri - * phabricator-drag-and-drop-file-upload - */ - -JX.behavior('files-drag-and-drop', function(config) { - - // The control renders hidden by default; if we don't have support for - // drag-and-drop just leave it hidden. - if (!JX.PhabricatorDragAndDropFileUpload.isSupported()) { - return; - } - - var pending = 0; - var files = []; - var errors = false; - - var control = JX.$(config.control); - // Show the control, since we have browser support. - control.style.display = ''; - - var drop = new JX.PhabricatorDragAndDropFileUpload(JX.$(config.target)) - .setActivatedClass(config.activatedClass) - .setURI(config.uri); - - drop.listen('willUpload', function(f) { - pending++; - redraw(); - }); - - drop.listen('didUpload', function(f) { - files.push(f); - - pending--; - if (pending == 0 && !errors) { - // If whatever the user dropped in has finished uploading, send them to - // their uploads. - var uri; - uri = JX.$U(config.browseURI); - var ids = []; - for (var ii = 0; ii < files.length; ii++) { - ids.push(files[ii].getID()); - } - uri.setQueryParam('h', ids.join(',')); - - // Reset so if you hit 'back' into the bfcache the page is still in a - // sensible state. - redraw(); - files = []; - - uri.go(); - } else { - redraw(); - } - }); - - drop.listen('didError', function(f) { - pending--; - errors = true; - redraw(); - }); - - drop.start(); - redraw(); - - function redraw() { - - var status; - if (pending) { - status = 'Uploading ' + pending + ' files...'; - } else { - var arrow = String.fromCharCode(0x21EA); - status = JX.$H( - arrow + ' Drag and Drop files here to upload them.'); - } - - JX.DOM.setContent(control, status); - } - -}); - diff --git a/webroot/rsrc/js/application/core/behavior-global-drag-and-drop.js b/webroot/rsrc/js/application/core/behavior-global-drag-and-drop.js new file mode 100644 index 0000000000..8d4b7a443b --- /dev/null +++ b/webroot/rsrc/js/application/core/behavior-global-drag-and-drop.js @@ -0,0 +1,68 @@ +/** + * @provides javelin-behavior-global-drag-and-drop + * @requires javelin-behavior + * javelin-dom + * javelin-uri + * javelin-mask + * phabricator-drag-and-drop-file-upload + */ + +JX.behavior('global-drag-and-drop', function(config) { + if (!JX.PhabricatorDragAndDropFileUpload.isSupported()) { + return; + } + + var pending = 0; + var files = []; + var errors = false; + + if (config.ifSupported) { + JX.$(config.ifSupported).style.display = ''; + } + + var drop = new JX.PhabricatorDragAndDropFileUpload(document.documentElement) + .setURI(config.uploadURI); + + drop.listen('didBeginDrag', function(f) { + JX.Mask.show(); + JX.DOM.show(JX.$(config.instructions)); + }); + + drop.listen('didEndDrag', function(f) { + JX.Mask.hide(); + JX.DOM.hide(JX.$(config.instructions)); + }); + + drop.listen('willUpload', function(f) { + pending++; + }); + + drop.listen('didUpload', function(f) { + files.push(f); + + pending--; + if (pending == 0 && !errors) { + // If whatever the user dropped in has finished uploading, send them to + // their uploads. + var uri; + uri = JX.$U(config.browseURI); + var ids = []; + for (var ii = 0; ii < files.length; ii++) { + ids.push(files[ii].getID()); + } + uri.setQueryParam('h', ids.join(',')); + + files = []; + + uri.go(); + } + }); + + drop.listen('didError', function(f) { + pending--; + errors = true; + }); + + drop.start(); +}); +