diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -159,7 +159,7 @@ 'rsrc/css/phui/phui-formation-view.css' => 'd2dec8ed', 'rsrc/css/phui/phui-head-thing.css' => 'd7f293df', 'rsrc/css/phui/phui-header-view.css' => '36c86a58', - 'rsrc/css/phui/phui-hovercard.css' => '6ca90fa0', + 'rsrc/css/phui/phui-hovercard.css' => '39fd2e14', 'rsrc/css/phui/phui-icon-set-selector.css' => '7aa5f3ec', 'rsrc/css/phui/phui-icon.css' => '4cbc684a', 'rsrc/css/phui/phui-image-mask.css' => '62c7f4d2', @@ -855,7 +855,7 @@ 'phui-header-view-css' => '36c86a58', 'phui-hovercard' => '6199f752', 'phui-hovercard-list' => 'de4b4919', - 'phui-hovercard-view-css' => '6ca90fa0', + 'phui-hovercard-view-css' => '39fd2e14', 'phui-icon-set-selector-css' => '7aa5f3ec', 'phui-icon-view-css' => '4cbc684a', 'phui-image-mask-css' => '62c7f4d2', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -5641,6 +5641,7 @@ 'PhrictionEditEngineController' => 'applications/phriction/controller/PhrictionEditEngineController.php', 'PhrictionHistoryConduitAPIMethod' => 'applications/phriction/conduit/PhrictionHistoryConduitAPIMethod.php', 'PhrictionHistoryController' => 'applications/phriction/controller/PhrictionHistoryController.php', + 'PhrictionHovercardEngineExtension' => 'applications/phriction/engineextension/PhrictionHovercardEngineExtension.php', 'PhrictionInfoConduitAPIMethod' => 'applications/phriction/conduit/PhrictionInfoConduitAPIMethod.php', 'PhrictionListController' => 'applications/phriction/controller/PhrictionListController.php', 'PhrictionMarkupPreviewController' => 'applications/phriction/controller/PhrictionMarkupPreviewController.php', @@ -12539,6 +12540,7 @@ 'PhrictionEditEngineController' => 'PhrictionController', 'PhrictionHistoryConduitAPIMethod' => 'PhrictionConduitAPIMethod', 'PhrictionHistoryController' => 'PhrictionController', + 'PhrictionHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'PhrictionInfoConduitAPIMethod' => 'PhrictionConduitAPIMethod', 'PhrictionListController' => 'PhrictionController', 'PhrictionMarkupPreviewController' => 'PhabricatorController', diff --git a/src/applications/phriction/engineextension/PhrictionHovercardEngineExtension.php b/src/applications/phriction/engineextension/PhrictionHovercardEngineExtension.php new file mode 100644 --- /dev/null +++ b/src/applications/phriction/engineextension/PhrictionHovercardEngineExtension.php @@ -0,0 +1,165 @@ + $this->getProjectHandlesOfDocuments($objects), + 'ancestors' => $this->getAncestorHandlesOfDocuments($objects), + ); + } + + public function renderHovercard( + PHUIHovercardView $hovercard, + PhabricatorObjectHandle $handle, + $object, + $data) { + + $viewer = $this->getViewer(); + $phid = $object->getPHID(); + + $detail_content = array( + id(new PHUIIconView())->setIcon('fa-book'), + ); + + $ancestor_handles = $data['ancestors'][$phid]; + if (count($ancestor_handles)) { + foreach ($ancestor_handles as $ancestor_handle) { + $detail_content[] = phutil_tag( + 'a', + array( + 'href' => $ancestor_handle->getUri(), + ), + $ancestor_handle->getName()); + + $detail_content[] = id(new PHUIIconView()) + ->setIcon('fa-angle-right') + ->addClass('phui-crumb-divider'); + } + array_pop($detail_content); + } else { + $detail_content[] = pht('Wiki Document'); + } + + $project_handles = $data['projects'][$phid]; + if (count($project_handles)) { + $list = id(new PHUIHandleTagListView()) + ->setHandles($project_handles) + ->setSlim(true) + ->setShowHovercards(false); + + $detail_content[] = $list; + } + + $hovercard->setDetail( + phutil_tag( + 'div', + array( + 'class' => 'phui-hovercard-object-type', + ), + $detail_content)); + + $content = $object->getContent(); + + if ($content) { + $hovercard->addField( + pht('Last Author'), + $viewer->renderHandle($content->getAuthorPHID())); + + $hovercard->addField( + pht('Last Edited'), + phabricator_dual_datetime($content->getDateCreated(), $viewer)); + } + } + + private function getProjectHandlesOfDocuments($documents) { + $viewer = $this->getViewer(); + $project_phids = array(); + $project_map = array(); + + foreach ($documents as $document) { + $document_phid = $document->getPHID(); + $document_project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( + $document_phid, + PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); + + $project_map[$document_phid] = array_reverse($document_project_phids); + foreach ($document_project_phids as $project_phid) { + if (!in_array($project_phid, $project_phids, true)) { + $project_phids[] = $project_phid; + } + } + } + + if ($project_phids) { + $project_handles = iterator_to_array($viewer->loadHandles($project_phids)); + $project_handles = mpull($project_handles, null, 'getPHID'); + + foreach ($project_map as $key => $document_project_phids) { + $project_map[$key] = array_select_keys( + $project_handles, + $document_project_phids); + } + } + + return $project_map; + } + + private function getAncestorHandlesOfDocuments($documents) { + $viewer = $this->getViewer(); + $ancestor_slugs = array(); + $ancestor_map = array(); + + foreach ($documents as $document) { + $document_phid = $document->getPHID(); + $document_ancestor_slugs = PhabricatorSlug::getAncestry( + $document->getSlug()); + + $ancestor_map[$document_phid] = $document_ancestor_slugs; + foreach ($document_ancestor_slugs as $slug) { + if (!in_array($slug, $ancestor_slugs, true)) { + $ancestor_slugs[] = $slug; + } + } + } + + if ($ancestor_slugs) { + $ancestors = id(new PhrictionDocumentQuery()) + ->setViewer($viewer) + ->withSlugs($ancestor_slugs) + ->execute(); + $ancestor_phids = mpull($ancestors, 'getPHID', 'getSlug'); + $ancestor_handles = $viewer->loadHandles($ancestor_phids); + $ancestor_handles = iterator_to_array($ancestor_handles); + $ancestor_handles = mpull($ancestor_handles, null, 'getPHID'); + + foreach ($ancestor_map as $key => $document_ancestor_slugs) { + $document_ancestor_phids = array_select_keys( + $ancestor_phids, + $document_ancestor_slugs); + $ancestor_map[$key] = array_select_keys( + $ancestor_handles, + $document_ancestor_phids); + } + } + + return $ancestor_map; + } + +} diff --git a/webroot/rsrc/css/phui/phui-hovercard.css b/webroot/rsrc/css/phui/phui-hovercard.css --- a/webroot/rsrc/css/phui/phui-hovercard.css +++ b/webroot/rsrc/css/phui/phui-hovercard.css @@ -115,3 +115,24 @@ .hovercard-task-view .phui-oi-disabled.phui-workcard { background-color: #fff; } + +.phui-hovercard-object-type { + font-size: 12px; +} + +.phui-hovercard-object-type .phui-icon-view { + margin-right: 6px; +} + +.phui-hovercard-object-type .phui-crumb-divider { + margin: 0px 6px; +} + +.phui-hovercard-object-type .phabricator-handle-tag-list { + margin-top: 10px; +} + +.phui-hovercard-object-type .phabricator-handle-tag-list-item { + display: inline-block; + margin: 0 4px 2px 0; +}