Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: GlobalScreen: Client-Side Notifications #2119

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php namespace ILIAS\BackgroundTasks\Provider;

use ILIAS\GlobalScreen\Scope\Notification\Factory\isItem;
use ILIAS\GlobalScreen\Scope\Notification\Provider\AbstractClientSideNotificationProvider;
use ILIAS\GlobalScreen\Scope\Notification\Provider\ClientSideNotificationProvider;

/**
* Class BTClientSideNotificationProvider
*
* @author Fabian Schmid <[email protected]>
*/
class BTClientSideNotificationProvider extends AbstractClientSideNotificationProvider implements ClientSideNotificationProvider
{

/**
* @inheritDoc
*/
public function getClientSideProviderName() : string
{
return "BTClientSideNotificationProvider";
}


/**
* @inheritDoc
*/
public function enrichItem(isItem $notification) : isItem
{
// here you can "fill" your notification server side

return $notification;
}
}
4 changes: 4 additions & 0 deletions Services/GlobalScreen/artifacts/global_screen_providers.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,8 @@
1 => 'ILIAS\\Contact\\Provider\\ContactNotificationProvider',
2 => 'ILIAS\\Mail\\Provider\\MailNotificationProvider',
),
'ILIAS\\GlobalScreen\\Client\\ClientSideProvider' =>
array (
0 => 'ILIAS\\BackgroundTasks\\Provider\\BTClientSideNotificationProvider',
),
);
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php

use ILIAS\GlobalScreen\Client\ClientSideProvider;
use ILIAS\GlobalScreen\Scope\Layout\Provider\ModificationProvider;
use ILIAS\GlobalScreen\Scope\MainMenu\Provider\StaticMainMenuProvider;
use ILIAS\GlobalScreen\Scope\MetaBar\Provider\StaticMetaBarProvider;
Expand Down Expand Up @@ -30,6 +31,7 @@ public function build() : Setup\Artifact
DynamicToolProvider::class,
ModificationProvider::class,
NotificationProvider::class,
ClientSideProvider::class,
];

foreach ($i as $interface) {
Expand Down
16 changes: 16 additions & 0 deletions Services/GlobalScreen/classes/class.ilGSProviderFactory.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

use ILIAS\DI\Container;
use ILIAS\GlobalScreen\Client\ClientSideProvider;
use ILIAS\GlobalScreen\Provider\Provider;
use ILIAS\GlobalScreen\Provider\ProviderFactory;
use ILIAS\GlobalScreen\Scope\Layout\Provider\ModificationProvider;
Expand Down Expand Up @@ -142,6 +143,21 @@ public function getNotificationsProvider() : array
}


/**
* @inheritDoc
*/
public function getClientSideProviders() : array
{
$providers = [];
// Core
$this->appendCore($providers, ClientSideProvider::class);

$this->registerInternal($providers);

return $providers;
}


/**
* @param array $array_of_core_providers
* @param string $interface
Expand Down
17 changes: 17 additions & 0 deletions src/GlobalScreen/Client/Provider/ClientSideProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php namespace ILIAS\GlobalScreen\Client;

use ILIAS\GlobalScreen\Provider\Provider;

/**
* Class ClientSideProvider
*
* @author Fabian Schmid <[email protected]>
*/
interface ClientSideProvider extends Provider
{

/**
* @return string
*/
public function getClientSideProviderName() : string;
}
50 changes: 50 additions & 0 deletions src/GlobalScreen/Client/Provider/ClientSideProviderRegistrar.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php namespace ILIAS\GlobalScreen\Client;

use ILIAS\GlobalScreen\Scope\Layout\MetaContent\MetaContent;

/**
* Class ClientSideProviderRegistrar
*
* @author Fabian Schmid <[email protected]>
*/
class ClientSideProviderRegistrar
{

/**
* @var MetaContent
*/
private $meta_content;


/**
* ClientSideProviderRegistrar constructor.
*
* @param MetaContent $meta_content
*/
public function __construct(MetaContent $meta_content)
{
$this->meta_content = $meta_content;
$this->meta_content->addJs('./src/GlobalScreen/Client/dist/GS.js', 1, 1);
$this->meta_content->addJs('./src/GlobalScreen/Client/dist/test.js', 1, 2);
}


/**
* @return string
*/
public function registerProviderClientSideCode(ClientSideProvider $provider)
{

$provider_name = $provider->getClientSideProviderName();

$deo = <<<EOT
$( document ).ready(function() {
var $provider_name;
$provider_name = il.GS.Services.provider().getByProviderName('$provider_name');
console.log($provider_name);
});
EOT;

$this->meta_content->addOnloadCode($deo);
}
}
73 changes: 73 additions & 0 deletions src/GlobalScreen/Client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
Client Side GlobalScreen
========================

> Attention: This is not a general approach how to do client-side rendering in ILIAS or even bypass it. This mechanism is implemented due to the missing client-side rendering for the requirements of chat notifications. The discussion about client-side rendering will be conducted separately and should provide a general approach.

> This part of the GlobalScreen service also contains TypeScript code. Work is already underway on this in a wide variety of places. This suggestion here is not to bypass this by any means or to deliver final concepts for the use of TypeScript in ILIAS. TypeScript was only used here to have a more understandable and secure structure in JS. We are already looking forward to the discussions about TypeScript.



There are different scenarios in which besides the `Items` provided by the GlobalScreen providers on the server side, `Items` on the client side can also arise.

Such a case are the `Notifications`: Beside all the notifications, which are offered on the server side by the NotificationProvider, the chat client side must have the possibility to communicate own notifications to the `MainNotificationCollector` as well.

For the moment, this requirement is solved as described below.

> At the moment some projects are taking place around ILIAS to find more central ways for such problems. As soon as an ILIAS-wide approach exists, the GlobalScreen service will adhere to it.

## ClientSideProvider
A `ClientSideProvider` allows you to generate your own items of a scope in a similar way as on the server side and communicate them to a collector. At the moment there is only the possibility to create `ClientSideNotificationProvider` within a POC. More about this under the description of the `Notifications`: Documentation](../Scope/Notification/README.md)

All `ClientSideProviders` are collected on the server side by a collector and registered on the client side using the `ClientSideProviderRegistrar`.

On the client side, similar services are available as on the server side:

```typescript
export class Services {

...

public static provider(): ProviderFactory {
...
}

public static identification(provider: isProvider, internal_identifier: string) {
...
}

public static collector(): CollectorFactory {
...
}

public static factory(): DTOFactory {
...
}
}
```

With the help of these services you can now compile NotificationDTOs on the client side and log on to the collector:

```javascript
// Get My Provider
var provider = il.GS.Services.provider().getByProviderName('BTClientSideNotificationProvider');

// Create a new Identification
var identification = il.GS.Services.identification(provider, 'my_first_notification');

// Create a new NotificationDTO and fill it with some stuff
var one_notification = il.GS.Services.factory().notifications().onScreen(identification);

one_notification.title = "My Title";
one_notification.summary = "My Summary";

// get the Notifications Collector and push my notification
var collector = il.GS.Services.collector().notifications();

collector.push(one_notification);

```

> From here on, a conceptual description of how the client side can communicate with the server side follows. This in connection with notifications. None of this is implemented yet.


In the case of the Notification Center, all NotificationDTS could now be sent with the asynchronous retrieval of the HTML content of the Notification Center. NotificationDTS can be serialized and converted to effective notifications, e.g. `StandardNotification`, during server-side readout. Since these do not have all the information that a `StandardNotification` should have, they can be supplemented by the corresponding `ClientSideNotificationProvider` with `public function enrichItem(isItem $notification) : isItem;` to full server-side notifications. These, together with all other server-side notifications, can then be rendered and displayed in the NotificationCenter.
52 changes: 52 additions & 0 deletions src/GlobalScreen/Client/dist/GS.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,10 @@ var il;
return new StandardIdentification(elements[1], provider);
}
Identification.getFromServerSideString = getFromServerSideString;
function getFromClientSideString(client_side_string, provider) {
return new StandardIdentification(client_side_string, provider);
}
Identification.getFromClientSideString = getFromClientSideString;
class StandardIdentification {
constructor(internal_identifier, provider) {
this.internal_identifier = internal_identifier;
Expand All @@ -314,5 +318,53 @@ var il;
}
Identification.StandardIdentification = StandardIdentification;
})(Identification = GS.Identification || (GS.Identification = {}));
let Collector;
(function (Collector) {
class CollectorFactory {
notifications() {
return new NotificationCollector();
}
}
Collector.CollectorFactory = CollectorFactory;
class NotificationCollector {
constructor() {
this.dtos = [];
}
getAll() {
return this.dtos;
}
push(dto) {
this.dtos.push(dto);
}
}
})(Collector = GS.Collector || (GS.Collector = {}));
let DTO;
(function (DTO) {
let Notifications;
(function (Notifications) {
var Logger = il.Utilities.Logger;
class OnScreenNotificationDTO {
constructor(identification) {
this.identification = identification;
this.date = new Date();
}
}
Notifications.OnScreenNotificationDTO = OnScreenNotificationDTO;
class NotificationDTOFactory {
onScreen(identification) {
Logger.log('want to have an OnScreenNotificationDTO for identification ' + identification.toString());
return new OnScreenNotificationDTO(identification);
}
}
Notifications.NotificationDTOFactory = NotificationDTOFactory;
})(Notifications = DTO.Notifications || (DTO.Notifications = {}));
var NotificationDTOFactory = il.GS.DTO.Notifications.NotificationDTOFactory;
class DTOFactory {
notifications() {
return new NotificationDTOFactory();
}
}
DTO.DTOFactory = DTOFactory;
})(DTO = GS.DTO || (GS.DTO = {}));
})(GS = il.GS || (il.GS = {}));
})(il || (il = {}));
14 changes: 14 additions & 0 deletions src/GlobalScreen/Client/dist/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
var provider = il.GS.Provider.getClientSideProvider('BTClientSideNotificationProvider')


var identification = il.GS.Identification.getFromClientSideString('my_first_notification', provider);
var one_notification = il.GS.DTO.notifications().onScreen(identification);

one_notification.title = "My Title";
one_notification.summary = "My Summary";

var collector = il.GS.Collector.NotificationCollector.notifications();

collector.push(one_notification);

console.log(collector.getAll());
Loading