NotificationInbox

TsgcHTMLComponent_NotificationInbox: um sino com um badge de não lidas e uma lista dropdown das notificações de um usuário, em Delphi, C++ Builder e .NET. A sua aplicação guarda as linhas, o componente as renderiza.

TsgcHTMLComponent_NotificationInbox

A biblioteca não guarda nada. A sua aplicação responde a OnLoadNotifications com as linhas que mantém e é informada por OnMarkRead e OnMarkAllRead do que o usuário fez, para poder persistir isso. O componente renderiza a interface e não impõe nenhuma autorização. Funciona em todas as edições, sobre WebSocket ou server-sent events.

Classe do componente

TsgcHTMLComponent_NotificationInbox (unit sgcHTML_Component_NotificationInbox)

Renderiza

Markup de dropdown do Bootstrap: um sino, um badge de não lidas e uma lista

Linguagens

Delphi, C++ Builder, .NET

Crie-o, trate três eventos, encaminhe as ações

Dê à caixa de entrada um InboxID, preencha-a a partir do seu próprio armazenamento em OnLoadNotifications, persista o que o usuário fez em OnMarkRead e OnMarkAllRead, e encaminhe as ações enviadas para ProcessAction com o usuário tirado da sessão.

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());

Principais propriedades & métodos

Os membros que você usa com mais frequência.

Items

Items é uma coleção TsgcHTMLInboxItems; cada TsgcHTMLInboxItem tem Id, Title, Text, Timestamp, Url, Icon e Read. Tudo em uma linha é dado e é escapado ao ser renderizado, inclusive o Icon: passe um glifo literal, nunca uma entidade HTML nem markup. Url é sanitizada e os links javascript: e data: são rejeitados.

Eventos de armazenamento

O componente guarda apenas o que está renderizando. OnLoadNotifications(aUserID, aList) dispara com aList já limpa: preencha-a com as notificações do usuário, das mais novas para as mais antigas. OnMarkRead(aUserID, aNotificationID) dispara depois que o item é marcado como lido, e OnMarkAllRead(aUserID) depois que todos são.

Ações no lado do servidor

LoadNotifications(aUserID), MarkRead(aUserID, aNotificationID) e MarkAllRead(aUserID) fazem o trabalho. ProcessAction(aUserID, aAction, aNotificationID) encaminha uma ação enviada para o método certo e devolve False quando a ação não é uma ação da caixa de entrada, para que você possa continuar procurando o seu dono.

Ações que ela envia

O dropdown envia inboxMarkRead (campos action, inbox, id), inboxMarkAllRead e inboxRefresh (campos action, inbox) como formulários data-sgc-ws-send. O campo inbox carrega o id do elemento da caixa de entrada que renderizou o formulário, que é InboxID quando você o define, e é assim que uma página com várias caixas de entrada encaminha a ação para o componente certo.

Autorização

O componente renderiza a interface e não impõe nenhuma autorização. Toda ação viaja como dado enviado pelo cliente, então um cliente hostil pode forjar qualquer ação e qualquer id de notificação. Nenhum id de usuário é escrito no markup: obtenha o usuário que age a partir da sessão da requisição (sgcHTMLRequestSession), nunca do formulário, e confira se o usuário é dono do id de notificação que chegou antes de persistir qualquer coisa.

Aparência

Title é o título do dropdown, EmptyText o placeholder quando não há nada a mostrar e BellIcon o glifo do gatilho, markup confiável com uma entidade HTML por padrão. MaxItems limita as linhas visíveis (padrão 10, 0 mostra todas), ShowMarkAllRead e ShowBadge vêm ativados por padrão, e AddNotification(aId, aTitle, aText, aTimestamp, aUrl, aIcon) adiciona uma linha ou atualiza a que tem o mesmo id.

Atualizações ao vivo

Cada notificação, o badge e a lista carregam um id de elemento estável. Depois de uma alteração, renderize apenas o markup afetado com GetItemFragmentHTML(aId), GetBadgeFragmentHTML ou GetListFragmentHTML e envie-o com TsgcHTMX_Engine_Server.PushFragment ou BroadcastFragment, em vez de renderizar a página de novo. UnreadCount conta os itens cujo Read é False.

Edições e canais

A unit compila quando SGC_HTML está definido, o que o sgcVer.inc não faz para Android e iOS. Funciona em todas as edições, sobre WebSocket ou server-sent events. O sgcHTML é um pacote autônomo, vendido de forma independente do sgcWebSockets.

Página ou push

A caixa de entrada não escolhe por si só entre a página e um push: isso é feito por TsgcHTMLComponent_Notification, veja Notification e WebPush. Os canais que cada usuário quer são definidos em NotificationPreferences.

Continue explorando

Ajuda onlineReferência completa da API e guia de uso para este componente.
Todos os Componentes sgcHTMLExplore a matriz completa de recursos com mais de 80 componentes.
Baixar Versão de Avaliação GratuitaA avaliação de 30 dias inclui os projetos de demonstração 60.HTML, entre eles o 17.FieldService, que usa a caixa de entrada.
PreçosLicenças Single, Team e Site com código-fonte completo.
Melhor custo-benefício: All-AccessTodos os produtos da eSeGeCe, com Suporte Premium incluído, a partir de €1,059/ano.
Ver preços do All-Access

Pronto para Começar?

Baixe a versão de avaliação gratuita e comece a construir UIs web em Delphi, C++ Builder e .NET.