@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.

Implements a more informative hovercard for wiki documents

Summary:
The current hovercard of a wiki document has no further information except the title. This commit adds object type, project tags, parent documents, last author and last edited time to the card.

Preview:

{F313614}

Preview in a pessimistic case:

{F325478}

Closes T15433

Test Plan: Edit a wiki document with/without project tags and parent documents and see the hovercard in the feed.

Reviewers: O1 Blessed Committers, valerio.bozzolan, avivey, Cigaryno

Reviewed By: O1 Blessed Committers, valerio.bozzolan, avivey, Cigaryno

Subscribers: avivey, speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno

Maniphest Tasks: T15433

Differential Revision: https://we.phorge.it/D25303

+194 -2
+2 -2
resources/celerity/map.php
··· 159 159 'rsrc/css/phui/phui-formation-view.css' => 'd2dec8ed', 160 160 'rsrc/css/phui/phui-head-thing.css' => 'd7f293df', 161 161 'rsrc/css/phui/phui-header-view.css' => '36c86a58', 162 - 'rsrc/css/phui/phui-hovercard.css' => '6ca90fa0', 162 + 'rsrc/css/phui/phui-hovercard.css' => '39fd2e14', 163 163 'rsrc/css/phui/phui-icon-set-selector.css' => '7aa5f3ec', 164 164 'rsrc/css/phui/phui-icon.css' => '084ac612', 165 165 'rsrc/css/phui/phui-image-mask.css' => '62c7f4d2', ··· 855 855 'phui-header-view-css' => '36c86a58', 856 856 'phui-hovercard' => '6199f752', 857 857 'phui-hovercard-list' => 'de4b4919', 858 - 'phui-hovercard-view-css' => '6ca90fa0', 858 + 'phui-hovercard-view-css' => '39fd2e14', 859 859 'phui-icon-set-selector-css' => '7aa5f3ec', 860 860 'phui-icon-view-css' => '084ac612', 861 861 'phui-image-mask-css' => '62c7f4d2',
+2
src/__phutil_library_map__.php
··· 5644 5644 'PhrictionEditEngineController' => 'applications/phriction/controller/PhrictionEditEngineController.php', 5645 5645 'PhrictionHistoryConduitAPIMethod' => 'applications/phriction/conduit/PhrictionHistoryConduitAPIMethod.php', 5646 5646 'PhrictionHistoryController' => 'applications/phriction/controller/PhrictionHistoryController.php', 5647 + 'PhrictionHovercardEngineExtension' => 'applications/phriction/engineextension/PhrictionHovercardEngineExtension.php', 5647 5648 'PhrictionInfoConduitAPIMethod' => 'applications/phriction/conduit/PhrictionInfoConduitAPIMethod.php', 5648 5649 'PhrictionListController' => 'applications/phriction/controller/PhrictionListController.php', 5649 5650 'PhrictionMarkupPreviewController' => 'applications/phriction/controller/PhrictionMarkupPreviewController.php', ··· 12545 12546 'PhrictionEditEngineController' => 'PhrictionController', 12546 12547 'PhrictionHistoryConduitAPIMethod' => 'PhrictionConduitAPIMethod', 12547 12548 'PhrictionHistoryController' => 'PhrictionController', 12549 + 'PhrictionHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 12548 12550 'PhrictionInfoConduitAPIMethod' => 'PhrictionConduitAPIMethod', 12549 12551 'PhrictionListController' => 'PhrictionController', 12550 12552 'PhrictionMarkupPreviewController' => 'PhabricatorController',
+169
src/applications/phriction/engineextension/PhrictionHovercardEngineExtension.php
··· 1 + <?php 2 + 3 + final class PhrictionHovercardEngineExtension 4 + extends PhabricatorHovercardEngineExtension { 5 + 6 + const EXTENSIONKEY = 'phriction'; 7 + 8 + public function isExtensionEnabled() { 9 + return PhabricatorApplication::isClassInstalled( 10 + 'PhabricatorPhrictionApplication'); 11 + } 12 + 13 + public function getExtensionName() { 14 + return pht('Wiki Documents'); 15 + } 16 + 17 + public function canRenderObjectHovercard($object) { 18 + return ($object instanceof PhrictionDocument); 19 + } 20 + 21 + public function willRenderHovercards(array $objects) { 22 + return array( 23 + 'projects' => $this->getProjectHandlesOfDocuments($objects), 24 + 'ancestors' => $this->getAncestorHandlesOfDocuments($objects), 25 + ); 26 + } 27 + 28 + public function renderHovercard( 29 + PHUIHovercardView $hovercard, 30 + PhabricatorObjectHandle $handle, 31 + $object, 32 + $data) { 33 + 34 + $viewer = $this->getViewer(); 35 + $phid = $object->getPHID(); 36 + 37 + $detail_content = array( 38 + id(new PHUIIconView())->setIcon('fa-book'), 39 + ); 40 + 41 + $ancestor_handles = $data['ancestors'][$phid]; 42 + if ($ancestor_handles) { 43 + foreach ($ancestor_handles as $ancestor_handle) { 44 + $detail_content[] = phutil_tag( 45 + 'a', 46 + array( 47 + 'href' => $ancestor_handle->getUri(), 48 + ), 49 + $ancestor_handle->getName()); 50 + 51 + $detail_content[] = id(new PHUIIconView()) 52 + ->setIcon('fa-angle-right') 53 + ->addClass('phui-crumb-divider'); 54 + } 55 + array_pop($detail_content); 56 + } else { 57 + $detail_content[] = pht('Wiki Document'); 58 + } 59 + 60 + $project_handles = $data['projects'][$phid]; 61 + if ($project_handles) { 62 + $list = id(new PHUIHandleTagListView()) 63 + ->setHandles($project_handles) 64 + ->setSlim(true) 65 + ->setShowHovercards(false); 66 + 67 + $detail_content[] = $list; 68 + } 69 + 70 + $hovercard->setDetail( 71 + phutil_tag( 72 + 'div', 73 + array( 74 + 'class' => 'phui-hovercard-object-type', 75 + ), 76 + $detail_content)); 77 + 78 + $content = $object->getContent(); 79 + 80 + if ($content) { 81 + $hovercard->addField( 82 + pht('Last Author'), 83 + $viewer->renderHandle($content->getAuthorPHID())); 84 + 85 + $hovercard->addField( 86 + pht('Last Edited'), 87 + phabricator_dual_datetime($content->getDateCreated(), $viewer)); 88 + } 89 + } 90 + 91 + private function getProjectHandlesOfDocuments($documents) { 92 + $viewer = $this->getViewer(); 93 + $project_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; 94 + $project_phids = array(); 95 + $project_map = array(); 96 + 97 + $project_edges = id(new PhabricatorEdgeQuery()) 98 + ->withSourcePHIDs(mpull($documents, 'getPHID')) 99 + ->withEdgeTypes(array($project_edge_type)) 100 + ->execute(); 101 + 102 + foreach ($project_edges as $document_phid => $edge_types) { 103 + $document_project_phids = array_keys($edge_types[$project_edge_type]); 104 + 105 + $project_map[$document_phid] = array_reverse($document_project_phids); 106 + foreach ($document_project_phids as $project_phid) { 107 + if (!in_array($project_phid, $project_phids, true)) { 108 + $project_phids[] = $project_phid; 109 + } 110 + } 111 + } 112 + 113 + if ($project_phids) { 114 + $project_handles = $viewer->loadHandles($project_phids); 115 + $project_handles = iterator_to_array($project_handles); 116 + $project_handles = mpull($project_handles, null, 'getPHID'); 117 + 118 + foreach ($project_map as $key => $document_project_phids) { 119 + $project_map[$key] = array_select_keys( 120 + $project_handles, 121 + $document_project_phids); 122 + } 123 + } 124 + 125 + return $project_map; 126 + } 127 + 128 + private function getAncestorHandlesOfDocuments($documents) { 129 + $viewer = $this->getViewer(); 130 + $ancestor_slugs = array(); 131 + $ancestor_map = array(); 132 + 133 + foreach ($documents as $document) { 134 + $document_phid = $document->getPHID(); 135 + $document_ancestor_slugs = PhabricatorSlug::getAncestry( 136 + $document->getSlug()); 137 + 138 + $ancestor_map[$document_phid] = $document_ancestor_slugs; 139 + foreach ($document_ancestor_slugs as $slug) { 140 + if (!in_array($slug, $ancestor_slugs, true)) { 141 + $ancestor_slugs[] = $slug; 142 + } 143 + } 144 + } 145 + 146 + if ($ancestor_slugs) { 147 + $ancestors = id(new PhrictionDocumentQuery()) 148 + ->setViewer($viewer) 149 + ->withSlugs($ancestor_slugs) 150 + ->execute(); 151 + $ancestor_phids = mpull($ancestors, 'getPHID', 'getSlug'); 152 + $ancestor_handles = $viewer->loadHandles($ancestor_phids); 153 + $ancestor_handles = iterator_to_array($ancestor_handles); 154 + $ancestor_handles = mpull($ancestor_handles, null, 'getPHID'); 155 + 156 + foreach ($ancestor_map as $key => $document_ancestor_slugs) { 157 + $document_ancestor_phids = array_select_keys( 158 + $ancestor_phids, 159 + $document_ancestor_slugs); 160 + $ancestor_map[$key] = array_select_keys( 161 + $ancestor_handles, 162 + $document_ancestor_phids); 163 + } 164 + } 165 + 166 + return $ancestor_map; 167 + } 168 + 169 + }
+21
webroot/rsrc/css/phui/phui-hovercard.css
··· 115 115 .hovercard-task-view .phui-oi-disabled.phui-workcard { 116 116 background-color: #fff; 117 117 } 118 + 119 + .phui-hovercard-object-type { 120 + font-size: 12px; 121 + } 122 + 123 + .phui-hovercard-object-type .phui-icon-view { 124 + margin-right: 6px; 125 + } 126 + 127 + .phui-hovercard-object-type .phui-crumb-divider { 128 + margin: 0px 6px; 129 + } 130 + 131 + .phui-hovercard-object-type .phabricator-handle-tag-list { 132 + margin-top: 10px; 133 + } 134 + 135 + .phui-hovercard-object-type .phabricator-handle-tag-list-item { 136 + display: inline-block; 137 + margin: 0 4px 2px 0; 138 + }