imagina/inotification

处理实时通知的模块

安装: 4

依赖: 0

建议者: 0

安全: 0

星标: 0

关注者: 6

分支: 8

类型:asgard-module

10.0.0 2024-06-11 20:52 UTC

README

Asgard Notification Module 的改进版本 - https://github.com/AsgardCms/Notification

##发布说明

新增

  • 规则 CreateNotificationRequest
  • 请求规则的验证消息
  • Labs Mobile 作为 SMS 通知的默认提供商
  • ProviderRuleTemplateTypeNotification Asgard 实体 Scaffold
  • defaultEmailView 配置
  • providerrecipient 列添加到 notification__notifications 表中
  • notificationTypes 配置添加到 notification__notification_types 表中
  • 添加新的提供商配置的 providers 配置
  • 依赖于配置的 NotificationTypeTableSeeder
  • 使用 EventServiceProvider 动态监听配置 providers 中定义的所有事件
  • 使用 NotificationHandler 处理由 EventServiceProvider 监听的所有事件
  • Rule->conditions 验证
  • ImaginaNotificationAsgardNotification 的改进版本

注意

使用新的 ImaginaNotification 服务,表 notification__notifications 中的 user_id 列被 recipient 列替换

安装

Composer

在终端中执行以下命令

composer require imagina/asgardcms-inotifications

注意

安装后,您需要为获取后端博客模块页面权限提供所需的权限。**

运行迁移和播种器

php artisan module:migrate notification --seed

提供商配置

#####/Config/config.php

提供商字段

配置提供商所需的所有字段:API 密钥、登录、用户名、密码。

每个字段都需要在 basequasar-app 中的 dynamic fields 配置中定义。以下是需要字段列表

注意

每个提供商字段可以定义指向公共配置的路线以替换 ENV 文件中的密钥,只需添加配置Route值

// example: broadcasting pusher config route
"configRoute" => "broadcasting.connections.pusher.options.encrypted"

此设置仅在发送通知时使用,其余应用程序将继续使用 .env 文件中的设置。

提供商设置

为每个规则定制提供商字段的必要设置

每个设置都需要在 basequasar-app 中的 dynamic fields 配置中定义。以下是需要设置列表

注意

提供商的必需字段比规则设置具有更高的优先级。

发布配置

php artisan module:publish-config notification

用法

有两种方法可以用来发送通知

###1 快速向您的前端应用程序发送通知。

在您需要的地方注入 Modules\Notification\Services\Inotification 接口并将其分配给类变量。

    // New Service Inotification
    use Modules\Notification\Services\Inotification;
  
    /**
    *  by type, to user->id recipient
    */ 
     $this->notification->type('broadcast')->to($user->id)
    ->push(
      [
        "title" => "test notification",
        "message" => "message notification",
        "icon_class" => "fas fa-test",
        "link" => url(''),
        "setting" => [
          "saveInDatabase" => 1 // now, the notifications with type broadcast need to be save in database to really send the notification
        ]
      ]
    );
    

/**
 *  by mutiple types, to user->id recipient
 */ 
  $this->notification->type(['broadcast', 'push'])->to($user->id)
    ->push(
      [
        "title" => "test notification",
        "message" => "message notification",
        "icon_class" => "fas fa-test",
        "link" => url(''),
        "setting" => [
          "saveInDatabase" => 1 // now, the notifications with type broadcast need to be save in database to really send the notification
        ]
      ]
    );
  

/**
*  by provider, to user->email recipient
*/
$this->notification->provider('email')->to($user->email)
  ->push(
    [
      "title" => "test notification",
      "message" => "message notification",
      "icon_class" => "fas fa-test",
      "link" => url(''),
      "view" => "email.view"
    ]
  );


/**
  *  by mutiple types defined in the to 
  */ 
  $this->notification->to([
    "broadcast" => $user->id,
    "email" => $user->email,
  ])->push(
      [
        "title" => "test notification",
        "message" => "message notification",
        "icon_class" => "fas fa-test",
        "link" => url(''),
        "view" => "email.view",
        "setting" => [
          "saveInDatabase" => 1 // now, the notifications with type broadcast need to be save in database to really send the notification
        ]
      ]
  );
            

2 使用事件并定义每个模块中的 Notifiable 配置,通过规则从数据库管理

Notifiable 配置

在模块中首先需要定义可通知配置,通知模块会检测配置并将其发送到前端以创建规则,每个规则都需要保存在数据库中以生效。

可通知条件配置

条件配置类似于basequasar-app的动态字段,但是只有三种类型的条件可用

1 递归

"EMail" => [
  "name" => "EMail",
  'value' => [
    "comparator" => "",
    "value" => ""
  ],
  'type' => 'recursive',
  "fields" => [
    "operator" => [
      "name" => "operator",
      'value' => 'any',
      'type' => 'select',
      'props' => [
        'label' => 'Email',
        'options' => [
          ['label' => 'Any', 'value' => 'any'],
          ['label' => 'Contains', 'value' => 'contains'],
          ['label' => 'Exact Match', 'value' => 'exactMatch']
        ]
      ],
    ],
    "value" => [
      "name" => "value",
      'value' => '',
      'type' => 'text',
      'props' => [
        'label' => ''
      ],
    ],
    "type" => [
      "name" => "type",
      'value' => 'comparatorSimple',
      'type' => 'hidden',
      'props' => [
        'label' => ''
      ],
    ]
  ]

],

2 选择静态选项

"NinetyMin" => [
  "name" => "NinetyMin",
  'value' => 'any',
  'type' => 'select',
  'props' => [
    'label' => 'Ninety Min',
    'options' => [
      ['label' => 'Any', 'value' => 'any'],
      ['label' => 'Yes', 'value' => 'Y'],
      ['label' => 'No', 'value' => 'N']
    ]
  ],
],

3 选择动态选项

"idSource" => [
  "name" => "idSource",
  'value' => 'any',
  'type' => 'select',
  'loadOptions' => [
    'apiRoute' => 'apiRoutes.setup.sources',
    'select' => ['label' => 'title', 'id' => 'id']
  ],
  'options' => [
    ['label' => 'Any', 'value' => 'any'],
  ],
  'props' => [
    'label' => 'Source'
  ],
],

注意

所有条件都需要设置默认值 any,处理程序会检测并验证它

##事件示例

namespace Modules\Iteam\Events;


class UserWasJoined
{
    public $user;
    public $team;
    
    // this attribute it's required
    public $entity;

    /**
     * Create a new event instance.
     *
     * @param $entity
     * @param array $data
     */
    public function __construct($user,$team)
    {
        $this->user = $user;
        $this->entity = $team;
        $this->team = $team;
    }
  
  // this method it's required
  
  public function notification(){
    
    return [
      "title" =>  "¡Buenas Noticias!, te han aceptado en el equipo: ".$this->team->title,
      "message" =>   "Has sido aceptado en el equipo: ".$this->team->title,
      "icon_class" => "fas fa-glass-cheers",
      "link" => "link",
      "view" => "iteam::emails.userJoined.userJoined",
      "recipients" => [
        "email" => [$this->user->email],
        "broadcast" => [$this->user->id],
        "push" => [$this->user->id],
      ],
      
      // here you can send all objects and params necessary to the view template
      "user" => $this->user,
      "team" => $this->team
    ];
  }

}

可通知配置示例

  'notifiable' => [
    
    [
      "title" => "Lead Opportunity",
      "entityName" => "Modules\\Ilead\\Entities\\LeadOpportunity",
      "events" => [
        [
          "title" => "New Lead Opportunity was created",
          "path" => "Modules\\Ilead\\Events\\LeadOpportunityWasCreated"
        ]
      ],
      
      "conditions" => [
        "EMail" => [
          "name" => "EMail",
          'value' => [
            "comparator" => "",
            "value" => ""
          ],
          'type' => 'recursive',
          "fields" => [
            "operator" => [
              "name" => "operator",
              'value' => 'any',
              'type' => 'select',
              'props' => [
                'label' => 'Email',
                'options' => [
                  ['label' => 'Any', 'value' => 'any'],
                  ['label' => 'Contains', 'value' => 'contains'],
                  ['label' => 'Exact Match', 'value' => 'exactMatch']
                ]
              ],
            ],
            "value" => [
              "name" => "value",
              'value' => '',
              'type' => 'text',
              'props' => [
                'label' => ''
              ],
            ],
            "type" => [
              "name" => "type",
              'value' => 'comparatorSimple',
              'type' => 'hidden',
              'props' => [
                'label' => ''
              ],
            ]
          ]
        
        ],
        "NinetyMin" => [
          "name" => "NinetyMin",
          'value' => 'any',
          'type' => 'select',
          'props' => [
            'label' => 'Ninety Min',
            'options' => [
              ['label' => 'Any', 'value' => 'any'],
              ['label' => 'Yes', 'value' => 'Y'],
              ['label' => 'No', 'value' => 'N']
            ]
          ],
        ],
        "idSource" => [
          "name" => "idSource",
          'value' => 'any',
          'type' => 'select',
          'loadOptions' => [
            'apiRoute' => 'apiRoutes.setup.sources',
            'select' => ['label' => 'title', 'id' => 'id']
          ],
          'options' => [
            ['label' => 'Any', 'value' => 'any'],
          ],
          'props' => [
            'label' => 'Source'
          ],
        ],
        "idStore" => [
          "name" => "idStore",
          'value' => 'any',
          'type' => 'select',
          'loadOptions' => [
            'apiRoute' => 'apiRoutes.setup.stores',
            'select' => ['label' => 'title', 'id' => 'id']
          ],
          'options' => [
            ['label' => 'Any', 'value' => 'any'],
          ],
          'props' => [
            'label' => 'Store'
          ],
        ],
      
      ],
      
      "settings" => [
        
        "email" => [
          
          "recipients" => [
            ['label' => 'Customer Email', 'value' => 'EMail']
          ]
        ],
        
        "sms" => [
          "recipients" => [
            ['label' => 'Day Phone', 'value' => 'DayPhone'],
            ['label' => 'Evening Phone', 'value' => 'EvePhone'],
            ['label' => 'Cell Phone', 'value' => 'CellPhone']
          ]
        ],
        
        "pusher" => [
          "recipients" => [
            ['label' => 'Rep 1', 'value' => 'repId'],
            ['label' => 'Rep 2', 'value' => 'repId2']
          ]
        ],
        
        "firebase" => [
          "recipients" => [
            ['label' => 'Rep 1', 'value' => 'repId'],
            ['label' => 'Rep 2', 'value' => 'repId2']
          ]
        ],
      ],
    ],
  ]

提供者配置示例 提供者

 "pusher" => [// PUSHER PROVIDER
      "name" => "Pusher",
      "systemName" => "pusher",
      "icon" => "far fa-bell",
      "color" => "#c223ce",
      "rules" => [
        "numeric",
        "min:1",
      ],
      "fields" => [
        "id" => [
          'value' => null,
        ],
        "pusherAppEncrypted" => [
          "name" => "pusherAppEncrypted",
          'value' => true,
          'type' => 'toggle',
          "isFakeField" => 'fields',
          'props' => [
            'label' => 'Pusher App Encrypted',
            'falseValue' => false,
            'trueValue' => true
          ],
          "configRoute" => "broadcasting.connections.pusher.options.encrypted"
        ],
        
        "pusherAppId" => [
          "name" => "pusherAppId",
          'value' => '',
          'type' => 'input',
          "isFakeField" => 'fields',
          'required' => true,
          'props' => [
            'label' => 'Pusher App Id *'
          ],
          "configRoute" => "broadcasting.connections.pusher.app_id"
        ],
        
        "pusherAppKey" => [
          "name" => "pusherAppKey",
          'value' => '',
          'type' => 'input',
          "isFakeField" => 'fields',
          'required' => true,
          'props' => [
            'label' => 'Pusher App Key *'
          ],
          "configRoute" => "broadcasting.connections.pusher.key"
        ],
        
        "pusherAppSecret" => [
          "name" => "pusherAppSecret",
          'value' => '',
          'type' => 'input',
          "isFakeField" => 'fields',
          'required' => true,
          'props' => [
            'label' => 'Pusher App Secret *'
          ],
          "configRoute" => "broadcasting.connections.pusher.secret"
        ],
        
        "pusherAppCluster" => [
          "name" => "pusherAppCluster",
          'value' => '',
          'type' => 'input',
          "isFakeField" => 'fields',
          'required' => true,
          'props' => [
            'label' => 'Pusher App Cluster *'
          ],
          "configRoute" => "broadcasting.connections.pusher.options.cluster"
        ],
        "status" => [
          "name" => "status",
          'value' => '0',
          'type' => 'select',
          'required' => true,
          'props' => [
            'label' => 'Status',
            'options' => [
              ["label" => 'enabled', "value" => '1'],
              ["label" => 'disabled', "value" => '0'],
            ],
          ],
        ],
        "default" => [
          "name" => "default",
          'value' => false,
          'type' => 'checkbox',
          'props' => [
            'label' => 'Default',
          ]
        ],
        "saveInDatabase" => [
          "name" => "saveInDatabase",
          'value' => '1',
          'type' => 'select',
          'required' => true,
          'props' => [
            'label' => 'Save in database',
            'options' => [
              ["label" => 'enabled', "value" => '1'],
              ["label" => 'disabled', "value" => '0'],
            ],
          ],
        ],
        "type" => ['value' => 'broadcast'],
      ],
      "settings" => [
        "recipients" => [
          "name" => "recipients",
          'value' => '',
          'type' => 'input',
          "isFakeField" => 'settings',
          'props' => [
            'label' => 'Recipients',
            "hint" => "Enter recipient ID - separate entries with commas"
          ],
        ],
        "status" => [
          "name" => "status",
          'value' => '0',
          'type' => 'select',
          'required' => true,
          'props' => [
            'label' => 'Enable',
            'options' => [
              ["label" => 'enabled', "value" => '1'],
              ["label" => 'disabled', "value" => '0'],
            ],
          ],
        ],
        "saveInDatabase" => [
          "name" => "saveInDatabase",
          'value' => '1',
          'type' => 'select',
          'required' => true,
          'props' => [
            'label' => 'Save in database',
            'options' => [
              ["label" => 'enabled', "value" => '1'],
              ["label" => 'disabled', "value" => '0'],
            ],
          ],
        ],
      ]
    ],

流程图

Flow Chart