NotificationInbox

TsgcHTMLComponent_NotificationInbox: 未読バッジ付きのベルアイコンと、1 人のユーザーの通知のドロップダウンリストを、Delphi、C++ Builder、.NET で提供します。行はアプリケーションが保持し、コンポーネントがそれをレンダリングします。

TsgcHTMLComponent_NotificationInbox

ライブラリは何も保存しません。アプリケーションが保持している行で OnLoadNotifications に応答し、ユーザーの操作は OnMarkReadOnMarkAllRead を通じて通知されるので、それを永続化できます。コンポーネントは UI をレンダリングするだけで、認可は行いません。WebSocket でも Server-Sent Events でも、すべてのエディションで動作します。

コンポーネントクラス

TsgcHTMLComponent_NotificationInbox(ユニット sgcHTML_Component_NotificationInbox

レンダリング内容

Bootstrap のドロップダウンマークアップ: ベルアイコン、未読バッジ、リスト

言語

Delphi, C++ Builder, .NET

作成し、3 つのイベントを処理し、アクションを振り分ける

インボックスに InboxID を指定し、OnLoadNotifications で独自のストレージから内容を埋め、OnMarkReadOnMarkAllRead でユーザーの操作を永続化し、ポストされたアクションはセッションから取得したユーザーとともに ProcessAction に振り分けます。

uses
  sgcHTML_Session, sgcHTML_Component_NotificationInbox;

var
  oInbox: TsgcHTMLComponent_NotificationInbox;
begin
  oInbox := TsgcHTMLComponent_NotificationInbox.Create(nil);
  try
    oInbox.InboxID := 'inbox';
    oInbox.Title := 'Notifications';
    oInbox.MaxItems := 10;
    oInbox.OnLoadNotifications := InboxLoad;
    oInbox.OnMarkRead := InboxMarkRead;
    oInbox.OnMarkAllRead := InboxMarkAllRead;

    // the user comes from the session, never from the form
    oInbox.LoadNotifications(sgcHTMLRequestSession.UserID);
    Response := oInbox.HTML;   // bell, unread badge and dropdown
  finally
    oInbox.Free;
  end;
end;

// the application owns the rows: fill the list, newest first
procedure TMain.InboxLoad(Sender: TObject; const aUserID: string;
  aList: TsgcHTMLInboxItems);
begin
  with aList.Add do
  begin
    Id := '1042';
    Title := 'New order';
    Text := 'Order #1042 was placed.';
    Timestamp := '2 min ago';
    Read := False;
  end;
end;

procedure TMain.InboxMarkRead(Sender: TObject; const aUserID,
  aNotificationID: string);
begin
  // persist it, after checking that aUserID owns aNotificationID
end;

// in the message handler that receives the actions the inbox posts
if oInbox.ProcessAction(vUser, vAction, vNotificationID) then
  oHTMX.PushFragment(vGuid, oInbox.GetListFragmentHTML +
    oInbox.GetBadgeFragmentHTML);
// includes: sgcHTML_Session.hpp, sgcHTML_Component_NotificationInbox.hpp

TsgcHTMLComponent_NotificationInbox *oInbox = new TsgcHTMLComponent_NotificationInbox(NULL);
try
{
  oInbox->InboxID = "inbox";
  oInbox->Title = "Notifications";
  oInbox->MaxItems = 10;
  oInbox->OnLoadNotifications = InboxLoad;
  oInbox->OnMarkRead = InboxMarkRead;
  oInbox->OnMarkAllRead = InboxMarkAllRead;

  // the user comes from the session, never from the form
  oInbox->LoadNotifications(sgcHTMLRequestSession()->UserID);
  String html = oInbox->HTML;   // bell, unread badge and dropdown
}
__finally
{
  delete oInbox;
}

// the application owns the rows: fill the list, newest first
void __fastcall TMain::InboxLoad(TObject *Sender, const String aUserID,
  TsgcHTMLInboxItems *aList)
{
  TsgcHTMLInboxItem *item = aList->Add();
  item->Id = "1042";
  item->Title = "New order";
  item->Text = "Order #1042 was placed.";
  item->Timestamp = "2 min ago";
  item->Read = false;
}

void __fastcall TMain::InboxMarkRead(TObject *Sender, const String aUserID,
  const String aNotificationID)
{
  // persist it, after checking that aUserID owns aNotificationID
}

// in the message handler that receives the actions the inbox posts
if (oInbox->ProcessAction(vUser, vAction, vNotificationID))
  oHTMX->PushFragment(vGuid, oInbox->GetListFragmentHTML() +
    oInbox->GetBadgeFragmentHTML());
using esegece.sgcWebSockets;

var inbox = new TsgcHTMLComponent_NotificationInbox();
inbox.InboxID = "inbox";
inbox.Title = "Notifications";
inbox.MaxItems = 10;
inbox.OnLoadNotifications += InboxLoad;
inbox.OnMarkRead += InboxMarkRead;
inbox.OnMarkAllRead += InboxMarkAllRead;

// the user comes from the session, never from the form
string user = sgcHTMLSessionHelpers.sgcHTMLRequestSession()?.UserID ?? "";
inbox.LoadNotifications(user);
string html = inbox.HTML;   // bell, unread badge and dropdown

// the application owns the rows: fill the list, newest first
void InboxLoad(object sender, string userID, TsgcHTMLInboxItems list)
{
    var item = list.Add();
    item.Id = "1042";
    item.Title = "New order";
    item.Text = "Order #1042 was placed.";
    item.Timestamp = "2 min ago";
    item.Read = false;
}

void InboxMarkRead(object sender, string userID, string notificationID)
{
    // persist it, after checking that userID owns notificationID
}

// in the message handler that receives the actions the inbox posts
if (inbox.ProcessAction(user, action, notificationId))
    htmx.PushFragment(guid, inbox.GetListFragmentHTML() + inbox.GetBadgeFragmentHTML());

主なプロパティとメソッド

最もよく使うメンバーです。

Items

ItemsTsgcHTMLInboxItems コレクションで、各 TsgcHTMLInboxItemIdTitleTextTimestampUrlIconRead を持ちます。行内のすべての値はデータであり、レンダリング時にエスケープされます。Icon も同様で、文字そのものを渡し、HTML エンティティやマークアップは渡さないでください。Url はサニタイズされ、javascript:data: のリンクは拒否されます。

ストレージのイベント

コンポーネントが保持するのは、レンダリングしている内容だけです。OnLoadNotifications(aUserID, aList)aList がすでにクリアされた状態で発生します。ユーザーの通知を新しい順に埋めてください。OnMarkRead(aUserID, aNotificationID) は項目が既読になった後に、OnMarkAllRead(aUserID) はすべての項目が既読になった後に発生します。

サーバー側のアクション

LoadNotifications(aUserID)MarkRead(aUserID, aNotificationID)MarkAllRead(aUserID) が実際の処理を行います。ProcessAction(aUserID, aAction, aNotificationID) は、ポストされた 1 つのアクションを適切なものに振り分け、そのアクションがインボックスのアクションでない場合は False を返すので、引き続きその所有者を探せます。

ポストするアクション

ドロップダウンは、inboxMarkRead(フィールドは actioninboxid)、inboxMarkAllReadinboxRefresh(フィールドは actioninbox)を data-sgc-ws-send フォームとしてポストします。inbox フィールドには、フォームをレンダリングしたインボックスの要素 ID が入り、InboxID を設定した場合はその値です。複数のインボックスがあるページでは、これによってアクションが正しいコンポーネントに振り分けられます。

認可

コンポーネントは UI をレンダリングするだけで、認可は行いません。すべてのアクションはクライアントから送られるデータとして届くため、悪意のあるクライアントは任意のアクションと任意の通知 ID を偽造できます。マークアップにはユーザー ID を書き込みません。操作しているユーザーは、フォームではなくリクエストのセッション(sgcHTMLRequestSession)から取得し、何かを永続化する前に、届いた通知 ID をそのユーザーが所有していることを確認してください。

Appearance

Title はドロップダウンの見出し、EmptyText は表示する項目がないときのプレースホルダー、BellIcon はトリガーのグリフで、既定では HTML エンティティを含む信頼されたマークアップです。MaxItems は表示する行数の上限(既定値 10、0 ならすべて表示)を決め、ShowMarkAllReadShowBadge は既定でオンで、AddNotification(aId, aTitle, aText, aTimestamp, aUrl, aIcon) は行を追加するか、同じ ID の行を更新します。

ライブ更新

すべての通知、バッジ、リストには、安定した要素 ID が付いています。1 つ変更された後は、ページ全体を再レンダリングする代わりに、GetItemFragmentHTML(aId)GetBadgeFragmentHTMLGetListFragmentHTML で影響を受けたマークアップだけをレンダリングし、TsgcHTMX_Engine_Server.PushFragment または BroadcastFragment でプッシュします。UnreadCount は、ReadFalse の項目を数えます。

エディションとチャネル

ユニットは SGC_HTML が定義されている場合にコンパイルされ、sgcVer.inc は Android と iOS についてはそれを定義しません。WebSocket でも Server-Sent Events でも、すべてのエディションで動作します。sgcHTML はスタンドアロンのパックで、sgcWebSockets とは別に販売されています。

ページかプッシュか

インボックス自体はページとプッシュのどちらかを選択しません。それを行うのは TsgcHTMLComponent_Notification です。NotificationWebPush を参照してください。各ユーザーがどのチャネルを希望するかは、NotificationPreferences で設定します。

さらに詳しく

オンラインヘルプこのコンポーネントの完全な API リファレンスと使用ガイドです。
すべての sgcHTML コンポーネント80 以上のコンポーネントの全機能マトリックスを閲覧できます。
無料体験版のダウンロード30 日間の体験版には 60.HTML デモプロジェクトが付属し、インボックスを使用する 17.FieldService も含まれます。
価格完全なソースコード付きの Single、Team、Site ライセンス。
最もお得な選択: All-AccesseSeGeCe の全製品にプレミアムサポートが付いて、年間 €1,059 からご利用いただけます。
All-Access の価格を見る

始める準備はできましたか?

無料体験版をダウンロードして、Delphi、C++ Builder、.NET で Web UI の構築を始めましょう。