@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Conpherence - Make the files widget more useful and ajaxify some more stuff

Summary: files widget updates as new files are added. made basically all edits "ajax" except for when you change the conpherence image which just does a reload. I will fix this in a future diff but it was starting to spiral out of control a bit.

Test Plan: commented on a task with files and noted the updated file widget. updated header image via drag and drop and dialogue -- noted a full reload. cropped image and re-titled conpherence - ajax updated as expected.

Reviewers: epriestley, chad

Reviewed By: epriestley

CC: aran, Korvin

Maniphest Tasks: T2530

Differential Revision: https://secure.phabricator.com/D5288

+344 -185
+51 -49
src/__celerity_resource_map__.php
··· 669 669 ), 670 670 'aphront-form-view-css' => 671 671 array( 672 - 'uri' => '/res/ec323d34/rsrc/css/aphront/form-view.css', 672 + 'uri' => '/res/c1cf5cce/rsrc/css/aphront/form-view.css', 673 673 'type' => 'css', 674 674 'requires' => 675 675 array( ··· 805 805 ), 806 806 'conpherence-widget-pane-css' => 807 807 array( 808 - 'uri' => '/res/6e5755bb/rsrc/css/application/conpherence/widget-pane.css', 808 + 'uri' => '/res/e67ad581/rsrc/css/application/conpherence/widget-pane.css', 809 809 'type' => 'css', 810 810 'requires' => 811 811 array( ··· 1167 1167 ), 1168 1168 'javelin-behavior-conpherence-menu' => 1169 1169 array( 1170 - 'uri' => '/res/0ad6ab54/rsrc/js/application/conpherence/behavior-menu.js', 1170 + 'uri' => '/res/cb1a5cf0/rsrc/js/application/conpherence/behavior-menu.js', 1171 1171 'type' => 'js', 1172 1172 'requires' => 1173 1173 array( 1174 1174 0 => 'javelin-behavior', 1175 1175 1 => 'javelin-dom', 1176 - 2 => 'javelin-workflow', 1177 - 3 => 'javelin-util', 1178 - 4 => 'javelin-stratcom', 1179 - 5 => 'javelin-uri', 1176 + 2 => 'javelin-request', 1177 + 3 => 'javelin-stratcom', 1178 + 4 => 'javelin-uri', 1179 + 5 => 'javelin-util', 1180 + 6 => 'javelin-workflow', 1180 1181 ), 1181 1182 'disk' => '/rsrc/js/application/conpherence/behavior-menu.js', 1182 1183 ), 1183 1184 'javelin-behavior-conpherence-pontificate' => 1184 1185 array( 1185 - 'uri' => '/res/06214a06/rsrc/js/application/conpherence/behavior-pontificate.js', 1186 + 'uri' => '/res/15263692/rsrc/js/application/conpherence/behavior-pontificate.js', 1186 1187 'type' => 'js', 1187 1188 'requires' => 1188 1189 array( 1189 1190 0 => 'javelin-behavior', 1190 1191 1 => 'javelin-dom', 1191 - 2 => 'javelin-request', 1192 + 2 => 'javelin-util', 1193 + 3 => 'javelin-workflow', 1192 1194 ), 1193 1195 'disk' => '/rsrc/js/application/conpherence/behavior-pontificate.js', 1194 1196 ), ··· 1933 1935 ), 1934 1936 'javelin-behavior-pholio-mock-view' => 1935 1937 array( 1936 - 'uri' => '/res/10573d54/rsrc/js/application/pholio/behavior-pholio-mock-view.js', 1938 + 'uri' => '/res/bee3cef2/rsrc/js/application/pholio/behavior-pholio-mock-view.js', 1937 1939 'type' => 'js', 1938 1940 'requires' => 1939 1941 array( ··· 3500 3502 ), array( 3501 3503 'packages' => 3502 3504 array( 3503 - '6beef3e5' => 3505 + '8e2735e2' => 3504 3506 array( 3505 3507 'name' => 'core.pkg.css', 3506 3508 'symbols' => ··· 3543 3545 35 => 'phabricator-object-item-list-view-css', 3544 3546 36 => 'global-drag-and-drop-css', 3545 3547 ), 3546 - 'uri' => '/res/pkg/6beef3e5/core.pkg.css', 3548 + 'uri' => '/res/pkg/8e2735e2/core.pkg.css', 3547 3549 'type' => 'css', 3548 3550 ), 3549 3551 'f24c209c' => ··· 3733 3735 'reverse' => 3734 3736 array( 3735 3737 'aphront-attached-file-view-css' => 'eb35a026', 3736 - 'aphront-crumbs-view-css' => '6beef3e5', 3737 - 'aphront-dialog-view-css' => '6beef3e5', 3738 - 'aphront-error-view-css' => '6beef3e5', 3739 - 'aphront-form-view-css' => '6beef3e5', 3740 - 'aphront-list-filter-view-css' => '6beef3e5', 3741 - 'aphront-pager-view-css' => '6beef3e5', 3742 - 'aphront-panel-view-css' => '6beef3e5', 3743 - 'aphront-table-view-css' => '6beef3e5', 3744 - 'aphront-tokenizer-control-css' => '6beef3e5', 3745 - 'aphront-tooltip-css' => '6beef3e5', 3746 - 'aphront-typeahead-control-css' => '6beef3e5', 3738 + 'aphront-crumbs-view-css' => '8e2735e2', 3739 + 'aphront-dialog-view-css' => '8e2735e2', 3740 + 'aphront-error-view-css' => '8e2735e2', 3741 + 'aphront-form-view-css' => '8e2735e2', 3742 + 'aphront-list-filter-view-css' => '8e2735e2', 3743 + 'aphront-pager-view-css' => '8e2735e2', 3744 + 'aphront-panel-view-css' => '8e2735e2', 3745 + 'aphront-table-view-css' => '8e2735e2', 3746 + 'aphront-tokenizer-control-css' => '8e2735e2', 3747 + 'aphront-tooltip-css' => '8e2735e2', 3748 + 'aphront-typeahead-control-css' => '8e2735e2', 3747 3749 'differential-changeset-view-css' => '8aaacd1b', 3748 3750 'differential-core-view-css' => '8aaacd1b', 3749 3751 'differential-inline-comment-editor' => '322728f3', ··· 3757 3759 'differential-table-of-contents-css' => '8aaacd1b', 3758 3760 'diffusion-commit-view-css' => 'c8ce2d88', 3759 3761 'diffusion-icons-css' => 'c8ce2d88', 3760 - 'global-drag-and-drop-css' => '6beef3e5', 3762 + 'global-drag-and-drop-css' => '8e2735e2', 3761 3763 'inline-comment-summary-css' => '8aaacd1b', 3762 3764 'javelin-aphlict' => 'f24c209c', 3763 3765 'javelin-behavior' => 'cd1d650a', ··· 3828 3830 'javelin-util' => 'cd1d650a', 3829 3831 'javelin-vector' => 'cd1d650a', 3830 3832 'javelin-workflow' => 'cd1d650a', 3831 - 'lightbox-attachment-css' => '6beef3e5', 3833 + 'lightbox-attachment-css' => '8e2735e2', 3832 3834 'maniphest-task-summary-css' => 'eb35a026', 3833 3835 'maniphest-transaction-detail-css' => 'eb35a026', 3834 3836 'phabricator-busy' => 'f24c209c', 3835 3837 'phabricator-content-source-view-css' => '8aaacd1b', 3836 - 'phabricator-core-buttons-css' => '6beef3e5', 3837 - 'phabricator-core-css' => '6beef3e5', 3838 - 'phabricator-crumbs-view-css' => '6beef3e5', 3839 - 'phabricator-directory-css' => '6beef3e5', 3838 + 'phabricator-core-buttons-css' => '8e2735e2', 3839 + 'phabricator-core-css' => '8e2735e2', 3840 + 'phabricator-crumbs-view-css' => '8e2735e2', 3841 + 'phabricator-directory-css' => '8e2735e2', 3840 3842 'phabricator-drag-and-drop-file-upload' => '322728f3', 3841 3843 'phabricator-dropdown-menu' => 'f24c209c', 3842 3844 'phabricator-file-upload' => 'f24c209c', 3843 - 'phabricator-filetree-view-css' => '6beef3e5', 3844 - 'phabricator-flag-css' => '6beef3e5', 3845 - 'phabricator-form-view-css' => '6beef3e5', 3846 - 'phabricator-header-view-css' => '6beef3e5', 3847 - 'phabricator-jump-nav' => '6beef3e5', 3845 + 'phabricator-filetree-view-css' => '8e2735e2', 3846 + 'phabricator-flag-css' => '8e2735e2', 3847 + 'phabricator-form-view-css' => '8e2735e2', 3848 + 'phabricator-header-view-css' => '8e2735e2', 3849 + 'phabricator-jump-nav' => '8e2735e2', 3848 3850 'phabricator-keyboard-shortcut' => 'f24c209c', 3849 3851 'phabricator-keyboard-shortcut-manager' => 'f24c209c', 3850 - 'phabricator-main-menu-view' => '6beef3e5', 3852 + 'phabricator-main-menu-view' => '8e2735e2', 3851 3853 'phabricator-menu-item' => 'f24c209c', 3852 - 'phabricator-nav-view-css' => '6beef3e5', 3854 + 'phabricator-nav-view-css' => '8e2735e2', 3853 3855 'phabricator-notification' => 'f24c209c', 3854 - 'phabricator-notification-css' => '6beef3e5', 3855 - 'phabricator-notification-menu-css' => '6beef3e5', 3856 - 'phabricator-object-item-list-view-css' => '6beef3e5', 3856 + 'phabricator-notification-css' => '8e2735e2', 3857 + 'phabricator-notification-menu-css' => '8e2735e2', 3858 + 'phabricator-object-item-list-view-css' => '8e2735e2', 3857 3859 'phabricator-object-selector-css' => '8aaacd1b', 3858 3860 'phabricator-paste-file-upload' => 'f24c209c', 3859 3861 'phabricator-prefab' => 'f24c209c', 3860 3862 'phabricator-project-tag-css' => 'eb35a026', 3861 - 'phabricator-remarkup-css' => '6beef3e5', 3863 + 'phabricator-remarkup-css' => '8e2735e2', 3862 3864 'phabricator-shaped-request' => '322728f3', 3863 - 'phabricator-side-menu-view-css' => '6beef3e5', 3864 - 'phabricator-standard-page-view' => '6beef3e5', 3865 + 'phabricator-side-menu-view-css' => '8e2735e2', 3866 + 'phabricator-standard-page-view' => '8e2735e2', 3865 3867 'phabricator-textareautils' => 'f24c209c', 3866 3868 'phabricator-tooltip' => 'f24c209c', 3867 - 'phabricator-transaction-view-css' => '6beef3e5', 3868 - 'phabricator-zindex-css' => '6beef3e5', 3869 - 'sprite-apps-large-css' => '6beef3e5', 3870 - 'sprite-gradient-css' => '6beef3e5', 3871 - 'sprite-icon-css' => '6beef3e5', 3872 - 'sprite-menu-css' => '6beef3e5', 3873 - 'syntax-highlighting-css' => '6beef3e5', 3869 + 'phabricator-transaction-view-css' => '8e2735e2', 3870 + 'phabricator-zindex-css' => '8e2735e2', 3871 + 'sprite-apps-large-css' => '8e2735e2', 3872 + 'sprite-gradient-css' => '8e2735e2', 3873 + 'sprite-icon-css' => '8e2735e2', 3874 + 'sprite-menu-css' => '8e2735e2', 3875 + 'syntax-highlighting-css' => '8e2735e2', 3874 3876 ), 3875 3877 ));
+2
src/__phutil_library_map__.php
··· 208 208 'ConpherenceController' => 'applications/conpherence/controller/ConpherenceController.php', 209 209 'ConpherenceDAO' => 'applications/conpherence/storage/ConpherenceDAO.php', 210 210 'ConpherenceEditor' => 'applications/conpherence/editor/ConpherenceEditor.php', 211 + 'ConpherenceFileWidgetView' => 'applications/conpherence/view/ConpherenceFileWidgetView.php', 211 212 'ConpherenceFormDragAndDropUploadControl' => 'applications/conpherence/view/ConpherenceFormDragAndDropUploadControl.php', 212 213 'ConpherenceImageData' => 'applications/conpherence/constants/ConpherenceImageData.php', 213 214 'ConpherenceListController' => 'applications/conpherence/controller/ConpherenceListController.php', ··· 1759 1760 'ConpherenceController' => 'PhabricatorController', 1760 1761 'ConpherenceDAO' => 'PhabricatorLiskDAO', 1761 1762 'ConpherenceEditor' => 'PhabricatorApplicationTransactionEditor', 1763 + 'ConpherenceFileWidgetView' => 'AphrontView', 1762 1764 'ConpherenceFormDragAndDropUploadControl' => 'AphrontFormControl', 1763 1765 'ConpherenceImageData' => 'ConpherenceConstants', 1764 1766 'ConpherenceListController' => 'ConpherenceController',
+5 -1
src/applications/conpherence/controller/ConpherenceController.php
··· 241 241 array( 242 242 'class' => 'edit', 243 243 'href' => $edit_href, 244 - 'sigil' => 'workflow edit-action', 244 + 'sigil' => 'conpherence-edit-metadata', 245 + 'meta' => array( 246 + 'action' => 'metadata' 247 + ) 245 248 ), 246 249 ''). 247 250 phutil_tag( ··· 340 343 'header' => 'conpherence-header-pane', 341 344 'menu_pane' => 'conpherence-menu', 342 345 'form_pane' => 'conpherence-form', 346 + 'file_widget' => 'widgets-files', 343 347 )); 344 348 } 345 349 }
+91 -62
src/applications/conpherence/controller/ConpherenceUpdateController.php
··· 35 35 ->executeOne(); 36 36 $supported_formats = PhabricatorFile::getTransformableImageFormats(); 37 37 38 + $action = $request->getStr('action', 'metadata'); 38 39 $latest_transaction_id = null; 40 + $fancy_ajax_style = true; 39 41 $error_view = null; 40 42 $e_file = array(); 41 43 $errors = array(); ··· 50 52 ->setContentSource($content_source) 51 53 ->setActor($user); 52 54 53 - $action = $request->getStr('action'); 54 55 switch ($action) { 55 56 case 'message': 56 57 $message = $request->getStr('text'); ··· 65 66 $left = $request->getInt('image_x'); 66 67 $file_id = $request->getInt('file_id'); 67 68 $title = $request->getStr('title'); 69 + $updated = false; 68 70 if ($file_id) { 69 71 $orig_file = id(new PhabricatorFileQuery()) 70 72 ->setViewer($user) ··· 101 103 } 102 104 // use the existing title in this image upload case 103 105 $title = $conpherence->getTitle(); 106 + $updated = true; 107 + $fancy_ajax_style = false; 104 108 } else if ($top !== null || $left !== null) { 105 109 $file = $conpherence->getImage(ConpherenceImageData::SIZE_ORIG); 106 110 $xformer = new PhabricatorImageTransformer(); ··· 115 119 $xactions[] = id(new ConpherenceTransaction()) 116 120 ->setTransactionType( 117 121 ConpherenceTransactionType::TYPE_PICTURE_CROP) 118 - ->setNewValue($image_phid); 122 + ->setNewValue($image_phid); 123 + $updated = true; 119 124 } 120 125 if ($title != $conpherence->getTitle()) { 121 126 $xactions[] = id(new ConpherenceTransaction()) 122 127 ->setTransactionType(ConpherenceTransactionType::TYPE_TITLE) 123 128 ->setNewValue($title); 129 + $updated = true; 130 + } 131 + if (!$updated && $request->isContinueRequest()) { 132 + $errors[] = pht( 133 + 'That was a non-update. Try cancel.'); 124 134 } 125 135 break; 126 136 default: ··· 130 140 if ($xactions) { 131 141 try { 132 142 $xactions = $editor->applyTransactions($conpherence, $xactions); 133 - if ($latest_transaction_id) { 134 - $content = $this->loadAndRenderNewTransactions( 143 + if ($fancy_ajax_style) { 144 + $content = $this->loadAndRenderUpdates( 135 145 $conpherence_id, 136 146 $latest_transaction_id); 137 147 return id(new AphrontAjaxResponse()) 138 148 ->setContent($content); 139 149 } else { 140 - return id(new AphrontRedirectResponse())->setURI( 141 - $this->getApplicationURI($conpherence_id.'/')); 150 + return id(new AphrontRedirectResponse()) 151 + ->setURI($this->getApplicationURI($conpherence->getID().'/')); 142 152 } 143 153 } catch (PhabricatorApplicationTransactionNoEffectException $ex) { 144 154 return id(new PhabricatorApplicationTransactionNoEffectResponse()) 145 155 ->setCancelURI($this->getApplicationURI($conpherence_id.'/')) 146 156 ->setException($ex); 147 157 } 148 - } else if (empty($errors)) { 149 - $errors[] = pht( 150 - 'That was a non-update. Try cancel.'); 151 158 } 152 159 } 153 160 ··· 158 165 ->setErrors($errors); 159 166 } 160 167 168 + switch ($action) { 169 + case 'metadata': 170 + default: 171 + $dialogue = $this->renderMetadataDialogue($conpherence, $error_view); 172 + break; 173 + } 174 + 175 + return id(new AphrontDialogResponse()) 176 + ->setDialog($dialogue 177 + ->setUser($user) 178 + ->setWidth(AphrontDialogView::WIDTH_FORM) 179 + ->setSubmitURI($this->getApplicationURI('update/'.$conpherence_id.'/')) 180 + ->addSubmitButton() 181 + ->addCancelButton($this->getApplicationURI($conpherence->getID().'/'))); 182 + 183 + } 184 + 185 + private function renderMetadataDialogue( 186 + ConpherenceThread $conpherence, 187 + $error_view) { 188 + 161 189 $form = id(new AphrontFormLayoutView()) 190 + ->appendChild($error_view) 162 191 ->appendChild( 163 192 id(new AphrontFormTextControl()) 164 193 ->setLabel(pht('Title')) ··· 177 206 'src' => 178 207 $conpherence->loadImageURI(ConpherenceImageData::SIZE_HEAD), 179 208 )))) 180 - ->appendChild( 181 - id(new AphrontFormCropControl()) 182 - ->setLabel(pht('Crop Image')) 183 - ->setValue($image) 184 - ->setWidth(ConpherenceImageData::HEAD_WIDTH) 185 - ->setHeight(ConpherenceImageData::HEAD_HEIGHT)) 186 - ->appendChild( 187 - id(new ConpherenceFormDragAndDropUploadControl()) 188 - ->setLabel(pht('Change Image'))); 209 + ->appendChild( 210 + id(new AphrontFormCropControl()) 211 + ->setLabel(pht('Crop Image')) 212 + ->setValue($image) 213 + ->setWidth(ConpherenceImageData::HEAD_WIDTH) 214 + ->setHeight(ConpherenceImageData::HEAD_HEIGHT)) 215 + ->appendChild( 216 + id(new ConpherenceFormDragAndDropUploadControl()) 217 + ->setLabel(pht('Change Image'))); 189 218 } else { 190 219 $form 191 220 ->appendChild( ··· 194 223 } 195 224 196 225 require_celerity_resource('conpherence-update-css'); 197 - return id(new AphrontDialogResponse()) 198 - ->setDialog( 199 - id(new AphrontDialogView()) 200 - ->setUser($user) 201 - ->setTitle(pht('Update Conpherence')) 202 - ->setWidth(AphrontDialogView::WIDTH_FORM) 203 - ->setSubmitURI($this->getApplicationURI('update/'.$conpherence_id.'/')) 204 - ->addHiddenInput('action', 'metadata') 205 - ->appendChild($error_view) 206 - ->appendChild($form) 207 - ->addSubmitButton() 208 - ->addCancelButton($this->getApplicationURI($conpherence->getID().'/'))); 226 + return id(new AphrontDialogView()) 227 + ->setTitle(pht('Update Conpherence')) 228 + ->addHiddenInput('action', 'metadata') 229 + ->addHiddenInput('__continue__', true) 230 + ->appendChild($form); 209 231 } 210 232 211 - private function loadAndRenderNewTransactions( 233 + private function loadAndRenderUpdates( 212 234 $conpherence_id, 213 235 $latest_transaction_id) { 214 236 215 - $user = $this->getRequest()->getUser(); 216 - $conpherence = id(new ConpherenceThreadQuery()) 217 - ->setViewer($user) 218 - ->setAfterID($latest_transaction_id) 219 - ->needHeaderPics(true) 220 - ->withIDs(array($conpherence_id)) 221 - ->executeOne(); 237 + $user = $this->getRequest()->getUser(); 238 + $conpherence = id(new ConpherenceThreadQuery()) 239 + ->setViewer($user) 240 + ->setAfterID($latest_transaction_id) 241 + ->needHeaderPics(true) 242 + ->needWidgetData(true) 243 + ->withIDs(array($conpherence_id)) 244 + ->executeOne(); 222 245 223 - $data = $this->renderConpherenceTransactions($conpherence); 224 - $rendered_transactions = $data['transactions']; 225 - $new_latest_transaction_id = $data['latest_transaction_id']; 246 + $data = $this->renderConpherenceTransactions($conpherence); 247 + $rendered_transactions = $data['transactions']; 248 + $new_latest_transaction_id = $data['latest_transaction_id']; 226 249 227 - $selected = true; 228 - $nav_item = $this->buildConpherenceMenuItem( 229 - $conpherence, 230 - '-nav-item', 231 - $selected); 232 - $menu_item = $this->buildConpherenceMenuItem( 233 - $conpherence, 234 - '-menu-item', 235 - $selected); 250 + $selected = true; 251 + $nav_item = $this->buildConpherenceMenuItem( 252 + $conpherence, 253 + '-nav-item', 254 + $selected); 255 + $menu_item = $this->buildConpherenceMenuItem( 256 + $conpherence, 257 + '-menu-item', 258 + $selected); 236 259 237 - $header = $this->buildHeaderPaneContent($conpherence); 260 + $header = $this->buildHeaderPaneContent($conpherence); 238 261 239 - $content = array( 240 - 'transactions' => $rendered_transactions, 241 - 'latest_transaction_id' => $new_latest_transaction_id, 242 - 'menu_item' => $menu_item->render(), 243 - 'nav_item' => $nav_item->render(), 244 - 'conpherence_phid' => $conpherence->getPHID(), 245 - 'header' => $header 246 - ); 247 - return $content; 248 - } 262 + $file_widget = id(new ConpherenceFileWidgetView()) 263 + ->setConpherence($conpherence) 264 + ->setUpdateURI( 265 + $this->getApplicationURI('update/'.$conpherence->getID().'/')); 266 + 267 + $content = array( 268 + 'transactions' => $rendered_transactions, 269 + 'latest_transaction_id' => $new_latest_transaction_id, 270 + 'menu_item' => $menu_item->render(), 271 + 'nav_item' => $nav_item->render(), 272 + 'conpherence_phid' => $conpherence->getPHID(), 273 + 'header' => $header, 274 + 'file_widget' => $file_widget->render() 275 + ); 276 + return $content; 277 + } 249 278 250 - } 279 + }
+30 -51
src/applications/conpherence/controller/ConpherenceWidgetController.php
··· 55 55 Javelin::initBehavior( 56 56 'conpherence-widget-pane', 57 57 array( 58 + 'form_pane' => 'conpherence-form', 59 + 'file_widget' => 'widgets-files', 58 60 'widgetRegistery' => array( 59 61 'widgets-files' => 1, 60 62 'widgets-tasks' => 1, ··· 106 108 'class' => 'sprite-conpher conpher_calendar_off', 107 109 ), 108 110 '') 109 - )). 110 - phutil_tag( 111 - 'div', 112 - array( 113 - 'class' => 'widgets-body', 114 - 'id' => 'widgets-files', 115 - 'style' => 'display: none;' 116 - ), 117 - $this->renderFilesWidgetPaneContent()). 118 - phutil_tag( 119 - 'div', 120 - array( 121 - 'class' => 'widgets-body', 122 - 'id' => 'widgets-tasks', 123 - ), 124 - $this->renderTaskWidgetPaneContent()). 125 - phutil_tag( 126 - 'div', 127 - array( 128 - 'class' => 'widgets-body', 129 - 'id' => 'widgets-calendar', 130 - 'style' => 'display: none;' 131 - ), 132 - $this->renderCalendarWidgetPaneContent()); 111 + )). 112 + phutil_tag( 113 + 'div', 114 + array( 115 + 'class' => 'widgets-body', 116 + 'id' => 'widgets-files', 117 + 'style' => 'display: none;' 118 + ), 119 + id(new ConpherenceFileWidgetView()) 120 + ->setConpherence($conpherence) 121 + ->setUpdateURI( 122 + $this->getApplicationURI('update/'.$conpherence->getID().'/')) 123 + ->render()). 124 + phutil_tag( 125 + 'div', 126 + array( 127 + 'class' => 'widgets-body', 128 + 'id' => 'widgets-tasks', 129 + ), 130 + $this->renderTaskWidgetPaneContent()). 131 + phutil_tag( 132 + 'div', 133 + array( 134 + 'class' => 'widgets-body', 135 + 'id' => 'widgets-calendar', 136 + 'style' => 'display: none;' 137 + ), 138 + $this->renderCalendarWidgetPaneContent()); 133 139 134 140 return array('widgets' => $widgets); 135 - } 136 - 137 - private function renderFilesWidgetPaneContent() { 138 - $conpherence = $this->getConpherence(); 139 - $widget_data = $conpherence->getWidgetData(); 140 - $files = $widget_data['files']; 141 - 142 - $table_data = array(); 143 - foreach ($files as $file) { 144 - $thumb = $file->getThumb60x45URI(); 145 - $table_data[] = array( 146 - phutil_tag( 147 - 'img', 148 - array( 149 - 'src' => $thumb 150 - ), 151 - ''), 152 - $file->getName() 153 - ); 154 - } 155 - $header = id(new PhabricatorHeaderView()) 156 - ->setHeader(pht('Attached Files')); 157 - $table = id(new AphrontTableView($table_data)) 158 - ->setNoDataString(pht('No files attached to conpherence.')) 159 - ->setHeaders(array('', pht('Name'))) 160 - ->setColumnClasses(array('', 'wide')); 161 - return new PhutilSafeHTML($header->render() . $table->render()); 162 141 } 163 142 164 143 private function renderTaskWidgetPaneContent() {
+11 -1
src/applications/conpherence/editor/ConpherenceEditor.php
··· 119 119 $editor = id(new PhabricatorEdgeEditor()) 120 120 ->setActor($this->getActor()); 121 121 $edge_type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_FILE; 122 - foreach ($xaction->getNewValue() as $file_phid) { 122 + $old = array_fill_keys($xaction->getOldValue(), true); 123 + $new = array_fill_keys($xaction->getNewValue(), true); 124 + $add_edges = array_keys(array_diff_key($new, $old)); 125 + $remove_edges = array_keys(array_diff_key($old, $new)); 126 + foreach ($add_edges as $file_phid) { 123 127 $editor->addEdge( 128 + $object->getPHID(), 129 + $edge_type, 130 + $file_phid); 131 + } 132 + foreach ($remove_edges as $file_phid) { 133 + $editor->removeEdge( 124 134 $object->getPHID(), 125 135 $edge_type, 126 136 $file_phid);
+23 -4
src/applications/conpherence/storage/ConpherenceTransaction.php
··· 65 65 } 66 66 return $title; 67 67 case ConpherenceTransactionType::TYPE_FILES: 68 - return pht( 69 - '%s updated the conpherence files.', 70 - $this->renderHandleLink($author_phid)); 68 + $add = array_diff($new, $old); 69 + $rem = array_diff($old, $new); 70 + 71 + if ($add && $rem) { 72 + $title = pht( 73 + '%s edited files(s), added %d and removed %d.', 74 + $this->renderHandleLink($author_phid), 75 + count($add), 76 + count($rem)); 77 + } else if ($add) { 78 + $title = pht( 79 + '%s added %d files(s).', 80 + $this->renderHandleLink($author_phid), 81 + count($add)); 82 + } else { 83 + $title = pht( 84 + '%s removed %d file(s).', 85 + $this->renderHandleLink($author_phid), 86 + count($rem)); 87 + } 88 + return $title; 89 + break; 71 90 case ConpherenceTransactionType::TYPE_PICTURE: 72 91 return pht( 73 92 '%s updated the conpherence image.', ··· 92 111 $this->renderHandleList($add)); 93 112 } else { 94 113 $title = pht( 95 - '%s removed %d partipant(s): %s.', 114 + '%s removed %d participant(s): %s.', 96 115 $this->renderHandleLink($author_phid), 97 116 count($rem), 98 117 $this->renderHandleList($rem));
+65
src/applications/conpherence/view/ConpherenceFileWidgetView.php
··· 1 + <?php 2 + 3 + final class ConpherenceFileWidgetView extends AphrontView { 4 + 5 + private $conpherence; 6 + private $updateURI; 7 + 8 + public function setUpdateURI($update_uri) { 9 + $this->updateURI = $update_uri; 10 + return $this; 11 + } 12 + public function getUpdateURI() { 13 + return $this->updateURI; 14 + } 15 + 16 + public function setConpherence(ConpherenceThread $conpherence) { 17 + $this->conpherence = $conpherence; 18 + return $this; 19 + } 20 + public function getConpherence() { 21 + return $this->conpherence; 22 + } 23 + 24 + public function render() { 25 + $conpherence = $this->getConpherence(); 26 + $widget_data = $conpherence->getWidgetData(); 27 + $files = $widget_data['files']; 28 + 29 + $table_data = array(); 30 + 31 + foreach ($files as $file) { 32 + $file_view = id(new PhabricatorFileLinkView()) 33 + ->setFilePHID($file->getPHID()) 34 + ->setFileName($file->getName()) 35 + ->setFileViewable(true) 36 + ->setFileViewURI($file->getBestURI()); 37 + $meta = $file_view->getMetadata(); 38 + 39 + $table_data[] = array( 40 + javelin_tag( 41 + 'a', 42 + array( 43 + 'sigil' => 'lightboxable', 44 + 'meta' => $meta 45 + ), 46 + phutil_tag( 47 + 'img', 48 + array( 49 + 'src' => $file->getThumb60x45URI() 50 + ), 51 + '')), 52 + $file_view->render() 53 + ); 54 + } 55 + $header = id(new PhabricatorHeaderView()) 56 + ->setHeader(pht('Attached Files')); 57 + $table = id(new AphrontTableView($table_data)) 58 + ->setNoDataString(pht('No files attached to conpherence.')) 59 + ->setHeaders(array('', pht('Name'))) 60 + ->setColumnClasses(array('', 'wide wrap')); 61 + return $this->renderSingleView(array($header, $table)); 62 + 63 + } 64 + 65 + }
+12 -8
src/view/layout/PhabricatorFileLinkView.php
··· 48 48 return $this->fileName; 49 49 } 50 50 51 + public function getMetadata() { 52 + return array( 53 + 'phid' => $this->getFilePHID(), 54 + 'viewable' => $this->getFileViewable(), 55 + 'uri' => $this->getFileViewURI(), 56 + 'dUri' => $this->getFileDownloadURI(), 57 + 'name' => $this->getFileName(), 58 + ); 59 + } 60 + 51 61 public function render() { 52 62 require_celerity_resource('phabricator-remarkup-css'); 53 63 require_celerity_resource('lightbox-attachment-css'); ··· 57 67 $mustcapture = false; 58 68 if ($this->getFileViewable()) { 59 69 $mustcapture = true; 60 - $sigil = 'lightboxable'; 61 - $meta = array( 62 - 'phid' => $this->getFilePHID(), 63 - 'viewable' => $this->getFileViewable(), 64 - 'uri' => $this->getFileViewURI(), 65 - 'dUri' => $this->getFileDownloadURI(), 66 - 'name' => $this->getFileName(), 67 - ); 70 + $sigil = 'lightboxable'; 71 + $meta = $this->getMetadata(); 68 72 } 69 73 70 74 return javelin_tag(
+10
webroot/rsrc/css/application/conpherence/widget-pane.css
··· 97 97 font-size: 11px; 98 98 width: 260px; 99 99 } 100 + 101 + .conpherence-widget-pane .widget-icon { 102 + display: block; 103 + height: 14px; 104 + width: 14px; 105 + } 106 + 107 + .conpherence-widget-pane .phabricator-remarkup-embed-layout-link { 108 + padding-bottom: 1px; 109 + }
+36 -8
webroot/rsrc/js/application/conpherence/behavior-menu.js
··· 2 2 * @provides javelin-behavior-conpherence-menu 3 3 * @requires javelin-behavior 4 4 * javelin-dom 5 - * javelin-workflow 6 - * javelin-util 5 + * javelin-request 7 6 * javelin-stratcom 8 7 * javelin-uri 8 + * javelin-util 9 + * javelin-workflow 9 10 */ 10 11 11 12 JX.behavior('conpherence-menu', function(config) { 13 + 14 + var root = JX.$(config.form_pane); 12 15 13 16 function onwidgetresponse(context, response) { 14 17 var widgets = JX.$H(response.widgets); ··· 107 110 } 108 111 ); 109 112 113 + JX.Stratcom.listen('click', 'conpherence-edit-metadata', function (e) { 114 + e.kill(); 115 + var form = JX.DOM.find(root, 'form'); 116 + var data = e.getNodeData('conpherence-edit-metadata'); 117 + new JX.Workflow.newFromForm(form, data) 118 + .setHandler(function (r) { 119 + // update the header 120 + JX.DOM.setContent( 121 + JX.$(config.header), 122 + JX.$H(r.header) 123 + ); 124 + 125 + // update the menu entry as well 126 + JX.DOM.replace( 127 + JX.$(r.conpherence_phid + '-nav-item'), 128 + JX.$H(r.nav_item) 129 + ); 130 + JX.DOM.replace( 131 + JX.$(r.conpherence_phid + '-menu-item'), 132 + JX.$H(r.menu_item) 133 + ); 134 + }) 135 + .start(); 136 + }); 137 + 110 138 JX.Stratcom.listen('click', 'show-older-messages', function(e) { 111 139 e.kill(); 112 140 console.log(document.URL); 113 - new JX.Request('/conpherence/view/1/', function(r) { 114 - console.log('100'); 115 - }) 116 - .setData({offset: 100}) // get the next page 117 - .send(); 118 - }); 141 + new JX.Request('/conpherence/view/1/', function(r) { 142 + console.log('100'); 143 + }) 144 + .setData({offset: 100}) // get the next page 145 + .send(); 146 + }); 119 147 120 148 });
+8 -1
webroot/rsrc/js/application/conpherence/behavior-pontificate.js
··· 2 2 * @provides javelin-behavior-conpherence-pontificate 3 3 * @requires javelin-behavior 4 4 * javelin-dom 5 - * javelin-request 5 + * javelin-util 6 + * javelin-workflow 6 7 */ 7 8 8 9 JX.behavior('conpherence-pontificate', function(config) { ··· 33 34 JX.DOM.setContent( 34 35 JX.$(config.header), 35 36 JX.$H(r.header) 37 + ); 38 + 39 + // update the file widget 40 + JX.DOM.setContent( 41 + JX.$(config.file_widget), 42 + JX.$H(r.file_widget) 36 43 ); 37 44 38 45 // clear the textarea