1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 16:52:41 +01:00

Add JS support for replacing Pholio mocks 1:1

Summary:
Ref T3572. Needs some CSS tweaks, but this lets you drag an image on top of another image to replace it. There's no server-side or transaction support (and I'm not planning to build that), I just wanted to clear the way on the JS side.

You'll get an additional array posted called `replaces`. Keys are old file PHIDs; values are new file PHIDs.

Note that a key may not exist yet (if a user adds an image, and then also replaces that same image). In this case, the server should just treat it as an add.

Test Plan: Dragged images on top of other images.

Reviewers: btrahan, chad

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T3572

Differential Revision: https://secure.phabricator.com/D6499
This commit is contained in:
epriestley 2013-07-19 14:07:22 -07:00
parent 83c29da594
commit 87871b3588
6 changed files with 166 additions and 47 deletions

View file

@ -2234,7 +2234,7 @@ celerity_register_resource_map(array(
), ),
'javelin-behavior-pholio-mock-edit' => 'javelin-behavior-pholio-mock-edit' =>
array( 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', 'type' => 'js',
'requires' => 'requires' =>
array( array(
@ -3744,7 +3744,7 @@ celerity_register_resource_map(array(
), ),
'pholio-edit-css' => 'pholio-edit-css' =>
array( array(
'uri' => '/res/89db9291/rsrc/css/application/pholio/pholio-edit.css', 'uri' => '/res/01a56a3b/rsrc/css/application/pholio/pholio-edit.css',
'type' => 'css', 'type' => 'css',
'requires' => 'requires' =>
array( array(

View file

@ -10,6 +10,10 @@ final class PholioImageUploadController extends PholioController {
$viewer = $request->getUser(); $viewer = $request->getUser();
$phid = $request->getStr('filePHID'); $phid = $request->getStr('filePHID');
$replaces_phid = $request->getStr('replacesPHID');
$title = $request->getStr('title');
$description = $request->getStr('description');
$file = id(new PhabricatorFileQuery()) $file = id(new PhabricatorFileQuery())
->setViewer($viewer) ->setViewer($viewer)
->withPHIDs(array($phid)) ->withPHIDs(array($phid))
@ -18,14 +22,20 @@ final class PholioImageUploadController extends PholioController {
return new Aphront404Response(); return new Aphront404Response();
} }
if (!strlen($title)) {
$title = $file->getName();
}
$image = id(new PholioImage()) $image = id(new PholioImage())
->attachFile($file) ->attachFile($file)
->setName($file->getName()) ->setName($title)
->setDescription($description)
->makeEphemeral(); ->makeEphemeral();
$view = id(new PholioUploadedImageView()) $view = id(new PholioUploadedImageView())
->setUser($viewer) ->setUser($viewer)
->setImage($image); ->setImage($image)
->setReplacesPHID($replaces_phid);
$content = array( $content = array(
'markup' => $view, 'markup' => $view,

View file

@ -6,6 +6,12 @@
final class PholioUploadedImageView extends AphrontView { final class PholioUploadedImageView extends AphrontView {
private $image; private $image;
private $replacesPHID;
public function setReplacesPHID($replaces_phid) {
$this->replacesPHID = $replaces_phid;
return $this;
}
public function setImage(PholioImage $image) { public function setImage(PholioImage $image) {
$this->image = $image; $this->image = $image;
@ -18,6 +24,7 @@ final class PholioUploadedImageView extends AphrontView {
$image = $this->image; $image = $this->image;
$file = $image->getFile(); $file = $image->getFile();
$phid = $file->getPHID(); $phid = $file->getPHID();
$replaces_phid = $this->replacesPHID;
$thumb = phutil_tag( $thumb = phutil_tag(
'img', 'img',
@ -32,13 +39,23 @@ final class PholioUploadedImageView extends AphrontView {
$title = id(new AphrontFormTextControl()) $title = id(new AphrontFormTextControl())
->setName('title_'.$phid) ->setName('title_'.$phid)
->setValue($image->getName()) ->setValue($image->getName())
->setSigil('image-title')
->setLabel(pht('Title')); ->setLabel(pht('Title'));
$description = id(new AphrontFormTextAreaControl()) $description = id(new AphrontFormTextAreaControl())
->setName('description_'.$phid) ->setName('description_'.$phid)
->setValue($image->getDescription()) ->setValue($image->getDescription())
->setSigil('image-description')
->setLabel(pht('Description')); ->setLabel(pht('Description'));
$thumb_frame = javelin_tag(
'div',
array(
'class' => 'pholio-thumb-frame',
'sigil' => 'pholio-thumb-frame',
),
$thumb);
$content = hsprintf( $content = hsprintf(
'<div class="thumb-box"> '<div class="thumb-box">
<div class="title"> <div class="title">
@ -53,7 +70,7 @@ final class PholioUploadedImageView extends AphrontView {
</div>', </div>',
$file->getName(), $file->getName(),
$remove, $remove,
$thumb, $thumb_frame,
$title, $title,
$description); $description);
@ -65,15 +82,28 @@ final class PholioUploadedImageView extends AphrontView {
'value' => $phid, 'value' => $phid,
)); ));
$replaces_input = phutil_tag(
'input',
array(
'type' => 'hidden',
'name' => 'replaces['.$replaces_phid.']',
'value' => $phid,
));
return javelin_tag( return javelin_tag(
'div', 'div',
array( array(
'class' => 'pholio-uploaded-image', 'class' => 'pholio-uploaded-image',
'sigil' => 'pholio-drop-image', 'sigil' => 'pholio-drop-image',
'meta' => array(
'filePHID' => $file->getPHID(),
'replacesPHID' => $replaces_phid,
),
), ),
array( array(
$content, $content,
$input, $input,
$replaces_input,
)); ));
} }

View file

@ -13,6 +13,16 @@ class AphrontFormTextAreaControl extends AphrontFormControl {
private $readOnly; private $readOnly;
private $customClass; private $customClass;
private $placeHolder; private $placeHolder;
private $sigil;
public function setSigil($sigil) {
$this->sigil = $sigil;
return $this;
}
public function getSigil() {
return $this->sigil;
}
public function setPlaceHolder($place_holder) { public function setPlaceHolder($place_holder) {
$this->placeHolder = $place_holder; $this->placeHolder = $place_holder;
@ -61,7 +71,7 @@ class AphrontFormTextAreaControl extends AphrontFormControl {
$classes[] = $this->customClass; $classes[] = $this->customClass;
$classes = trim(implode(' ', $classes)); $classes = trim(implode(' ', $classes));
return phutil_tag( return javelin_tag(
'textarea', 'textarea',
array( array(
'name' => $this->getName(), 'name' => $this->getName(),
@ -70,6 +80,7 @@ class AphrontFormTextAreaControl extends AphrontFormControl {
'class' => $classes, 'class' => $classes,
'style' => $this->getControlStyle(), 'style' => $this->getControlStyle(),
'id' => $this->getID(), 'id' => $this->getID(),
'sigil' => $this->sigil,
'placeholder' => $this->getPlaceHolder(), 'placeholder' => $this->getPlaceHolder(),
), ),
// NOTE: This needs to be string cast, because if we pass `null` the // NOTE: This needs to be string cast, because if we pass `null` the

View file

@ -3,6 +3,8 @@
*/ */
.pholio-uploaded-image { .pholio-uploaded-image {
padding: 4px;
border: 1px solid transparent;
margin: 0 0 12px 0; margin: 0 0 12px 0;
overflow: hidden; overflow: hidden;
} }
@ -30,13 +32,13 @@
border-bottom: 1px solid #D5D9DF; border-bottom: 1px solid #D5D9DF;
} }
.pholio-uploaded-image .thumb-box .thumb { .pholio-thumb-frame {
background: white; background: #ffffff;
padding: 12px 0px 0px 0px; padding: 12px 0px 0px 0px;
width: 100%; width: 100%;
} }
.pholio-uploaded-image .thumb-box .thumb img { .pholio-uploaded-image .thumb-box .pholio-thumb-frame img {
margin: 0 auto; margin: 0 auto;
} }
@ -93,7 +95,15 @@
color: #666666; color: #666666;
} }
.pholio-uploaded-image.pholio-drop-active,
.pholio-edit-drop.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}; border-color: {$green};
background-color: {$lightgreen}; background-color: {$lightgreen};
} }

View file

@ -17,44 +17,6 @@ JX.behavior('pholio-mock-edit', function(config) {
var uploading = []; 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 )---------------------------------------------------- */ /* -( 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 )---------------------------------------------------------- */ /* -( Rendering )---------------------------------------------------------- */
@ -100,4 +153,9 @@ JX.behavior('pholio-mock-edit', function(config) {
}; };
/* -( Init )--------------------------------------------------------------- */
build_add_control(nodes.drop);
build_list_controls(nodes.list);
}); });