1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-31 17:08:22 +01:00

Conpherence - make the files widget purdy-ish

Summary:
does the title and also a few other small tweaks

- kills the init js behavior; now its part of menu where it belongs.
- adds the underline to the icon when its toggled in the widget menu
- fixed JS initialization errors on the "create conpherence" page. Note I still like keeping all that init stuff in one function because its typing the same data a bunch to be passed over to the JS layer. Other ways to accomplish this obvi...

Only fun wrinkle here is I think Chad intended me to display "when the file was attached". Instead, I display when the file was *uploaded*. I think this jives better with our version where you can't delete and all that. Files are pretty powerful, long-living objects in Phabricator land.

Test Plan: added files to a conpherence and noted widget loaded updated okay. added a file with no author (generated by the system) and verified it still rendered okay. switched between conpherences and verified proper data in each files widget. uploaded image and text files to check the icons were correct.

Reviewers: epriestley, chad

Reviewed By: epriestley

CC: aran, Korvin

Maniphest Tasks: T2530

Differential Revision: https://secure.phabricator.com/D5337
This commit is contained in:
Bob Trahan 2013-03-15 23:41:36 -07:00
parent 0bd135b1e6
commit a161617d8e
13 changed files with 426 additions and 264 deletions

View file

@ -1174,21 +1174,9 @@ celerity_register_resource_map(array(
), ),
'disk' => '/rsrc/js/application/conpherence/behavior-drag-and-drop-photo.js', 'disk' => '/rsrc/js/application/conpherence/behavior-drag-and-drop-photo.js',
), ),
'javelin-behavior-conpherence-init' =>
array(
'uri' => '/res/700bba2e/rsrc/js/application/conpherence/behavior-init.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/application/conpherence/behavior-init.js',
),
'javelin-behavior-conpherence-menu' => 'javelin-behavior-conpherence-menu' =>
array( array(
'uri' => '/res/cb1a5cf0/rsrc/js/application/conpherence/behavior-menu.js', 'uri' => '/res/e5da1c05/rsrc/js/application/conpherence/behavior-menu.js',
'type' => 'js', 'type' => 'js',
'requires' => 'requires' =>
array( array(

View file

@ -309,27 +309,21 @@ abstract class ConpherenceController extends PhabricatorController {
} }
protected function initJavelinBehaviors() { protected function initJavelinBehaviors($more_than_menu = false) {
Javelin::initBehavior('conpherence-menu', Javelin::initBehavior('conpherence-menu',
array( array(
'base_uri' => $this->getApplicationURI(''), 'base_uri' => $this->getApplicationURI(''),
'header' => 'conpherence-header-pane', 'header' => 'conpherence-header-pane',
'messages' => 'conpherence-messages', 'messages' => 'conpherence-messages',
'messages_pane' => 'conpherence-message-pane',
'widgets_pane' => 'conpherence-widget-pane', 'widgets_pane' => 'conpherence-widget-pane',
'form_pane' => 'conpherence-form', 'form_pane' => 'conpherence-form',
'menu_pane' => 'conpherence-menu', 'menu_pane' => 'conpherence-menu',
'selected_conpherence_id' => $this->getSelectedConpherencePHID(),
'fancy_ajax' => (bool) $this->getSelectedConpherencePHID() 'fancy_ajax' => (bool) $this->getSelectedConpherencePHID()
)); ));
Javelin::initBehavior('conpherence-init', if ($more_than_menu) {
array(
'selected_conpherence_id' => $this->getSelectedConpherencePHID(),
'menu_pane' => 'conpherence-menu',
'messages_pane' => 'conpherence-message-pane',
'messages' => 'conpherence-messages',
'widgets_pane' => 'conpherence-widget-pane',
'form_pane' => 'conpherence-form'
));
Javelin::initBehavior('conpherence-drag-and-drop-photo', Javelin::initBehavior('conpherence-drag-and-drop-photo',
array( array(
'target' => 'conpherence-header-pane', 'target' => 'conpherence-header-pane',
@ -346,4 +340,5 @@ abstract class ConpherenceController extends PhabricatorController {
'file_widget' => 'widgets-files', 'file_widget' => 'widgets-files',
)); ));
} }
}
} }

View file

@ -63,7 +63,7 @@ final class ConpherenceListController extends
} }
private function renderEmptyMainPane() { private function renderEmptyMainPane() {
$this->initJavelinBehaviors(); $this->initJavelinBehaviors(true);
return phutil_tag( return phutil_tag(
'div', 'div',
array( array(

View file

@ -260,6 +260,7 @@ final class ConpherenceUpdateController extends
$header = $this->buildHeaderPaneContent($conpherence); $header = $this->buildHeaderPaneContent($conpherence);
$file_widget = id(new ConpherenceFileWidgetView()) $file_widget = id(new ConpherenceFileWidgetView())
->setUser($this->getRequest()->getUser())
->setConpherence($conpherence) ->setConpherence($conpherence)
->setUpdateURI( ->setUpdateURI(
$this->getApplicationURI('update/'.$conpherence->getID().'/')); $this->getApplicationURI('update/'.$conpherence->getID().'/'));
@ -276,4 +277,4 @@ final class ConpherenceUpdateController extends
return $content; return $content;
} }
} }

View file

@ -76,6 +76,11 @@ final class ConpherenceWidgetController extends
array( array(
'class' => 'widgets-header' 'class' => 'widgets-header'
), ),
phutil_tag(
'div',
array(
'class' => 'widgets-header-icon-holder'
),
array( array(
javelin_tag( javelin_tag(
'a', 'a',
@ -122,7 +127,8 @@ final class ConpherenceWidgetController extends
'toggleClass' => 'conpherence_files_on' 'toggleClass' => 'conpherence_files_on'
), ),
'id' => 'widgets-files-toggle', 'id' => 'widgets-files-toggle',
'class' => 'sprite-conpherence conpherence_files_off' 'class' =>
'sprite-conpherence conpherence_files_on conpherence_files_off'
), ),
''), ''),
javelin_tag( javelin_tag(
@ -149,12 +155,13 @@ final class ConpherenceWidgetController extends
'class' => 'sprite-conpherence conpherence_settings_off', 'class' => 'sprite-conpherence conpherence_settings_off',
), ),
'') '')
)). ))).
phutil_tag( phutil_tag(
'div', 'div',
array( array(
'class' => 'widgets-body', 'class' => 'widgets-body',
'id' => 'widgets-people', 'id' => 'widgets-people',
'style' => 'display: none;'
), ),
$this->renderPeopleWidgetPaneContent()). $this->renderPeopleWidgetPaneContent()).
phutil_tag( phutil_tag(
@ -162,9 +169,9 @@ final class ConpherenceWidgetController extends
array( array(
'class' => 'widgets-body', 'class' => 'widgets-body',
'id' => 'widgets-files', 'id' => 'widgets-files',
'style' => 'display: none;'
), ),
id(new ConpherenceFileWidgetView()) id(new ConpherenceFileWidgetView())
->setUser($this->getRequest()->getUser())
->setConpherence($conpherence) ->setConpherence($conpherence)
->setUpdateURI( ->setUpdateURI(
$this->getApplicationURI('update/'.$conpherence->getID().'/')) $this->getApplicationURI('update/'.$conpherence->getID().'/'))

View file

@ -170,12 +170,19 @@ final class ConpherenceThreadQuery
// attached files // attached files
$files = array(); $files = array();
$file_author_phids = array();
$authors = array();
if ($file_phids) { if ($file_phids) {
$files = id(new PhabricatorFileQuery()) $files = id(new PhabricatorFileQuery())
->setViewer($this->getViewer()) ->setViewer($this->getViewer())
->withPHIDs($file_phids) ->withPHIDs($file_phids)
->execute(); ->execute();
$files = mpull($files, null, 'getPHID'); $files = mpull($files, null, 'getPHID');
$file_author_phids = mpull($files, 'getAuthorPHID', 'getPHID');
$authors = id(new PhabricatorObjectHandleData($file_author_phids))
->setViewer($this->getViewer())
->loadHandles();
$authors = mpull($authors, null, 'getPHID');
} }
foreach ($conpherences as $phid => $conpherence) { foreach ($conpherences as $phid => $conpherence) {
@ -183,9 +190,23 @@ final class ConpherenceThreadQuery
$statuses = array_select_keys($statuses, $participant_phids); $statuses = array_select_keys($statuses, $participant_phids);
$statuses = array_mergev($statuses); $statuses = array_mergev($statuses);
$statuses = msort($statuses, 'getDateFrom'); $statuses = msort($statuses, 'getDateFrom');
$conpherence_files = array();
$files_authors = array();
foreach ($conpherence->getFilePHIDs() as $curr_phid) {
$conpherence_files[$curr_phid] = $files[$curr_phid];
// some files don't have authors so be careful
$current_author = null;
$current_author_phid = idx($file_author_phids, $curr_phid);
if ($current_author_phid) {
$current_author = $authors[$current_author_phid];
}
$files_authors[$curr_phid] = $current_author;
}
$widget_data = array( $widget_data = array(
'statuses' => $statuses, 'statuses' => $statuses,
'files' => array_select_keys($files, $conpherence->getFilePHIDs()), 'files' => $conpherence_files,
'files_authors' => $files_authors
); );
$conpherence->attachWidgetData($widget_data); $conpherence->attachWidgetData($widget_data);
} }

View file

@ -22,43 +22,89 @@ final class ConpherenceFileWidgetView extends AphrontView {
} }
public function render() { public function render() {
require_celerity_resource('sprite-docs-css');
$conpherence = $this->getConpherence(); $conpherence = $this->getConpherence();
$widget_data = $conpherence->getWidgetData(); $widget_data = $conpherence->getWidgetData();
$files = $widget_data['files']; $files = $widget_data['files'];
$files_authors = $widget_data['files_authors'];
$table_data = array(); $files_html = array();
foreach ($files as $file) { foreach ($files as $file) {
$icon_class = $file->getDisplayIconForMimeType();
$icon_view = phutil_tag(
'div',
array(
'class' => 'file-icon sprite-docs '.$icon_class
),
'');
$file_view = id(new PhabricatorFileLinkView()) $file_view = id(new PhabricatorFileLinkView())
->setFilePHID($file->getPHID()) ->setFilePHID($file->getPHID())
->setFileName($file->getName()) ->setFileName($file->getName())
->setFileViewable(true) ->setFileViewable($file->isViewableImage())
->setFileViewURI($file->getBestURI()); ->setFileViewURI($file->getBestURI())
$meta = $file_view->getMetadata(); ->setCustomClass('file-title');
$table_data[] = array( $who_done_it_text = '';
javelin_tag( // system generated files don't have authors
if ($file->getAuthorPHID()) {
$who_done_it_text = pht(
'by %s ',
$files_authors[$file->getPHID()]->renderLink());
}
$date_text = phabricator_relative_date(
$file->getDateCreated(),
$this->getUser());
$who_done_it = phutil_tag(
'div',
array(
'class' => 'file-uploaded-by'
),
pht('Uploaded %s%s.', $who_done_it_text, $date_text));
$extra = '';
if ($file->isViewableImage()) {
$meta = $file_view->getMetadata();
$extra = javelin_tag(
'a', 'a',
array( array(
'sigil' => 'lightboxable', 'sigil' => 'lightboxable',
'meta' => $meta 'meta' => $meta,
'class' => 'file-extra',
), ),
phutil_tag( phutil_tag(
'img', 'img',
array( array(
'src' => $file->getThumb60x45URI() 'src' => $file->getThumb160x120URI()
), ),
'')), ''));
$file_view->render()
);
} }
$header = id(new PhabricatorHeaderView())
->setHeader(pht('Attached Files')); $divider = phutil_tag(
$table = id(new AphrontTableView($table_data)) 'div',
->setNoDataString(pht('No files attached to conpherence.')) array(
->setHeaders(array('', pht('Name'))) 'class' => 'divider'
->setColumnClasses(array('', 'wide wrap')); ),
return array($header, $table); '');
$files_html[] = phutil_tag(
'div',
array(
'class' => 'file-entry'
),
array(
$icon_view,
$file_view,
$who_done_it,
$extra,
$divider
));
}
return phutil_tag(
'div',
array('class' => 'file-list'),
$files_html);
} }

View file

@ -38,6 +38,35 @@ final class PhabricatorFilesConfigOptions
'image/vnd.microsoft.icon' => true, 'image/vnd.microsoft.icon' => true,
); );
// largely lifted from http://en.wikipedia.org/wiki/Internet_media_type
$icon_default = array(
// audio file icon
'audio/basic' => 'docs_audio',
'audio/L24' => 'docs_audio',
'audio/mp4' => 'docs_audio',
'audio/mpeg' => 'docs_audio',
'audio/ogg' => 'docs_audio',
'audio/vorbis' => 'docs_audio',
'audio/vnd.rn-realaudio' => 'docs_audio',
'audio/vnd.wave' => 'docs_audio',
'audio/webm' => 'docs_audio',
// movie file icon
'video/mpeg' => 'docs_movie',
'video/mp4' => 'docs_movie',
'video/ogg' => 'docs_movie',
'video/quicktime' => 'docs_movie',
'video/webm' => 'docs_movie',
'video/x-matroska' => 'docs_movie',
'video/x-ms-wmv' => 'docs_movie',
'video/x-flv' => 'docs_movie',
// pdf file icon
'application/pdf' => 'docs_pdf',
// zip file icon
'application/zip' => 'docs_zip',
// msword icon
'application/msword' => 'docs_doc',
) + array_fill_keys(array_keys($image_default), 'docs_image');
return array( return array(
$this->newOption('files.viewable-mime-types', 'wild', $viewable_default) $this->newOption('files.viewable-mime-types', 'wild', $viewable_default)
->setSummary( ->setSummary(
@ -58,6 +87,12 @@ final class PhabricatorFilesConfigOptions
pht( pht(
'List of MIME types which can be used as the `src` for an '. 'List of MIME types which can be used as the `src` for an '.
'`<img />` tag.')), '`<img />` tag.')),
$this->newOption('files.icon-mime-types', 'wild', $icon_default)
->setSummary(pht('Configure which MIME types map to which icons.'))
->setDescription(
pht(
'Map of MIME type to icon name. MIME types which can not be '.
'found default to icon `doc_files`.')),
$this->newOption('storage.mysql-engine.max-size', 'int', 1000000) $this->newOption('storage.mysql-engine.max-size', 'int', 1000000)
->setSummary( ->setSummary(
pht( pht(

View file

@ -586,6 +586,12 @@ final class PhabricatorFile extends PhabricatorFileDAO
return idx($mime_map, $mime_type); return idx($mime_map, $mime_type);
} }
public function getDisplayIconForMimeType() {
$mime_map = PhabricatorEnv::getEnvConfig('files.icon-mime-types');
$mime_type = $this->getMimeType();
return idx($mime_map, $mime_type, 'docs_file');
}
public function validateSecretKey($key) { public function validateSecretKey($key) {
return ($key == $this->getSecretKey()); return ($key == $this->getSecretKey());
} }

View file

@ -7,6 +7,15 @@ final class PhabricatorFileLinkView extends AphrontView {
private $fileViewURI; private $fileViewURI;
private $fileViewable; private $fileViewable;
private $filePHID; private $filePHID;
private $customClass;
public function setCustomClass($custom_class) {
$this->customClass = $custom_class;
return $this;
}
public function getCustomClass() {
return $this->customClass;
}
public function setFilePHID($file_phid) { public function setFilePHID($file_phid) {
$this->filePHID = $file_phid; $this->filePHID = $file_phid;
@ -71,11 +80,16 @@ final class PhabricatorFileLinkView extends AphrontView {
$meta = $this->getMetadata(); $meta = $this->getMetadata();
} }
$class = 'phabricator-remarkup-embed-layout-link';
if ($this->getCustomClass()) {
$class = $this->getCustomClass();
}
return javelin_tag( return javelin_tag(
'a', 'a',
array( array(
'href' => $this->getFileViewURI(), 'href' => $this->getFileViewURI(),
'class' => 'phabricator-remarkup-embed-layout-link', 'class' => $class,
'sigil' => $sigil, 'sigil' => $sigil,
'meta' => $meta, 'meta' => $meta,
'mustcapture' => $mustcapture, 'mustcapture' => $mustcapture,

View file

@ -5,7 +5,7 @@
.conpherence-widget-pane { .conpherence-widget-pane {
position: fixed; position: fixed;
right: 0px; right: 0px;
top: 125px; top: 124px;
width: 320px; width: 320px;
height: 100%; height: 100%;
border-width: 0 0 0 1px; border-width: 0 0 0 1px;
@ -21,10 +21,17 @@
} }
.conpherence-widget-pane .widgets-header { .conpherence-widget-pane .widgets-header {
background-color: #d8dce2;
width: 320px;
box-shadow: 0px 2px 2px rgba(0,0,0,0.15);
}
.conpherence-widget-pane .widgets-header .widgets-header-icon-holder {
height: 40px; height: 40px;
} }
.device-desktop .conpherence-widget-pane .widgets-header { .device-desktop .conpherence-widget-pane .widgets-header
.widgets-header-icon-holder {
width: 196px; width: 196px;
margin: 0px auto 0px auto; margin: 0px auto 0px auto;
} }
@ -32,12 +39,21 @@
.conpherence-widget-pane .widgets-header .sprite-conpherence { .conpherence-widget-pane .widgets-header .sprite-conpherence {
display: block; display: block;
width: 29px; width: 29px;
height: 33px; height: 34px;
margin: 4px 0px 0px 20px; margin: 4px 0px 0px 20px;
float: left; float: left;
clear: none; clear: none;
} }
.conpherence-widget-pane .widgets-header .conpherence_list_on,
.conpherence-widget-pane .widgets-header .conpherence_conversation_on,
.conpherence-widget-pane .widgets-header .conpherence_people_on,
.conpherence-widget-pane .widgets-header .conpherence_files_on,
.conpherence-widget-pane .widgets-header .conpherence_calendar_on,
.conpherence-widget-pane .widgets-header .conpherence_settings_on {
border-bottom: 3px solid #525252;
}
.device-desktop .conpherence-widget-pane .widgets-header .device-desktop .conpherence-widget-pane .widgets-header
#widgets-conpherence-list-toggle, #widgets-conpherence-list-toggle,
.device-desktop .conpherence-widget-pane .widgets-header .device-desktop .conpherence-widget-pane .widgets-header
@ -53,10 +69,52 @@
width: 320px; width: 320px;
} }
/* calendar widget */ /* files widget */
.conpherence-widget-pane #widgets-calendar { .conpherence-widget-pane #widgets-files .file-entry {
padding: 12px 0px 14px 0px;
width: 320px;
} }
.conpherence-widget-pane #widgets-files .file-icon {
position: relative;
top: 0px;
left: 8px;
width: 32px;
height: 32px;
float: left;
}
.conpherence-widget-pane #widgets-files .file-title {
position: relative;
top: -4px;
left: 20px;
font-weight: bold;
}
.conpherence-widget-pane #widgets-files .file-uploaded-by {
color: #bfbfbf;
position: relative;
top: 0px;
left: 20px;
width: 270px;
font-size: 11px;
}
.conpherence-widget-pane #widgets-files .file-extra {
display: block;
height: 120px;
width: 160px;
margin: 8px 0px 8px 52px;
border: 1px solid rgb(24, 85, 157);
}
.conpherence-widget-pane #widgets-files .divider {
float: left;
clear: both;
width: 242px;
margin: 8px 0px 0px 52px;
border: 1px dashed #bfbfbf;
}
/* calendar widget */
.conpherence-widget-pane #widgets-calendar .user-status { .conpherence-widget-pane #widgets-calendar .user-status {
height: 60px; height: 60px;

View file

@ -1,20 +0,0 @@
/**
* @provides javelin-behavior-conpherence-init
* @requires javelin-behavior
* javelin-dom
* javelin-stratcom
*/
JX.behavior('conpherence-init', function(config) {
// select the current message
var selectedConpherence = false;
if (config.selected_conpherence_id) {
var selected = JX.$(config.selected_conpherence_id + '-nav-item');
JX.Stratcom.invoke(
'conpherence-initial-selected',
null,
{ selected : selected }
);
selectedConpherence = true;
}
});

View file

@ -11,8 +11,6 @@
JX.behavior('conpherence-menu', function(config) { JX.behavior('conpherence-menu', function(config) {
var root = JX.$(config.form_pane);
function onwidgetresponse(context, response) { function onwidgetresponse(context, response) {
var widgets = JX.$H(response.widgets); var widgets = JX.$H(response.widgets);
var widgetsRoot = JX.$(config.widgets_pane); var widgetsRoot = JX.$(config.widgets_pane);
@ -112,6 +110,7 @@ JX.behavior('conpherence-menu', function(config) {
JX.Stratcom.listen('click', 'conpherence-edit-metadata', function (e) { JX.Stratcom.listen('click', 'conpherence-edit-metadata', function (e) {
e.kill(); e.kill();
var root = JX.$(config.form_pane);
var form = JX.DOM.find(root, 'form'); var form = JX.DOM.find(root, 'form');
var data = e.getNodeData('conpherence-edit-metadata'); var data = e.getNodeData('conpherence-edit-metadata');
new JX.Workflow.newFromForm(form, data) new JX.Workflow.newFromForm(form, data)
@ -145,4 +144,16 @@ JX.behavior('conpherence-menu', function(config) {
.send(); .send();
}); });
// select the current message
var selectedConpherence = false;
if (config.selected_conpherence_id) {
var selected = JX.$(config.selected_conpherence_id + '-nav-item');
JX.Stratcom.invoke(
'conpherence-initial-selected',
null,
{ selected : selected }
);
selectedConpherence = true;
}
}); });