mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 08:52:39 +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:
parent
83c29da594
commit
87871b3588
6 changed files with 166 additions and 47 deletions
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
'<div class="thumb-box">
|
||||
<div class="title">
|
||||
|
@ -53,7 +70,7 @@ final class PholioUploadedImageView extends AphrontView {
|
|||
</div>',
|
||||
$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,
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue