1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-18 18:51:12 +01:00

Show editor

Summary: Show editor when user clicks edit button for inline comment.

Test Plan: Verified that editor is shown.

Reviewers: epriestley

CC: aran, Korvin

Maniphest Tasks: T2446

Differential Revision: https://secure.phabricator.com/D5030
This commit is contained in:
Lauri-Henrik Jalonen 2013-02-22 06:39:08 -08:00 committed by epriestley
parent 83e4e1ce7f
commit b180c3a009
15 changed files with 673 additions and 82 deletions

View file

@ -1873,7 +1873,7 @@ celerity_register_resource_map(array(
),
'javelin-behavior-pholio-mock-view' =>
array(
'uri' => '/res/18129e67/rsrc/js/application/pholio/behavior-pholio-mock-view.js',
'uri' => '/res/84215004/rsrc/js/application/pholio/behavior-pholio-mock-view.js',
'type' => 'js',
'requires' =>
array(
@ -3224,6 +3224,15 @@ celerity_register_resource_map(array(
),
'disk' => '/rsrc/css/application/pholio/pholio.css',
),
'pholio-inline-comments-css' =>
array(
'uri' => '/res/2b32b3b6/rsrc/css/application/pholio/pholio-inline-comments.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/pholio/pholio-inline-comments.css',
),
'phriction-document-css' =>
array(
'uri' => '/res/8d09bd7f/rsrc/css/application/phriction/phriction-document-css.css',

View file

@ -1446,9 +1446,12 @@ phutil_register_library_map(array(
'PholioController' => 'applications/pholio/controller/PholioController.php',
'PholioDAO' => 'applications/pholio/storage/PholioDAO.php',
'PholioImage' => 'applications/pholio/storage/PholioImage.php',
'PholioInlineCommentEditView' => 'applications/pholio/view/PholioInlineCommentEditView.php',
'PholioInlineCommentSaveView' => 'applications/pholio/view/PholioInlineCommentSaveView.php',
'PholioInlineCommentView' => 'applications/pholio/view/PholioInlineCommentView.php',
'PholioInlineController' => 'applications/pholio/controller/PholioInlineController.php',
'PholioInlineDeleteController' => 'applications/pholio/controller/PholioInlineDeleteController.php',
'PholioInlineEditController' => 'applications/pholio/controller/PholioInlineEditController.php',
'PholioInlineSaveController' => 'applications/pholio/controller/PholioInlineSaveController.php',
'PholioInlineViewController' => 'applications/pholio/controller/PholioInlineViewController.php',
'PholioMock' => 'applications/pholio/storage/PholioMock.php',
@ -2920,9 +2923,12 @@ phutil_register_library_map(array(
0 => 'PholioDAO',
1 => 'PhabricatorMarkupInterface',
),
'PholioInlineCommentEditView' => 'AphrontView',
'PholioInlineCommentSaveView' => 'AphrontView',
'PholioInlineCommentView' => 'AphrontView',
'PholioInlineController' => 'PholioController',
'PholioInlineDeleteController' => 'PholioController',
'PholioInlineEditController' => 'PholioController',
'PholioInlineSaveController' => 'PholioController',
'PholioInlineViewController' => 'PholioController',
'PholioMock' =>

View file

@ -47,7 +47,8 @@ final class PhabricatorApplicationPholio extends PhabricatorApplication {
'(?P<id>\d+)/' => 'PholioInlineController',
'save/' => 'PholioInlineSaveController',
'delete/(?P<id>\d+)/' => 'PholioInlineDeleteController',
'view/(?P<id>\d+)/' => 'PholioInlineViewController'
'view/(?P<id>\d+)/' => 'PholioInlineViewController',
'edit/(?P<id>\d+)/' => 'PholioInlineEditController'
),
),
);

View file

@ -38,6 +38,7 @@ final class PholioInlineController extends PholioController {
}
$inlines[] = array(
'id' => $inline_comment->getID(),
'phid' => $inline_comment->getPHID(),
'transactionphid' => $inline_comment->getTransactionPHID(),
'x' => $inline_comment->getX(),

View file

@ -23,6 +23,8 @@ final class PholioInlineDeleteController extends PholioController {
if ($inline_comment == null) {
return new Aphront404Response();
} else {
$inline_comment->delete();
return id(new AphrontAjaxResponse())
->setContent(array('success' => true));
}

View file

@ -0,0 +1,82 @@
<?php
/**
* @group pholio
*/
final class PholioInlineEditController extends PholioController {
private $id;
private $operation;
public function getOperation() {
return $this->operation;
}
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$this->operation = $request->getBool('op');
$inline_comment = id(new PholioTransactionComment())->loadOneWhere(
'id = %d AND authorphid = %s AND transactionphid IS NULL',
$this->id,
$user->getPHID());
if ($inline_comment == null) {
return new Aphront404Response();
}
switch ($this->getOperation()) {
case 'update':
$new_content = $request->getStr('content');
if (strlen(trim($new_content)) == 0) {
return id(new AphrontAjaxResponse())
->setContent(array('success' => false))
->setError(pht('Empty comment'));
}
$inline_comment->setContent($request->getStr('content'));
$inline_comment->save();
return id(new AphrontAjaxResponse())
->setContent(array('success' => true));
default:
$dialog = new PholioInlineCommentEditView();
$dialog->setInlineComment($inline_comment);
$dialog->setUser($user);
$dialog->setSubmitURI($request->getRequestURI());
$dialog->setTitle(pht('Edit inline comment'));
$dialog->addHiddenInput('id', $this->id);
$dialog->addHiddenInput('op', 'edit');
$dialog->appendChild(
$this->renderTextArea($inline_comment->getContent()));
return id(new AphrontAjaxResponse())->setContent($dialog->render());
}
}
private function renderTextArea($text) {
return javelin_tag(
'textarea',
array(
'class' => 'pholio-inline-comment-dialog-textarea',
'name' => 'text',
),
$text);
}
}

View file

@ -5,6 +5,12 @@
*/
final class PholioInlineSaveController extends PholioController {
private $operation;
public function getOperation() {
return $this->operation;
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
@ -18,46 +24,84 @@ final class PholioInlineSaveController extends PholioController {
return new Aphront404Response();
}
$draft = id(new PholioTransactionComment());
$draft->setImageID($request->getInt('imageID'));
$draft->setX($request->getInt('startX'));
$draft->setY($request->getInt('startY'));
$this->operation = $request->getBool('op');
$draft->setCommentVersion(1);
$draft->setAuthorPHID($user->getPHID());
$draft->setEditPolicy($user->getPHID());
$draft->setViewPolicy(PhabricatorPolicies::POLICY_PUBLIC);
if ($this->getOperation() == 'save') {
$new_content = $request->getStr('comment');
$content_source = PhabricatorContentSource::newForSource(
PhabricatorContentSource::SOURCE_WEB,
array(
'ip' => $request->getRemoteAddr(),
));
if (strlen(trim($new_content)) == 0) {
return id(new AphrontAjaxResponse())
->setContent(array('success' => false));
}
$draft->setContentSource($content_source);
$draft = id(new PholioTransactionComment());
$draft->setImageID($request->getInt('imageID'));
$draft->setX($request->getInt('startX'));
$draft->setY($request->getInt('startY'));
$draft->setWidth($request->getInt('endX') - $request->getInt('startX'));
$draft->setHeight($request->getInt('endY') - $request->getInt('startY'));
$draft->setCommentVersion(1);
$draft->setAuthorPHID($user->getPHID());
$draft->setEditPolicy($user->getPHID());
$draft->setViewPolicy(PhabricatorPolicies::POLICY_PUBLIC);
$draft->setContent($request->getStr('comment'));
$content_source = PhabricatorContentSource::newForSource(
PhabricatorContentSource::SOURCE_WEB,
array(
'ip' => $request->getRemoteAddr(),
));
$draft->save();
$inlineID = $draft->getID();
$draft->setContentSource($content_source);
if ($request->isAjax()) {
$inline_view = id(new PholioInlineCommentView())
->setInlineComment($draft)
->setEditable(true)
->setHandle(
PhabricatorObjectHandleData::loadOneHandle($user->getPHID()));
$draft->setWidth($request->getInt('endX') - $request->getInt('startX'));
$draft->setHeight($request->getInt('endY') - $request->getInt('startY'));
return id(new AphrontAjaxResponse())
->setContent(array('contentHTML' => $inline_view->render()));
$draft->setContent($new_content);
} else {
return id(new AphrontRedirectResponse())->setUri('/M'.$mock->getID());
$draft->save();
if ($request->isAjax()) {
$inline_view = id(new PholioInlineCommentView())
->setInlineComment($draft)
->setEditable(true)
->setHandle(
PhabricatorObjectHandleData::loadOneHandle($user->getPHID()));
return id(new AphrontAjaxResponse())
->setContent(array(
'success' => true,
'phid' => $draft->getPHID(),
'contentHTML' => $inline_view->render()
));
} else {
return id(new AphrontRedirectResponse())->setUri('/M'.$mock->getID());
}
}
else {
$dialog = new PholioInlineCommentSaveView();
$dialog->setUser($user);
$dialog->setSubmitURI($request->getRequestURI());
$dialog->setTitle(pht('Make inline comment'));
$dialog->addHiddenInput('op', 'save');
$dialog->appendChild($this->renderTextArea(''));
return id(new AphrontAjaxResponse())->setContent($dialog->render());
}
}
private function renderTextArea($text) {
return javelin_tag(
'textarea',
array(
'class' => 'pholio-inline-comment-dialog-textarea',
'name' => 'text',
),
$text);
}
}

View file

@ -29,7 +29,11 @@ final class PholioInlineViewController extends PholioController {
}
return id(new AphrontAjaxResponse())->setContent(
array('contentHTML' => $inline_view->render()));
array(
'id' => $inline_comment->getID(),
'phid' => $inline_comment->getPHID(),
'contentHTML' => $inline_view->render()
));
}
}

View file

@ -63,6 +63,7 @@ final class PholioMockViewController extends PholioController {
$properties = $this->buildPropertyView($mock, $engine, $subscribers);
require_celerity_resource('pholio-css');
require_celerity_resource('pholio-inline-comments-css');
$output = new PholioMockImagesView();
$output->setMock($mock);

View file

@ -0,0 +1,144 @@
<?php
/**
* @group pholio
*/
final class PholioInlineCommentEditView extends AphrontView {
private $inputs = array();
private $uri;
private $title;
private $inlineComment;
public function addHiddenInput($key, $value) {
$this->inputs[] = array($key, $value);
return $this;
}
public function setSubmitURI($uri) {
$this->uri = $uri;
return $this;
}
public function setTitle($title) {
$this->title = $title;
return $this;
}
public function setInlineComment($inline_comment) {
$this->inlineComment = $inline_comment;
return $this;
}
public function render() {
if (!$this->uri) {
throw new Exception("Call setSubmitURI() before render()!");
}
if (!$this->user) {
throw new Exception("Call setUser() before render()!");
}
$content = phabricator_form(
$this->user,
array(
'action' => $this->uri,
'method' => 'POST',
'sigil' => 'inline-edit-form',
),
$this->renderSingleView(
array(
$this->renderInputs(),
$this->renderBody(),
)));
return $content;
}
private function renderInputs() {
$out = array();
foreach ($this->inputs as $input) {
list($name, $value) = $input;
$out[] = phutil_tag(
'input',
array(
'type' => 'hidden',
'name' => $name,
'value' => $value,
));
}
return $out;
}
private function renderBody() {
$buttons = array();
$buttons[] = javelin_tag(
'button',
array(
'sigil' => 'inline-edit-submit',
'meta' => array(
'id' => $this->inlineComment->getID(),
'phid' => $this->inlineComment->getPHID()
)
),
pht('Ready'));
$buttons[] = javelin_tag(
'button',
array(
'sigil' => 'inline-edit-cancel',
'meta' => array(
'id' => $this->inlineComment->getID()
),
'class' => 'grey',
),
pht('Cancel'));
$formatting = phutil_tag(
'a',
array(
'href' => PhabricatorEnv::getDoclink(
'article/Remarkup_Reference.html'),
'tabindex' => '-1',
'target' => '_blank',
),
pht('Formatting Reference'));
$title = phutil_tag(
'div',
array(
'class' => 'pholio-inline-comment-dialog-title',
),
$this->title);
$body = phutil_tag(
'div',
array(),
$this->renderChildren());
$edit = phutil_tag(
'edit',
array(
'class' => 'pholio-inline-comment-dialog-buttons',
),
$this->renderSingleView(
array(
$formatting,
$buttons,
phutil_tag('div', array('style' => 'clear: both'), ''),
)));
return javelin_tag(
'div',
array(
'class' => 'pholio-inline-comment-dialog',
),
$this->renderSingleView(
array(
$title,
$body,
$edit,
)));
}
}

View file

@ -0,0 +1,131 @@
<?php
/**
* @group pholio
*/
final class PholioInlineCommentSaveView extends AphrontView {
private $inputs = array();
private $uri;
private $title;
public function addHiddenInput($key, $value) {
$this->inputs[] = array($key, $value);
return $this;
}
public function setSubmitURI($uri) {
$this->uri = $uri;
return $this;
}
public function setTitle($title) {
$this->title = $title;
return $this;
}
public function render() {
if (!$this->uri) {
throw new Exception("Call setSubmitURI() before render()!");
}
if (!$this->user) {
throw new Exception("Call setUser() before render()!");
}
$content = phabricator_form(
$this->user,
array(
'action' => $this->uri,
'method' => 'POST',
'sigil' => 'inline-save-form',
),
$this->renderSingleView(
array(
$this->renderInputs(),
$this->renderBody(),
)));
return $content;
}
private function renderInputs() {
$out = array();
foreach ($this->inputs as $input) {
list($name, $value) = $input;
$out[] = phutil_tag(
'input',
array(
'type' => 'hidden',
'name' => $name,
'value' => $value,
));
}
return $out;
}
private function renderBody() {
$buttons = array();
$buttons[] = javelin_tag(
'button',
array(
'sigil' => 'inline-save-submit',
),
pht('Done'));
$buttons[] = javelin_tag(
'button',
array(
'sigil' => 'inline-save-cancel',
'class' => 'grey',
),
pht('Cancel'));
$formatting = phutil_tag(
'a',
array(
'href' => PhabricatorEnv::getDoclink(
'article/Remarkup_Reference.html'),
'tabindex' => '-1',
'target' => '_blank',
),
pht('Formatting Reference'));
$title = phutil_tag(
'div',
array(
'class' => 'pholio-inline-comment-dialog-title',
),
$this->title);
$body = phutil_tag(
'div',
array(),
$this->renderChildren());
$edit = phutil_tag(
'edit',
array(
'class' => 'pholio-inline-comment-dialog-buttons',
),
$this->renderSingleView(
array(
$formatting,
$buttons,
phutil_tag('div', array('style' => 'clear: both'), ''),
)));
return javelin_tag(
'div',
array(
'class' => 'pholio-new-inline-comment',
'id' => 'pholio-new-inline-comment-dialog'
),
$this->renderSingleView(
array(
$title,
$body,
$edit,
)));
}
}

View file

@ -40,7 +40,8 @@ final class PholioInlineCommentView extends AphrontView {
'href' => '/pholio/inline/edit/'.$this->inlineComment->getID(),
'sigil' => 'inline-edit',
'meta' => array(
'phid' => $this->inlineComment->getPHID()
'phid' => $this->inlineComment->getPHID(),
'id' => $this->inlineComment->getID()
)
),
pht('Edit'));
@ -51,7 +52,8 @@ final class PholioInlineCommentView extends AphrontView {
'href' => '/pholio/inline/delete/'.$this->inlineComment->getID(),
'sigil' => 'inline-delete',
'meta' => array(
'phid' => $this->inlineComment->getPHID()
'phid' => $this->inlineComment->getPHID(),
'id' => $this->inlineComment->getID()
)
),
pht('Delete'));

View file

@ -61,6 +61,7 @@ final class PholioMockImagesView extends AphrontView {
'div',
array(
'class' => 'pholio-mock-image-container',
'id' => 'pholio-mock-image-container'
),
array($main_image_tag, $inline_comments_holder));

View file

@ -0,0 +1,36 @@
/**
* @provides pholio-inline-comments-css
*/
.pholio-inline-comment-dialog-title {
font-weight: bold;
color: #333333;
border-bottom: 1px solid #ccccaa;
padding-bottom: 2px;
margin-bottom: 6px;
}
.pholio-inline-comment-dialog-buttons {
padding: 2px 0px;
}
.pholio-inline-comment-dialog-buttons button {
float: right;
margin-left: 6px;
}
.pholio-inline-comment-dialog {
padding: 8px 18px 8px 12px;
}
.pholio-inline-comment-dialog-textarea {
width: 99%;
height: 12em;
}
.pholio-new-inline-comment {
position: absolute;
border: 1px solid #aa8;
background: #f9f9f1;
z-index: 100;
padding: 8px 18px 8px 12px;
}

View file

@ -9,6 +9,8 @@
*/
JX.behavior('pholio-mock-view', function(config) {
var is_dragging = false;
var is_typing = false;
var wrapper = JX.$('mock-wrapper');
var image;
var imageData;
@ -38,7 +40,6 @@ JX.behavior('pholio-mock-view', function(config) {
load_inline_comments();
});
function draw_rectangle(nodes, current, init) {
for (var ii = 0; ii < nodes.length; ii++) {
var node = nodes[ii];
@ -70,6 +71,12 @@ JX.behavior('pholio-mock-view', function(config) {
return;
}
if (is_typing) {
JX.DOM.remove(JX.$('pholio-new-inline-comment-dialog'));
JX.DOM.remove(selection_fill);
JX.DOM.remove(selection_border);
}
image = JX.$(config.mainID);
imageData = JX.Stratcom.getData(image);
@ -112,37 +119,27 @@ JX.behavior('pholio-mock-view', function(config) {
return;
}
is_dragging = false;
is_typing = true;
endPos = getRealXY(JX.$V(wrapper), JX.$V(e));
comment = window.prompt("Add your comment");
if (comment == null || comment == "") {
JX.DOM.remove(selection_border);
JX.DOM.remove(selection_fill);
return;
}
var create_inline = new JX.Request("/pholio/inline/save/", function(r) {
JX.DOM.appendContent(JX.$('pholio-mock-image-container'), JX.$H(r));
selection_fill.title = comment;
var dialog = JX.$('pholio-new-inline-comment-dialog');
var saveURL = "/pholio/inline/save/";
var wrapperVector = JX.$V(wrapper);
var wrapperDimensions = JX.Vector.getDim(wrapper);
var inlineComment = new JX.Request(saveURL, function(r) {
JX.DOM.appendContent(
JX.$('mock-inline-comments'),
JX.$H(r.contentHTML));
});
JX.$V(
wrapperVector.x + Math.max(startPos.x,endPos.x),
wrapperVector.y + Math.max(startPos.y,endPos.y)
).setPos(dialog);
var commentToAdd = {
mockID: config.mockID,
imageID: imageData['imageID'],
startX: Math.min(startPos.x, endPos.x),
startY: Math.min(startPos.y, endPos.y),
endX: Math.max(startPos.x,endPos.x),
endY: Math.max(startPos.y,endPos.y),
comment: comment};
});
create_inline.addData({mockID: config.mockID});
create_inline.send();
inlineComment.addData(commentToAdd);
inlineComment.send();
});
function load_inline_comments() {
@ -150,8 +147,8 @@ JX.behavior('pholio-mock-view', function(config) {
var comment_holder = JX.$('mock-inline-comments');
JX.DOM.setContent(comment_holder, '');
var inline_comments_url = "/pholio/inline/" + data['imageID'] + "/";
var inline_comments = new JX.Request(inline_comments_url, function(r) {
var inline_comments_uri = "/pholio/inline/" + data['imageID'] + "/";
var inline_comments = new JX.Request(inline_comments_uri, function(r) {
if (r.length > 0) {
for(i=0; i < r.length; i++) {
@ -196,28 +193,6 @@ JX.behavior('pholio-mock-view', function(config) {
}
}
JX.Stratcom.listen(
'click',
'inline-delete',
function(e) {
var data = e.getNodeData('inline-delete');
e.kill();
JX.DOM.hide(
JX.$(data.phid + "_comment"),
JX.$(data.phid + "_fill"),
JX.$(data.phid + "_selection")
);
});
JX.Stratcom.listen(
'click',
'inline-edit',
function(e) {
e.kill();
alert("WIP");
}
);
JX.Stratcom.listen(
'mouseover',
'image_selection',
@ -239,10 +214,162 @@ JX.behavior('pholio-mock-view', function(config) {
JX.DOM.alterClass(inline_comment,
'pholio-mock-inline-comment-highlight', false);
});
});
inline_comments.send();
}
JX.Stratcom.listen(
'click',
'inline-delete',
function(e) {
var data = e.getNodeData('inline-delete');
e.kill();
interrupt_typing();
JX.DOM.hide(
JX.$(data.phid + "_comment"),
JX.$(data.phid + "_fill"),
JX.$(data.phid + "_selection"));
var deleteURI = '/pholio/inline/delete/' + data.id + '/';
var del = new JX.Request(deleteURI, function(r) {
});
del.send();
});
JX.Stratcom.listen(
'click',
'inline-edit',
function(e) {
var data = e.getNodeData('inline-edit');
e.kill();
interrupt_typing();
var editURI = "/pholio/inline/edit/" + data.id + '/';
var edit_dialog = new JX.Request(editURI, function(r) {
var dialog = JX.$N(
'div',
{
className: 'pholio-edit-inline-popup'
},
JX.$H(r));
JX.DOM.setContent(JX.$(data.phid + '_comment'), dialog);
});
edit_dialog.send();
});
JX.Stratcom.listen(
'click',
'inline-edit-cancel',
function(e) {
var data = e.getNodeData('inline-edit-cancel');
e.kill();
load_inline_comment(data.id);
});
JX.Stratcom.listen(
'click',
'inline-edit-submit',
function(e) {
var data = e.getNodeData('inline-edit-submit');
var editURI = "/pholio/inline/edit/" + data.id + '/';
e.kill();
var edit = new JX.Request(editURI, function(r) {
load_inline_comment(data.id);
});
edit.addData({
op: 'update',
content: JX.DOM.find(JX.$(data.phid + '_comment'), 'textarea').value
});
edit.send();
});
JX.Stratcom.listen(
'click',
'inline-save-cancel',
function(e) {
e.kill();
interrupt_typing();
}
);
JX.Stratcom.listen(
'click',
'inline-save-submit',
function(e) {
e.kill();
var new_content = JX.DOM.find(
JX.$('pholio-new-inline-comment-dialog'),
'textarea').value;
if (new_content == null || new_content.length == 0) {
alert("Empty comment")
return;
}
var saveURI = "/pholio/inline/save/";
var inlineComment = new JX.Request(saveURI, function(r) {
if (!r.success) return;
JX.DOM.appendContent(
JX.$('mock-inline-comments'),
JX.$H(r.contentHTML));
JX.Stratcom.addSigil(selection_fill, 'image_selection');
selection_fill.id = r.phid + '_fill';
JX.Stratcom.addData(selection_fill, {phid: r.phid});
selection_border.id = r.phid + '_selection';
JX.DOM.remove(JX.$('pholio-new-inline-comment-dialog'));
is_typing = false;
});
var commentToAdd = {
mockID: config.mockID,
op: 'save',
imageID: imageData['imageID'],
startX: Math.min(startPos.x, endPos.x),
startY: Math.min(startPos.y, endPos.y),
endX: Math.max(startPos.x,endPos.x),
endY: Math.max(startPos.y,endPos.y),
comment: new_content
};
inlineComment.addData(commentToAdd);
inlineComment.send();
}
);
function load_inline_comment(id) {
var viewInlineURI = '/pholio/inline/view/' + id + '/';
var inline_comment = new JX.Request(viewInlineURI, function(r) {
JX.DOM.replace(JX.$(r.phid + '_comment'), JX.$H(r.contentHTML));
});
inline_comment.send();
}
function interrupt_typing() {
if (is_typing == true) {
JX.DOM.remove(selection_fill);
JX.DOM.remove(selection_border);
JX.DOM.remove(JX.$('pholio-new-inline-comment-dialog'));
is_typing = false;
}
}
load_inline_comments();
});