Page MenuHomePhorge

No OneTemporary

diff --git a/src/applications/pholio/view/PholioInlineCommentView.php b/src/applications/pholio/view/PholioInlineCommentView.php
index 65f3626065..eb2707083f 100644
--- a/src/applications/pholio/view/PholioInlineCommentView.php
+++ b/src/applications/pholio/view/PholioInlineCommentView.php
@@ -1,95 +1,99 @@
<?php
final class PholioInlineCommentView extends AphrontView {
private $inlineComment;
private $handle;
private $editable;
public function setInlineComment(PholioTransactionComment $inline_comment) {
if ($inline_comment->getImageID() === null) {
throw new Exception("Comment provided is not inline comment");
}
$this->inlineComment = $inline_comment;
return $this;
}
public function setHandle(PhabricatorObjectHandle $handle) {
$this->handle = $handle;
return $this;
}
public function setEditable($editable) {
$this->editable = $editable;
return $this;
}
public function render() {
if (!$this->inlineComment) {
throw new Exception("Call setInlineComment() before render()!");
}
$actions = null;
if ($this->editable) {
$edit_action = javelin_tag(
'a',
array(
'href' => '/pholio/inline/edit/'.$this->inlineComment->getID(),
'sigil' => 'inline-edit',
'meta' => array(
'phid' => $this->inlineComment->getPHID(),
'id' => $this->inlineComment->getID()
)
),
pht('Edit'));
$delete_action = javelin_tag(
'a',
array(
'href' => '/pholio/inline/delete/'.$this->inlineComment->getID(),
'sigil' => 'inline-delete',
'meta' => array(
'phid' => $this->inlineComment->getPHID(),
'id' => $this->inlineComment->getID()
)
),
pht('Delete'));
$actions = phutil_tag(
'span',
array(
'class' => 'pholio-inline-head-links'
),
array($edit_action, $delete_action));
}
$comment_header = phutil_tag(
'div',
array(
'class' => 'pholio-inline-comment-header'
),
array($this->handle->getName(), $actions));
$comment_body = phutil_tag(
'div',
array(
),
$this->inlineComment->getContent());
$comment_block = javelin_tag(
'div',
array(
'id' => $this->inlineComment->getPHID()."_comment",
- 'class' => 'pholio-inline-comment'
+ 'class' => 'pholio-inline-comment',
+ 'sigil' => 'inline_comment',
+ 'meta' => array(
+ 'phid' => $this->inlineComment->getPHID()
+ )
),
array($comment_header, $comment_body));
return $this->renderSingleView($comment_block);
}
}
diff --git a/src/applications/pholio/view/PholioMockImagesView.php b/src/applications/pholio/view/PholioMockImagesView.php
index 7fe3a2eb09..1764244dd5 100644
--- a/src/applications/pholio/view/PholioMockImagesView.php
+++ b/src/applications/pholio/view/PholioMockImagesView.php
@@ -1,118 +1,119 @@
<?php
final class PholioMockImagesView extends AphrontView {
private $mock;
public function setMock(PholioMock $mock) {
$this->mock = $mock;
return $this;
}
public function render() {
if (!$this->mock) {
throw new Exception("Call setMock() before render()!");
}
$mock = $this->mock;
require_celerity_resource('javelin-behavior-pholio-mock-view');
$images = array();
$panel_id = celerity_generate_unique_node_id();
$viewport_id = celerity_generate_unique_node_id();
foreach ($mock->getImages() as $image) {
$images[] = array(
'id' => $image->getID(),
'fullURI' => $image->getFile()->getBestURI(),
);
}
$config = array(
'mockID' => $mock->getID(),
'panelID' => $panel_id,
'viewportID' => $viewport_id,
'images' => $images,
);
Javelin::initBehavior('pholio-mock-view', $config);
$mockview = '';
$mock_wrapper = phutil_tag(
'div',
array(
'id' => $viewport_id,
'class' => 'pholio-mock-image-viewport'
),
'');
$mock_wrapper = javelin_tag(
'div',
array(
'id' => $panel_id,
'sigil' => 'mock-panel',
'class' => 'pholio-mock-image-panel',
),
$mock_wrapper);
$inline_comments_holder = javelin_tag(
'div',
array(
'id' => 'mock-inline-comments',
'sigil' => 'mock-inline-comments',
'class' => 'pholio-mock-inline-comments'
),
'');
$mockview[] = phutil_tag(
'div',
array(
'class' => 'pholio-mock-image-container',
'id' => 'pholio-mock-image-container'
),
array($mock_wrapper, $inline_comments_holder));
if (count($mock->getImages()) > 1) {
$thumbnails = array();
foreach ($mock->getImages() as $image) {
$thumbfile = $image->getFile();
$dimensions = PhabricatorImageTransformer::getPreviewDimensions(
$thumbfile,
140);
$tag = phutil_tag(
'img',
array(
'width' => $dimensions['sdx'],
'height' => $dimensions['sdy'],
'src' => $thumbfile->getPreview140URI(),
'class' => 'pholio-mock-carousel-thumbnail',
'style' => 'top: '.floor((140 - $dimensions['sdy'] ) / 2).'px',
));
$thumbnails[] = javelin_tag(
'div',
array(
'sigil' => 'mock-thumbnail',
'class' => 'pholio-mock-carousel-thumb-item',
'meta' => array(
'imageID' => $image->getID(),
),
),
$tag);
}
$mockview[] = phutil_tag(
'div',
array(
+ 'id' => 'pholio-mock-carousel',
'class' => 'pholio-mock-carousel',
),
$thumbnails);
}
return $this->renderSingleView($mockview);
}
}
diff --git a/webroot/rsrc/css/application/pholio/pholio.css b/webroot/rsrc/css/application/pholio/pholio.css
index bbda5bdc1a..a742015bd9 100644
--- a/webroot/rsrc/css/application/pholio/pholio.css
+++ b/webroot/rsrc/css/application/pholio/pholio.css
@@ -1,104 +1,104 @@
/**
* @provides pholio-css
*/
.pholio-mock-image-container {
background-color: #282828;
text-align: center;
vertical-align: middle;
position: relative;
}
.pholio-mock-carousel {
background-color: #202020;
text-align: center;
border-top: 1px solid #101010;
}
.pholio-mock-carousel-thumb-item {
display: inline-block;
cursor: pointer;
width: 140px;
height: 140px;
padding: 5px;
margin: 3px;
background: #282828;
vertical-align: middle;
border: 1px solid #383838;
position: relative;
}
-.device-desktop .pholio-mock-carousel-thumb-item:hover {
+.device-desktop .pholio-mock-carousel-thumb-item:hover,
+ .pholio-mock-carousel-thumb-current {
background: #383838;
border-color: #686868;
}
.pholio-mock-carousel-thumbnail {
margin: auto;
position: relative;
}
.pholio-mock-image {
margin: auto;
cursor: crosshair;
}
.pholio-mock-select-border {
position: absolute;
background: #ffffff;
opacity: 0.25;
box-sizing: border-box;
border: 1px solid #000000;
}
.pholio-mock-select-fill {
position: absolute;
border: 1px dashed #ffffff;
box-sizing: border-box;
}
.pholio-mock-image-panel {
padding: 20px;
margin-right: 320px;
}
.pholio-mock-image-viewport {
position: relative;
margin: auto;
display: inline-block;
}
.pholio-mock-inline-comments {
width: 320px;
border-left: 1px solid #101010;
position: absolute;
top: 0;
bottom: 0;
right: 0;
overflow-x: auto;
text-align: left;
}
.pholio-inline-comment {
border: 1px solid #aa8;
background: #f9f9f1;
margin: 2px;
padding: 8px 10px;
}
.pholio-inline-comment-header {
border-bottom: 1px solid #cca;
color: #333;
font-weight: bold;
padding-bottom: 6px;
margin-bottom: 4px;
}
.pholio-mock-inline-comment-highlight {
background-color: #F0B160;
}
.pholio-inline-head-links a {
font-weight: normal;
margin-left: 5px;
}
-
diff --git a/webroot/rsrc/js/application/pholio/behavior-pholio-mock-view.js b/webroot/rsrc/js/application/pholio/behavior-pholio-mock-view.js
index cc8c48ce42..6ee7ab7833 100644
--- a/webroot/rsrc/js/application/pholio/behavior-pholio-mock-view.js
+++ b/webroot/rsrc/js/application/pholio/behavior-pholio-mock-view.js
@@ -1,469 +1,497 @@
/**
* @provides javelin-behavior-pholio-mock-view
* @requires javelin-behavior
* javelin-util
* javelin-stratcom
* javelin-dom
* javelin-vector
* javelin-magical-init
* javelin-request
*/
JX.behavior('pholio-mock-view', function(config) {
var is_dragging = false;
var drag_begin;
var drag_end;
var panel = JX.$(config.panelID);
var viewport = JX.$(config.viewportID);
var selection_border;
var selection_fill;
var active_image;
var inline_comments = {};
function get_image(id) {
for (var ii = 0; ii < config.images.length; ii++) {
if (config.images[ii].id == id) {
return config.images[ii];
}
}
return null;
}
function onload_image(id) {
if (active_image.id != id) {
// The user has clicked another image before this one loaded, so just
// bail.
return;
}
active_image.tag = this;
redraw_image();
}
function redraw_image() {
if (!active_image || !active_image.tag) {
return;
}
var tag = active_image.tag;
// If the image is too wide for the viewport, scale it down so it fits.
// (If it is too tall, we just let the user scroll.)
var w = JX.Vector.getDim(panel);
w.x -= 40;
if (w.x < tag.naturalWidth) {
var scale = w.x / tag.naturalWidth;
tag.width = Math.floor(scale * tag.naturalWidth);
tag.height = Math.floor(scale * tag.naturalHeight);
} else {
tag.width = tag.naturalWidth;
tag.height = tag.naturalHeight;
}
var new_y = (JX.Vector.getViewport().y * 0.85) - 150;
new_y = Math.max(320, new_y);
if (tag.height + 40 < new_y) {
panel.style.height = new_y + 'px';
viewport.style.top = Math.floor(((new_y + 40) - tag.height) / 2) + 'px';
} else {
panel.style.height = '';
viewport.style.top = '';
}
// NOTE: This also clears inline comment reticles.
JX.DOM.setContent(viewport, tag);
redraw_inlines(active_image.id);
}
function select_image(image_id) {
active_image = get_image(image_id);
active_image.tag = null;
var img = JX.$N('img', {className: 'pholio-mock-image'});
img.onload = JX.bind(img, onload_image, active_image.id);
img.src = active_image.fullURI;
+ var thumbs = JX.DOM.scry(
+ JX.$('pholio-mock-carousel'),
+ 'div',
+ 'mock-thumbnail');
+
+ for(var k in thumbs) {
+ var thumb_meta = JX.Stratcom.getData(thumbs[k]);
+
+ JX.DOM.alterClass(
+ thumbs[k],
+ 'pholio-mock-carousel-thumb-current',
+ (active_image.id == thumb_meta.imageID));
+ }
+
load_inline_comments();
}
JX.Stratcom.listen(
'click',
'mock-thumbnail',
function(e) {
e.kill();
select_image(e.getNodeData('mock-thumbnail').imageID);
});
// Select and show the first image.
select_image(config.images[0].id);
JX.Stratcom.listen('mousedown', 'mock-panel', function(e) {
if (!e.isNormalMouseEvent()) {
return;
}
if (drag_begin) {
return;
}
e.kill();
is_dragging = true;
drag_begin = get_image_xy(JX.$V(e));
drag_end = drag_begin;
redraw_selection();
});
JX.enableDispatch(document.body, 'mousemove');
JX.Stratcom.listen('mousemove', null, function(e) {
if (!is_dragging) {
return;
}
drag_end = get_image_xy(JX.$V(e));
redraw_selection();
});
JX.Stratcom.listen(
['mouseover', 'mouseout'],
'image_selection',
function(e) {
var data = e.getNodeData('image_selection');
var comment = JX.$(data.phid + "_comment");
var highlight = (e.getType() == 'mouseover');
JX.DOM.alterClass(
comment,
'pholio-mock-inline-comment-highlight',
highlight);
});
+ JX.Stratcom.listen(
+ ['mouseover', 'mouseout'],
+ 'inline_comment',
+ function(e) {
+ var data = e.getNodeData('inline_comment');
+ var selection = JX.$(data.phid + "_selection");
+ var highlight = (e.getType() == 'mouseover');
+
+ JX.DOM.alterClass(
+ selection,
+ 'pholio-mock-inline-comment-highlight',
+ highlight);
+ });
+
JX.Stratcom.listen(
'mouseup',
null,
function(e) {
if (!is_dragging) {
return;
}
is_dragging = false;
drag_end = get_image_xy(JX.$V(e));
var create_inline = new JX.Request("/pholio/inline/save/", function(r) {
JX.DOM.appendContent(JX.$('pholio-mock-image-container'), JX.$H(r));
var dialog = JX.$('pholio-new-inline-comment-dialog');
var viewportVector = JX.$V(viewport);
var viewportDimensions = JX.Vector.getDim(viewport);
JX.$V(
// TODO: This is a little funky for now.
Math.max(drag_begin.x, drag_end.x),
Math.max(drag_begin.y, drag_end.y)
).setPos(dialog);
});
create_inline.addData({mockID: config.mockID});
create_inline.send();
});
function redraw_inlines(id) {
if (!active_image) {
return;
}
if (active_image.id != id) {
return;
}
var comment_holder = JX.$('mock-inline-comments');
JX.DOM.setContent(comment_holder, '');
var inlines = inline_comments[active_image.id];
if (!inlines || !inlines.length) {
return;
}
for (var ii = 0; ii < inlines.length; ii++) {
var inline = inlines[ii];
JX.DOM.appendContent(comment_holder, JX.$H(inline.contentHTML));
if (!active_image.tag) {
// The image itself hasn't loaded yet, so we can't draw the inline
// reticles.
continue;
}
var inlineSelection = JX.$N(
'div',
{
id: inline.phid + "_selection",
className: 'pholio-mock-select-border'
});
JX.Stratcom.addData(
inlineSelection,
{phid: inline.phid});
JX.Stratcom.addSigil(inlineSelection, "image_selection");
JX.DOM.appendContent(viewport, inlineSelection);
position_inline_rectangle(inline, inlineSelection);
if (!inline.transactionphid) {
var inlineDraft = JX.$N(
'div',
{
className: 'pholio-mock-select-fill',
id: inline.phid + "_fill"
});
position_inline_rectangle(inline, inlineDraft);
JX.Stratcom.addData(
inlineDraft,
{phid: inline.phid});
JX.Stratcom.addSigil(inlineDraft, "image_selection");
JX.DOM.appendContent(viewport, inlineDraft);
}
}
}
function position_inline_rectangle(inline, rect) {
var scale = active_image.tag.width / active_image.tag.naturalWidth;
JX.$V(scale * inline.x, scale * inline.y).setPos(rect);
JX.$V(scale * inline.width, scale * inline.height).setDim(rect);
}
function get_image_xy(p) {
var img = active_image.tag;
var imgp = JX.$V(img);
var scale = 1 / get_image_scale();
var x = scale * Math.max(0, Math.min(p.x - imgp.x, img.width));
var y = scale * Math.max(0, Math.min(p.y - imgp.y, img.height));
return {
x: x,
y: y
};
}
function get_image_scale() {
var img = active_image.tag;
return img.width / img.naturalWidth;
}
function redraw_selection() {
selection_border = selection_border || JX.$N(
'div',
{className: 'pholio-mock-select-border'});
selection_fill = selection_fill || JX.$N(
'div',
{className: 'pholio-mock-select-fill'});
var p = JX.$V(
Math.min(drag_begin.x, drag_end.x),
Math.min(drag_begin.y, drag_end.y));
var d = JX.$V(
Math.max(drag_begin.x, drag_end.x) - p.x,
Math.max(drag_begin.y, drag_end.y) - p.y);
var scale = get_image_scale();
p.x *= scale;
p.y *= scale;
d.x *= scale;
d.y *= scale;
var nodes = [selection_border, selection_fill];
for (var ii = 0; ii < nodes.length; ii++) {
var node = nodes[ii];
viewport.appendChild(node);
p.setPos(node);
d.setDim(node);
}
}
function clear_selection() {
selection_fill && JX.DOM.remove(selection_fill);
selection_border && JX.DOM.remove(selection_border);
}
function load_inline_comments() {
var comment_holder = JX.$('mock-inline-comments');
JX.DOM.setContent(comment_holder, '');
var id = active_image.id;
var inline_comments_uri = "/pholio/inline/" + id + "/";
new JX.Request(inline_comments_uri, function(r) {
inline_comments[id] = r;
redraw_inlines(id);
}).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 (!inline_comments[active_image.id]) {
inline_comments[active_image.id] = [];
}
inline_comments[active_image.id].push(r);
interrupt_typing();
redraw_inlines(active_image.id);
});
var commentToAdd = {
mockID: config.mockID,
op: 'save',
imageID: active_image.id,
startX: Math.min(drag_begin.x, drag_end.x),
startY: Math.min(drag_begin.y, drag_end.y),
endX: Math.max(drag_begin.x, drag_end.x),
endY: Math.max(drag_begin.y, drag_end.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() {
clear_selection();
try {
JX.DOM.remove(JX.$('pholio-new-inline-comment-dialog'));
} catch (x) {
// TODO: For now, ignore this.
}
drag_begin = null;
}
load_inline_comments();
JX.Stratcom.listen('resize', null, redraw_image);
redraw_image();
});

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 19, 18:08 (2 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1127278
Default Alt Text
(20 KB)

Event Timeline