1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-02-16 16:58:38 +01:00

Pholio - make the form maintain client side edits between file uploads

Summary: Fixes T3553. Did it by adding some code that refreshes the File object on keyup events within a given file entry. also fixes an html derp I found trying to fix this.

Test Plan: added cool things like 'bbb' to every field and noted they were maintained when I added more files

Reviewers: btrahan

Reviewed By: btrahan

CC: aran, Korvin, chad

Maniphest Tasks: T3553

Differential Revision: https://secure.phabricator.com/D6488
This commit is contained in:
epriestley 2013-07-18 15:04:08 -07:00
parent 33bc4d8841
commit dd76143399
17 changed files with 290 additions and 452 deletions

View file

@ -141,7 +141,6 @@ $package_spec = array(
'javelin-behavior-differential-comment-jump',
'javelin-behavior-differential-add-reviewers-and-ccs',
'javelin-behavior-differential-keyboard-navigation',
'javelin-behavior-aphront-drag-and-drop',
'javelin-behavior-aphront-drag-and-drop-textarea',
'javelin-behavior-phabricator-object-selector',
'javelin-behavior-repository-crossreference',
@ -164,7 +163,6 @@ $package_spec = array(
'maniphest.pkg.css' => array(
'maniphest-task-summary-css',
'maniphest-transaction-detail-css',
'aphront-attached-file-view-css',
'phabricator-project-tag-css',
),
'maniphest.pkg.js' => array(

View file

@ -798,15 +798,6 @@ celerity_register_resource_map(array(
'disk' => '/rsrc/swf/aphlict.swf',
'type' => 'swf',
),
'aphront-attached-file-view-css' =>
array(
'uri' => '/res/a6ca5487/rsrc/css/aphront/attached-file-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/attached-file-view.css',
),
'aphront-bars' =>
array(
'uri' => '/res/95a907d6/rsrc/css/aphront/aphront-bars.css',
@ -1289,19 +1280,6 @@ celerity_register_resource_map(array(
),
'disk' => '/rsrc/js/core/behavior-crop.js',
),
'javelin-behavior-aphront-drag-and-drop' =>
array(
'uri' => '/res/fde3763f/rsrc/js/core/behavior-drag-and-drop.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'phabricator-file-upload',
3 => 'phabricator-drag-and-drop-file-upload',
),
'disk' => '/rsrc/js/core/behavior-drag-and-drop.js',
),
'javelin-behavior-aphront-drag-and-drop-textarea' =>
array(
'uri' => '/res/a261f6e6/rsrc/js/core/behavior-drag-and-drop-textarea.js',
@ -2254,6 +2232,21 @@ celerity_register_resource_map(array(
),
'disk' => '/rsrc/js/application/phame/phame-post-preview.js',
),
'javelin-behavior-pholio-mock-edit' =>
array(
'uri' => '/res/34a066b1/rsrc/js/application/pholio/behavior-pholio-mock-edit.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-workflow',
4 => 'phabricator-phtize',
5 => 'phabricator-drag-and-drop-file-upload',
),
'disk' => '/rsrc/js/application/pholio/behavior-pholio-mock-edit.js',
),
'javelin-behavior-pholio-mock-view' =>
array(
'uri' => '/res/415cd66a/rsrc/js/application/pholio/behavior-pholio-mock-view.js',
@ -3751,7 +3744,7 @@ celerity_register_resource_map(array(
),
'pholio-edit-css' =>
array(
'uri' => '/res/c4a1f392/rsrc/css/application/pholio/pholio-edit.css',
'uri' => '/res/56034479/rsrc/css/application/pholio/pholio-edit.css',
'type' => 'css',
'requires' =>
array(
@ -4319,7 +4312,7 @@ celerity_register_resource_map(array(
'uri' => '/res/pkg/dd27a69b/differential.pkg.css',
'type' => 'css',
),
'bb59a901' =>
'48040be9' =>
array(
'name' => 'differential.pkg.js',
'symbols' =>
@ -4335,17 +4328,16 @@ celerity_register_resource_map(array(
8 => 'javelin-behavior-differential-comment-jump',
9 => 'javelin-behavior-differential-add-reviewers-and-ccs',
10 => 'javelin-behavior-differential-keyboard-navigation',
11 => 'javelin-behavior-aphront-drag-and-drop',
12 => 'javelin-behavior-aphront-drag-and-drop-textarea',
13 => 'javelin-behavior-phabricator-object-selector',
14 => 'javelin-behavior-repository-crossreference',
15 => 'javelin-behavior-load-blame',
16 => 'differential-inline-comment-editor',
17 => 'javelin-behavior-differential-dropdown-menus',
18 => 'javelin-behavior-differential-toggle-files',
19 => 'javelin-behavior-differential-user-select',
11 => 'javelin-behavior-aphront-drag-and-drop-textarea',
12 => 'javelin-behavior-phabricator-object-selector',
13 => 'javelin-behavior-repository-crossreference',
14 => 'javelin-behavior-load-blame',
15 => 'differential-inline-comment-editor',
16 => 'javelin-behavior-differential-dropdown-menus',
17 => 'javelin-behavior-differential-toggle-files',
18 => 'javelin-behavior-differential-user-select',
),
'uri' => '/res/pkg/bb59a901/differential.pkg.js',
'uri' => '/res/pkg/48040be9/differential.pkg.js',
'type' => 'js',
),
'c8ce2d88' =>
@ -4400,17 +4392,16 @@ celerity_register_resource_map(array(
'uri' => '/res/pkg/a9f14d76/javelin.pkg.js',
'type' => 'js',
),
'adc3c36d' =>
'06bacb9a' =>
array(
'name' => 'maniphest.pkg.css',
'symbols' =>
array(
0 => 'maniphest-task-summary-css',
1 => 'maniphest-transaction-detail-css',
2 => 'aphront-attached-file-view-css',
3 => 'phabricator-project-tag-css',
2 => 'phabricator-project-tag-css',
),
'uri' => '/res/pkg/adc3c36d/maniphest.pkg.css',
'uri' => '/res/pkg/06bacb9a/maniphest.pkg.css',
'type' => 'css',
),
'98f64f07' =>
@ -4430,7 +4421,6 @@ celerity_register_resource_map(array(
),
'reverse' =>
array(
'aphront-attached-file-view-css' => 'adc3c36d',
'aphront-dialog-view-css' => 'f69c023f',
'aphront-error-view-css' => 'f69c023f',
'aphront-form-view-css' => 'f69c023f',
@ -4443,7 +4433,7 @@ celerity_register_resource_map(array(
'aphront-typeahead-control-css' => 'f69c023f',
'differential-changeset-view-css' => 'dd27a69b',
'differential-core-view-css' => 'dd27a69b',
'differential-inline-comment-editor' => 'bb59a901',
'differential-inline-comment-editor' => '48040be9',
'differential-local-commits-view-css' => 'dd27a69b',
'differential-results-table-css' => 'dd27a69b',
'differential-revision-add-comment-css' => 'dd27a69b',
@ -4461,24 +4451,23 @@ celerity_register_resource_map(array(
'javelin-behavior-aphlict-dropdown' => '75ccea43',
'javelin-behavior-aphlict-listen' => '75ccea43',
'javelin-behavior-aphront-basic-tokenizer' => '75ccea43',
'javelin-behavior-aphront-drag-and-drop' => 'bb59a901',
'javelin-behavior-aphront-drag-and-drop-textarea' => 'bb59a901',
'javelin-behavior-aphront-drag-and-drop-textarea' => '48040be9',
'javelin-behavior-aphront-form-disable-on-submit' => '75ccea43',
'javelin-behavior-audit-preview' => '96909266',
'javelin-behavior-dark-console' => '4ccfeb47',
'javelin-behavior-device' => '75ccea43',
'javelin-behavior-differential-accept-with-errors' => 'bb59a901',
'javelin-behavior-differential-add-reviewers-and-ccs' => 'bb59a901',
'javelin-behavior-differential-comment-jump' => 'bb59a901',
'javelin-behavior-differential-diff-radios' => 'bb59a901',
'javelin-behavior-differential-dropdown-menus' => 'bb59a901',
'javelin-behavior-differential-edit-inline-comments' => 'bb59a901',
'javelin-behavior-differential-feedback-preview' => 'bb59a901',
'javelin-behavior-differential-keyboard-navigation' => 'bb59a901',
'javelin-behavior-differential-populate' => 'bb59a901',
'javelin-behavior-differential-show-more' => 'bb59a901',
'javelin-behavior-differential-toggle-files' => 'bb59a901',
'javelin-behavior-differential-user-select' => 'bb59a901',
'javelin-behavior-differential-accept-with-errors' => '48040be9',
'javelin-behavior-differential-add-reviewers-and-ccs' => '48040be9',
'javelin-behavior-differential-comment-jump' => '48040be9',
'javelin-behavior-differential-diff-radios' => '48040be9',
'javelin-behavior-differential-dropdown-menus' => '48040be9',
'javelin-behavior-differential-edit-inline-comments' => '48040be9',
'javelin-behavior-differential-feedback-preview' => '48040be9',
'javelin-behavior-differential-keyboard-navigation' => '48040be9',
'javelin-behavior-differential-populate' => '48040be9',
'javelin-behavior-differential-show-more' => '48040be9',
'javelin-behavior-differential-toggle-files' => '48040be9',
'javelin-behavior-differential-user-select' => '48040be9',
'javelin-behavior-diffusion-commit-graph' => '96909266',
'javelin-behavior-diffusion-pull-lastmodified' => '96909266',
'javelin-behavior-error-log' => '4ccfeb47',
@ -4486,7 +4475,7 @@ celerity_register_resource_map(array(
'javelin-behavior-history-install' => '75ccea43',
'javelin-behavior-konami' => '75ccea43',
'javelin-behavior-lightbox-attachments' => '75ccea43',
'javelin-behavior-load-blame' => 'bb59a901',
'javelin-behavior-load-blame' => '48040be9',
'javelin-behavior-maniphest-batch-selector' => '98f64f07',
'javelin-behavior-maniphest-subpriority-editor' => '98f64f07',
'javelin-behavior-maniphest-transaction-controls' => '98f64f07',
@ -4498,7 +4487,7 @@ celerity_register_resource_map(array(
'javelin-behavior-phabricator-hovercards' => '75ccea43',
'javelin-behavior-phabricator-keyboard-shortcuts' => '75ccea43',
'javelin-behavior-phabricator-nav' => '75ccea43',
'javelin-behavior-phabricator-object-selector' => 'bb59a901',
'javelin-behavior-phabricator-object-selector' => '48040be9',
'javelin-behavior-phabricator-oncopy' => '75ccea43',
'javelin-behavior-phabricator-remarkup-assist' => '75ccea43',
'javelin-behavior-phabricator-reveal-content' => '75ccea43',
@ -4506,7 +4495,7 @@ celerity_register_resource_map(array(
'javelin-behavior-phabricator-tooltips' => '75ccea43',
'javelin-behavior-phabricator-watch-anchor' => '75ccea43',
'javelin-behavior-refresh-csrf' => '75ccea43',
'javelin-behavior-repository-crossreference' => 'bb59a901',
'javelin-behavior-repository-crossreference' => '48040be9',
'javelin-behavior-toggle-class' => '75ccea43',
'javelin-behavior-workflow' => '75ccea43',
'javelin-dom' => 'a9f14d76',
@ -4529,15 +4518,15 @@ celerity_register_resource_map(array(
'javelin-vector' => 'a9f14d76',
'javelin-workflow' => 'a9f14d76',
'lightbox-attachment-css' => 'f69c023f',
'maniphest-task-summary-css' => 'adc3c36d',
'maniphest-transaction-detail-css' => 'adc3c36d',
'maniphest-task-summary-css' => '06bacb9a',
'maniphest-transaction-detail-css' => '06bacb9a',
'phabricator-action-list-view-css' => 'f69c023f',
'phabricator-application-launch-view-css' => 'f69c023f',
'phabricator-busy' => '75ccea43',
'phabricator-content-source-view-css' => 'dd27a69b',
'phabricator-core-css' => 'f69c023f',
'phabricator-crumbs-view-css' => 'f69c023f',
'phabricator-drag-and-drop-file-upload' => 'bb59a901',
'phabricator-drag-and-drop-file-upload' => '48040be9',
'phabricator-dropdown-menu' => '75ccea43',
'phabricator-file-upload' => '75ccea43',
'phabricator-filetree-view-css' => 'f69c023f',
@ -4558,10 +4547,10 @@ celerity_register_resource_map(array(
'phabricator-object-selector-css' => 'dd27a69b',
'phabricator-phtize' => '75ccea43',
'phabricator-prefab' => '75ccea43',
'phabricator-project-tag-css' => 'adc3c36d',
'phabricator-project-tag-css' => '06bacb9a',
'phabricator-property-list-view-css' => 'f69c023f',
'phabricator-remarkup-css' => 'f69c023f',
'phabricator-shaped-request' => 'bb59a901',
'phabricator-shaped-request' => '48040be9',
'phabricator-side-menu-view-css' => 'f69c023f',
'phabricator-standard-page-view' => 'f69c023f',
'phabricator-tag-view-css' => 'f69c023f',

View file

@ -15,10 +15,8 @@ phutil_register_library_map(array(
'Aphront403Response' => 'aphront/response/Aphront403Response.php',
'Aphront404Response' => 'aphront/response/Aphront404Response.php',
'AphrontAbstractAttachedFileView' => 'view/control/AphrontAbstractAttachedFileView.php',
'AphrontAbstractFormDragAndDropUploadControl' => 'view/form/control/AphrontAbstractFormDragAndDropUploadControl.php',
'AphrontAjaxResponse' => 'aphront/response/AphrontAjaxResponse.php',
'AphrontApplicationConfiguration' => 'aphront/configuration/AphrontApplicationConfiguration.php',
'AphrontAttachedFileView' => 'view/control/AphrontAttachedFileView.php',
'AphrontBarView' => 'view/widget/bars/AphrontBarView.php',
'AphrontCSRFException' => 'aphront/exception/AphrontCSRFException.php',
'AphrontCalendarEventView' => 'applications/calendar/view/AphrontCalendarEventView.php',
@ -38,7 +36,6 @@ phutil_register_library_map(array(
'AphrontFormCropControl' => 'view/form/control/AphrontFormCropControl.php',
'AphrontFormDateControl' => 'view/form/control/AphrontFormDateControl.php',
'AphrontFormDividerControl' => 'view/form/control/AphrontFormDividerControl.php',
'AphrontFormDragAndDropUploadControl' => 'view/form/control/AphrontFormDragAndDropUploadControl.php',
'AphrontFormFileControl' => 'view/form/control/AphrontFormFileControl.php',
'AphrontFormImageControl' => 'view/form/control/AphrontFormImageControl.php',
'AphrontFormInsetView' => 'view/form/AphrontFormInsetView.php',
@ -1715,9 +1712,8 @@ phutil_register_library_map(array(
'PholioConstants' => 'applications/pholio/constants/PholioConstants.php',
'PholioController' => 'applications/pholio/controller/PholioController.php',
'PholioDAO' => 'applications/pholio/storage/PholioDAO.php',
'PholioDragAndDropUploadControl' => 'applications/pholio/view/PholioDragAndDropUploadControl.php',
'PholioDropUploadController' => 'applications/pholio/controller/PholioDropUploadController.php',
'PholioImage' => 'applications/pholio/storage/PholioImage.php',
'PholioImageUploadController' => 'applications/pholio/controller/PholioImageUploadController.php',
'PholioInlineCommentEditView' => 'applications/pholio/view/PholioInlineCommentEditView.php',
'PholioInlineCommentSaveView' => 'applications/pholio/view/PholioInlineCommentSaveView.php',
'PholioInlineCommentView' => 'applications/pholio/view/PholioInlineCommentView.php',
@ -1972,9 +1968,7 @@ phutil_register_library_map(array(
'Aphront403Response' => 'AphrontHTMLResponse',
'Aphront404Response' => 'AphrontHTMLResponse',
'AphrontAbstractAttachedFileView' => 'AphrontView',
'AphrontAbstractFormDragAndDropUploadControl' => 'AphrontFormControl',
'AphrontAjaxResponse' => 'AphrontResponse',
'AphrontAttachedFileView' => 'AphrontAbstractAttachedFileView',
'AphrontBarView' => 'AphrontView',
'AphrontCSRFException' => 'AphrontException',
'AphrontCalendarEventView' => 'AphrontView',
@ -1994,7 +1988,6 @@ phutil_register_library_map(array(
'AphrontFormCropControl' => 'AphrontFormControl',
'AphrontFormDateControl' => 'AphrontFormControl',
'AphrontFormDividerControl' => 'AphrontFormControl',
'AphrontFormDragAndDropUploadControl' => 'AphrontAbstractFormDragAndDropUploadControl',
'AphrontFormFileControl' => 'AphrontFormControl',
'AphrontFormImageControl' => 'AphrontFormControl',
'AphrontFormInsetView' => 'AphrontView',
@ -3705,13 +3698,12 @@ phutil_register_library_map(array(
'PhluxViewController' => 'PhluxController',
'PholioController' => 'PhabricatorController',
'PholioDAO' => 'PhabricatorLiskDAO',
'PholioDragAndDropUploadControl' => 'AphrontAbstractFormDragAndDropUploadControl',
'PholioDropUploadController' => 'PholioController',
'PholioImage' =>
array(
0 => 'PholioDAO',
1 => 'PhabricatorMarkupInterface',
),
'PholioImageUploadController' => 'PholioController',
'PholioInlineCommentEditView' => 'AphrontView',
'PholioInlineCommentSaveView' => 'AphrontView',
'PholioInlineCommentView' => 'AphrontView',
@ -3747,7 +3739,7 @@ phutil_register_library_map(array(
'PholioTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PholioTransactionType' => 'PholioConstants',
'PholioTransactionView' => 'PhabricatorApplicationTransactionView',
'PholioUploadedImageView' => 'AphrontAbstractAttachedFileView',
'PholioUploadedImageView' => 'AphrontView',
'PhortuneAccount' =>
array(
0 => 'PhortuneDAO',

View file

@ -3,20 +3,6 @@
final class PhabricatorFileDropUploadController
extends PhabricatorFileController {
private $viewObject;
public function setViewObject(AphrontAbstractAttachedFileView $view) {
$this->viewObject = $view;
return $this;
}
public function getViewObject() {
if (!$this->viewObject) {
$this->viewObject = new AphrontAttachedFileView();
}
return $this->viewObject;
}
/**
* @phutil-external-symbol class PhabricatorStartup
*/
@ -38,14 +24,10 @@ final class PhabricatorFileDropUploadController
'isExplicitUpload' => true,
));
$view = $this->getViewObject();
$view->setFile($file);
return id(new AphrontAjaxResponse())->setContent(
array(
'id' => $file->getID(),
'phid' => $file->getPHID(),
'html' => $view->render(),
'uri' => $file->getBestURI(),
));
}

View file

@ -57,7 +57,9 @@ final class PhabricatorApplicationPholio extends PhabricatorApplication {
'edit/(?P<id>\d+)/' => 'PholioInlineEditController',
'thumb/(?P<imageid>\d+)/' => 'PholioInlineThumbController'
),
'image/upload/' => 'PholioDropUploadController',
'image/' => array(
'upload/' => 'PholioImageUploadController',
),
),
);
}

View file

@ -1,14 +0,0 @@
<?php
/**
* @group pholio
*/
final class PholioDropUploadController extends PholioController {
public function processRequest() {
return $this->delegateToController(
id(new PhabricatorFileDropUploadController($this->getRequest()))
->setViewObject(new PholioUploadedImageView()));
}
}

View file

@ -0,0 +1,37 @@
<?php
/**
* @group pholio
*/
final class PholioImageUploadController extends PholioController {
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$phid = $request->getStr('filePHID');
$file = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($phid))
->executeOne();
if (!$file) {
return new Aphront404Response();
}
$image = id(new PholioImage())
->attachFile($file)
->setName($file->getName())
->makeEphemeral();
$view = id(new PholioUploadedImageView())
->setUser($viewer)
->setImage($image);
$content = array(
'markup' => $view,
);
return id(new AphrontAjaxResponse())->setContent($content);
}
}

View file

@ -92,6 +92,8 @@ final class PholioMockEditController extends PholioController {
->execute();
$files = mpull($files, null, 'getPHID');
$files = array_select_keys($files, $file_phids);
} else {
$files = array();
}
if (!$files) {
@ -111,8 +113,8 @@ final class PholioMockEditController extends PholioController {
$sequence = 0;
foreach ($files as $file_phid => $file) {
$mock_image = idx($mock_images, $file_phid);
$title = $request->getStr('title_'.$file_phid);
$description = $request->getStr('description_'.$file_phid);
$title = (string)$request->getStr('title_'.$file_phid);
$description = (string)$request->getStr('description_'.$file_phid);
if (!$mock_image) {
// this is an add
$add_image = id(new PholioImage())
@ -195,15 +197,44 @@ final class PholioMockEditController extends PholioController {
$cc_tokens = mpull($handles, 'getFullName', 'getPHID');
$images_controller =
id(new PholioDragAndDropUploadControl($request))
->setUploadURI($this->getApplicationURI('image/upload/'))
->setValue($files)
->setImages($mock_images)
->setName('file_phids')
->setLabel(pht('Images'))
->setActivatedClass('aphront-textarea-drag-and-drop')
->setError($e_images);
$image_elements = array();
foreach ($mock_images as $mock_image) {
$image_elements[] = id(new PholioUploadedImageView())
->setUser($user)
->setImage($mock_image);
}
$list_id = celerity_generate_unique_node_id();
$drop_id = celerity_generate_unique_node_id();
$list_control = phutil_tag(
'div',
array(
'id' => $list_id,
'class' => 'pholio-edit-list',
),
$image_elements);
$drop_control = phutil_tag(
'div',
array(
'id' => $drop_id,
'class' => 'pholio-edit-drop',
),
'Drag and drop images here to add them to the mock.');
Javelin::initBehavior(
'pholio-mock-edit',
array(
'listID' => $list_id,
'dropID' => $drop_id,
'uploadURI' => '/file/dropupload/',
'renderURI' => $this->getApplicationURI('image/upload/'),
'pht' => array(
'uploading' => pht('Uploading Image...'),
'uploaded' => pht('Upload Complete...'),
),
));
require_celerity_resource('pholio-edit-css');
$form = id(new AphrontFormView())
@ -235,7 +266,13 @@ final class PholioMockEditController extends PholioController {
->setPolicyObject($mock)
->setPolicies($policies)
->setName('can_view'))
->appendChild($images_controller)
->appendChild(
id(new AphrontFormMarkupControl())
->setValue($list_control))
->appendChild(
id(new AphrontFormMarkupControl())
->setValue($drop_control)
->setError($e_images))
->appendChild($submit);
$crumbs = $this->buildApplicationCrumbs($this->buildSideNav());

View file

@ -1,25 +0,0 @@
<?php
/**
* @group pholio
*/
final class PholioDragAndDropUploadControl
extends AphrontAbstractFormDragAndDropUploadControl {
private $images;
public function setImages(array $images) {
assert_instances_of($images, 'PholioImage');
$this->images = $images;
return $this;
}
public function getImages() {
return $this->images;
}
protected function getFileView() {
return id(new PholioUploadedImageView())
->setImages($this->getImages());
}
}

View file

@ -3,29 +3,21 @@
/**
* @group pholio
*/
final class PholioUploadedImageView extends AphrontAbstractAttachedFileView {
final class PholioUploadedImageView extends AphrontView {
private $images = array();
private $image;
public function setImages(array $images) {
assert_instances_of($images, 'PholioImage');
$this->images = $images;
public function setImage(PholioImage $image) {
$this->image = $image;
return $this;
}
public function getImages() {
return $this->images;
}
public function getImage($phid) {
$images = $this->getImages();
return idx($images, $phid, new PholioImage());
}
public function render() {
require_celerity_resource('pholio-edit-css');
$file = $this->getFile();
$image = $this->image;
$file = $image->getFile();
$phid = $file->getPHID();
$image = $this->getImage($phid);
$thumb = phutil_tag(
'img',
@ -35,11 +27,7 @@ final class PholioUploadedImageView extends AphrontAbstractAttachedFileView {
'height' => 210,
));
$file_link = $this->getName();
if (!$image->getName()) {
$image->setName($this->getFile()->getName());
}
$remove = $this->getRemoveElement();
$remove = $this->renderRemoveElement();
$title = id(new AphrontFormTextControl())
->setName('title_'.$phid)
@ -51,25 +39,52 @@ final class PholioUploadedImageView extends AphrontAbstractAttachedFileView {
->setValue($image->getDescription())
->setLabel(pht('Description'));
return hsprintf(
'<div class="pholio-uploaded-image">
<div class="thumb-box">
<div class="title">
<div class="text">%s</div>
<div class="remove">%s</div>
</div>
<div class="thumb">%s</div>
$content = hsprintf(
'<div class="thumb-box">
<div class="title">
<div class="text">%s</div>
<div class="remove">%s</div>
</div>
<div class="image-data">
<div class="title">%s</title>
<div class="description">%s</description>
</div>',
$file_link,
<div class="thumb">%s</div>
</div>
<div class="image-data">
<div class="title">%s</div>
<div class="description">%s</div>
</div>',
$file->getName(),
$remove,
$thumb,
$title,
$description);
$input = phutil_tag(
'input',
array(
'type' => 'hidden',
'name' => 'file_phids[]',
'value' => $phid,
));
return javelin_tag(
'div',
array(
'class' => 'pholio-uploaded-image',
'sigil' => 'pholio-drop-image',
),
array(
$content,
$input,
));
}
private function renderRemoveElement() {
return javelin_tag(
'a',
array(
'class' => 'button grey',
'sigil' => 'pholio-drop-remove',
),
'X');
}
}

View file

@ -1,38 +0,0 @@
<?php
final class AphrontAttachedFileView extends AphrontAbstractAttachedFileView {
public function render() {
require_celerity_resource('aphront-attached-file-view-css');
$file = $this->getFile();
$phid = $file->getPHID();
$thumb = phutil_tag(
'img',
array(
'src' => $file->getThumb60x45URI(),
'width' => 60,
'height' => 45,
));
$name = $this->getName();
$size = number_format($file->getByteSize()).' ' .pht('bytes');
$remove = $this->getRemoveElement();
return hsprintf(
'<table class="aphront-attached-file-view">
<tr>
<td>%s</td>
<th><strong>%s</strong><br />%s</th>
<td class="aphront-attached-file-view-remove">%s</td>
</tr>
</table>',
$thumb,
$name,
$size,
$remove);
}
}

View file

@ -1,73 +0,0 @@
<?php
abstract class AphrontAbstractFormDragAndDropUploadControl
extends AphrontFormControl {
private $activatedClass;
private $uploadURI = '/file/dropupload/';
public function __construct() {
$this->setControlID(celerity_generate_unique_node_id());
$this->setControlStyle('display: none;');
}
protected function getCustomControlClass() {
return 'aphront-form-drag-and-drop-upload';
}
public function setUploadURI($upload_uri) {
$this->uploadURI = $upload_uri;
return $this;
}
public function getUploadURI() {
return $this->uploadURI;
}
public function setActivatedClass($class) {
$this->activatedClass = $class;
return $this;
}
protected function getFileView() {
return new AphrontAttachedFileView();
}
protected function renderInput() {
require_celerity_resource('aphront-attached-file-view-css');
$list_id = celerity_generate_unique_node_id();
$files = $this->getValue();
$value = array();
if ($files) {
foreach ($files as $file) {
$view = $this->getFileView();
$view->setFile($file);
$value[$file->getPHID()] = array(
'phid' => $file->getPHID(),
'html' => $view->render(),
);
}
}
Javelin::initBehavior(
'aphront-drag-and-drop',
array(
'control' => $this->getControlID(),
'name' => $this->getName(),
'value' => nonempty($value, null),
'list' => $list_id,
'uri' => $this->getUploadURI(),
'activatedClass' => $this->activatedClass,
));
return phutil_tag(
'div',
array(
'id' => $list_id,
'class' => 'aphront-form-drag-and-drop-file-list',
),
'');
}
}

View file

@ -1,6 +0,0 @@
<?php
final class AphrontFormDragAndDropUploadControl
extends AphrontAbstractFormDragAndDropUploadControl {
}

View file

@ -1,43 +0,0 @@
/**
* @provides aphront-attached-file-view-css
*/
.aphront-attached-file-view {
border: 1px solid #aaaaaa;
background: #f9f9f9;
width: 100%;
margin: 4px 0;
}
.aphront-attached-file-view td,
.aphront-attached-file-view th {
padding: 4px;
}
.aphront-attached-file-view th {
width: 100%;
font-size: 11px;
}
.aphront-attached-file-view-remove {
vertical-align: middle;
}
.aphront-file-preview-view {
float: left;
margin: 4px 4px 12px;
text-align: center;
font-size: 11px;
color: #333333;
overflow: hidden;
width: 166px;
white-space: nowrap;
}
.aphront-file-preview-thumb {
padding: 2px;
border: 1px solid #000000;
background: #ffffff;
margin-bottom: 2px;
width: 160px;
}

View file

@ -3,8 +3,8 @@
*/
.pholio-uploaded-image {
float: left;
margin: 0px 0px 12px 0px;
margin: 0 0 12px 0;
overflow: hidden;
}
.pholio-uploaded-image .thumb-box {
@ -13,6 +13,7 @@
min-width: 280px;
width: 48%;
float: left;
text-align: center;
}
.pholio-uploaded-image .image-data {
@ -30,12 +31,15 @@
}
.pholio-uploaded-image .thumb-box .thumb {
float: left;
background: white;
padding: 12px 0px 0px 0px;
width: 100%;
}
.pholio-uploaded-image .thumb-box .thumb img {
margin: 0 auto;
}
.pholio-uploaded-image .thumb-box .title .text {
width: 220px;
float: left;
@ -79,3 +83,25 @@
padding: 20px;
clear: both;
}
.pholio-edit-drop {
border-width: 1px;
border-style: dashed;
border-color: #999999;
text-align: center;
padding: 16px;
color: #666666;
}
.pholio-edit-drop.pholio-drop-active {
border-color: {$green};
background-color: {$lightgreen};
}
.pholio-drop-uploading {
padding: 24px;
text-align: center;
border: 1px solid #bbbbbb;
background: #fcfcfc;
color: #666666;
}

View file

@ -0,0 +1,71 @@
/**
* @provides javelin-behavior-pholio-mock-edit
* @requires javelin-behavior
* javelin-stratcom
* javelin-dom
* javelin-workflow
* phabricator-phtize
* phabricator-drag-and-drop-file-upload
*/
JX.behavior('pholio-mock-edit', function(config) {
var pht = JX.phtize(config.pht);
var nodes = {
list: JX.$(config.listID),
drop: JX.$(config.dropID)
};
var uploading = [];
var drop = new JX.PhabricatorDragAndDropFileUpload(nodes.drop)
.setURI(config.uploadURI);
drop.listen('didBeginDrag', function(e) {
JX.DOM.alterClass(nodes.drop, 'pholio-drop-active', true);
});
drop.listen('didEndDrag', function(e) {
JX.DOM.alterClass(nodes.drop, 'pholio-drop-active', false);
});
drop.listen('willUpload', function(file) {
var node = JX.$N(
'div',
{className: 'pholio-drop-uploading'},
pht('uploading'));
uploading.push({node: node, file: file});
nodes.list.appendChild(node);
});
drop.listen('didUpload', function(file) {
var node;
for (var ii = 0; ii < uploading.length; ii++) {
if (uploading[ii].file === file) {
node = uploading[ii].node;
uploading.splice(ii, 1);
break;
}
}
JX.DOM.setContent(node, pht('uploaded'));
new JX.Workflow(config.renderURI, {filePHID: file.getPHID()})
.setHandler(function(response) {
JX.DOM.replace(node, JX.$H(response.markup));
})
.start();
});
drop.start();
/* -( Deleting Images )---------------------------------------------------- */
// TODO: It would be nice to replace this with an "image will be removed,
// click to undo" kind of thing.
JX.Stratcom.listen('click', 'pholio-drop-remove', function(e) {
e.kill();
JX.DOM.remove(e.getNode('pholio-drop-image'));
});
});

View file

@ -1,112 +0,0 @@
/**
* @provides javelin-behavior-aphront-drag-and-drop
* @requires javelin-behavior
* javelin-dom
* phabricator-file-upload
* phabricator-drag-and-drop-file-upload
*/
JX.behavior('aphront-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;
}
// Show the control, since we have browser support.
JX.$(config.control).style.display = '';
var files = {};
if (config.value) {
for (var k in config.value) {
var file = config.value[k];
files[k] = new JX.PhabricatorFileUpload()
.setPHID(file.phid)
.setMarkup(file.html);
}
}
var pending = 0;
var list = JX.$(config.list);
var drop = new JX.PhabricatorDragAndDropFileUpload(JX.$(config.list))
.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();
});
drop.listen('didUpload', function(f) {
files[f.getPHID()] = f;
// This redraws "Upload complete!"
pending--;
redraw(true);
// This redraws the instructions and clears "Upload complete!"
setTimeout(redraw, 1000);
});
drop.start();
redraw();
JX.DOM.listen(
list,
'click',
'aphront-attached-file-view-remove',
function(e) {
e.kill();
delete files[e.getTarget().getAttribute('ref')];
redraw();
});
function redraw(completed) {
var items = [];
for (var k in files) {
var file = files[k];
items.push(JX.$N('div', {}, JX.$H(file.getMarkup())));
items.push(JX.$N(
'input',
{
type: "hidden",
name: config.name + "[" + file.getPHID() + "]",
value: file.getPHID()
}));
}
var status;
var extra = '';
if (!pending) {
if (completed) {
status = JX.$H('<strong>Upload complete!</strong>');
} else {
arrow = String.fromCharCode(0x21EA);
status = JX.$H(
arrow + ' <strong>Drag and Drop</strong> files here to upload them.');
extra = ' drag-and-drop-file-target';
}
} else {
status = JX.$H(
'Uploading <strong>' + parseInt(pending, 10) + '</strong> files...');
}
status = JX.$N(
'div',
{className: 'drag-and-drop-instructions' + extra},
status);
items.push(status);
JX.DOM.setContent(list, items);
}
});