Xtodo: Unterschied zwischen den Versionen
(→==) |
|||
(14 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 52: | Zeile 52: | ||
Um das ToDo-System in ein Kommando zu integrieren, muss zunächst einmal eine entsprechende Kategorie angelegt werden, das wurde eben beschrieben. | Um das ToDo-System in ein Kommando zu integrieren, muss zunächst einmal eine entsprechende Kategorie angelegt werden, das wurde eben beschrieben. | ||
+ | |||
+ | ===ToDos anlegen=== | ||
Der nächste Schritt ist das Hinzufügen einer entsprechenden Page-Kategorie für xuser_page_user, was implizit durch xtodo_page_add passiert: | Der nächste Schritt ist das Hinzufügen einer entsprechenden Page-Kategorie für xuser_page_user, was implizit durch xtodo_page_add passiert: | ||
Zeile 70: | Zeile 72: | ||
Und da zwischen Vor- und Nachname ein Leerzeichen steht, kommt der ganze Parameter ''cmd'' in doppelte Anführungszeichen. | Und da zwischen Vor- und Nachname ein Leerzeichen steht, kommt der ganze Parameter ''cmd'' in doppelte Anführungszeichen. | ||
+ | |||
+ | ===Verlinkung ermöglichen=== | ||
Ist das nun schon alles? Nicht ganz: Wenn wir hier xuser mit einer ID als Parameter aufrufen, muss darauf entsprechend reagiert werden. Dazu wird zunächst in xuser die ID (also der erste CommandParameter, 0-relativ mit dem Index 0) in eine Variable geschrieben: | Ist das nun schon alles? Nicht ganz: Wenn wir hier xuser mit einer ID als Parameter aufrufen, muss darauf entsprechend reagiert werden. Dazu wird zunächst in xuser die ID (also der erste CommandParameter, 0-relativ mit dem Index 0) in eine Variable geschrieben: | ||
Zeile 86: | Zeile 90: | ||
~ | ~ | ||
+ | |||
+ | ===Übersichtsseite=== | ||
+ | |||
+ | Auf der Übersichtsseite werden alle Aufgaben zu der Kategorie gelistet. | ||
+ | |||
+ | [[file:Xtodo list.png|1137px|Übersichtsseite]] | ||
+ | |||
+ | #tree_add u=root c=ToDo s="#page_fill d=xtodo_page_todo(XU)" | ||
+ | |||
+ | In der Prozedur #page_fill wird als Parameter d=xtodo_page_todo(XU) aufgerufen. Als Parameter des Kommandos xtodo_page_todo muss hier lediglich die Kategorie (XU) übergeben werden. | ||
==Tabellen== | ==Tabellen== | ||
Zeile 123: | Zeile 137: | ||
progchg varchar(40) | progchg varchar(40) | ||
); | ); | ||
− | + | ||
create table todo_type2group ( | create table todo_type2group ( | ||
todo_type2group_id varchar(40) not null primary key, | todo_type2group_id varchar(40) not null primary key, | ||
Zeile 148: | Zeile 162: | ||
==Code== | ==Code== | ||
+ | |||
+ | ===xtodo=== | ||
+ | |||
+ | #rights n=frm r_user=w | ||
+ | #frm y=page c="xtodo" | ||
+ | |||
+ | #page | ||
+ | #prim as=Y | ||
+ | #cat as=Y c=ToDo | ||
+ | |||
+ | #sql2 select ctype as ckey, name as cvalue from todo_type | ||
+ | |||
+ | #grd_seg frc=0 fcc=1 clt=ss n=grid ro=Y | ||
+ | #grd_col f=todo_todo_id c1=ID y=guid w=30 ro=Y | ||
+ | #grd_col f=ctype c1=$T(type) y=lookup ld=sql2 w=250 wst=250 ro=Y | ||
+ | #grd_col f=ref w=30 y=link ro=Y cmdn=xtodo_add(link,$COPY($PVAL(grid,ctype,sel),1,2)) | ||
+ | #grd_col f=ref_text h=ref_hint c1=$T(reference) w=150 ro=Y | ||
+ | #grd_col f=deadline c1="Deadline" y=date w=90 | ||
+ | #grd_col f=ctext c1=Text w=200 wst=200 | ||
+ | #grd_col f=status c1="Status" y=lookup ld=todo_status w=90 ro=Y | ||
+ | #grd_col f=grp_short c1=$T(groups) w=150 wst=150 | ||
+ | #sql select t.*, y.grp_short | ||
+ | #sql from todo_todo t | ||
+ | #sql inner join todo_todo2group z on z.todo_todo_id = t.todo_todo_id and z.active = 'A' | ||
+ | #sql inner join user_group g1 on g1.user_group_id = z.user_group_id | ||
+ | #sql inner join user_group g2 on g2.path like g1.path || '%' and g2.status = 1 | ||
+ | #sql inner join user_user2group z2 on z2.user_group_id = g2.user_group_id and z2.user_user_id = :kid | ||
+ | #sql inner join todo_type2group y on y.user_group_id = z.user_group_id and t.ctype like y.ctype || '%' | ||
+ | #sql where t.status < 7 | ||
+ | #sql order by t.deadline, t.todo_todo_id | ||
+ | #grd_data q=join t=todo_todo kid=$RIGHTUSERID() | ||
+ | |||
+ | #page_ready | ||
+ | |||
+ | Wir haben hier einen der seltenen Fälle, dass wir keinen Tree verwenden, sondern der Typ unseres Formulars x=page ist. Somit haben wir auch kein Filter-Statement, sondern bauen gleich die Page auf. Das bedingt auch, dass wir nach dem Aufbau der Page die Prozedur #page_ready aufrufen. "Normalerweise" ist das nicht erforderlich, da diese Prozedur implizit von #page_fill aufgerufen wird. Eben diese verwenden wir hier aber nicht. | ||
+ | |||
+ | Wir haben hier nur ein Grid-Segment. Das dazugehörende SQL-Statement holt sich alle Einträge in der Tabelle todo_todo, die den Gruppen zugeordnet sind, in denen der User explizit oder implizit Mitglied ist. Damit das auch mit der impliziten Mitgliedschaft funktioniert, muss hier zweimal die Tabelle user_group hinzugefügt werden. | ||
+ | |||
+ | Ein ToDo kann mehr als einer Gruppe zugeordnet sein. Die Gruppennamen kommen aus der Abfrage als einzelne Zeilen, sollen im Grid jedoch durch Kommata getrennt in einer Zeile dargestellt werden. Deswegen wird die Datenquelle auf q=join gesetzt. Gruppiert werden die Zeilen nach der Schlüsselspalte, die hier aus t_todo_todo abgeleitet wird. | ||
+ | |||
+ | Für die Spalte Typ wird hier eine Nachschlageliste verwendet, die mit einem SQL-Statement gefüllt wird. Zur Abwechslung wird hier mal Special verwendet, sondern das Statement mit #sql2 definiert und die Datenquelle auf ld=sql2 gesetzt. | ||
+ | |||
+ | Wir auf das Link-Symbol geklickt, dann xtodo_add mit dem Parameter link aufgerufen. Als zweiter Parameter ist der Typ der Kategorie zu übergeben, damit daraus das Command ermittelt werden kann. Die ersten beiden Stellen des Typs eines ToDos ist der Typ der Kategorie, so dass diese mit der Funktion $COPY() ermittelt werden können. An den Typ des ToDos kommt man mit der Funktion $PVAL; das Segment lautet ''grid'', die Spalte ''ctype'', und es ist die aktuell selektierte Zeile zu verwenden. Ein Hinweis noch dazu, dass hier der Parameter cmdn statt cmd gesetzt wird: Bei cmd würden die Funktionen bereits bei der Aufbau der Seite ersetzt werden, zu dem Zeitpunkt ist jedoch noch völlig unklar, was später die selektierte Zeile sein wird. Von daher dürfen die Funktionen erst ausgewertet werden, wenn auf das Link-Symbol geklickt wurde; eben dazu wird cmdn verwendet. | ||
+ | |||
+ | ===xtodo_add=== | ||
+ | |||
+ | ~ $ICP(0,todo) | ||
+ | #var_set n=todo_todo_id z=$GUID() | ||
+ | #grd_add i=todo_add f_ref=$VAR(todo_id) f_ref_text=$VAR(todo_text) f_ref_hint=$VAR(todo_hint) f_status=1 | ||
+ | |||
+ | ~ $ICP(0,link) | ||
+ | #sql select ccommand from todo_type_category where ctype = :ktype | ||
+ | #sql_openval ktype=$CP(1) f_ccommand=1 | ||
+ | |||
+ | #exec cmd=$VAL(1) | ||
+ | |||
+ | ~~ | ||
+ | |||
+ | Das Kommando xtodo_add wird für zwei Zwecke verwendet, die durch den Parameter unterschieden werden. Mit dem Parameter todo werden ein weiteres Todo eingefügt, also dem Grid i=todo_add eine weitere Zeile hinzugefügt. Warum davor in die Variable todo_todo_id eine GUID gepackt werden, klären wir bei xtodo_page_add. Der hinzugefügten Zeile werden einige Werte zugewiesen, die aus Variablen kommen. | ||
+ | |||
+ | Wird auf der Seite xtodo auf das Link-Symbol geklickt, wird xtodo_add mit dem Parameter link aufgerufen, als zweiter Parameter wird der Typ des ToDos mitgegeben. Mit diesem wird mit einem SQL-Befehl das Kommando ermittelt und dieses aufgerufen. | ||
+ | |||
+ | ===xtodo_page_add=== | ||
+ | |||
+ | #var_set n=todo_id z=$CP(1) | ||
+ | #var_set n=todo_text z=$CP(2) | ||
+ | #var_set n=todo_hint z=$CP(3) | ||
+ | |||
+ | #prim as=Y | ||
+ | #cat as=Y c=ToDo | ||
+ | #btns_seg | ||
+ | #btns_btn c=$T(Add_todo) w=120 cmd=xtodo_add(todo) | ||
+ | |||
+ | #sql2 select ctype as ckey, name as cvalue from todo_type where ctype like '$CP(0)%' | ||
+ | |||
+ | #xgrd_seg frc=0 fcc=1 clt=ss n=todo_add c=" " b=H | ||
+ | #xgrd_col f=todo_todo_id c1=ID ro=Y y=guid w=30 nvi=$VAR(todo_todo_id) q=y2 | ||
+ | #xgrd_col f=todo_todo_id w=0 nv=$VAR(todo_todo_id) | ||
+ | #xgrd_col f=ctype c1=$T(type) y=lookup ld=sql2 q=y2 w=150 | ||
+ | #xgrd_col f=ref c1="Ref" w=0 q=y2 | ||
+ | #xgrd_col f=ref_text c1="Ref Text" w=0 q=y2 | ||
+ | #xgrd_col f=ref_hint c1="Ref Hint" w=0 q=y2 | ||
+ | #xgrd_col f=deadline c1="Deadline" y=date w=90 q=y2 | ||
+ | #xgrd_col f=ctext c1=Text l=200 w=200 wst=500 q=y2 | ||
+ | #xgrd_col f=status c1="Status" y=lookup ld=todo_status w=80 q=y2 | ||
+ | |||
+ | #xgrd_xcol f=todo_todo2group_id f1=user_group_id w=0 | ||
+ | #xgrd_xcol f=active y=todo f1=grp_short w=50 a1=c | ||
+ | #sql select user_group_id, grp_short from todo_type2group where ctype = :kcat and status = 1 | ||
+ | #xgrd_xdata q=sql kcat=$CP(0) | ||
+ | |||
+ | #sql select t.todo_todo_id, t.ctype, t.ref, t.ref_text, t.ref_hint, t.deadline, t.ctext, t.status, | ||
+ | #sql g.user_group_id, g.grp_short, z.todo_todo2group_id, z.active | ||
+ | #sql from todo_todo t | ||
+ | #sql left outer join todo_type2group g on g.ctype = :kcat1 | ||
+ | #sql left outer join todo_todo2group z on z.user_group_id=g.user_group_id and z.todo_todo_id = t.todo_todo_id | ||
+ | #sql where t.ctype like :kcat2 and t.ref = :kref order by t.todo_todo_id | ||
+ | #xgrd_data t=todo_todo2group t2=todo_todo kcat1=$CP(0) kcat2=$CP(0)% kref=$CP(1) fcol=user_group_id frow=todo_todo_id | ||
+ | |||
+ | Beim Aufruf des Kommandos werden Referenz-ID, Referenz-Name und Hint-Text als Parameter übergeben. Diese werden dann im Kommando xtodo_add benötigt und daher in Variablen gespeichert. | ||
+ | |||
+ | Die meisten Spalten kommen aus der Tabelle todo_todo. Wir haben jedoch hinten die Zuordnung zu den Gruppen, die aus den Tabellen todo_type2group und todo_todo2group kommen. Von daher muss hier ein XGrid-Segment verwendet werden. Dort muss jedoch die Verknüpfungstabelle (hier todo_todo2group) die Primärtabelle sein (zumindest dann, wenn Daten geschrieben werden sollen). Als zweite Tabelle haben wir dann t2=todo_todo, nutzen also Y-Funktionalität in einem XGrid-Segment. | ||
+ | |||
+ | Soll eine Aufgabe hinzugefügt werden, so wird mit dem entsprechenden Button das Kommando todo_add aufgerufen. In diesem Fall muss eine GUID generiert werden. Diese GUID muss jedoch in zwei Spalten geschrieben werden, da wir Y-Funktionalität nutzen. Daher wird die GUID im Kommando todo_add erstellt und mittels der Variablen todo_todo_id den Spalten zugewiesen. | ||
+ | |||
+ | Als X-Spalten werden alle Gruppen hinzugefügt, die der entsprechenden Kategorie zugewiesen sind. Eine Filterung auf die Kategorie - die als erster Parameter (also Index 0) übergeben wird - wird auch für die Typen der Aufgaben benötigt, entsprechend das Statement #sql2 für die Nachschlageliste. | ||
+ | |||
+ | |||
+ | Etwas unübersichtlich mögen die vielen Parameter in #xgrd_data sein: t und t2 sind die beiden Tabellen, in die Daten geschrieben werden. Das entsprechende SQL-Statement hat drei Parameter, denen in zwei Fällen die Kategorie zugewiesen wird, allerdings bei kcat2 mit dem SQL-Jokerzeichen %. Der dritte Parameter ist kref, also die Referenz, in diesem Fall also die UserID, damit nur Aufgaben zum entsprechenden User auf dessen Seite angezeigt werden. Jede Zeile ist einem Datensatz in der Tabelle todo_todo zugeordnet, somit ist frow=todo_todo_id. Im X-Teil des Grids werden die Aufgaben den Gruppen zugeordnet, dementsprechend ist fcol=user_group_id. | ||
+ | |||
+ | ===xtodo_page_todo=== | ||
+ | |||
+ | #prim as=Y | ||
+ | #cat as=Y c=ToDo | ||
+ | |||
+ | #sql2 select ctype as ckey, name as cvalue from todo_type where ctype like '$CP(0)%' | ||
+ | |||
+ | #xgrd_seg frc=0 fcc=1 clt=ss n=todo_add c=" " b=H | ||
+ | #xgrd_col f=todo_todo_id c1=ID ro=Y y=guid w=30 q=y2 | ||
+ | #xgrd_col f=todo_todo_id w=0 | ||
+ | #xgrd_col f=ref c1="Ref" w=30 y=link q=y2 ro=Y cmd=xtodo_add(link,$CP(0)) | ||
+ | #xgrd_col f=ref_text h=ref_hint c1=$T(reference) w=150 q=y2 ro=Y | ||
+ | #xgrd_col f=ctype c1=$T(type) y=lookup ld=sql2 q=y2 w=150 | ||
+ | #xgrd_col f=deadline c1="Deadline" y=date w=90 q=y2 | ||
+ | #xgrd_col f=ctext c1=Text l=200 w=200 wst=500 q=y2 | ||
+ | #xgrd_col f=status c1="Status" y=lookup ld=todo_status w=80 q=y2 | ||
+ | |||
+ | #xgrd_xcol f=todo_todo2group_id f1=user_group_id w=0 | ||
+ | #xgrd_xcol f=active y=todo f1=grp_short w=50 a1=c | ||
+ | #sql select user_group_id, grp_short from todo_type2group where ctype = :kcat and status = 1 | ||
+ | #xgrd_xdata q=sql kcat=$CP(0) | ||
+ | |||
+ | #sql select t.todo_todo_id, t.ctype, t.ref, t.ref_text, t.ref_hint, t.deadline, t.ctext, t.status, | ||
+ | #sql g.user_group_id, g.grp_short, z.todo_todo2group_id, z.active | ||
+ | #sql from todo_todo t | ||
+ | #sql left outer join todo_type2group g on g.ctype = :kcat1 | ||
+ | #sql left outer join todo_todo2group z on z.user_group_id=g.user_group_id and z.todo_todo_id = t.todo_todo_id | ||
+ | #sql where t.ctype like :kcat2 and t.status < 4 order by t.todo_todo_id | ||
+ | #xgrd_data t=todo_todo2group t2=todo_todo kcat1=$CP(0) kcat2=$CP(0)% fcol=user_group_id frow=todo_todo_id | ||
+ | |||
+ | Das Kommando xtodo_page_todo ähnelt weitgehend xtodo_page_add (es wurde von diesem kopiert und an einzelnen Stellen abgeändert), so dass wir nur die Unterschiede besprechen wollen. Zunächst einmal: Das Statement filtert die auf die Referenz (in diesem Fall die UserID), sondern nur auf die Kategorie - es werden auf dieser Übersichtsseite die Aufgaben bezüglich aller User angezeigt. | ||
+ | |||
+ | Es werden auf dieser Übersichtsseite auch keine neuen Aufgaben angelegt (welchem User sollten die auch zugeordnet sein?), von daher braucht es keinen Button, auch die Parameter nvi und nv in den entsprechenden Spalten können entfallen. | ||
+ | |||
+ | Mit diesem Übersichtsliste können auch Daten geändert werden, allerdings keine, welche die User-Zuordnung betreffen, die beiden Spalten sind auf ro=Y gesetzt (ReadOnly). | ||
+ | |||
+ | ===xtodo_config=== | ||
+ | |||
+ | #rights n=frm r_admin=w | ||
+ | #frm y=treepage c="xtodo_config - Configuration of the ToDo-System" flt=xtodo_config_flt w=200 | ||
+ | |||
+ | #btn y=save s=#save se=c | ||
+ | #btn y=cancel s=#cancel se=cp | ||
+ | #btn y=back s=#treeback se=b | ||
+ | #btn y=backback s=#treebackback se=b | ||
+ | #btn c=$T(Refresh) se=b s=#filter w=100 | ||
+ | #btn c=$T(new_category) se=b s=xtodo_config_add(cat) w=100 | ||
+ | |||
+ | #filter | ||
+ | |||
+ | Hier haben wir ein Formular-Kommando, das ziemlich "Standard" ist. | ||
+ | |||
+ | ===xtodo_config_add=== | ||
+ | |||
+ | ~ $ICP(0,cat) | ||
+ | #tree_add u=root c=$T(new_category) t=todo_type_category c1=ctype c2=name si=Y s="#page_fill d=xtodo_config_page_category" | ||
+ | |||
+ | ~ $ICP(0,type) | ||
+ | #grd_add i=grid f_ctype=$FND(s,ctype) f_sort=0 f_status=1 | ||
+ | |||
+ | ~ $ICP(0,group) | ||
+ | #grd_add i=group f_ctype=$FND(s,ctype) f_status=1 | ||
+ | |||
+ | ~~ | ||
+ | |||
+ | Hinzufügen lassen sic Kategorien, Typen und Gruppen, wobei Kategorien im Baum und die Typen und Gruppen im Grid ergänzt werden. | ||
+ | |||
+ | ===xtodo_config_flt=== | ||
+ | |||
+ | #tree_clear | ||
+ | |||
+ | #sql select * from todo_type_category order by csort, name | ||
+ | #tree_node u=root t=todo_type_category c1=ctype c2=name s="#page_fill d=xtodo_config_page_category" | ||
+ | #tree_fillsql | ||
+ | |||
+ | Im Baum werden alle Kategorien entsprechend der angegebenen Sortierreihenfolge gelistet. | ||
+ | |||
+ | ===xtodo_config_page_category=== | ||
+ | |||
+ | #page | ||
+ | |||
+ | #prim as=Y | ||
+ | #cat as=Y c=$T(category) | ||
+ | |||
+ | #vl_seg cc=4 clt=ss w1=100 w2=100 w3=100 w4=300 wst4=200 n=vl c=" " b=H | ||
+ | #vl_line c1="Type" f2=ctype l=2 c3=ID f4=todo_type_category_id ro4=Y nvi4=$GUID() | ||
+ | #vl_line c1="Sort" f2=csort y2=int z2=0 c3="Status" f4=status y4=lookup ld4=general_status z4=1 | ||
+ | #vl_line c1="Name" f2=name l=40 cs2=3 | ||
+ | #vl_line c1="Command" f2=ccommand l=200 cs2=3 | ||
+ | #sql select * from todo_type_category where todo_type_category_id = :kid | ||
+ | #vl_data q=sql t=todo_type_category kid=$FND(s,todo_type_category_id) | ||
+ | |||
+ | #prim as=Y | ||
+ | #cat as=Y c=$T(type) | ||
+ | |||
+ | #btns_seg | ||
+ | #btns_btn c=$T(new_type) w=160 cmd=xtodo_config_add(type) | ||
+ | |||
+ | #grd_seg frc=0 fcc=1 clt=ss n=grid c=" " b=H | ||
+ | #grd_col f=todo_type_id c1=ID ro=Y w=30 y=guid nvi=$GUID() | ||
+ | #grd_col f=ctype c1="Type" w=60 l=4 | ||
+ | #grd_col f=name c1="Name" l=40 w=200 st=200 | ||
+ | #grd_col f=csort c1="Sort" y=int w=50 | ||
+ | #grd_col f=status c1="Status" y=lookup ld=general_status | ||
+ | #sql select * from todo_type where ctype like :cat order by status, csort, name | ||
+ | #grd_data q=sql t=todo_type cat=$FND(s,ctype)% | ||
+ | |||
+ | #prim as=Y | ||
+ | #cat as=Y c=$T(groups) | ||
+ | |||
+ | #btns_seg | ||
+ | #btns_btn c=$T(new_group) w=160 cmd=xtodo_config_add(group) | ||
+ | |||
+ | #grd_seg frc=0 fcc=1 clt=ss n=group | ||
+ | #grd_col f=todo_type2group_id c1=ID ro=Y w=30 y=guid nvi=$GUID() | ||
+ | #grd_col f=ctype c1="Ctype" w=0 | ||
+ | #grd_col f=user_group_id c1=$T(group) y=lookup ls=system_groups_all w=200 wst=200 | ||
+ | #grd_col f=grp_short c1=Grp w=50 l=4 | ||
+ | #grd_col f=status c1="Status" y=lookup ld=general_status w=80 | ||
+ | #sql select * from todo_type2group where ctype = :cat order by status | ||
+ | #grd_data q=sql t=todo_type2group cat=$FND(s,ctype) | ||
+ | |||
+ | Auf dieser Seite haben wir ein VL-Segment für die Daten der Kategorie sowie zwei Grid-Segmente für die Typen und Gruppen der Kategorie. Alles hier ist ziemlich "Standard". |
Aktuelle Version vom 29. Mai 2021, 13:10 Uhr
Inhaltsverzeichnis
xtodo - Aufgabenliste
Die Aufgabenliste ist eine Möglichkeit, in verschiedenen Kommandos Aufgabenlisten hinzuzufügen. Der User hat dann die Möglichkeit, alle "seine" Aufgaben (die Aufgaben der Gruppen, in denen er explizit oder implizit Mitglied ist) in der zentralen Liste xtodo einzusehen.
Die Stärke von xtodo besteht darin, dass mit wenigen Codezeilen die Aufgabenliste beliebigen Seiten hinzugefügt werden kann.
xtodo
Mit dem Kommando xtodo wird die zentrale Aufgabenliste aufgerufen.
Mit den Standard-Tabellen gibt es lediglich eine einzige Aufgabe: Das Passwort des Users example zu ändern. Diese Aufgabe reicht jedoch, um die Spalten dieses Grids erläutern zu können.
- In der Spalte ID ist- gekürzt - die ID des Datensatzes enthalten und kann dort kopiert werden. Das brauchen vor allem Entwickler für die Fehlersuche.
- Der Typ der Aufgabe ist Passwort ändern. Nach Möglichkeit werden alle Typen so definiert, dass kein Text mehr erforderlich ist - dann entsteht dort auch kein Übersetzungsproblem.
- Es folgt die Spalte mit dem Link-Symbol. Mit einem Mausklick auf dieses Symbol springt man direkt zu der Aufgabe, hier im Beispiel in die User-Verwaltung zum User example.
- In der Spalte Referenz wird ein Wert angezeigt, der die zu erledigende Aufgabe konkretisiert - hier im Beispiel der Benutzername. Zusätzlich kann auch noch ein Hint-Text übergeben, hier der vollständige Name des Benutzers.
- Die Deadline ist das Datum, bis zu dem die Aufgabe erledigt werden sollte - und das ist hier bereits abgelaufen (das Ändern des Passwortes sollte also schleunigst nachgeholt werden...)
- In der Spalte Text kann die Aufgabe konkretisiert werden. Im Idealfall ist das gar nicht erforderlich, weil der Typ selbsterklärend ist.
- Der Status ist hier todo, die Aufgabe ist also noch zu erledigen.
- Zuletzt werden die Gruppen angezeigt, denen die Aufgabe zugeordnet ist. Dass die Aufgabe auch der Gruppe User zugeordnet ist, ist hier eher etwas "Beispiel", weil sich ohne Admin-Rechte in der User-Verwaltung keine Passwörter ändern lassen.
xtodo_config
Wenn das Todo-System einem neuen Kommando hinzugefügt werden soll, dann muss das in xtodo_config entsprechend konfiguriert werden.
Kategorie
Die Kategorie entspricht meist dem Kommando, dem die Aufgabenliste hinzugefügt werden soll. Dafür muss zunächst der Type benannt werden und zwar mit einem Kürzel aus zwei Zeichen. Wir wollen hier die Aufgabenliste für die Userverwaltung xuser hinzufügen und verwenden pragmatisch das Kürzel XU. Der Wert in Sort dient vor allem der Sortierung hier im Baum.
Von Bedeutung ist noch der Wert in Command. Dies ist das Kommando, das ausgeführt wird, wenn der Anwender auf das Link-Symbol klickt. Üblicherweise wird hier in einem neuen Tab das Kommando ausgeführt und als Parameter mittels der Funktion $PAGE(link) die ID des betreffenden Datensatzes übergeben.
Zum kopieren:
#tab_new c=xuser cmd=xuser($PAGE(link))
(Es muss dann lediglich an den beiden Stellen xuser durch den eigenen Kommandonamen ersetzt werden)
Typ
Der Typ ist der Typ der Aufgabe. Dieser hat zunächst ein vierstelliges Kürzel, wobei die ersten beiden Stellen dem Kürzel der Kategorie entsprechen müssen. Hier im Beispiel: XU kommt von der Kategorie und CP steht für change password.
Im Namen können auch Funktionen verwendet werden. Meist wird das die Funktion $T() sein, um den Namen übersetzen zu können. Das ist auch der Grund, weswegen man umfangreich Typen anlegen sollte, statt auf das Freitextfeld Text zu vertrauen.
Gruppen
Die Kategorie können verschiedenen Usergruppen zugeordnet werden, nun denen kann später die Aufgabe zugewiesen werden.
Integration in ein Kommando
Um das ToDo-System in ein Kommando zu integrieren, muss zunächst einmal eine entsprechende Kategorie angelegt werden, das wurde eben beschrieben.
ToDos anlegen
Der nächste Schritt ist das Hinzufügen einer entsprechenden Page-Kategorie für xuser_page_user, was implizit durch xtodo_page_add passiert:
#exec cmd="xtodo_page_add(XU,$PVAL(vl,user_user_id),$PVAL(vl,login),$PVAL(vl,shortname)$CHR(crlf)$PVAL(vl,firstname) $PVAL(vl,lastname))"
Das sieht dann im Formular wie folgt aus:
Hier können dann neue Todos hinzugefügt werden, deren Typ ausgewählt, bei Bedarf ergänzender Text hinzugefügt werden, der Status gesetzt und die Aufgabe den dem Typ hinzugefügten Gruppen zugewiesen werden. Mit Mausklick auf die Symbole schaltet man den erledigt-Status weiter (leer, ToDo, erledigt, verworfen).
Die Codezeile, die hier zu verwenden ist, sieht etwas komplex aus, ist bei näherer Betrachtung eigentlich harmlos bis auf den etwas umfangreicheren Hint-Text. Das Kommando lautet xtodo_page_add und hat die folgenden vier Parameter:
- Der Typ der Todo-Kategorie, hier also XU.
- Die Referenz-ID, das ist hier die ID des Users, und die ziehen wir aus der Page ($PVAL(vl,user_user_id)). Die Referenz-ID wird benötigt, um direkt zum betreffenden Datensatz springen zu können.
- Der Login-Name als Wert, der dann in der Spalte Referenz angezeigt wird ($PVAL(vl,login)).
- Und schließlich der Hint-Text, der über der Referenz angezeigt wird. Hier nehmen wir die Spalte shortname und in der zweiten Zeile (Zeilenumbruch mit $CHR(crlf)) die Spalten firstname und lastname. (Also vollständig $PVAL(vl,shortname)$CHR(crlf)$PVAL(vl,firstname) $PVAL(vl,lastname).) Wird kein Hint-Text angegeben, wird auch keiner angezeigt.
Und da zwischen Vor- und Nachname ein Leerzeichen steht, kommt der ganze Parameter cmd in doppelte Anführungszeichen.
Verlinkung ermöglichen
Ist das nun schon alles? Nicht ganz: Wenn wir hier xuser mit einer ID als Parameter aufrufen, muss darauf entsprechend reagiert werden. Dazu wird zunächst in xuser die ID (also der erste CommandParameter, 0-relativ mit dem Index 0) in eine Variable geschrieben:
#var_set n=link z=$CP(0)
Und beim Aufbau des Trees in xuser_flt muss dann diese Variable berücksichtigt werden:
~ $NEMPTY($VAR(link)) #sql select user_user_id, login, shortname from user_user where user_user_id = :kid #tree_node u=root t=user_user c1=login c2=shortname s="#page_fill d=xuser_page_user" #tree_fillsql fi=Y kid=$VAR(link) #tree_add u=root c=$T(Groups) s="#page_fill d=xuser_page_groups(G)" o=xuser_open(g) #tree_add u=root c=$T(Individual_groups) s="#page_fill d=xuser_page_groups(I)" o=xuser_open(ig) ~
Übersichtsseite
Auf der Übersichtsseite werden alle Aufgaben zu der Kategorie gelistet.
#tree_add u=root c=ToDo s="#page_fill d=xtodo_page_todo(XU)"
In der Prozedur #page_fill wird als Parameter d=xtodo_page_todo(XU) aufgerufen. Als Parameter des Kommandos xtodo_page_todo muss hier lediglich die Kategorie (XU) übergeben werden.
Tabellen
create table todo_todo ( todo_todo_id varchar(40) not null primary key, ctype char(4) not null, ref varchar(40), ref_text vachar(40), ref_hint varchar(200), deadline date, ctext varchar(200), status int, datechg date, usrchg varchar(40), progchg varchar(40) );
create table todo_todo2group ( todo_todo2group_id varchar(40) not null primary key, todo_todo_id varchar(40) not null, user_group_id varchar2(40) not null, active char(1), datechg date, usrchg varchar(40), progchg varchar(40) );
create table todo_type ( todo_type_id varchar(40) not null primary key, ctype char(4) not null unique, name varchar(40), csort int, status int, datechg date, usrchg varchar(40), progchg varchar(40) );
create table todo_type2group ( todo_type2group_id varchar(40) not null primary key, ctype char(2) not null, grp_short varchar(4) not null, user_group_id varchar(40) not null, status int, datechg date, usrchg varchar(40), progchg varchar(40) );
create table todo_type_category ( todo_type_category_id varchar(40) not null primary key, ctype char(2) not null unique, name varchar(40), ccommand varchar(200), csort int, status int, datechg date, usrchg varchar(40), progchg varchar(40) );
Code
xtodo
#rights n=frm r_user=w #frm y=page c="xtodo" #page #prim as=Y #cat as=Y c=ToDo #sql2 select ctype as ckey, name as cvalue from todo_type #grd_seg frc=0 fcc=1 clt=ss n=grid ro=Y #grd_col f=todo_todo_id c1=ID y=guid w=30 ro=Y #grd_col f=ctype c1=$T(type) y=lookup ld=sql2 w=250 wst=250 ro=Y #grd_col f=ref w=30 y=link ro=Y cmdn=xtodo_add(link,$COPY($PVAL(grid,ctype,sel),1,2)) #grd_col f=ref_text h=ref_hint c1=$T(reference) w=150 ro=Y #grd_col f=deadline c1="Deadline" y=date w=90 #grd_col f=ctext c1=Text w=200 wst=200 #grd_col f=status c1="Status" y=lookup ld=todo_status w=90 ro=Y #grd_col f=grp_short c1=$T(groups) w=150 wst=150 #sql select t.*, y.grp_short #sql from todo_todo t #sql inner join todo_todo2group z on z.todo_todo_id = t.todo_todo_id and z.active = 'A' #sql inner join user_group g1 on g1.user_group_id = z.user_group_id #sql inner join user_group g2 on g2.path like g1.path || '%' and g2.status = 1 #sql inner join user_user2group z2 on z2.user_group_id = g2.user_group_id and z2.user_user_id = :kid #sql inner join todo_type2group y on y.user_group_id = z.user_group_id and t.ctype like y.ctype || '%' #sql where t.status < 7 #sql order by t.deadline, t.todo_todo_id #grd_data q=join t=todo_todo kid=$RIGHTUSERID() #page_ready
Wir haben hier einen der seltenen Fälle, dass wir keinen Tree verwenden, sondern der Typ unseres Formulars x=page ist. Somit haben wir auch kein Filter-Statement, sondern bauen gleich die Page auf. Das bedingt auch, dass wir nach dem Aufbau der Page die Prozedur #page_ready aufrufen. "Normalerweise" ist das nicht erforderlich, da diese Prozedur implizit von #page_fill aufgerufen wird. Eben diese verwenden wir hier aber nicht.
Wir haben hier nur ein Grid-Segment. Das dazugehörende SQL-Statement holt sich alle Einträge in der Tabelle todo_todo, die den Gruppen zugeordnet sind, in denen der User explizit oder implizit Mitglied ist. Damit das auch mit der impliziten Mitgliedschaft funktioniert, muss hier zweimal die Tabelle user_group hinzugefügt werden.
Ein ToDo kann mehr als einer Gruppe zugeordnet sein. Die Gruppennamen kommen aus der Abfrage als einzelne Zeilen, sollen im Grid jedoch durch Kommata getrennt in einer Zeile dargestellt werden. Deswegen wird die Datenquelle auf q=join gesetzt. Gruppiert werden die Zeilen nach der Schlüsselspalte, die hier aus t_todo_todo abgeleitet wird.
Für die Spalte Typ wird hier eine Nachschlageliste verwendet, die mit einem SQL-Statement gefüllt wird. Zur Abwechslung wird hier mal Special verwendet, sondern das Statement mit #sql2 definiert und die Datenquelle auf ld=sql2 gesetzt.
Wir auf das Link-Symbol geklickt, dann xtodo_add mit dem Parameter link aufgerufen. Als zweiter Parameter ist der Typ der Kategorie zu übergeben, damit daraus das Command ermittelt werden kann. Die ersten beiden Stellen des Typs eines ToDos ist der Typ der Kategorie, so dass diese mit der Funktion $COPY() ermittelt werden können. An den Typ des ToDos kommt man mit der Funktion $PVAL; das Segment lautet grid, die Spalte ctype, und es ist die aktuell selektierte Zeile zu verwenden. Ein Hinweis noch dazu, dass hier der Parameter cmdn statt cmd gesetzt wird: Bei cmd würden die Funktionen bereits bei der Aufbau der Seite ersetzt werden, zu dem Zeitpunkt ist jedoch noch völlig unklar, was später die selektierte Zeile sein wird. Von daher dürfen die Funktionen erst ausgewertet werden, wenn auf das Link-Symbol geklickt wurde; eben dazu wird cmdn verwendet.
xtodo_add
~ $ICP(0,todo) #var_set n=todo_todo_id z=$GUID() #grd_add i=todo_add f_ref=$VAR(todo_id) f_ref_text=$VAR(todo_text) f_ref_hint=$VAR(todo_hint) f_status=1 ~ $ICP(0,link) #sql select ccommand from todo_type_category where ctype = :ktype #sql_openval ktype=$CP(1) f_ccommand=1 #exec cmd=$VAL(1) ~~
Das Kommando xtodo_add wird für zwei Zwecke verwendet, die durch den Parameter unterschieden werden. Mit dem Parameter todo werden ein weiteres Todo eingefügt, also dem Grid i=todo_add eine weitere Zeile hinzugefügt. Warum davor in die Variable todo_todo_id eine GUID gepackt werden, klären wir bei xtodo_page_add. Der hinzugefügten Zeile werden einige Werte zugewiesen, die aus Variablen kommen.
Wird auf der Seite xtodo auf das Link-Symbol geklickt, wird xtodo_add mit dem Parameter link aufgerufen, als zweiter Parameter wird der Typ des ToDos mitgegeben. Mit diesem wird mit einem SQL-Befehl das Kommando ermittelt und dieses aufgerufen.
xtodo_page_add
#var_set n=todo_id z=$CP(1) #var_set n=todo_text z=$CP(2) #var_set n=todo_hint z=$CP(3) #prim as=Y #cat as=Y c=ToDo #btns_seg #btns_btn c=$T(Add_todo) w=120 cmd=xtodo_add(todo) #sql2 select ctype as ckey, name as cvalue from todo_type where ctype like '$CP(0)%' #xgrd_seg frc=0 fcc=1 clt=ss n=todo_add c=" " b=H #xgrd_col f=todo_todo_id c1=ID ro=Y y=guid w=30 nvi=$VAR(todo_todo_id) q=y2 #xgrd_col f=todo_todo_id w=0 nv=$VAR(todo_todo_id) #xgrd_col f=ctype c1=$T(type) y=lookup ld=sql2 q=y2 w=150 #xgrd_col f=ref c1="Ref" w=0 q=y2 #xgrd_col f=ref_text c1="Ref Text" w=0 q=y2 #xgrd_col f=ref_hint c1="Ref Hint" w=0 q=y2 #xgrd_col f=deadline c1="Deadline" y=date w=90 q=y2 #xgrd_col f=ctext c1=Text l=200 w=200 wst=500 q=y2 #xgrd_col f=status c1="Status" y=lookup ld=todo_status w=80 q=y2 #xgrd_xcol f=todo_todo2group_id f1=user_group_id w=0 #xgrd_xcol f=active y=todo f1=grp_short w=50 a1=c #sql select user_group_id, grp_short from todo_type2group where ctype = :kcat and status = 1 #xgrd_xdata q=sql kcat=$CP(0) #sql select t.todo_todo_id, t.ctype, t.ref, t.ref_text, t.ref_hint, t.deadline, t.ctext, t.status, #sql g.user_group_id, g.grp_short, z.todo_todo2group_id, z.active #sql from todo_todo t #sql left outer join todo_type2group g on g.ctype = :kcat1 #sql left outer join todo_todo2group z on z.user_group_id=g.user_group_id and z.todo_todo_id = t.todo_todo_id #sql where t.ctype like :kcat2 and t.ref = :kref order by t.todo_todo_id #xgrd_data t=todo_todo2group t2=todo_todo kcat1=$CP(0) kcat2=$CP(0)% kref=$CP(1) fcol=user_group_id frow=todo_todo_id
Beim Aufruf des Kommandos werden Referenz-ID, Referenz-Name und Hint-Text als Parameter übergeben. Diese werden dann im Kommando xtodo_add benötigt und daher in Variablen gespeichert.
Die meisten Spalten kommen aus der Tabelle todo_todo. Wir haben jedoch hinten die Zuordnung zu den Gruppen, die aus den Tabellen todo_type2group und todo_todo2group kommen. Von daher muss hier ein XGrid-Segment verwendet werden. Dort muss jedoch die Verknüpfungstabelle (hier todo_todo2group) die Primärtabelle sein (zumindest dann, wenn Daten geschrieben werden sollen). Als zweite Tabelle haben wir dann t2=todo_todo, nutzen also Y-Funktionalität in einem XGrid-Segment.
Soll eine Aufgabe hinzugefügt werden, so wird mit dem entsprechenden Button das Kommando todo_add aufgerufen. In diesem Fall muss eine GUID generiert werden. Diese GUID muss jedoch in zwei Spalten geschrieben werden, da wir Y-Funktionalität nutzen. Daher wird die GUID im Kommando todo_add erstellt und mittels der Variablen todo_todo_id den Spalten zugewiesen.
Als X-Spalten werden alle Gruppen hinzugefügt, die der entsprechenden Kategorie zugewiesen sind. Eine Filterung auf die Kategorie - die als erster Parameter (also Index 0) übergeben wird - wird auch für die Typen der Aufgaben benötigt, entsprechend das Statement #sql2 für die Nachschlageliste.
Etwas unübersichtlich mögen die vielen Parameter in #xgrd_data sein: t und t2 sind die beiden Tabellen, in die Daten geschrieben werden. Das entsprechende SQL-Statement hat drei Parameter, denen in zwei Fällen die Kategorie zugewiesen wird, allerdings bei kcat2 mit dem SQL-Jokerzeichen %. Der dritte Parameter ist kref, also die Referenz, in diesem Fall also die UserID, damit nur Aufgaben zum entsprechenden User auf dessen Seite angezeigt werden. Jede Zeile ist einem Datensatz in der Tabelle todo_todo zugeordnet, somit ist frow=todo_todo_id. Im X-Teil des Grids werden die Aufgaben den Gruppen zugeordnet, dementsprechend ist fcol=user_group_id.
xtodo_page_todo
#prim as=Y #cat as=Y c=ToDo #sql2 select ctype as ckey, name as cvalue from todo_type where ctype like '$CP(0)%' #xgrd_seg frc=0 fcc=1 clt=ss n=todo_add c=" " b=H #xgrd_col f=todo_todo_id c1=ID ro=Y y=guid w=30 q=y2 #xgrd_col f=todo_todo_id w=0 #xgrd_col f=ref c1="Ref" w=30 y=link q=y2 ro=Y cmd=xtodo_add(link,$CP(0)) #xgrd_col f=ref_text h=ref_hint c1=$T(reference) w=150 q=y2 ro=Y #xgrd_col f=ctype c1=$T(type) y=lookup ld=sql2 q=y2 w=150 #xgrd_col f=deadline c1="Deadline" y=date w=90 q=y2 #xgrd_col f=ctext c1=Text l=200 w=200 wst=500 q=y2 #xgrd_col f=status c1="Status" y=lookup ld=todo_status w=80 q=y2 #xgrd_xcol f=todo_todo2group_id f1=user_group_id w=0 #xgrd_xcol f=active y=todo f1=grp_short w=50 a1=c #sql select user_group_id, grp_short from todo_type2group where ctype = :kcat and status = 1 #xgrd_xdata q=sql kcat=$CP(0) #sql select t.todo_todo_id, t.ctype, t.ref, t.ref_text, t.ref_hint, t.deadline, t.ctext, t.status, #sql g.user_group_id, g.grp_short, z.todo_todo2group_id, z.active #sql from todo_todo t #sql left outer join todo_type2group g on g.ctype = :kcat1 #sql left outer join todo_todo2group z on z.user_group_id=g.user_group_id and z.todo_todo_id = t.todo_todo_id #sql where t.ctype like :kcat2 and t.status < 4 order by t.todo_todo_id #xgrd_data t=todo_todo2group t2=todo_todo kcat1=$CP(0) kcat2=$CP(0)% fcol=user_group_id frow=todo_todo_id
Das Kommando xtodo_page_todo ähnelt weitgehend xtodo_page_add (es wurde von diesem kopiert und an einzelnen Stellen abgeändert), so dass wir nur die Unterschiede besprechen wollen. Zunächst einmal: Das Statement filtert die auf die Referenz (in diesem Fall die UserID), sondern nur auf die Kategorie - es werden auf dieser Übersichtsseite die Aufgaben bezüglich aller User angezeigt.
Es werden auf dieser Übersichtsseite auch keine neuen Aufgaben angelegt (welchem User sollten die auch zugeordnet sein?), von daher braucht es keinen Button, auch die Parameter nvi und nv in den entsprechenden Spalten können entfallen.
Mit diesem Übersichtsliste können auch Daten geändert werden, allerdings keine, welche die User-Zuordnung betreffen, die beiden Spalten sind auf ro=Y gesetzt (ReadOnly).
xtodo_config
#rights n=frm r_admin=w #frm y=treepage c="xtodo_config - Configuration of the ToDo-System" flt=xtodo_config_flt w=200 #btn y=save s=#save se=c #btn y=cancel s=#cancel se=cp #btn y=back s=#treeback se=b #btn y=backback s=#treebackback se=b #btn c=$T(Refresh) se=b s=#filter w=100 #btn c=$T(new_category) se=b s=xtodo_config_add(cat) w=100 #filter
Hier haben wir ein Formular-Kommando, das ziemlich "Standard" ist.
xtodo_config_add
~ $ICP(0,cat) #tree_add u=root c=$T(new_category) t=todo_type_category c1=ctype c2=name si=Y s="#page_fill d=xtodo_config_page_category" ~ $ICP(0,type) #grd_add i=grid f_ctype=$FND(s,ctype) f_sort=0 f_status=1 ~ $ICP(0,group) #grd_add i=group f_ctype=$FND(s,ctype) f_status=1 ~~
Hinzufügen lassen sic Kategorien, Typen und Gruppen, wobei Kategorien im Baum und die Typen und Gruppen im Grid ergänzt werden.
xtodo_config_flt
#tree_clear #sql select * from todo_type_category order by csort, name #tree_node u=root t=todo_type_category c1=ctype c2=name s="#page_fill d=xtodo_config_page_category" #tree_fillsql
Im Baum werden alle Kategorien entsprechend der angegebenen Sortierreihenfolge gelistet.
xtodo_config_page_category
#page #prim as=Y #cat as=Y c=$T(category) #vl_seg cc=4 clt=ss w1=100 w2=100 w3=100 w4=300 wst4=200 n=vl c=" " b=H #vl_line c1="Type" f2=ctype l=2 c3=ID f4=todo_type_category_id ro4=Y nvi4=$GUID() #vl_line c1="Sort" f2=csort y2=int z2=0 c3="Status" f4=status y4=lookup ld4=general_status z4=1 #vl_line c1="Name" f2=name l=40 cs2=3 #vl_line c1="Command" f2=ccommand l=200 cs2=3 #sql select * from todo_type_category where todo_type_category_id = :kid #vl_data q=sql t=todo_type_category kid=$FND(s,todo_type_category_id) #prim as=Y #cat as=Y c=$T(type) #btns_seg #btns_btn c=$T(new_type) w=160 cmd=xtodo_config_add(type) #grd_seg frc=0 fcc=1 clt=ss n=grid c=" " b=H #grd_col f=todo_type_id c1=ID ro=Y w=30 y=guid nvi=$GUID() #grd_col f=ctype c1="Type" w=60 l=4 #grd_col f=name c1="Name" l=40 w=200 st=200 #grd_col f=csort c1="Sort" y=int w=50 #grd_col f=status c1="Status" y=lookup ld=general_status #sql select * from todo_type where ctype like :cat order by status, csort, name #grd_data q=sql t=todo_type cat=$FND(s,ctype)% #prim as=Y #cat as=Y c=$T(groups) #btns_seg #btns_btn c=$T(new_group) w=160 cmd=xtodo_config_add(group) #grd_seg frc=0 fcc=1 clt=ss n=group #grd_col f=todo_type2group_id c1=ID ro=Y w=30 y=guid nvi=$GUID() #grd_col f=ctype c1="Ctype" w=0 #grd_col f=user_group_id c1=$T(group) y=lookup ls=system_groups_all w=200 wst=200 #grd_col f=grp_short c1=Grp w=50 l=4 #grd_col f=status c1="Status" y=lookup ld=general_status w=80 #sql select * from todo_type2group where ctype = :cat order by status #grd_data q=sql t=todo_type2group cat=$FND(s,ctype)
Auf dieser Seite haben wir ein VL-Segment für die Daten der Kategorie sowie zwei Grid-Segmente für die Typen und Gruppen der Kategorie. Alles hier ist ziemlich "Standard".