diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php
index d6f118f30a..562ac01d7a 100644
--- a/src/__celerity_resource_map__.php
+++ b/src/__celerity_resource_map__.php
@@ -2234,7 +2234,7 @@ celerity_register_resource_map(array(
),
'javelin-behavior-pholio-mock-edit' =>
array(
- 'uri' => '/res/ad171300/rsrc/js/application/pholio/behavior-pholio-mock-edit.js',
+ 'uri' => '/res/e537a994/rsrc/js/application/pholio/behavior-pholio-mock-edit.js',
'type' => 'js',
'requires' =>
array(
@@ -3744,7 +3744,7 @@ celerity_register_resource_map(array(
),
'pholio-edit-css' =>
array(
- 'uri' => '/res/89db9291/rsrc/css/application/pholio/pholio-edit.css',
+ 'uri' => '/res/01a56a3b/rsrc/css/application/pholio/pholio-edit.css',
'type' => 'css',
'requires' =>
array(
diff --git a/src/applications/pholio/controller/PholioImageUploadController.php b/src/applications/pholio/controller/PholioImageUploadController.php
index 67b68478a5..f24c7adb7d 100644
--- a/src/applications/pholio/controller/PholioImageUploadController.php
+++ b/src/applications/pholio/controller/PholioImageUploadController.php
@@ -10,6 +10,10 @@ final class PholioImageUploadController extends PholioController {
$viewer = $request->getUser();
$phid = $request->getStr('filePHID');
+ $replaces_phid = $request->getStr('replacesPHID');
+ $title = $request->getStr('title');
+ $description = $request->getStr('description');
+
$file = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($phid))
@@ -18,14 +22,20 @@ final class PholioImageUploadController extends PholioController {
return new Aphront404Response();
}
+ if (!strlen($title)) {
+ $title = $file->getName();
+ }
+
$image = id(new PholioImage())
->attachFile($file)
- ->setName($file->getName())
+ ->setName($title)
+ ->setDescription($description)
->makeEphemeral();
$view = id(new PholioUploadedImageView())
->setUser($viewer)
- ->setImage($image);
+ ->setImage($image)
+ ->setReplacesPHID($replaces_phid);
$content = array(
'markup' => $view,
diff --git a/src/applications/pholio/view/PholioUploadedImageView.php b/src/applications/pholio/view/PholioUploadedImageView.php
index d5d0746b25..2c2b77ea0b 100644
--- a/src/applications/pholio/view/PholioUploadedImageView.php
+++ b/src/applications/pholio/view/PholioUploadedImageView.php
@@ -6,6 +6,12 @@
final class PholioUploadedImageView extends AphrontView {
private $image;
+ private $replacesPHID;
+
+ public function setReplacesPHID($replaces_phid) {
+ $this->replacesPHID = $replaces_phid;
+ return $this;
+ }
public function setImage(PholioImage $image) {
$this->image = $image;
@@ -18,6 +24,7 @@ final class PholioUploadedImageView extends AphrontView {
$image = $this->image;
$file = $image->getFile();
$phid = $file->getPHID();
+ $replaces_phid = $this->replacesPHID;
$thumb = phutil_tag(
'img',
@@ -32,13 +39,23 @@ final class PholioUploadedImageView extends AphrontView {
$title = id(new AphrontFormTextControl())
->setName('title_'.$phid)
->setValue($image->getName())
+ ->setSigil('image-title')
->setLabel(pht('Title'));
$description = id(new AphrontFormTextAreaControl())
->setName('description_'.$phid)
->setValue($image->getDescription())
+ ->setSigil('image-description')
->setLabel(pht('Description'));
+ $thumb_frame = javelin_tag(
+ 'div',
+ array(
+ 'class' => 'pholio-thumb-frame',
+ 'sigil' => 'pholio-thumb-frame',
+ ),
+ $thumb);
+
$content = hsprintf(
'
@@ -53,7 +70,7 @@ final class PholioUploadedImageView extends AphrontView {
',
$file->getName(),
$remove,
- $thumb,
+ $thumb_frame,
$title,
$description);
@@ -65,15 +82,28 @@ final class PholioUploadedImageView extends AphrontView {
'value' => $phid,
));
+ $replaces_input = phutil_tag(
+ 'input',
+ array(
+ 'type' => 'hidden',
+ 'name' => 'replaces['.$replaces_phid.']',
+ 'value' => $phid,
+ ));
+
return javelin_tag(
'div',
array(
'class' => 'pholio-uploaded-image',
'sigil' => 'pholio-drop-image',
+ 'meta' => array(
+ 'filePHID' => $file->getPHID(),
+ 'replacesPHID' => $replaces_phid,
+ ),
),
array(
$content,
$input,
+ $replaces_input,
));
}
diff --git a/src/view/form/control/AphrontFormTextAreaControl.php b/src/view/form/control/AphrontFormTextAreaControl.php
index bd36122ee9..9087a7e24b 100644
--- a/src/view/form/control/AphrontFormTextAreaControl.php
+++ b/src/view/form/control/AphrontFormTextAreaControl.php
@@ -13,6 +13,16 @@ class AphrontFormTextAreaControl extends AphrontFormControl {
private $readOnly;
private $customClass;
private $placeHolder;
+ private $sigil;
+
+ public function setSigil($sigil) {
+ $this->sigil = $sigil;
+ return $this;
+ }
+
+ public function getSigil() {
+ return $this->sigil;
+ }
public function setPlaceHolder($place_holder) {
$this->placeHolder = $place_holder;
@@ -61,7 +71,7 @@ class AphrontFormTextAreaControl extends AphrontFormControl {
$classes[] = $this->customClass;
$classes = trim(implode(' ', $classes));
- return phutil_tag(
+ return javelin_tag(
'textarea',
array(
'name' => $this->getName(),
@@ -70,6 +80,7 @@ class AphrontFormTextAreaControl extends AphrontFormControl {
'class' => $classes,
'style' => $this->getControlStyle(),
'id' => $this->getID(),
+ 'sigil' => $this->sigil,
'placeholder' => $this->getPlaceHolder(),
),
// NOTE: This needs to be string cast, because if we pass `null` the
diff --git a/webroot/rsrc/css/application/pholio/pholio-edit.css b/webroot/rsrc/css/application/pholio/pholio-edit.css
index 3d4c15f779..28cab33343 100644
--- a/webroot/rsrc/css/application/pholio/pholio-edit.css
+++ b/webroot/rsrc/css/application/pholio/pholio-edit.css
@@ -3,6 +3,8 @@
*/
.pholio-uploaded-image {
+ padding: 4px;
+ border: 1px solid transparent;
margin: 0 0 12px 0;
overflow: hidden;
}
@@ -30,13 +32,13 @@
border-bottom: 1px solid #D5D9DF;
}
-.pholio-uploaded-image .thumb-box .thumb {
- background: white;
+.pholio-thumb-frame {
+ background: #ffffff;
padding: 12px 0px 0px 0px;
width: 100%;
}
-.pholio-uploaded-image .thumb-box .thumb img {
+.pholio-uploaded-image .thumb-box .pholio-thumb-frame img {
margin: 0 auto;
}
@@ -93,7 +95,15 @@
color: #666666;
}
+.pholio-uploaded-image.pholio-drop-active,
.pholio-edit-drop.pholio-drop-active {
+ border-style: solid;
+ border-color: {$green};
+ background-color: {$lightgreen};
+}
+
+.pholio-replacing {
+ opacity: 0.5;
border-color: {$green};
background-color: {$lightgreen};
}
diff --git a/webroot/rsrc/js/application/pholio/behavior-pholio-mock-edit.js b/webroot/rsrc/js/application/pholio/behavior-pholio-mock-edit.js
index d6213be13c..c4cb69c050 100644
--- a/webroot/rsrc/js/application/pholio/behavior-pholio-mock-edit.js
+++ b/webroot/rsrc/js/application/pholio/behavior-pholio-mock-edit.js
@@ -17,44 +17,6 @@ JX.behavior('pholio-mock-edit', function(config) {
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 = render_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 )---------------------------------------------------- */
@@ -77,6 +39,97 @@ JX.behavior('pholio-mock-edit', function(config) {
});
+/* -( Build )-------------------------------------------------------------- */
+
+
+ var build_drop_upload = function(node) {
+ var drop = new JX.PhabricatorDragAndDropFileUpload(node)
+ .setURI(config.uploadURI);
+
+ drop.listen('didBeginDrag', function(e) {
+ JX.DOM.alterClass(node, 'pholio-drop-active', true);
+ });
+
+ drop.listen('didEndDrag', function(e) {
+ JX.DOM.alterClass(node, 'pholio-drop-active', false);
+ });
+
+ return drop;
+ };
+
+ var build_add_control = function(add_node) {
+ var drop = build_drop_upload(add_node);
+
+ drop.listen('willUpload', function(file) {
+ var node = render_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) {
+ var new_node = JX.$H(response.markup).getFragment().firstChild;
+ build_update_control(new_node);
+
+ JX.DOM.replace(node, new_node);
+ })
+ .start();
+ });
+
+ drop.start();
+ };
+
+ var build_list_controls = function(list_node) {
+ var nodes = JX.DOM.scry(list_node, 'div', 'pholio-drop-image');
+ for (var ii = 0; ii < nodes.length; ii++) {
+ build_update_control(nodes[ii]);
+ }
+ };
+
+ var build_update_control = function(node) {
+ var drop = build_drop_upload(node);
+
+ drop.listen('willUpload', function(file) {
+ JX.DOM.alterClass(node, 'pholio-replacing', true);
+ });
+
+ drop.listen('didUpload', function(file) {
+ var node_data = JX.Stratcom.getData(node);
+
+ var data = {
+ filePHID: file.getPHID(),
+ replacesPHID: node_data.replacesPHID || node_data.filePHID || null,
+ title: JX.DOM.find(node, 'input', 'image-title').value,
+ description: JX.DOM.find(node, 'textarea', 'image-description').value
+ };
+
+ new JX.Workflow(config.renderURI, data)
+ .setHandler(function(response) {
+ var new_node = JX.$H(response.markup).getFragment().firstChild;
+ build_update_control(new_node);
+
+ JX.DOM.replace(node, new_node);
+ JX.DOM.alterClass(node, 'pholio-replacing', false);
+ })
+ .start();
+ });
+
+ drop.start();
+ };
+
+
/* -( Rendering )---------------------------------------------------------- */
@@ -100,4 +153,9 @@ JX.behavior('pholio-mock-edit', function(config) {
};
+/* -( Init )--------------------------------------------------------------- */
+
+ build_add_control(nodes.drop);
+ build_list_controls(nodes.list);
+
});