Meta search: Highlight keyword in single content view (#6971)

* Meta search: Highlight keyword in single content view

* Meta search: Highlight keyword in single content view

---------

Co-authored-by: Lucas Bartholemy <luke-@users.noreply.github.com>
This commit is contained in:
Yuriy Bakhtin 2024-05-01 22:49:54 +02:00 committed by GitHub
parent 4639b2635c
commit 735718aded
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 94 additions and 7 deletions

View File

@ -16,9 +16,11 @@ HumHub Changelog
- Enh #6968: Meta search: open external links in new window
- Fix #6970: MultiSelect loads wrong options (since #6768 in 1.16.0-beta.1)
- Enh #6974: Highlight a content searching keyword on show more comments
- Enh #6971: Meta search: Highlight keyword in single content view
- Fix #6977: Index sub comments for searching
- Fix #6978: Fix module enabling from marketplace
1.16.0-beta.2 (April 9, 2024)
-----------------------------
- Fix #6928: Disabled users without "ignoredDN" settings

View File

@ -11,13 +11,13 @@ namespace humhub\modules\content;
use humhub\commands\CronController;
use humhub\commands\IntegrityController;
use humhub\components\Event;
use humhub\modules\content\assets\ContentHighlightAsset;
use humhub\modules\content\components\ContentActiveRecord;
use humhub\modules\content\models\Content;
use humhub\modules\content\services\ContentSearchService;
use humhub\modules\user\events\UserEvent;
use Yii;
use yii\base\BaseObject;
use yii\console\Controller;
use yii\helpers\Console;
/**
@ -143,6 +143,11 @@ class Events extends BaseObject
}
}
public static function onViewBeginBody($event)
{
ContentHighlightAsset::register($event->sender);
}
private static function canPublishScheduledContent(): bool
{

View File

@ -0,0 +1,40 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\modules\content\assets;
use humhub\components\assets\AssetBundle;
use Yii;
class ContentHighlightAsset extends AssetBundle
{
/**
* @inheritdoc
*/
public $sourcePath = '@content/resources';
/**
* @inheritdoc
*/
public $js = [
'js/humhub.content.highlight.js',
];
/**
* @inheritdoc
*/
public static function register($view)
{
$highlight = Yii::$app->session->get('contentHighlight');
if ($highlight !== null && $highlight !== '') {
Yii::$app->session->remove('contentHighlight');
$view->registerJsConfig('content.highlight', ['keyword' => $highlight]);
}
return parent::register($view);
}
}

View File

@ -8,6 +8,7 @@ use humhub\modules\content\widgets\WallEntryAddons;
use humhub\modules\user\models\User;
use humhub\modules\space\models\Space;
use humhub\modules\content\components\ContentActiveRecord;
use yii\web\View;
return [
'id' => 'content',
@ -22,6 +23,7 @@ return [
['class' => ContentActiveRecord::class, 'event' => ContentActiveRecord::EVENT_AFTER_DELETE, 'callback' => [Events::class, 'onContentActiveRecordDelete']],
['class' => CronController::class, 'event' => CronController::EVENT_ON_DAILY_RUN, 'callback' => [Events::class, 'onCronDailyRun']],
['class' => CronController::class, 'event' => CronController::EVENT_BEFORE_ACTION, 'callback' => [Events::class, 'onCronBeforeAction']],
['class' => View::class, 'event' => View::EVENT_BEGIN_BODY, 'callback' => [Events::class, 'onViewBeginBody']],
],
'consoleControllerMap' => [
'content-search' => '\humhub\modules\content\commands\SearchController',

View File

@ -9,10 +9,9 @@
namespace humhub\modules\content\controllers;
use humhub\components\behaviors\AccessControl;
use Yii;
use humhub\components\Controller;
use humhub\modules\content\models\WallEntry;
use humhub\modules\content\models\Content;
use Yii;
use yii\web\HttpException;
/**
@ -47,6 +46,10 @@ class PermaController extends Controller
$content = Content::findOne(['id' => $id]);
if ($content !== null) {
$highlight = Yii::$app->request->get('highlight');
if ($highlight !== null) {
Yii::$app->session->set('contentHighlight', $highlight);
}
if (method_exists($content->getPolymorphicRelation(), 'getUrl')) {
$url = $content->getPolymorphicRelation()->getUrl();

View File

@ -0,0 +1,31 @@
humhub.module('content.highlight', function (module, require, $) {
const Widget = require('ui.widget').Widget;
const event = require('event');
const layout = $('.layout-content-container');
const init = function () {
event.on('humhub:modules:content:highlight:afterInit', () => highlight());
layout.find('[data-ui-widget="ui.richtext.prosemirror.RichText"]')
.on('afterRender', (obj) => highlight($(obj.target)));
const wallStream = Widget.instance('[data-ui-widget="stream.wall.WallStream"]');
if (wallStream) {
wallStream.on('humhub:stream:afterAddEntries', () => highlight());
}
}
function highlight(object) {
if (typeof module.config.keyword === 'string') {
if (typeof object === 'undefined') {
object = layout;
}
module.config.keyword.split(' ').forEach((keyword) => object.highlight(keyword));
}
}
module.export({
init,
initOnPjaxLoad: true,
})
})

View File

@ -82,7 +82,7 @@ class ContentSearchProvider implements MetaSearchProviderInterface
$results = [];
foreach ($resultSet->results as $content) {
$results[] = new SearchRecord($content);
$results[] = new SearchRecord($content, $this->getKeyword());
}
return [

View File

@ -14,6 +14,7 @@ use humhub\modules\content\widgets\richtext\RichText;
use humhub\modules\ui\icon\widgets\Icon;
use humhub\modules\user\models\User;
use Yii;
use yii\helpers\Url;
/**
* Search Record for Content
@ -24,10 +25,12 @@ use Yii;
class SearchRecord implements MetaSearchResultInterface
{
public ?Content $content = null;
public ?string $keyword = null;
public function __construct(Content $content)
public function __construct(Content $content, ?string $keyword = null)
{
$this->content = $content;
$this->keyword = $keyword;
}
/**
@ -75,6 +78,6 @@ class SearchRecord implements MetaSearchResultInterface
*/
public function getUrl(): string
{
return $this->content->getUrl();
return Url::to(['/content/perma', 'id' => $this->content->id, 'highlight' => $this->keyword]);
}
}

View File

@ -305,7 +305,8 @@ humhub.module('ui.search', function(module, require, $) {
provider.replaceWith(newProviderContent);
const records = newProviderContent.find(that.selectors.providerRecord);
if (records.length) {
records.find(that.selectors.providerRecordText).highlight(data.keyword);
const highlightedText = records.find(that.selectors.providerRecordText);
data.keyword.split(' ').forEach((keyword) => highlightedText.highlight(keyword));
} else if (newProviderContent.data('hide-on-empty') !== undefined) {
newProviderContent.hide();
}