Skip to content

Commit 9f65a5e

Browse files
author
epriestley
committed
Drag-and-drop upload for Maniphest
Summary: This needs a bunch of UI polish (critically, it's totally undiscoverable) but it basically works correctly. I'll clean it up in some followups. Test Plan: Uploaded some files via drag-and-drop, made comments, etc. Reviewed By: aran Reviewers: tomo, aran, jungejason, tuomaspelkonen CC: anjali, aran Differential Revision: 332
1 parent 3f11c8a commit 9f65a5e

File tree

13 files changed

+388
-80
lines changed

13 files changed

+388
-80
lines changed

src/__celerity_resource_map__.php

Lines changed: 77 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
),
8282
'aphront-panel-view-css' =>
8383
array(
84-
'uri' => '/res/5ca2f692/rsrc/css/aphront/panel-view.css',
84+
'uri' => '/res/e0139b9c/rsrc/css/aphront/panel-view.css',
8585
'type' => 'css',
8686
'requires' =>
8787
array(
@@ -381,6 +381,16 @@
381381
),
382382
'disk' => '/rsrc/js/application/differential/behavior-show-all-comments.js',
383383
),
384+
0 =>
385+
array(
386+
'uri' => '/res/39de799e/rsrc/js/javelin/docs/Base.js',
387+
'type' => 'js',
388+
'requires' =>
389+
array(
390+
0 => 'javelin-install',
391+
),
392+
'disk' => '/rsrc/js/javelin/docs/Base.js',
393+
),
384394
'javelin-behavior-differential-show-more' =>
385395
array(
386396
'uri' => '/res/9cbf1c9c/rsrc/js/application/differential/behavior-show-more.js',
@@ -456,6 +466,18 @@
456466
),
457467
'disk' => '/rsrc/js/application/maniphest/behavior-transaction-controls.js',
458468
),
469+
'javelin-behavior-maniphest-transaction-drag-and-drop' =>
470+
array(
471+
'uri' => '/res/5bf1f40c/rsrc/js/application/maniphest/behavior-transaction-drag-and-drop.js',
472+
'type' => 'js',
473+
'requires' =>
474+
array(
475+
0 => 'javelin-behavior',
476+
1 => 'javelin-dom',
477+
2 => 'phabricator-drag-and-drop-file-upload',
478+
),
479+
'disk' => '/rsrc/js/application/maniphest/behavior-transaction-drag-and-drop.js',
480+
),
459481
'javelin-behavior-maniphest-transaction-expand' =>
460482
array(
461483
'uri' => '/res/966410de/rsrc/js/application/maniphest/behavior-transaction-expand.js',
@@ -533,16 +555,6 @@
533555
),
534556
'disk' => '/rsrc/js/javelin/lib/DOM.js',
535557
),
536-
0 =>
537-
array(
538-
'uri' => '/res/39de799e/rsrc/js/javelin/docs/Base.js',
539-
'type' => 'js',
540-
'requires' =>
541-
array(
542-
0 => 'javelin-install',
543-
),
544-
'disk' => '/rsrc/js/javelin/docs/Base.js',
545-
),
546558
'javelin-event' =>
547559
array(
548560
'uri' => '/res/25c7c9e8/rsrc/js/javelin/core/Event.js',
@@ -768,7 +780,7 @@
768780
),
769781
'maniphest-transaction-detail-css' =>
770782
array(
771-
'uri' => '/res/927f4430/rsrc/css/application/maniphest/transaction-detail.css',
783+
'uri' => '/res/14758b00/rsrc/css/application/maniphest/transaction-detail.css',
772784
'type' => 'css',
773785
'requires' =>
774786
array(
@@ -853,6 +865,20 @@
853865
),
854866
'disk' => '/rsrc/css/application/directory/phabricator-directory.css',
855867
),
868+
'phabricator-drag-and-drop-file-upload' =>
869+
array(
870+
'uri' => '/res/711efc61/rsrc/js/application/core/DragAndDropFileUpload.js',
871+
'type' => 'js',
872+
'requires' =>
873+
array(
874+
0 => 'javelin-install',
875+
1 => 'javelin-util',
876+
2 => 'javelin-request',
877+
3 => 'javelin-dom',
878+
4 => 'javelin-uri',
879+
),
880+
'disk' => '/rsrc/js/application/core/DragAndDropFileUpload.js',
881+
),
856882
'phabricator-object-selector-css' =>
857883
array(
858884
'uri' => '/res/ced4098a/rsrc/css/application/objectselector/object-selector.css',
@@ -933,30 +959,6 @@
933959
'uri' => '/res/pkg/03ef179e/diffusion.pkg.css',
934960
'type' => 'css',
935961
),
936-
'0ab8eff6' =>
937-
array (
938-
'name' => 'core.pkg.css',
939-
'symbols' =>
940-
array (
941-
0 => 'phabricator-core-css',
942-
1 => 'phabricator-core-buttons-css',
943-
2 => 'phabricator-standard-page-view',
944-
3 => 'aphront-dialog-view-css',
945-
4 => 'aphront-form-view-css',
946-
5 => 'aphront-panel-view-css',
947-
6 => 'aphront-side-nav-view-css',
948-
7 => 'aphront-table-view-css',
949-
8 => 'aphront-crumbs-view-css',
950-
9 => 'aphront-tokenizer-control-css',
951-
10 => 'aphront-typeahead-control-css',
952-
11 => 'aphront-list-filter-view-css',
953-
12 => 'phabricator-directory-css',
954-
13 => 'phabricator-remarkup-css',
955-
14 => 'syntax-highlighting-css',
956-
),
957-
'uri' => '/res/pkg/0ab8eff6/core.pkg.css',
958-
'type' => 'css',
959-
),
960962
'122a6b6d' =>
961963
array (
962964
'name' => 'workflow.pkg.js',
@@ -1002,6 +1004,30 @@
10021004
'uri' => '/res/pkg/33f413ef/typeahead.pkg.js',
10031005
'type' => 'js',
10041006
),
1007+
'ac3f56cc' =>
1008+
array (
1009+
'name' => 'core.pkg.css',
1010+
'symbols' =>
1011+
array (
1012+
0 => 'phabricator-core-css',
1013+
1 => 'phabricator-core-buttons-css',
1014+
2 => 'phabricator-standard-page-view',
1015+
3 => 'aphront-dialog-view-css',
1016+
4 => 'aphront-form-view-css',
1017+
5 => 'aphront-panel-view-css',
1018+
6 => 'aphront-side-nav-view-css',
1019+
7 => 'aphront-table-view-css',
1020+
8 => 'aphront-crumbs-view-css',
1021+
9 => 'aphront-tokenizer-control-css',
1022+
10 => 'aphront-typeahead-control-css',
1023+
11 => 'aphront-list-filter-view-css',
1024+
12 => 'phabricator-directory-css',
1025+
13 => 'phabricator-remarkup-css',
1026+
14 => 'syntax-highlighting-css',
1027+
),
1028+
'uri' => '/res/pkg/ac3f56cc/core.pkg.css',
1029+
'type' => 'css',
1030+
),
10051031
'ce1d51a9' =>
10061032
array (
10071033
'name' => 'javelin.pkg.js',
@@ -1038,15 +1064,15 @@
10381064
),
10391065
'reverse' =>
10401066
array (
1041-
'aphront-crumbs-view-css' => '0ab8eff6',
1042-
'aphront-dialog-view-css' => '0ab8eff6',
1043-
'aphront-form-view-css' => '0ab8eff6',
1044-
'aphront-list-filter-view-css' => '0ab8eff6',
1045-
'aphront-panel-view-css' => '0ab8eff6',
1046-
'aphront-side-nav-view-css' => '0ab8eff6',
1047-
'aphront-table-view-css' => '0ab8eff6',
1048-
'aphront-tokenizer-control-css' => '0ab8eff6',
1049-
'aphront-typeahead-control-css' => '0ab8eff6',
1067+
'aphront-crumbs-view-css' => 'ac3f56cc',
1068+
'aphront-dialog-view-css' => 'ac3f56cc',
1069+
'aphront-form-view-css' => 'ac3f56cc',
1070+
'aphront-list-filter-view-css' => 'ac3f56cc',
1071+
'aphront-panel-view-css' => 'ac3f56cc',
1072+
'aphront-side-nav-view-css' => 'ac3f56cc',
1073+
'aphront-table-view-css' => 'ac3f56cc',
1074+
'aphront-tokenizer-control-css' => 'ac3f56cc',
1075+
'aphront-typeahead-control-css' => 'ac3f56cc',
10501076
'differential-changeset-view-css' => '1ac25e8a',
10511077
'differential-core-view-css' => '1ac25e8a',
10521078
'differential-revision-add-comment-css' => '1ac25e8a',
@@ -1081,11 +1107,11 @@
10811107
'javelin-util' => 'ce1d51a9',
10821108
'javelin-vector' => 'ce1d51a9',
10831109
'javelin-workflow' => '122a6b6d',
1084-
'phabricator-core-buttons-css' => '0ab8eff6',
1085-
'phabricator-core-css' => '0ab8eff6',
1086-
'phabricator-directory-css' => '0ab8eff6',
1087-
'phabricator-remarkup-css' => '0ab8eff6',
1088-
'phabricator-standard-page-view' => '0ab8eff6',
1089-
'syntax-highlighting-css' => '0ab8eff6',
1110+
'phabricator-core-buttons-css' => 'ac3f56cc',
1111+
'phabricator-core-css' => 'ac3f56cc',
1112+
'phabricator-directory-css' => 'ac3f56cc',
1113+
'phabricator-remarkup-css' => 'ac3f56cc',
1114+
'phabricator-standard-page-view' => 'ac3f56cc',
1115+
'syntax-highlighting-css' => 'ac3f56cc',
10901116
),
10911117
));

src/__phutil_library_map__.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@
312312
'PhabricatorFile' => 'applications/files/storage/file',
313313
'PhabricatorFileController' => 'applications/files/controller/base',
314314
'PhabricatorFileDAO' => 'applications/files/storage/base',
315+
'PhabricatorFileDropUploadController' => 'applications/files/controller/dropupload',
315316
'PhabricatorFileImageMacro' => 'applications/files/storage/imagemacro',
316317
'PhabricatorFileListController' => 'applications/files/controller/list',
317318
'PhabricatorFileMacroDeleteController' => 'applications/files/controller/macrodelete',
@@ -749,6 +750,7 @@
749750
'PhabricatorFile' => 'PhabricatorFileDAO',
750751
'PhabricatorFileController' => 'PhabricatorController',
751752
'PhabricatorFileDAO' => 'PhabricatorLiskDAO',
753+
'PhabricatorFileDropUploadController' => 'PhabricatorFileController',
752754
'PhabricatorFileImageMacro' => 'PhabricatorFileDAO',
753755
'PhabricatorFileListController' => 'PhabricatorFileController',
754756
'PhabricatorFileMacroDeleteController' => 'PhabricatorFileController',

src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public function getURIMap() {
5252
'/file/' => array(
5353
'$' => 'PhabricatorFileListController',
5454
'upload/$' => 'PhabricatorFileUploadController',
55+
'dropupload/$' => 'PhabricatorFileDropUploadController',
5556
'(?P<view>info)/(?P<phid>[^/]+)/' => 'PhabricatorFileViewController',
5657
'(?P<view>view)/(?P<phid>[^/]+)/' => 'PhabricatorFileViewController',
5758
'(?P<view>download)/(?P<phid>[^/]+)/' => 'PhabricatorFileViewController',
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* Copyright 2011 Facebook, Inc.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
class PhabricatorFileDropUploadController extends PhabricatorFileController {
20+
21+
public function processRequest() {
22+
$request = $this->getRequest();
23+
24+
$data = file_get_contents('php://input');
25+
$name = $request->getStr('name');
26+
27+
$file = PhabricatorFile::newFromFileData(
28+
$data,
29+
array(
30+
'name' => $request->getStr('name'),
31+
));
32+
33+
return id(new AphrontAjaxResponse())->setContent(
34+
array(
35+
'name' => $file->getName(),
36+
'phid' => $file->getPHID(),
37+
'size' => $file->getByteSize(),
38+
'uri' => $file->getViewURI(),
39+
));
40+
}
41+
42+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
/**
3+
* This file is automatically generated. Lint this module to rebuild it.
4+
* @generated
5+
*/
6+
7+
8+
9+
phutil_require_module('phabricator', 'aphront/response/ajax');
10+
phutil_require_module('phabricator', 'applications/files/controller/base');
11+
phutil_require_module('phabricator', 'applications/files/storage/file');
12+
13+
phutil_require_module('phutil', 'utils');
14+
15+
16+
phutil_require_source('PhabricatorFileDropUploadController.php');

src/applications/maniphest/controller/taskdetail/ManiphestTaskDetailController.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,13 @@ public function processRequest() {
285285
->setName('comments')
286286
->setValue($draft_text)
287287
->setID('transaction-comments'))
288+
->appendChild(
289+
id(new AphrontFormMarkupControl())
290+
->setLabel('Attached Files')
291+
->setValue(
292+
'<div id="file-list">'.
293+
'None'.
294+
'</div>'))
288295
->appendChild(
289296
id(new AphrontFormSubmitControl())
290297
->setValue('Avast!'));
@@ -328,11 +335,22 @@ public function processRequest() {
328335
'map' => $control_map,
329336
));
330337

338+
$id = celerity_generate_unique_node_id();
331339

332340
$comment_panel = new AphrontPanelView();
333341
$comment_panel->appendChild($comment_form);
334-
$comment_panel->setHeader('Weigh In');
342+
$comment_panel->setID($id);
335343
$comment_panel->addClass('aphront-panel-accent');
344+
$comment_panel->setHeader('Leap Into Action');
345+
346+
Javelin::initBehavior(
347+
'maniphest-transaction-drag-and-drop',
348+
array(
349+
'target' => $id,
350+
'activatedClass' => 'aphront-panel-view-drag-and-drop',
351+
'uri' => '/file/dropupload/',
352+
'list' => 'file-list',
353+
));
336354

337355
$preview_panel =
338356
'<div class="aphront-panel-preview">

src/applications/maniphest/controller/taskdetail/__init__.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
phutil_require_module('phabricator', 'infrastructure/javelin/api');
2323
phutil_require_module('phabricator', 'view/form/base');
2424
phutil_require_module('phabricator', 'view/form/control/file');
25+
phutil_require_module('phabricator', 'view/form/control/markup');
2526
phutil_require_module('phabricator', 'view/form/control/select');
2627
phutil_require_module('phabricator', 'view/form/control/submit');
2728
phutil_require_module('phabricator', 'view/form/control/textarea');

0 commit comments

Comments
 (0)