Informationssystem für APEX-Applikationen

05.
Juli
2014
Veröffentlicht von: Bernhard Koch

Hatten Sie auch schon einmal den Wunsch, den Anwendern einer Applikation etwas mitzuteilen? Und wäre es nicht manchmal gut, wenn jeder Anwender nachweislich die Information gelesen hat? Die Informationen sollen sofort, also auch in einer laufenden Session, in einem modalen Popup- Fenster angezeigt werden. Dieses Problem stellte sich vor einiger Zeit in einem APEX-Projekt und aus diesem Grund haben wir ein Informationssystem für APEX-Anwendungen entwickelt.

Hatten Sie auch schon einmal den Wunsch, den Anwendern einer Applikation etwas mitzuteilen? Und wäre es nicht manchmal gut, wenn jeder Anwender nachweislich die Information gelesen hat? Die Informationen sollen sofort, also auch in einer laufenden Session, in einem modalen Popup- Fenster angezeigt werden. Dieses Problem stellte sich vor einiger Zeit in einem APEX-Projekt und aus diesem Grund haben wir ein Informationssystem für APEX-Anwendungen entwickelt.

Um die Anforderungen abzudecken brauchen wir im ersten Schritt zwei Tabellen. In der ersten werden die "Nachrichten" gespeichert, in der zweiten die Information, wer wann das Lesen bestätigt hat.

CREATE TABLE INFORMATIONEN
(
  ID          NUMBER,        -- Eindeutige ID, Trigger und Sequence
  APP_ID      NUMBER,        -- Applikations ID der Apexanwendung
  STATUS      CHAR(1),       -- A für aktiv oder I für inaktiv
  INFORMATION VARCHAR2(500), -- Freitext für die Informationsn
  CONSTRAINT PK_INFORMATIONEN PRIMARY KEY (ID)
);

CREATE TABLE INFORMATION_READ
(
  INFO_ID     NUMBER,        -- ID der Information die gelesen wurde 
  APP_USER    VARCHAR2(30),  -- Welcher User hat gelesen
  READ_DATE   DATE           -- Wann wurde gelesen, Trigger mit SYSDATE
);


Der nächste Schritt ist, eine Seite in der Applikation zu erstellen auf der die Informationen angezeigt werden sollen. Als Template wählen wir Popup. Im Bereich "Page HTML Body Attribute" kommt noch folgende Anweisung dazu:

style="background:none;background-image:none;background-color:transparent;padding:0;margin:0;overflow:scroll"


Jetzt sollte man sich auch überlegen wie viele Informationen gleichzeitig angezeigt werden müssen. Entsprechend viele Items müssen erzeugt werden.
Wir benötigen je Info ein "Display only" Item (PX_INFOTEXT_X). Dabei sollte beachtet werden, dass die Eigenschaft "Escape special characters" auf NO steht, dadurch können HTML Formatierungen in den Text integriert werden. Zu jedem Infotext kommt noch eine Checkbox (return 1 when ckecked), damit können die Nachrichten einzeln bestätigt werden. Infotext und Checkbox werden nur angezeigt, wenn Infotext "NOT NULL" ist. Schließlich fehlt noch je ein Hidden Item zum Speichern der ID und ein Button zum Bestätigen der Seite.

Jetzt fehlen noch zwei Prozesse, der erste "On Load - Before Header" mit dem die Inhalte gefüllt werden:

declare
 v_cnt number := 1;
 v_trenner varchar2(30) := '<p><hr><p>';
begin
 for rec in (select id, information from informationen
               where app_id = :APP_ID and status = 'A'
               and id not in (select info_id
                from information_read where app_user = :APP_USER)
                order by id) loop
  if v_cnt = 1 then
   :PX_ID1 := rec.id;
   :PX_INFOTEXT_1 := rec.information;
  end if;
  if v_cnt = 2 then
   :PX_ID2 := rec.id;
   :PX_INFOTEXT_2 := rec.information;
  end if;
  v_cnt := v_cnt + 1;
 end loop;
end;


Dann kommt der Prozess zum Speichern der Informationen, wenn der Button gedrückt wurde:

begin
 if :PX_CHECK1 = 1 then
  insert into information_read values(:PX_ID1, :APP_USER, SYSDATE);
 end if;
 if :PX_CHECK2 = 1 then
  insert into information_read values(:PX_ID2, :APP_USER, SYSDATE);
 end if;
 :FXXX_HIDE := 'TRUE';
 :FXXX_INFO := '0';
end;


Hier tauchen erstmals die Applikations Items FXXX_HIDE und FXXX_INFO auf. Diese werden für die Steuerung des Infofensters benötigt. Bei Betätigung des Buttons wird auf jeden Fall das Item HIDE auf TRUE gesetzt, damit wird eine weitere Anzeige innerhalb der gleichen Session verhindert. Die Nachrichten können separat bestätigt werden, das heißt der Anwender kann entscheiden, ob sie in der nächsten Session wieder erscheinen sollen.

Nachdem es sich um ein modales Popup-Fenster handelt brauchen wir noch einen Branch, um es nach der Verarbeitung zu schließen. Der Branch Typ ist "Branch to PL/SQL Procedure".

begin
 htp.p('<body>');
 htp.p('<script type="text/javascript">');
 htp.p('parent.$("#modalDialog").dialog("close");');
 htp.p('</script>');
 htp.p('</body>');
end;


Kommen wir nun zur Steuerung. Bedingung war ja, dass es auch in einer laufenden Session erscheinen soll. Dafür müssen wir bei jedem Neuladen einer Seite nachsehen, ob es eine Nachricht gibt die der jeweilige User noch nicht gelesen hat. Weiterhin soll es die Möglichkeit geben, das modale Fenster zu schließen ohne die Nachrichten zu bestätigen. Dafür werden die Applikationsitems FXXX_HIDE und FXXX_INFO angelegt.
Dazu gehört auch ein Applikations Prozess mit dem Zündpunkt "On Load: Before Header".

begin
 select count(*)into :FXXX_INFO
             from informationen
             where app_id = :APP_ID
             and status = 'A'
             and id not in (select info_id from information_read where app_user = :APP_USER);
end;


Jetzt der zentrale Punkt: wann und wie zeige ich das modale Fenster an!

Dazu wird auf der Seite 0 eine "Dynamic Action" mit folgenden Einstellungen angelegt.

When:      Event = Page Load
           Condition = No Condition
Advanced:  Event Scope = once
Condition: Type = PL/SQL Expression
           Expression1 = NVL(:FXXX_HIDE,'F') != 'TRUE' and :FXXX_INFO > 0 and :APP_PAGE_ID not in (101,X)


Es müssen Loginseite und die Seite die als Popup erscheint ausgeschlossen werden.

TRUE ACTION: Execute JavaScriptCode (In diesem Beispiel wird in der Applikation 100 die Seite 7 als modales Popup aufgerufen)

var ev = this.browserEvent;
ev.preventDefault;
var horizontalPadding = 20;
var verticalPadding = 20;
$('<iframe id="modalDialog" src="f?p=100:7:&APP_SESSION.::NO::" />').dialog(
       {title: "APEX System Info",
        autoOpen: true,
        width: 700,
        hight: 350,
        modal: true,
        close: function(event, ui) { $(this).remove();},
        overlay: {opacity: 0.5, background: "black"}
        }
  ).width(700 - horizontalPadding).height(350 - verticalPadding);
return false;

Der Anwender bekommt "neue Informationen" auch während einer laufenden Session sofort angezeigt und er muss aktiv werden und die Meldungen bestätigen, um sie dauerhaft auszublenden. 

Achtung! Ab der APEX Version 4.1 sind aus Sicherheitsgründen Frames per default nicht erlaubt. Damit dieses Beispiel funktioniert muss in den Security Attributen "Embed in Frames" auf "Allow from same origin" umgestellt werden.

 

Weitere Informationen und Tipps zur Entwicklung mit APEX bekommen Sie auch in unseren Opens internal link in current windowSchulungen Entwicklung mit Application Express. 

Jede Menge Know-how für Sie!

In unserer Know-How Datenbank finden Sie mehr als 300 ausführliche Beiträge zu den Oracle-Themen wie DBA, SQL, PL/SQL, APEX und vielem mehr.
Hier erhalten Sie Antworten auf Ihre Fragen.