From f45a73cdc23b805ae3ce8af3e31e84194d9a3f12 Mon Sep 17 00:00:00 2001 From: Fabian Schmid Date: Fri, 16 Aug 2019 10:12:20 +0200 Subject: [PATCH 1/2] [FEATURE] Notifications and Client-side GlobalScreen (Draft) --- .../BTClientSideNotificationProvider.php | 33 +++ .../Provider/BTNotificationProvider.php | 41 ++++ .../artifacts/global_screen_providers.php | 13 +- ...lGlobalScreenBuildProviderMapObjective.php | 4 + .../classes/class.ilGSProviderFactory.php | 32 +++ .../Client/Provider/ClientSideProvider.php | 17 ++ .../Provider/ClientSideProviderRegistrar.php | 50 +++++ src/GlobalScreen/Client/README.md | 67 ++++++ src/GlobalScreen/Client/dist/GS.js | 144 +++++++++++++ src/GlobalScreen/Client/dist/test.js | 12 ++ src/GlobalScreen/Client/src/GS.ts | 200 ++++++++++++++++++ src/GlobalScreen/Client/tsconfig.json | 16 ++ .../Collector/CollectorFactory.php | 13 +- .../Provider/NullProviderFactory.php | 18 ++ src/GlobalScreen/Provider/ProviderFactory.php | 14 ++ src/GlobalScreen/README.md | 4 + .../Layout/Collector/MainLayoutCollector.php | 33 ++- .../Renderer/NotificationCenterRenderer.php | 58 +++++ .../MetaBar/Factory/MetaBarItemFactory.php | 17 ++ .../MetaBar/Factory/NotificationCenter.php | 90 ++++++++ .../Provider/NotificationCenterProvider.php | 38 ++++ .../Collector/MainNotificationCollector.php | 44 ++++ .../AbstractBaseNotificationRenderer.php | 45 ++++ .../Renderer/NotificationRenderer.php | 24 +++ .../StandardNotificationGroupRenderer.php | 45 ++++ .../Renderer/StandardNotificationRenderer.php | 31 +++ .../Factory/AbstractBaseNotification.php | 48 +++++ .../Factory/AbstractTitleNotification.php | 57 +++++ .../Factory/NotificationFactory.php | 33 +++ .../Factory/StandardNotification.php | 196 +++++++++++++++++ .../Factory/StandardNotificationGroup.php | 49 +++++ .../Notification/Factory/canHaveSymbol.php | 31 +++ .../Scope/Notification/Factory/hasActions.php | 65 ++++++ .../Scope/Notification/Factory/hasTitle.php | 37 ++++ .../Scope/Notification/Factory/isItem.php | 24 +++ .../Notification/NotificationServices.php | 24 +++ ...AbstractClientSideNotificationProvider.php | 46 ++++ .../Provider/AbstractNotificationProvider.php | 39 ++++ .../ClientSideNotificationProvider.php | 20 ++ .../Provider/NotificationProvider.php | 18 ++ src/GlobalScreen/Scope/Notification/README.md | 64 ++++++ src/GlobalScreen/Services.php | 10 + 42 files changed, 1859 insertions(+), 5 deletions(-) create mode 100644 Services/BackgroundTasks/classes/Provider/BTClientSideNotificationProvider.php create mode 100644 Services/BackgroundTasks/classes/Provider/BTNotificationProvider.php create mode 100644 src/GlobalScreen/Client/Provider/ClientSideProvider.php create mode 100644 src/GlobalScreen/Client/Provider/ClientSideProviderRegistrar.php create mode 100644 src/GlobalScreen/Client/README.md create mode 100644 src/GlobalScreen/Client/dist/GS.js create mode 100644 src/GlobalScreen/Client/dist/test.js create mode 100644 src/GlobalScreen/Client/src/GS.ts create mode 100644 src/GlobalScreen/Client/tsconfig.json create mode 100644 src/GlobalScreen/Scope/MetaBar/Collector/Renderer/NotificationCenterRenderer.php create mode 100644 src/GlobalScreen/Scope/MetaBar/Factory/NotificationCenter.php create mode 100644 src/GlobalScreen/Scope/MetaBar/Provider/NotificationCenterProvider.php create mode 100644 src/GlobalScreen/Scope/Notification/Collector/MainNotificationCollector.php create mode 100644 src/GlobalScreen/Scope/Notification/Collector/Renderer/AbstractBaseNotificationRenderer.php create mode 100644 src/GlobalScreen/Scope/Notification/Collector/Renderer/NotificationRenderer.php create mode 100644 src/GlobalScreen/Scope/Notification/Collector/Renderer/StandardNotificationGroupRenderer.php create mode 100644 src/GlobalScreen/Scope/Notification/Collector/Renderer/StandardNotificationRenderer.php create mode 100644 src/GlobalScreen/Scope/Notification/Factory/AbstractBaseNotification.php create mode 100644 src/GlobalScreen/Scope/Notification/Factory/AbstractTitleNotification.php create mode 100644 src/GlobalScreen/Scope/Notification/Factory/NotificationFactory.php create mode 100644 src/GlobalScreen/Scope/Notification/Factory/StandardNotification.php create mode 100644 src/GlobalScreen/Scope/Notification/Factory/StandardNotificationGroup.php create mode 100644 src/GlobalScreen/Scope/Notification/Factory/canHaveSymbol.php create mode 100644 src/GlobalScreen/Scope/Notification/Factory/hasActions.php create mode 100644 src/GlobalScreen/Scope/Notification/Factory/hasTitle.php create mode 100644 src/GlobalScreen/Scope/Notification/Factory/isItem.php create mode 100644 src/GlobalScreen/Scope/Notification/NotificationServices.php create mode 100644 src/GlobalScreen/Scope/Notification/Provider/AbstractClientSideNotificationProvider.php create mode 100644 src/GlobalScreen/Scope/Notification/Provider/AbstractNotificationProvider.php create mode 100644 src/GlobalScreen/Scope/Notification/Provider/ClientSideNotificationProvider.php create mode 100644 src/GlobalScreen/Scope/Notification/Provider/NotificationProvider.php create mode 100644 src/GlobalScreen/Scope/Notification/README.md diff --git a/Services/BackgroundTasks/classes/Provider/BTClientSideNotificationProvider.php b/Services/BackgroundTasks/classes/Provider/BTClientSideNotificationProvider.php new file mode 100644 index 000000000000..2423622f143a --- /dev/null +++ b/Services/BackgroundTasks/classes/Provider/BTClientSideNotificationProvider.php @@ -0,0 +1,33 @@ + + */ +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; + } +} diff --git a/Services/BackgroundTasks/classes/Provider/BTNotificationProvider.php b/Services/BackgroundTasks/classes/Provider/BTNotificationProvider.php new file mode 100644 index 000000000000..d9461d48c899 --- /dev/null +++ b/Services/BackgroundTasks/classes/Provider/BTNotificationProvider.php @@ -0,0 +1,41 @@ + + */ +class BTNotificationProvider extends AbstractNotificationProvider implements NotificationProvider +{ + + /** + * @inheritDoc + */ + public function getNotifications() : array + { + $id = function (string $id) : IdentificationInterface { + return $this->if->identifier($id); + }; + + $factory = $this->globalScreen()->notifications()->factory(); + + $group = $factory->standardGroup($id('bg_bucket_group'))->withTitle("Some Notifications"); + + for ($x = 1; $x < 10; $x++) { + $n = $factory->standard($id('bg_bucket_id_' . $x)) + ->withTitle("A Notification " . $x) + ->withSummary("with a super summary " . $x) + ->withAction("#"); + + $group->addNotification($n); + } + + return [ + $group, + ]; + } +} diff --git a/Services/GlobalScreen/artifacts/global_screen_providers.php b/Services/GlobalScreen/artifacts/global_screen_providers.php index bcac6d4dde96..0d3c04867e36 100644 --- a/Services/GlobalScreen/artifacts/global_screen_providers.php +++ b/Services/GlobalScreen/artifacts/global_screen_providers.php @@ -26,8 +26,9 @@ 'ILIAS\\GlobalScreen\\Scope\\MetaBar\\Provider\\StaticMetaBarProvider' => array ( 0 => 'ILIAS\\BackgroundTasks\\Provider\\BackgroundTasksMetaBarProvider', - 1 => 'ILIAS\\Search\\Provider\\SearchMetaBarProvider', - 2 => 'ILIAS\\User\\Provider\\UserMetaBarProvider', + 1 => 'ILIAS\\GlobalScreen\\Scope\\MetaBar\\Provider\\NotificationCenterProvider', + 2 => 'ILIAS\\Search\\Provider\\SearchMetaBarProvider', + 3 => 'ILIAS\\User\\Provider\\UserMetaBarProvider', ), 'ILIAS\\GlobalScreen\\Scope\\Tool\\Provider\\DynamicToolProvider' => array ( @@ -38,4 +39,12 @@ 0 => 'ILIAS\\Container\\Screen\\MemberViewLayoutProvider', 1 => 'ILIAS\\UICore\\PageContentProvider', ), + 'ILIAS\\GlobalScreen\\Scope\\Notification\\Provider\\NotificationProvider' => + array ( + 0 => 'ILIAS\\BackgroundTasks\\Provider\\BTNotificationProvider', + ), + 'ILIAS\\GlobalScreen\\Client\\ClientSideProvider' => + array ( + 0 => 'ILIAS\\BackgroundTasks\\Provider\\BTClientSideNotificationProvider', + ), ); \ No newline at end of file diff --git a/Services/GlobalScreen/classes/Setup/class.ilGlobalScreenBuildProviderMapObjective.php b/Services/GlobalScreen/classes/Setup/class.ilGlobalScreenBuildProviderMapObjective.php index 2200d8662b98..61cc48e06067 100644 --- a/Services/GlobalScreen/classes/Setup/class.ilGlobalScreenBuildProviderMapObjective.php +++ b/Services/GlobalScreen/classes/Setup/class.ilGlobalScreenBuildProviderMapObjective.php @@ -1,8 +1,10 @@ appendCore($providers, NotificationProvider::class); + + $this->registerInternal($providers); + + return $providers; + } + + + /** + * @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 diff --git a/src/GlobalScreen/Client/Provider/ClientSideProvider.php b/src/GlobalScreen/Client/Provider/ClientSideProvider.php new file mode 100644 index 000000000000..5923ea6bf9c1 --- /dev/null +++ b/src/GlobalScreen/Client/Provider/ClientSideProvider.php @@ -0,0 +1,17 @@ + + */ +interface ClientSideProvider extends Provider +{ + + /** + * @return string + */ + public function getClientSideProviderName() : string; +} diff --git a/src/GlobalScreen/Client/Provider/ClientSideProviderRegistrar.php b/src/GlobalScreen/Client/Provider/ClientSideProviderRegistrar.php new file mode 100644 index 000000000000..ec49c9b6c4b5 --- /dev/null +++ b/src/GlobalScreen/Client/Provider/ClientSideProviderRegistrar.php @@ -0,0 +1,50 @@ + + */ +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 = <<meta_content->addOnloadCode($deo); + } +} diff --git a/src/GlobalScreen/Client/README.md b/src/GlobalScreen/Client/README.md new file mode 100644 index 000000000000..77f6147eaf27 --- /dev/null +++ b/src/GlobalScreen/Client/README.md @@ -0,0 +1,67 @@ +Client Side GlobalScreen +======================== + +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. \ No newline at end of file diff --git a/src/GlobalScreen/Client/dist/GS.js b/src/GlobalScreen/Client/dist/GS.js new file mode 100644 index 000000000000..f5ffdd4713fe --- /dev/null +++ b/src/GlobalScreen/Client/dist/GS.js @@ -0,0 +1,144 @@ +var il; +(function (il) { + var GS; + (function (GS) { + var Logger = (function () { + function Logger() { + } + Logger.log = function (item) { + if (this.debug) { + var line = String(item); + console.log("GlobalScreen: " + line); + } + }; + Logger.debug = true; + return Logger; + }()); + var Provider; + (function (Provider) { + var ProviderFactory = (function () { + function ProviderFactory() { + this.providers = []; + } + ProviderFactory.prototype.getByProviderName = function (provider_name) { + for (var _i = 0, _a = this.providers; _i < _a.length; _i++) { + var provider = _a[_i]; + if (provider.provider_name === provider_name) { + return provider; + } + } + var clientSideProvider = new ClientSideProvider(provider_name); + this.providers.push(clientSideProvider); + return clientSideProvider; + }; + return ProviderFactory; + }()); + Provider.ProviderFactory = ProviderFactory; + var ClientSideProvider = (function () { + function ClientSideProvider(provider_name) { + this.provider_name = provider_name; + } + return ClientSideProvider; + }()); + Provider.ClientSideProvider = ClientSideProvider; + })(Provider = GS.Provider || (GS.Provider = {})); + var Identification; + (function (Identification) { + var StandardIdentification = (function () { + function StandardIdentification(internal_identifier, provider) { + this.internal_identifier = internal_identifier; + this.provider = provider; + } + StandardIdentification.prototype.toString = function () { + return this.provider.provider_name + "|" + this.internal_identifier; + }; + return StandardIdentification; + }()); + Identification.StandardIdentification = StandardIdentification; + })(Identification = GS.Identification || (GS.Identification = {})); + var Collector; + (function (Collector) { + var CollectorFactory = (function () { + function CollectorFactory() { + } + CollectorFactory.prototype.notifications = function () { + return new NotificationCollector(); + }; + return CollectorFactory; + }()); + Collector.CollectorFactory = CollectorFactory; + var NotificationCollector = (function () { + function NotificationCollector() { + this.dtos = []; + } + NotificationCollector.prototype.getAll = function () { + return this.dtos; + }; + NotificationCollector.prototype.push = function (dto) { + this.dtos.push(dto); + }; + return NotificationCollector; + }()); + })(Collector = GS.Collector || (GS.Collector = {})); + var DTO; + (function (DTO) { + var Notifications; + (function (Notifications) { + var OnScreenNotificationDTO = (function () { + function OnScreenNotificationDTO(identification) { + this.identification = identification; + this.date = new Date(); + } + return OnScreenNotificationDTO; + }()); + Notifications.OnScreenNotificationDTO = OnScreenNotificationDTO; + var NotificationDTOFactory = (function () { + function NotificationDTOFactory() { + } + NotificationDTOFactory.prototype.onScreen = function (identification) { + Logger.log('want to have an OnScreenNotificationDTO for identification ' + identification.toString()); + return new OnScreenNotificationDTO(identification); + }; + return NotificationDTOFactory; + }()); + Notifications.NotificationDTOFactory = NotificationDTOFactory; + })(Notifications = DTO.Notifications || (DTO.Notifications = {})); + var DTOFactory = (function () { + function DTOFactory() { + } + DTOFactory.prototype.notifications = function () { + return new NotificationDTOFactory(); + }; + return DTOFactory; + }()); + DTO.DTOFactory = DTOFactory; + })(DTO = GS.DTO || (GS.DTO = {})); + var DTOFactory = il.GS.DTO.DTOFactory; + var NotificationDTOFactory = il.GS.DTO.Notifications.NotificationDTOFactory; + var StandardIdentification = il.GS.Identification.StandardIdentification; + var ProviderFactory = il.GS.Provider.ProviderFactory; + var CollectorFactory = il.GS.Collector.CollectorFactory; + var Services = (function () { + function Services() { + } + Services.provider = function () { + return this.provider_factory; + }; + Services.identification = function (provider, internal_identifier) { + Logger.log("register identification for provider " + provider.provider_name + " and internal id " + internal_identifier); + return new StandardIdentification(internal_identifier, provider); + }; + Services.collector = function () { + return this.collector_factory; + }; + Services.factory = function () { + return this.dto_factory; + }; + Services.provider_factory = new ProviderFactory(); + Services.collector_factory = new CollectorFactory(); + Services.dto_factory = new DTOFactory(); + return Services; + }()); + GS.Services = Services; + })(GS = il.GS || (il.GS = {})); +})(il || (il = {})); diff --git a/src/GlobalScreen/Client/dist/test.js b/src/GlobalScreen/Client/dist/test.js new file mode 100644 index 000000000000..7073c7b9a0b7 --- /dev/null +++ b/src/GlobalScreen/Client/dist/test.js @@ -0,0 +1,12 @@ +var provider = il.GS.Services.provider().getByProviderName('BTClientSideNotificationProvider'); +var identification = il.GS.Services.identification(provider, 'my_first_notification'); +var one_notification = il.GS.Services.factory().notifications().onScreen(identification); + +one_notification.title = "My Title"; +one_notification.summary = "My Summary"; + +var collector = il.GS.Services.collector().notifications(); + +collector.push(one_notification); + +console.log(collector.getAll()); \ No newline at end of file diff --git a/src/GlobalScreen/Client/src/GS.ts b/src/GlobalScreen/Client/src/GS.ts new file mode 100644 index 000000000000..4fad3f7797bf --- /dev/null +++ b/src/GlobalScreen/Client/src/GS.ts @@ -0,0 +1,200 @@ +namespace il { + + /** + * Module GlobalScreen + */ + export module GS { + + + /** + * Logger + */ + class Logger { + private static readonly debug = true; + + static log(item: any): void { + if (this.debug) { + let line = String(item); + console.log("GlobalScreen: " + line) + } + + } + } + + /** + * Provider + */ + export namespace Provider { + export class ProviderFactory { + private readonly providers: isProvider[]; + + + constructor() { + this.providers = []; + } + + public getByProviderName(provider_name: string) { + for (let provider of this.providers) { + if (provider.provider_name === provider_name) { + return provider; + } + } + let clientSideProvider = new ClientSideProvider(provider_name); + this.providers.push(clientSideProvider); + return clientSideProvider; + } + } + + export interface isProvider { + provider_name: string; + } + + export class ClientSideProvider implements isProvider { + + constructor(provider_name: string) { + this.provider_name = provider_name; + } + + provider_name: string; + + } + } + + + /** + * Identification + */ + export namespace Identification { + import isProvider = il.GS.Provider.isProvider; + + export interface isIdentification { + provider: isProvider, + internal_identifier: string; + + toString(): string; + } + + + export class StandardIdentification implements isIdentification { + + constructor(internal_identifier: string, provider: isProvider) { + this.internal_identifier = internal_identifier; + this.provider = provider; + } + + internal_identifier: string; + provider: isProvider; + + toString(): string { + return this.provider.provider_name + "|" + this.internal_identifier; + } + } + } + + /** + * Collector + */ + export namespace Collector { + import isDTO = il.GS.DTO.isDTO; + + export class CollectorFactory { + notifications(): NotificationCollector { + return new NotificationCollector(); + } + } + + + class NotificationCollector { + private dtos: isDTO[] = []; + + + getAll(): isDTO[] { + return this.dtos; + } + + push(dto: isDTO): void { + this.dtos.push(dto); + } + } + } + export namespace DTO { + /** + * DTO + */ + import isIdentification = il.GS.Identification.isIdentification; + + + export interface isDTO { + identification: isIdentification; + } + + export namespace Notifications { + export class OnScreenNotificationDTO implements isDTO { + constructor(identification: il.GS.Identification.isIdentification) { + this.identification = identification; + this.date = new Date(); + } + + identification: isIdentification; + title: string; + summary: string; + date: Date; + } + + export class NotificationDTOFactory { + public onScreen(identification: isIdentification): OnScreenNotificationDTO { + Logger.log('want to have an OnScreenNotificationDTO for identification ' + identification.toString()) + return new OnScreenNotificationDTO(identification); + } + } + } + + + export class DTOFactory { + public notifications(): NotificationDTOFactory { + return new NotificationDTOFactory(); + } + } + + } + + + /** + * PUBLIC INTERFACE + */ + + + import DTOFactory = il.GS.DTO.DTOFactory; + import NotificationDTOFactory = il.GS.DTO.Notifications.NotificationDTOFactory; + import StandardIdentification = il.GS.Identification.StandardIdentification; + import ProviderFactory = il.GS.Provider.ProviderFactory; + import isProvider = il.GS.Provider.isProvider; + import CollectorFactory = il.GS.Collector.CollectorFactory; + + export class Services { + + private static provider_factory: ProviderFactory = new ProviderFactory(); + private static collector_factory: CollectorFactory = new CollectorFactory(); + private static dto_factory: DTOFactory = new DTOFactory(); + + public static provider(): ProviderFactory { + return this.provider_factory; + } + + public static identification(provider: isProvider, internal_identifier: string) { + Logger.log("register identification for provider " + provider.provider_name + " and internal id " + internal_identifier); + return new StandardIdentification(internal_identifier, provider); + } + + public static collector(): CollectorFactory { + return this.collector_factory + } + + public static factory(): DTOFactory { + return this.dto_factory; + } + } + + + } +} \ No newline at end of file diff --git a/src/GlobalScreen/Client/tsconfig.json b/src/GlobalScreen/Client/tsconfig.json new file mode 100644 index 000000000000..c35de717cbe4 --- /dev/null +++ b/src/GlobalScreen/Client/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "none", + "noImplicitAny": true, + "removeComments": true, + "preserveConstEnums": true, + "declaration": false, + "outDir": "./dist", + "rootDir": "./src", + "sourceMap": false, + "target": "es5" + }, + "include": [ + "src/GS.ts" + ] +} diff --git a/src/GlobalScreen/Collector/CollectorFactory.php b/src/GlobalScreen/Collector/CollectorFactory.php index b66731679693..60d0467cc266 100644 --- a/src/GlobalScreen/Collector/CollectorFactory.php +++ b/src/GlobalScreen/Collector/CollectorFactory.php @@ -4,6 +4,7 @@ use ILIAS\GlobalScreen\Scope\Layout\Collector\MainLayoutCollector; use ILIAS\GlobalScreen\Scope\MainMenu\Collector\MainMenuMainCollector; use ILIAS\GlobalScreen\Scope\MetaBar\Collector\MetaBarMainCollector; +use ILIAS\GlobalScreen\Scope\Notification\Collector\MainNotificationCollector; use ILIAS\GlobalScreen\Scope\Tool\Collector\MainToolCollector; use ILIAS\GlobalScreen\SingletonTrait; @@ -74,9 +75,19 @@ public function tool() : MainToolCollector /** * @return MainLayoutCollector + * @throws \ReflectionException */ public function layout() : MainLayoutCollector { - return $this->getWithArgument(MainLayoutCollector::class, $this->provider_factory->getModificationProvider()); + return $this->getWithMultipleArguments(MainLayoutCollector::class, [$this->provider_factory->getModificationProvider(), $this->provider_factory->getClientSideProviders()]); + } + + + /** + * @return MainNotificationCollector + */ + public function notifications() : MainNotificationCollector + { + return $this->getWithArgument(MainNotificationCollector::class, $this->provider_factory->getNotificationsProvider()); } } diff --git a/src/GlobalScreen/Provider/NullProviderFactory.php b/src/GlobalScreen/Provider/NullProviderFactory.php index 75d2c4dbac13..2a51ee25c893 100644 --- a/src/GlobalScreen/Provider/NullProviderFactory.php +++ b/src/GlobalScreen/Provider/NullProviderFactory.php @@ -55,6 +55,24 @@ public function getMetaBarProvider() : array } + /** + * @inheritDoc + */ + public function getNotificationsProvider() : array + { + return []; + } + + + /** + * @inheritDoc + */ + public function getClientSideProviders() : array + { + return []; + } + + /** * @inheritDoc */ diff --git a/src/GlobalScreen/Provider/ProviderFactory.php b/src/GlobalScreen/Provider/ProviderFactory.php index 45249fd8ef66..c4abd70a5c1f 100644 --- a/src/GlobalScreen/Provider/ProviderFactory.php +++ b/src/GlobalScreen/Provider/ProviderFactory.php @@ -1,9 +1,11 @@ providers = $providers; + $this->client_side_providers = $client_side_providers; $this->modification_handler = new ModificationHandler(); } @@ -114,6 +123,15 @@ public function getFinalPage() : Page $this->modification_handler->modifyMetaBarWithClosure($final_meta_bar_modification->getModification()); } + // + // POC Notification ClientSide + // + + $registrar = new ClientSideProviderRegistrar($this->getMetaContent()); + foreach ($this->client_side_providers as $client_side_provider) { + $registrar->registerProviderClientSideCode($client_side_provider); + } + return $this->modification_handler->getPageWithPagePartProviders(); } @@ -128,4 +146,15 @@ private function getContextStack() : CalledContexts return $called_contexts; } + + + /** + * @return MetaContent + */ + private function getMetaContent() : MetaContent + { + global $DIC; + + return $DIC->globalScreen()->layout()->meta(); + } } diff --git a/src/GlobalScreen/Scope/MetaBar/Collector/Renderer/NotificationCenterRenderer.php b/src/GlobalScreen/Scope/MetaBar/Collector/Renderer/NotificationCenterRenderer.php new file mode 100644 index 000000000000..335ee5f877b6 --- /dev/null +++ b/src/GlobalScreen/Scope/MetaBar/Collector/Renderer/NotificationCenterRenderer.php @@ -0,0 +1,58 @@ + + */ +class NotificationCenterRenderer implements MetaBarItemRenderer +{ + + use isSupportedTrait; + /** + * @var \ILIAS\GlobalScreen\Services + */ + private $ui; + /** + * @var \ILIAS\GlobalScreen\Services + */ + private $gs; + + + /** + * BaseMetaBarItemRenderer constructor. + */ + public function __construct() + { + global $DIC; + $this->ui = $DIC->ui(); + $this->gs = $DIC->globalScreen(); + } + + + /** + * @param NotificationCenter $item + * + * @return Component + */ + public function getComponentForItem(isItem $item) : Component + { + $f = $this->ui->factory(); + + $combined = $f->mainControls()->slate()->combined("Notification Center", $item->getSymbol()); + + foreach ($this->gs->collector()->notifications()->getNotifications() as $notification) { + $component = $notification->getRenderer()->getComponentForItem($notification); + if ($this->isComponentSupportedForCombinedSlate($component)) { + $combined = $combined->withAdditionalEntry($component); + } + } + + return $combined; + } +} diff --git a/src/GlobalScreen/Scope/MetaBar/Factory/MetaBarItemFactory.php b/src/GlobalScreen/Scope/MetaBar/Factory/MetaBarItemFactory.php index 8b87d91c9413..9aed08c718e1 100644 --- a/src/GlobalScreen/Scope/MetaBar/Factory/MetaBarItemFactory.php +++ b/src/GlobalScreen/Scope/MetaBar/Factory/MetaBarItemFactory.php @@ -54,4 +54,21 @@ public function topLinkItem(IdentificationInterface $identification) : TopLinkIt { return new TopLinkItem($identification); } + + + /** + * @param IdentificationInterface $identification + * + * @return NotificationCenter + */ + public function notificationCenter(IdentificationInterface $identification) + { + static $created; + if ($created === true) { + throw new \LogicException("only one NotificationCenter can exist"); + } + $created = true; + + return new NotificationCenter($identification); + } } diff --git a/src/GlobalScreen/Scope/MetaBar/Factory/NotificationCenter.php b/src/GlobalScreen/Scope/MetaBar/Factory/NotificationCenter.php new file mode 100644 index 000000000000..3dfd900eb09d --- /dev/null +++ b/src/GlobalScreen/Scope/MetaBar/Factory/NotificationCenter.php @@ -0,0 +1,90 @@ + + */ +class NotificationCenter extends AbstractBaseItem implements isItem, hasSymbol +{ + + /** + * @var isItem[] + */ + private $notifications = []; + + + /** + * @inheritDoc + */ + public function __construct(IdentificationInterface $provider_identification) + { + parent::__construct($provider_identification); + $this->renderer = new NotificationCenterRenderer(); + } + + + /** + * @param isItem[] $notifications + * + * @return NotificationCenter + */ + public function withNotifications(array $notifications) : NotificationCenter + { + $this->notifications = $notifications; + + return $this; + } + + + /** + * @return isItem[] + */ + public function getNotifications() : array + { + return $this->notifications; + } + + + /** + * @inheritDoc + */ + public function withSymbol(Symbol $symbol) : hasSymbol + { + return $this; + } + + + /** + * @inheritDoc + */ + public function hasSymbol() : bool + { + return true; + } + + + /** + * @return Symbol + */ + public function getSymbol() : Symbol + { + global $DIC; + + // TODO implement counter + return $DIC->ui()->factory()->symbol()->glyph()->notification(); + } + + + /** + * @inheritDoc + */ + public function getPosition() : int + { + return 1; + } +} diff --git a/src/GlobalScreen/Scope/MetaBar/Provider/NotificationCenterProvider.php b/src/GlobalScreen/Scope/MetaBar/Provider/NotificationCenterProvider.php new file mode 100644 index 000000000000..ed6c1c8c798b --- /dev/null +++ b/src/GlobalScreen/Scope/MetaBar/Provider/NotificationCenterProvider.php @@ -0,0 +1,38 @@ + + */ +class NotificationCenterProvider extends AbstractStaticMetaBarProvider implements StaticMetaBarProvider +{ + + /** + * @inheritDoc + */ + public function getMetaBarItems() : array + { + + $mb = $this->globalScreen()->metaBar(); + $id = function ($id) : IdentificationInterface { + return $this->if->identifier($id); + }; + $item = []; + + $item[] = $mb->notificationCenter($id('notification_center')) + ->withAvailableCallable(function () { + // Check if notifications available + return true; + }) + ->withVisibilityCallable( + function () { + return !$this->dic->user()->isAnonymous(); + } + ); + + return $item; + } +} \ No newline at end of file diff --git a/src/GlobalScreen/Scope/Notification/Collector/MainNotificationCollector.php b/src/GlobalScreen/Scope/Notification/Collector/MainNotificationCollector.php new file mode 100644 index 000000000000..54bebb45b6c9 --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Collector/MainNotificationCollector.php @@ -0,0 +1,44 @@ + + */ +class MainNotificationCollector +{ + + /** + * @var NotificationProvider[] + */ + private $providers = []; + + + /** + * MetaBarMainCollector constructor. + * + * @param NotificationProvider[] $providers + */ + public function __construct(array $providers) + { + $this->providers = $providers; + } + + + /** + * @return isItem[] + */ + public function getNotifications() : array + { + $notifications = []; + + foreach ($this->providers as $provider) { + $notifications = array_merge($notifications, $provider->getNotifications()); + } + + return $notifications; + } +} diff --git a/src/GlobalScreen/Scope/Notification/Collector/Renderer/AbstractBaseNotificationRenderer.php b/src/GlobalScreen/Scope/Notification/Collector/Renderer/AbstractBaseNotificationRenderer.php new file mode 100644 index 000000000000..fdefe7c17b9c --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Collector/Renderer/AbstractBaseNotificationRenderer.php @@ -0,0 +1,45 @@ + + */ +abstract class AbstractBaseNotificationRenderer implements NotificationRenderer +{ + + /** + * @var Factory + */ + protected $ui_factory; + + + /** + * StandardNotificationRenderer constructor. + */ + public function __construct() + { + global $DIC; + $this->ui_factory = $DIC->ui()->factory(); + } + + + /** + * @param isItem $item + * + * @return Symbol + */ + protected function getStandardSymbol(isItem $item) : Symbol + { + if ($item instanceof canHaveSymbol && $item->hasSymbol()) { + return $item->getSymbol(); + } + + return $this->ui_factory->symbol()->icon()->custom("./src/UI/examples/Layout/Page/Standard/question.svg", 'ILIAS', 'small', true); + } +} diff --git a/src/GlobalScreen/Scope/Notification/Collector/Renderer/NotificationRenderer.php b/src/GlobalScreen/Scope/Notification/Collector/Renderer/NotificationRenderer.php new file mode 100644 index 000000000000..142d5f55c2c0 --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Collector/Renderer/NotificationRenderer.php @@ -0,0 +1,24 @@ + + */ +interface NotificationRenderer +{ + + /** + * @param isItem $item + * + * @return Component + */ + public function getComponentForItem(isItem $item) : Component; +} + diff --git a/src/GlobalScreen/Scope/Notification/Collector/Renderer/StandardNotificationGroupRenderer.php b/src/GlobalScreen/Scope/Notification/Collector/Renderer/StandardNotificationGroupRenderer.php new file mode 100644 index 000000000000..be1cfc92861f --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Collector/Renderer/StandardNotificationGroupRenderer.php @@ -0,0 +1,45 @@ + + */ +class StandardNotificationGroupRenderer extends AbstractBaseNotificationRenderer implements NotificationRenderer +{ + + use isSupportedTrait; + + + /** + * @param isItem $item + * + * @return Component + * @throws \Exception + */ + public function getComponentForItem(isItem $item) : Component + { + if (!$item instanceof StandardNotificationGroup) { + throw new \LogicException("item is not a StandardNotificationGroup"); + } + /** + * @var $item StandardNotificationGroup + */ + + $slate = $this->ui_factory->mainControls()->slate()->combined($item->getTitle(), $this->getStandardSymbol($item)); + + foreach ($item->getNotifications() as $standard_notification) { + $component = $standard_notification->getRenderer()->getComponentForItem($standard_notification); + if ($this->isComponentSupportedForCombinedSlate($component)) { + $slate = $slate->withAdditionalEntry($component); + } + } + + return $slate; + } +} diff --git a/src/GlobalScreen/Scope/Notification/Collector/Renderer/StandardNotificationRenderer.php b/src/GlobalScreen/Scope/Notification/Collector/Renderer/StandardNotificationRenderer.php new file mode 100644 index 000000000000..603c1073b39f --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Collector/Renderer/StandardNotificationRenderer.php @@ -0,0 +1,31 @@ + + */ +class StandardNotificationRenderer extends AbstractBaseNotificationRenderer implements NotificationRenderer +{ + + /** + * @param isItem|hasActions|canHaveSymbol $item + * + * @return Component + */ + public function getComponentForItem(isItem $item) : Component + { + + $label = $item instanceof hasTitle ? $item->getTitle() : ""; + + $action = $item instanceof hasActions ? $item->getAction() : "#"; + + return $this->ui_factory->button()->bulky($this->getStandardSymbol($item), $label, $action); + } +} diff --git a/src/GlobalScreen/Scope/Notification/Factory/AbstractBaseNotification.php b/src/GlobalScreen/Scope/Notification/Factory/AbstractBaseNotification.php new file mode 100644 index 000000000000..382cc344af5a --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Factory/AbstractBaseNotification.php @@ -0,0 +1,48 @@ + + */ +abstract class AbstractBaseNotification implements isItem +{ + + /** + * @var IdentificationInterface + */ + protected $provider_identification; + + + /** + * StandardNotification constructor. + * + * @param IdentificationInterface $identification + */ + public function __construct(IdentificationInterface $identification) + { + $this->provider_identification = $identification; + } + + + /** + * @inheritDoc + */ + public function getProviderIdentification() : IdentificationInterface + { + return $this->provider_identification; + } + + + /** + * @inheritDoc + */ + public function getRenderer() : NotificationRenderer + { + return new StandardNotificationRenderer(); + } +} diff --git a/src/GlobalScreen/Scope/Notification/Factory/AbstractTitleNotification.php b/src/GlobalScreen/Scope/Notification/Factory/AbstractTitleNotification.php new file mode 100644 index 000000000000..211f20d55388 --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Factory/AbstractTitleNotification.php @@ -0,0 +1,57 @@ + + */ +abstract class AbstractTitleNotification extends AbstractBaseNotification implements hasTitle, isItem +{ + + /** + * @var string + */ + protected $title = ""; + + + /** + * @inheritDoc + */ + public function withTitle(string $title) : hasTitle + { + $clone = clone $this; + $clone->title = $title; + + return $clone; + } + + + /** + * @inheritDoc + */ + public function getTitle() : string + { + return $this->title; + } + + + /** + * @inheritDoc + */ + public function withSummary(string $summary) : isItem + { + $clone = clone $this; + $clone->summary = $summary; + + return $clone; + } + + + /** + * @inheritDoc + */ + public function getSummary() : string + { + return $this->summary; + } +} diff --git a/src/GlobalScreen/Scope/Notification/Factory/NotificationFactory.php b/src/GlobalScreen/Scope/Notification/Factory/NotificationFactory.php new file mode 100644 index 000000000000..ef457ba7d785 --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Factory/NotificationFactory.php @@ -0,0 +1,33 @@ + + */ +class NotificationFactory +{ + + /** + * @param IdentificationInterface $identification + * + * @return StandardNotification + */ + public function standard(IdentificationInterface $identification) : StandardNotification + { + return new StandardNotification($identification); + } + + + /** + * @param IdentificationInterface $identification + * + * @return StandardNotificationGroup + */ + public function standardGroup(IdentificationInterface $identification) : StandardNotificationGroup + { + return new StandardNotificationGroup($identification); + } +} diff --git a/src/GlobalScreen/Scope/Notification/Factory/StandardNotification.php b/src/GlobalScreen/Scope/Notification/Factory/StandardNotification.php new file mode 100644 index 000000000000..01185f0730a5 --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Factory/StandardNotification.php @@ -0,0 +1,196 @@ + + */ +class StandardNotification extends AbstractTitleNotification implements isItem, hasTitle, canHaveSymbol, hasActions +{ + + /** + * @var Symbol + */ + private $symbol; + /** + * @var array + */ + private $additional_actions = []; + /** + * @var int + */ + private $progress; + /** + * @var string + */ + private $action; + /** + * @var DateTimeImmutable + */ + protected $date; + /** + * @var string + */ + protected $summary; + /** + * @var Closure + */ + protected $close_action_callback; + + + /** + * @inheritDoc + */ + public function withDate(DateTimeImmutable $date_time_immutable) : isItem + { + $clone = clone $this; + $clone->date = $date_time_immutable; + + return $clone; + } + + + /** + * @inheritDoc + */ + public function getDate() : DateTimeImmutable + { + return $this->date; + } + + + /** + * @inheritDoc + */ + public function withCloseActionCallback(Closure $callback) : isItem + { + $clone = clone $this; + $clone->close_action_callback = $callback; + + return $clone; + } + + + /** + * @inheritDoc + */ + public function getCloseActionCallback() : Closure + { + return $this->close_action_callback; + } + + + /** + * @inheritDoc + */ + public function withAction(string $action) : isItem + { + $clone = clone $this; + $clone->action = $action; + + return $clone; + } + + + /** + * @inheritDoc + */ + public function hasAction() : bool + { + return is_string($this->action); + } + + + /** + * @inheritDoc + */ + public function getAction() : string + { + return $this->action; + } + + + /** + * @inheritDoc + */ + public function withSymbol(Symbol $symbol) : canHaveSymbol + { + $clone = clone $this; + $clone->symbol = $symbol; + + return $clone; + } + + + /** + * @inheritDoc + */ + public function hasSymbol() : bool + { + return ($this->symbol instanceof Symbol); + } + + + /** + * @inheritDoc + */ + public function getSymbol() : Symbol + { + return $this->symbol; + } + + + /** + * @inheritDoc + */ + public function withAdditionalAction(string $title, string $action) : isItem + { + $clone = clone $this; + $clone->additional_actions[$title] = $action; + + return $clone; + } + + + /** + * @inheritDoc + */ + public function getAdditionalActions() : array + { + return $this->additional_actions; + } + + + /** + * @inheritDoc + */ + public function withProgress(int $progress) : isItem + { + $clone = clone $this; + $clone->progress = $progress; + + return $clone; + } + + + /** + * @inheritDoc + */ + public function hasProgress() : bool + { + return is_int($this->progress); + } + + + /** + * @inheritDoc + */ + public function getProgress() : int + { + return $this->progress; + } +} diff --git a/src/GlobalScreen/Scope/Notification/Factory/StandardNotificationGroup.php b/src/GlobalScreen/Scope/Notification/Factory/StandardNotificationGroup.php new file mode 100644 index 000000000000..f48036c1b1ab --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Factory/StandardNotificationGroup.php @@ -0,0 +1,49 @@ + + */ +class StandardNotificationGroup extends AbstractTitleNotification implements hasTitle, isItem +{ + + /** + * @var StandardNotification[] + */ + private $notifications = []; + + + /** + * @param StandardNotification $notification + * + * @return StandardNotificationGroup + */ + public function addNotification(StandardNotification $notification) : StandardNotificationGroup + { + $this->notifications[] = $notification; + + return $this; + } + + + /** + * @return StandardNotification[] + */ + public function getNotifications() : array + { + return $this->notifications; + } + + + /** + * @inheritDoc + */ + public function getRenderer() : NotificationRenderer + { + return new StandardNotificationGroupRenderer(); + } +} diff --git a/src/GlobalScreen/Scope/Notification/Factory/canHaveSymbol.php b/src/GlobalScreen/Scope/Notification/Factory/canHaveSymbol.php new file mode 100644 index 000000000000..79559f01b06d --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Factory/canHaveSymbol.php @@ -0,0 +1,31 @@ + + */ +interface canHaveSymbol +{ + + /** + * @param Symbol $symbol + * + * @return canHaveSymbol + */ + public function withSymbol(Symbol $symbol) : self; + + + /** + * @return bool + */ + public function hasSymbol() : bool; + + + /** + * @return Symbol + */ + public function getSymbol() : Symbol; +} diff --git a/src/GlobalScreen/Scope/Notification/Factory/hasActions.php b/src/GlobalScreen/Scope/Notification/Factory/hasActions.php new file mode 100644 index 000000000000..ed3b45663964 --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Factory/hasActions.php @@ -0,0 +1,65 @@ + + */ +interface hasActions +{ + + // + // TODO + // - additional actions ev. auch als callback, beide varianten (auch URl) anbieten + // + + /** + * @param string $action + * + * @return isItem + */ + public function withAction(string $action) : isItem; + + + /** + * @return bool + */ + public function hasAction() : bool; + + + /** + * @return string + */ + public function getAction() : string; + + + /** + * @param Closure $callback + * + * @return isItem + */ + public function withCloseActionCallback(Closure $callback) : isItem; + + + /** + * @return Closure + */ + public function getCloseActionCallback() : Closure; + + + /** + * @param string $title + * @param string $action + * + * @return isItem + */ + public function withAdditionalAction(string $title, string $action) : isItem; + + + /** + * @return array + */ + public function getAdditionalActions() : array; +} diff --git a/src/GlobalScreen/Scope/Notification/Factory/hasTitle.php b/src/GlobalScreen/Scope/Notification/Factory/hasTitle.php new file mode 100644 index 000000000000..1f3a10a6ee5e --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Factory/hasTitle.php @@ -0,0 +1,37 @@ + + */ +interface hasTitle +{ + + /** + * @param string $title + * + * @return hasTitle + */ + public function withTitle(string $title) : hasTitle; + + + /** + * @return string + */ + public function getTitle() : string; + + + /** + * @param string $summary + * + * @return isItem + */ + public function withSummary(string $summary) : isItem; + + + /** + * @return string + */ + public function getSummary() : string; +} diff --git a/src/GlobalScreen/Scope/Notification/Factory/isItem.php b/src/GlobalScreen/Scope/Notification/Factory/isItem.php new file mode 100644 index 000000000000..81d32c1a544f --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Factory/isItem.php @@ -0,0 +1,24 @@ + + */ +interface isItem +{ + + /** + * @return IdentificationInterface + */ + public function getProviderIdentification() : IdentificationInterface; + + + /** + * @return NotificationRenderer + */ + public function getRenderer() : NotificationRenderer; +} diff --git a/src/GlobalScreen/Scope/Notification/NotificationServices.php b/src/GlobalScreen/Scope/Notification/NotificationServices.php new file mode 100644 index 000000000000..397c9f29629d --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/NotificationServices.php @@ -0,0 +1,24 @@ + + */ +class NotificationServices +{ + + use SingletonTrait; + + + /** + * @return NotificationFactory + */ + public function factory() : NotificationFactory + { + return $this->get(NotificationFactory::class); + } +} diff --git a/src/GlobalScreen/Scope/Notification/Provider/AbstractClientSideNotificationProvider.php b/src/GlobalScreen/Scope/Notification/Provider/AbstractClientSideNotificationProvider.php new file mode 100644 index 000000000000..fecdc8de75a9 --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Provider/AbstractClientSideNotificationProvider.php @@ -0,0 +1,46 @@ + + */ +abstract class AbstractClientSideNotificationProvider extends AbstractProvider implements ClientSideNotificationProvider +{ + + /** + * @var Container + */ + protected $dic; + /** + * @var IdentificationProviderInterface + */ + protected $if; + /** + * @var NotificationFactory + */ + protected $notification_factory; + + + /** + * @inheritDoc + */ + public function __construct(Container $dic) + { + parent::__construct($dic); + $this->notification_factory = $this->globalScreen()->notifications()->factory(); + $this->if = $this->globalScreen()->identification()->core($this); + } + + + /** + * @inheritDoc + */ + abstract public function enrichItem(isItem $notification) : isItem; +} diff --git a/src/GlobalScreen/Scope/Notification/Provider/AbstractNotificationProvider.php b/src/GlobalScreen/Scope/Notification/Provider/AbstractNotificationProvider.php new file mode 100644 index 000000000000..a3a16070abb6 --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Provider/AbstractNotificationProvider.php @@ -0,0 +1,39 @@ + + */ +abstract class AbstractNotificationProvider extends AbstractProvider implements NotificationProvider +{ + + /** + * @var Container + */ + protected $dic; + /** + * @var IdentificationProviderInterface + */ + protected $if; + /** + * @var NotificationFactory + */ + protected $notification_factory; + + + /** + * @inheritDoc + */ + public function __construct(Container $dic) + { + parent::__construct($dic); + $this->notification_factory = $this->globalScreen()->notifications()->factory(); + $this->if = $this->globalScreen()->identification()->core($this); + } +} diff --git a/src/GlobalScreen/Scope/Notification/Provider/ClientSideNotificationProvider.php b/src/GlobalScreen/Scope/Notification/Provider/ClientSideNotificationProvider.php new file mode 100644 index 000000000000..6f0c42bb2470 --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Provider/ClientSideNotificationProvider.php @@ -0,0 +1,20 @@ + + */ +interface ClientSideNotificationProvider extends ClientSideProvider +{ + + /** + * @param isItem $notification + * + * @return isItem + */ + public function enrichItem(isItem $notification) : isItem; +} diff --git a/src/GlobalScreen/Scope/Notification/Provider/NotificationProvider.php b/src/GlobalScreen/Scope/Notification/Provider/NotificationProvider.php new file mode 100644 index 000000000000..26584c0728bc --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/Provider/NotificationProvider.php @@ -0,0 +1,18 @@ + + */ +interface NotificationProvider extends Provider +{ + + /** + * @return isItem[] + */ + public function getNotifications() : array; +} diff --git a/src/GlobalScreen/Scope/Notification/README.md b/src/GlobalScreen/Scope/Notification/README.md new file mode 100644 index 000000000000..74e5e5a6e3c7 --- /dev/null +++ b/src/GlobalScreen/Scope/Notification/README.md @@ -0,0 +1,64 @@ +Scope Notifications +=================== +This scope addresses notifications that are displayed to the user in the NotificationCenter (a dedicated item in the MetaBar). Components can - as in all other scopes - via an implementation of a `NotificationProvider` provide the `MainNotificationCollector` with a list of notifications. These are summarized and displayed in the NotificationCenter. + +The following types are currently available via the Factory: + +- `StandardNotification` +- `StandardNotificationGroup` + +# Provider + +An own provider is quickly implemented, e.g: + +```php + + */ +class BTNotificationProvider extends AbstractNotificationProvider implements NotificationProvider +{ + + /** + * @inheritDoc + */ + public function getNotifications() : array + { + $id = function (string $id) : IdentificationInterface { + return $this->if->identifier($id); + }; + + $factory = $this->globalScreen()->notifications()->factory(); + + $group = $factory->standardGroup($id('bg_bucket_group')); + + for ($x = 1; $x < 10; $x++) { + $n = $factory->standard($id('bg_bucket_id_' . $x)) + ->withTitle("A Notification " . $x) + ->withSummary("with a super summary " . $x) + ->withAction("#"); + + $group->addNotification($n); + } + + return [ + $group, + ]; + } +} + +``` + +In this case, the effective notifications are collected in a NotificationGroup. These can then also be rendered as a group in the NotificationCenter. + +# Client side +The Scope Notifications can also be used on the client side. Therefore a `ClientSideNotificationProvider` is implemented. For more information on using GlobalScreen on the client side, see [src/GlobalScreen/Client/README.md](../../Client/README.md). diff --git a/src/GlobalScreen/Services.php b/src/GlobalScreen/Services.php index 4e4ee9d38155..424a27bc1100 100644 --- a/src/GlobalScreen/Services.php +++ b/src/GlobalScreen/Services.php @@ -6,6 +6,7 @@ use ILIAS\GlobalScreen\Scope\Layout\LayoutServices; use ILIAS\GlobalScreen\Scope\MainMenu\Factory\MainMenuItemFactory; use ILIAS\GlobalScreen\Scope\MetaBar\Factory\MetaBarItemFactory; +use ILIAS\GlobalScreen\Scope\Notification\NotificationServices; use ILIAS\GlobalScreen\Scope\Tool\ToolServices; /** @@ -92,6 +93,15 @@ public function layout() : LayoutServices } + /** + * @return NotificationServices + */ + public function notifications() : NotificationServices + { + return $this->get(NotificationServices::class); + } + + /** * @return CollectorFactory */ From 417acf4f1a565114f78b2df2b486acc7d0507810 Mon Sep 17 00:00:00 2001 From: Fabian Schmid Date: Wed, 21 Aug 2019 18:09:44 +0200 Subject: [PATCH 2/2] updated readme --- src/GlobalScreen/Client/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/GlobalScreen/Client/README.md b/src/GlobalScreen/Client/README.md index 77f6147eaf27..16d38ce0408b 100644 --- a/src/GlobalScreen/Client/README.md +++ b/src/GlobalScreen/Client/README.md @@ -1,6 +1,12 @@ 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.