diff --git a/composer.lock b/composer.lock index 29fc9f4dd..6b26b3396 100644 --- a/composer.lock +++ b/composer.lock @@ -4108,16 +4108,16 @@ }, { "name": "olcs/olcs-transfer", - "version": "v6.0.1", + "version": "v6.1.0", "source": { "type": "git", "url": "https://github.com/dvsa/olcs-transfer.git", - "reference": "43132a1630e82c8c2231c37b03178ebb1aa2663f" + "reference": "ff4249e741de87991c0b999513e754e96de1446b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dvsa/olcs-transfer/zipball/43132a1630e82c8c2231c37b03178ebb1aa2663f", - "reference": "43132a1630e82c8c2231c37b03178ebb1aa2663f", + "url": "https://api.github.com/repos/dvsa/olcs-transfer/zipball/ff4249e741de87991c0b999513e754e96de1446b", + "reference": "ff4249e741de87991c0b999513e754e96de1446b", "shasum": "" }, "require": { @@ -4158,9 +4158,9 @@ "notification-url": "https://packagist.org/downloads/", "description": "OLCS Transfer", "support": { - "source": "https://github.com/dvsa/olcs-transfer/tree/v6.0.1" + "source": "https://github.com/dvsa/olcs-transfer/tree/v6.1.0" }, - "time": "2024-02-22T14:58:13+00:00" + "time": "2024-02-22T15:22:13+00:00" }, { "name": "olcs/olcs-utils", diff --git a/module/Olcs/config/module.config.php b/module/Olcs/config/module.config.php index eb30f7230..46b310152 100644 --- a/module/Olcs/config/module.config.php +++ b/module/Olcs/config/module.config.php @@ -1081,6 +1081,13 @@ 'id' => 'dashboard-messaging', 'label' => 'dashboard-nav-messaging', 'route' => 'conversations', + 'pages' => array( + array( + 'id' => 'messaging-create-conversation', + 'label' => 'New Conversation', + 'route' => 'conversations/new', + ), + ), ), ), ), diff --git a/module/Olcs/src/Controller/ConversationsController.php b/module/Olcs/src/Controller/ConversationsController.php index 9ea7e4665..43f9e86fe 100644 --- a/module/Olcs/src/Controller/ConversationsController.php +++ b/module/Olcs/src/Controller/ConversationsController.php @@ -17,6 +17,7 @@ use Dvsa\Olcs\Transfer\Query\Messaging\Conversations\ByOrganisation as ByOrganisationQuery; use Dvsa\Olcs\Utils\Translation\NiTextTranslation; use Laminas\Http\Response; +use Laminas\Navigation\Navigation; use Laminas\View\Model\ViewModel; use LmcRbacMvc\Service\AuthorizationService; use Olcs\Form\Model\Form\Message\Reply as ReplyForm; @@ -34,17 +35,20 @@ class ConversationsController extends AbstractController implements ToggleAwareI protected FlashMessengerHelperService $flashMessengerHelper; protected TableFactory $tableFactory; protected FormHelperService $formHelperService; + protected Navigation $navigationService; public function __construct( NiTextTranslation $niTextTranslationUtil, AuthorizationService $authService, FlashMessengerHelperService $flashMessengerHelper, TableFactory $tableFactory, - FormHelperService $formHelperService + FormHelperService $formHelperService, + Navigation $navigationService ) { $this->flashMessengerHelper = $flashMessengerHelper; $this->tableFactory = $tableFactory; $this->formHelperService = $formHelperService; + $this->navigationService = $navigationService; parent::__construct($niTextTranslationUtil, $authService); } @@ -150,6 +154,8 @@ private function mapFormDataToCommand(\Laminas\Form\Form $form): Create /** @return ViewModel|Response */ public function viewAction() { + $this->navigationService->findBy('id', 'dashboard-messaging')->setActive(); + $params = [ 'page' => $this->params()->fromQuery('page', 1), 'limit' => $this->params()->fromQuery('limit', 10), diff --git a/module/Olcs/src/Controller/Factory/ConversationsControllerFactory.php b/module/Olcs/src/Controller/Factory/ConversationsControllerFactory.php index c4f4a45b3..ed687c40b 100644 --- a/module/Olcs/src/Controller/Factory/ConversationsControllerFactory.php +++ b/module/Olcs/src/Controller/Factory/ConversationsControllerFactory.php @@ -8,6 +8,7 @@ use Common\Service\Helper\FormHelperService; use Common\Service\Table\TableFactory; use Dvsa\Olcs\Utils\Translation\NiTextTranslation; +use Laminas\Navigation\Navigation; use Psr\Container\ContainerInterface; use Laminas\ServiceManager\Factory\FactoryInterface; use LmcRbacMvc\Service\AuthorizationService; @@ -25,6 +26,7 @@ public function __invoke( $flashMessengerHelper = $container->get(FlashMessengerHelperService::class); $tableFactory = $container->get(TableFactory::class); $formHelperService = $container->get(FormHelperService::class); + $navigationService = $container->get(Navigation::class); return new ConversationsController( $niTextTranslationUtil, @@ -32,6 +34,7 @@ public function __invoke( $flashMessengerHelper, $tableFactory, $formHelperService, + $navigationService ); } } diff --git a/module/Olcs/src/Controller/Listener/Navigation.php b/module/Olcs/src/Controller/Listener/Navigation.php index 30286423e..93eea7f79 100644 --- a/module/Olcs/src/Controller/Listener/Navigation.php +++ b/module/Olcs/src/Controller/Listener/Navigation.php @@ -5,6 +5,7 @@ use Common\FeatureToggle; use Common\Rbac\User as RbacUser; use Common\Service\Cqrs\Query\QuerySender; +use Dvsa\Olcs\Transfer\Query\Messaging\Messages\UnreadCountByOrganisationAndUser; use Laminas\EventManager\EventManagerInterface; use Laminas\EventManager\ListenerAggregateInterface; use Laminas\EventManager\ListenerAggregateTrait; @@ -168,6 +169,8 @@ private function toggleMessagesTab(bool $shouldShowMessagesTab): void { $this->navigation->findBy('id', 'dashboard-messaging') ->setVisible($shouldShowMessagesTab); + + $this->addUnreadMessagingCount(); } private function shouldShowMessagesTab(): bool @@ -201,4 +204,26 @@ public function setGovUkReferers(array $govUkReferers): void { $this->govUkReferers = $govUkReferers; } + + public function getUnreadMessageCount(): int + { + $userOrganisationId = $this->identity->getUserData()['organisationUsers'][0]['organisation']['id']; + + $unreadByOrganisation = $this->querySender->send( + UnreadCountByOrganisationAndUser::create( + [ + 'organisation' => $userOrganisationId, + 'user' => $this->identity->getId(), + ] + ) + ); + + return($unreadByOrganisation->getResult()['count'] ?? 0); + } + + public function addUnreadMessagingCount(){ + $this->navigation->findBy('id', 'dashboard-licences-applications') + ->findBy('id','dashboard-messaging') + ->set('unreadMessageCount', $this->getUnreadMessageCount()); + } } diff --git a/module/Olcs/src/Service/Data/MessagingAppOrLicNo.php b/module/Olcs/src/Service/Data/MessagingAppOrLicNo.php index 1c9a24a49..bb648f2b0 100644 --- a/module/Olcs/src/Service/Data/MessagingAppOrLicNo.php +++ b/module/Olcs/src/Service/Data/MessagingAppOrLicNo.php @@ -63,8 +63,7 @@ public function formatDataForGroups(array $data): array private function prefixArrayKey(array &$array, string $prefix): void { - foreach ($array as $k => $v) - { + foreach ($array as $k => $v) { $array[$prefix . $k] = $v; unset($array[$k]); } diff --git a/module/Olcs/view/partials/tabs-nav.phtml b/module/Olcs/view/partials/tabs-nav.phtml index 3cd74166f..920939d4e 100644 --- a/module/Olcs/view/partials/tabs-nav.phtml +++ b/module/Olcs/view/partials/tabs-nav.phtml @@ -7,6 +7,15 @@ escapeHtml($this->translate($page->getLabel())); ?> get('count') ? '('.$page->get('count').')' : '';?> + id == "dashboard-messaging" && $page->get('unreadMessageCount') > 0): ?> +
+ + get('unreadMessageCount'); + ?> + +
+ diff --git a/test/Olcs/src/Controller/ConversationsControllerTest.php b/test/Olcs/src/Controller/ConversationsControllerTest.php index 34da9f68f..87bc2d90f 100644 --- a/test/Olcs/src/Controller/ConversationsControllerTest.php +++ b/test/Olcs/src/Controller/ConversationsControllerTest.php @@ -17,6 +17,7 @@ use Laminas\Http\Response as HttpResponse; use Laminas\Mvc\Controller\Plugin\Params; use Dvsa\Olcs\Transfer\Command\Messaging\Message\Create as CreateMessageCommand; +use Laminas\Navigation\Navigation; use Laminas\View\Model\ViewModel; use Mockery as m; use Mockery\Adapter\Phpunit\MockeryTestCase as TestCase; @@ -36,6 +37,7 @@ public function setUp(): void $this->mockFlashMessengerHelper = m::mock(FlashMessengerHelperService::class)->makePartial(); $this->mockTableFactory = m::mock(TableFactory::class)->makePartial(); $this->mockFormHelperService = m::mock(FormHelperService::class)->makePartial(); + $this->mockNavigation = m::mock(Navigation::class)->shouldIgnoreMissing(); $this->mockForm = m::mock(Form::class); $this->mockParams = m::mock(Params::class); @@ -49,6 +51,7 @@ public function setUp(): void $this->setMockedProperties($reflectionClass, 'flashMessengerHelper', $this->mockFlashMessengerHelper); $this->setMockedProperties($reflectionClass, 'tableFactory', $this->mockTableFactory); $this->setMockedProperties($reflectionClass, 'formHelperService', $this->mockFormHelperService); + $this->setMockedProperties($reflectionClass, 'navigationService', $this->mockNavigation); $this->mockFormHelperService->shouldReceive('createForm') ->once() @@ -120,6 +123,10 @@ public function testViewAction(): void ) ->andReturn($table); + $this->mockNavigation + ->shouldReceive('findBy->setActive') + ->once(); + $view = $this->sut->viewAction(); $this->assertInstanceOf(ViewModel::class, $view); $this->assertEquals($table, $view->getVariable('table')); diff --git a/test/Olcs/src/Controller/Listener/NavigationTest.php b/test/Olcs/src/Controller/Listener/NavigationTest.php index 0a5b4fa59..865dace7d 100644 --- a/test/Olcs/src/Controller/Listener/NavigationTest.php +++ b/test/Olcs/src/Controller/Listener/NavigationTest.php @@ -4,6 +4,7 @@ use Common\Rbac\User as RbacUser; use Common\Service\Cqrs\Query\QuerySender; +use Laminas\Navigation\Page\AbstractPage; use Olcs\Controller\Listener\Navigation as NavigationListener; use Mockery as m; use Laminas\Http\Header\Referer as HttpReferer; @@ -11,6 +12,7 @@ use Laminas\Navigation\Navigation; use Laminas\Navigation\Page\Uri; use Laminas\Mvc\MvcEvent; +use Common\Service\Cqrs\Response as CqrsResponse; /** * Class NavigationToggleTest @@ -34,6 +36,7 @@ public function setUp(): void { $this->mockNavigation = m::mock(Navigation::class); $this->mockQuerySender = m::mock(QuerySender::class); + $this->mockResponse = m::mock(CqrsResponse::class); $this->mockIdentity = m::mock(RbacUser::class); $this->sut = new NavigationListener($this->mockNavigation, $this->mockQuerySender, $this->mockIdentity); @@ -42,6 +45,10 @@ public function setUp(): void $this->dashboardMessagingKey = 'dashboard-messaging'; $this->dashboardMessagingPage = new Uri(); + + $this->dashboardMenuKey = 'dashboard-licences-applications'; + $this->mockDashboardMenu = m::mock(AbstractPage::class); + $this->messagingToggle = 'messaging'; } @@ -60,13 +67,14 @@ public function testOnDispatchWithNoReferalAnonymousUser() $this->mockIdentity->shouldReceive('isAnonymous')->once()->withNoArgs()->andReturn(true); $this->mockIdentity->expects('getUserData') - ->once() + ->twice() ->andReturn([ 'hasOrganisationSubmittedLicenceApplication' => false, 'organisationUsers' => [ 0 => [ 'organisation' => [ - 'isMessagingDisabled' => false + 'isMessagingDisabled' => false, + 'id' => 1, ] ] ] @@ -76,16 +84,39 @@ public function testOnDispatchWithNoReferalAnonymousUser() $this->mockNavigation ->shouldReceive('findBy') - ->with('id', $this->dashboardPermitsKey) ->twice() + ->with('id', $this->dashboardPermitsKey) ->andReturn($this->dashboardPermitsPage); $this->mockNavigation ->shouldReceive('findBy') - ->with('id', $this->dashboardMessagingKey) ->twice() + ->with('id', $this->dashboardMessagingKey) + ->andReturn($this->dashboardMessagingPage); + + $this->mockNavigation + ->shouldReceive('findBy') + ->with('id', $this->dashboardMenuKey) + ->once() + ->andReturn($this->mockDashboardMenu); + + $this->mockDashboardMenu + ->shouldReceive('findBy') + ->with('id', $this->dashboardMessagingKey) + ->once() ->andReturn($this->dashboardMessagingPage); + $this->mockIdentity->shouldReceive('getId') + ->once() + ->andReturn(1); + + $this->mockQuerySender->shouldReceive('send') + ->once() + ->andReturn($this->mockResponse); + + $this->mockResponse->shouldReceive('getResult') + ->once(); + $request = m::mock(HttpRequest::class); $request->shouldReceive('getHeader')->once()->with('referer')->andReturn(false); @@ -114,14 +145,15 @@ public function testOnDispatchWithNoReferal($eligibleForPermits) $this->mockIdentity->shouldReceive('isAnonymous')->once()->withNoArgs()->andReturn(false); $this->mockIdentity->expects('getUserData') - ->twice() + ->times(3) ->andReturn([ 'eligibleForPermits' => $eligibleForPermits, 'hasOrganisationSubmittedLicenceApplication' => false, 'organisationUsers' => [ 0 => [ 'organisation' => [ - 'isMessagingDisabled' => false + 'isMessagingDisabled' => false, + 'id' => 1, ] ] ] @@ -129,17 +161,7 @@ public function testOnDispatchWithNoReferal($eligibleForPermits) $this->mockQuerySender->shouldReceive('featuresEnabled')->with([$this->messagingToggle])->once(); - $this->mockNavigation - ->shouldReceive('findBy') - ->with('id', $this->dashboardPermitsKey) - ->twice() - ->andReturn($this->dashboardPermitsPage); - - $this->mockNavigation - ->shouldReceive('findBy') - ->with('id', $this->dashboardMessagingKey) - ->once() - ->andReturn($this->dashboardMessagingPage); + $this->navigationExpectations(); $request = m::mock(HttpRequest::class); $request->shouldReceive('getHeader')->once()->with('referer')->andReturn(false); @@ -176,13 +198,14 @@ public function testOnDispatchWithGovUkReferalMatch() $request->shouldReceive('getHeader')->once()->with('referer')->andReturn($referer); $this->mockIdentity->expects('getUserData') - ->once() + ->twice() ->andReturn([ 'hasOrganisationSubmittedLicenceApplication' => false, 'organisationUsers' => [ 0 => [ 'organisation' => [ - 'isMessagingDisabled' => false + 'isMessagingDisabled' => false, + 'id' => 1, ] ] ] @@ -190,17 +213,7 @@ public function testOnDispatchWithGovUkReferalMatch() $this->mockQuerySender->shouldReceive('featuresEnabled')->once()->with([$this->messagingToggle]); - $this->mockNavigation - ->shouldReceive('findBy') - ->twice() - ->with('id', $this->dashboardPermitsKey) - ->andReturn($this->dashboardPermitsPage); - - $this->mockNavigation - ->shouldReceive('findBy') - ->with('id', $this->dashboardMessagingKey) - ->once() - ->andReturn($this->dashboardMessagingPage); + $this->navigationExpectations(); /** @var \Laminas\Mvc\MvcEvent | m\MockInterface $mockEvent */ $mockEvent = m::mock(\Laminas\Mvc\MvcEvent::class); @@ -222,30 +235,21 @@ public function testOnDispatchWithNoGovUkReferal($eligibleForPermits) ->andReturn(false); $this->mockIdentity->expects('getUserData') - ->twice() + ->times(3) ->andReturn([ 'eligibleForPermits' => $eligibleForPermits, 'hasOrganisationSubmittedLicenceApplication' => false, 'organisationUsers' => [ 0 => [ 'organisation' => [ - 'isMessagingDisabled' => false + 'isMessagingDisabled' => false, + 'id' => 1, ] ] ] ]); - $this->mockNavigation - ->shouldReceive('findBy') - ->twice() - ->with('id', $this->dashboardPermitsKey) - ->andReturn($this->dashboardPermitsPage); - - $this->mockNavigation - ->shouldReceive('findBy') - ->once() - ->with('id', $this->dashboardMessagingKey) - ->andReturn($this->dashboardMessagingPage); + $this->navigationExpectations(); //mock the http referer - this will be checked against our list of gov.uk referers (and won't match) $referer = m::mock(HttpReferer::class); @@ -274,4 +278,42 @@ public function dpDispatchWithoutMatchedReferer() [false], ]; } + + public function navigationExpectations(){ + $this->mockNavigation + ->shouldReceive('findBy') + ->twice() + ->with('id', $this->dashboardPermitsKey) + ->andReturn($this->dashboardPermitsPage); + + $this->mockNavigation + ->shouldReceive('findBy') + ->once() + ->with('id', $this->dashboardMessagingKey) + ->andReturn($this->dashboardMessagingPage); + + $this->mockNavigation + ->shouldReceive('findBy') + ->with('id', $this->dashboardMenuKey) + ->once() + ->andReturn($this->mockDashboardMenu); + + $this->mockDashboardMenu + ->shouldReceive('findBy') + ->with('id', $this->dashboardMessagingKey) + ->once() + ->andReturn($this->dashboardMessagingPage); + + $this->mockIdentity->shouldReceive('getId') + ->once() + ->andReturn(1); + + $this->mockQuerySender->shouldReceive('send') + ->once() + ->andReturn($this->mockResponse); + + $this->mockResponse->shouldReceive('getResult') + ->once(); + } + }