Personal Info AddOn Documentation
User personalisation and reference tool.
See
PersonalInfoAddOn for an introduction and installation instructions.
This topic is meant for administrators and serves as introduction springboard to PersonalInfoAddOn topics. Keep this topic as reference.
Reference for administrators
Distribution files:
All these files need to reside in your user web (by default Main).
Diagram of main pages
Documentation of the INCLUDE sections in PersonalInfo .
personalInfo
This block is intended as a quick introduction of the user (picture!) and to provide the most common information at hand. It makes it easy to edit the data "on the fly".
This block is included on every user page when
PersonalInfoUserViewTemplate is set as view template:
To set PersonalInfoUserViewTemplate as view template, follow these steps:
Include the personal info block in existing pages using either of these 2 methods:
To have this set automatically for new users, change the last line in TWiki.NewUserTemplate to
%META:PREFERENCE{name="VIEW_TEMPLATE" title="VIEW_TEMPLATE" type="Local" value="PersonalInfoUserView"}%
To customize which fields are displayed, follow these steps:
Add the custom fields and field formats to the table in TWiki.UserForm . Below is an example, so change the fields as you like, but keep the fields Image
and WorkStatus
(including the value 'Current') (both fields are not displayed to the user in topic view). In the current setup the value for WorkStatus
can be set when editing the topic.
| Image | label | 1 | | | H |
| <nop>WorkStatus | select | 1 | Current, Former | | H |
| <nop>WorkEmail | text | 40 | | | H |
| <nop>WorkPhone | text | 40 | | | H |
| <nop>WorkPhoneMobile | text | 40 | | | H |
| <nop>WorkLocation | text | 40 | | | H |
Edit PersonalInfo and write the fields and field labels by editing the INCLUDE
variables. The variable fieldName
corresponds to the field names in UserForm . The variable label
can be any text you wish.
If you want to change the layout:
Some more indepth information what happens when the user saves her data:
When AllowRedirectUrl
is enabled in configure, topic PersonalInfo will be saved as well. This setting is not advisable for public installations, but is ok for intranets.
If TWiki:Plugins/AttachContentPlugin is enabled, on saving PersonalInfo the javascript attachment for directSearch will be saved as well.
The javascript file will make directSearch quite a bit faster. If AttachContentPlugin is not installed, the search will fall back on TWiki's (slower) live search.
The same idea may be used to create an XML file, this is turned off for performance. See phoneListXML .
On large intranets this will have a performance hit. Possibly a different timing of updating the javascript will be needed.
This include is written in
PersonalInfoUserViewTemplate :
%INCLUDE{"PersonalInfo" section="personalInfo"}%
Creates:
directSearch
Creates a search box to directly find users with their WorkPhone number.
When AttachContentPlugin is enabled, an updated javascript file attachment is created each time
PersonalInfo is saved. This will make loading of the directSearch module a lot faster.
To disable the auto-creation of the attachment, change
PersonalInfo#createDirectSearchAttachment : change
%STARTATTACH{
to
%<nop>STARTATTACH{
Usage:
%INCLUDE{"PersonalInfo" section="directSearch" title="*Phone list*" maxresults="10"}%
Parameter
Description
Default value
title
Title above the input box
no title
maxresults
The number of users that are displayed; use -1
to show all users
12
inputfieldsize
The width of the input field
12
Creates:
Phone list
Personal Info AddOn Custom Data
Admin topic for PersonalInfoAddOn . For a general overview see
PersonalInfoHome .
This current topic and
PersonalInfoModules work in tandem:
How can I customize a section?
To replace the default implementation: replace the %INCLUDE{}%
variable by custom text.
To add to the custom implementation: leave the %INCLUDE{}%
variable in place and add text before or after
Customizable sections
personalInfoFields
%STARTSECTION{"personalInfoFields"}%<table cellspacing=
Personal Info AddOn Application Sections
Admin topic for PersonalInfoAddOn .
This topic holds a number of modules (INCLUDE sections) to display and search user information. See also
PersonalInfoHome for documentation and usage examples.
Leave this file intact - always make custom changes to PersonalInfo .
personalInfo
%STARTSECTION{"personalInfoFields"}% This block is only defined in PersonalInfo %ENDSECTION{"personalInfoFields"}%
%STARTSECTION{"personalInfoDataRow" fieldName=%FIELDNAME% label=%LABEL%}%<tr>
<th> %label% </th><td> %IF{"defined editUserData" then="<input type='text' name='%fieldName%' id='%fieldName%' $percntIF{$quot\'%editable%\'=\'no\'$quot then=$quotdisabled=\'disabled\'$quot}$percnt $percntIF{$quot\'%editable%\'=\'no\'$quot then=$quotclass=\'twikiInputFieldDisabled\'$quot else=$quotclass=\'twikiInputField\'$quot}$percnt size='40' value='%FORMFIELD{"%fieldName%" topic="%BASETOPIC%" format="$value"}%' />" else="%FORMFIELD{"%fieldName%" topic="%BASETOPIC%" format="$percntIF{$quot\'%link%\'=\'yes\'$quot then=$quot[[$value]]$quot else=$quot$value$quot}$percnt"}%" }% </td>
</tr>%ENDSECTION{"personalInfoDataRow"}%
personalInfoStyle
In view template
PersonalInfoUserViewTemplate these styles are added to the HTML head. Other pages need to include the styles using
%INCLUDE{}%
.
%STARTSECTION{"personalInfoStyle"}%<style type="text/css" media="all">
.personalInfo {
margin:0 0 1em 0;
}
.personalInfo .pIparagraphWithImageLeftText table {
border-width:1px 0 0 0;
border-collapse:collapse;
}
.personalInfo .pIparagraphWithImageLeftText th {
font-weight:normal;
text-align:left;
color:#555;
overflow:hidden;
white-space:nowrap;
}
.personalInfo .pIparagraphWithImageLeftText td {
width:100%;
overflow:hidden;
white-space:nowrap;
}
.personalInfo .pIparagraphWithImageLeftText td,
.personalInfo .pIparagraphWithImageLeftText th {
line-height:1.3em;
border-width:0 0 1px 0;
padding:.4em .8em;
vertical-align:middle;
}
.personalInfo .pIparagraphWithImageLeftText table,
.personalInfo .pIparagraphWithImageLeftText td,
.personalInfo .pIparagraphWithImageLeftText th {
border-style:solid;
border-color:#e5e2db;
}
.personalInfoFormDataActions {
margin:.5em 0 2em 0;
padding:0 .8em; /* same as .pIparagraphWithImageLeftText td */
}
.personalInfoFormDataActions a {
font-size:86%; /* same as .twikiSmall */
}
.personalInfoFormDataActions .twikiSeparator {
color:#ccc;
}
</style>%ENDSECTION{"personalInfoStyle"}%
%STARTSECTION{"personalInfo"}%<div class="pIparagraphFrame personalInfo%IF{"$'FORMFIELD{WorkStatus}'!='Current'" then=" pIFormer"}%">
---+!! <nop>%FORMFIELD{"FirstName" topic="%BASETOPIC%"}% %FORMFIELD{"LastName" topic="%BASETOPIC%"}%
%INCLUDE{"PersonalInfoLayoutModules" section="paragraphWithImageLeftStyle"}%
<form name="main" action="%SCRIPTURLPATH{"save"}%/%BASEWEB%/%BASETOPIC%" method="post">
<input type="hidden" name="editaction" value="form" />
<!-- if !AllowRedirectUrl is enabled in configure, !PersonalInfo is updated to save the search data as javascript file -->
%IF{"context AttachContentPluginEnabled" then='<input type="hidden" name="redirectto" value="%SCRIPTURL{save}%/%WEB%/PersonalInfo?redirectto=%BASETOPIC%" />'}%
%INCLUDE{"PersonalInfoLayoutModules" section="paragraphWithImageLeft" imgName="%FORMFIELD{"Image" topic="%BASEWEB%.%BASETOPIC%" format="$value" default="" alttext=""}%" imgWeb="%BASEWEB%" imgTopic="%BASETOPIC%" imgWidth="120" imgTitle="" text="%INCLUDE{"PersonalInfo" section="personalInfoFields"}%
%IF{"not defined editUserData" then="<div class='personalInfoFormDataActions twikiUnvisited'>[[%SCRIPTURL{view}%/%BASEWEB%/%BASETOPIC%?editUserData=on][Edit data]] <span class='twikiSeparator'>|</span> [[%SCRIPTURL{view}%/%BASEWEB%/%BASETOPIC%?template=PersonalInfoPictureView][Change picture]]</div>" }% %IF{"defined editUserData" then="<div class='personalInfoFormDataActions'><input type='submit' class='twikiSubmit' name='action_save' id='save' value='Save' /> <input type='submit' class='twikiButton' name='action_cancel' id='cancel' value='Cancel' /></div>" }%" }% </form></div><!--/pIparagraphFrame-->%ENDSECTION{"personalInfo"}%
phoneList
%STARTSECTION{"phoneList"}%%SEARCH{ "[W]orkPhone;[W]orkStatus.*value=.*(Current)" web="%MAINWEB%" type="regex" nonoise="on" excludetopic="UserForm,PersonalInfo,PersonalInfoDocumentation" format=" * [[$web.$topic][$topic]] $formfield(WorkPhone)"}%%ENDSECTION{"phoneList"}%
phoneListXML
%STARTSECTION{"phoneListXML"}%<?xml version="1.0" encoding="ISO-8859-1"?>
<users>
%SEARCH{ "[F]irstName.*value=.*();[W]orkStatus.*value=.*(Current)" web="%MAINWEB%" type="regex" nonoise="on" excludetopic="UserForm,PersonalInfo,PersonalInfoDocumentation,TWikiContributor,TWikiGuest,UnknownUser" format="<user><firstname><![CDATA[$formfield(FirstName)]]></firstname><lastname><![CDATA[$formfield(LastName)]]></lastname><phone><![CDATA[$formfield(WorkPhone)]]></phone><url><![CDATA[%SCRIPTURL{view}%/%WEB%/$topic]]></url><imgname><![CDATA[$formfield(Image)]]></imgname><imgurl><![CDATA[%PUBURL%/Main/$topic/]]></imgurl></user>" "}%
</users>
%ENDSECTION{"phoneListXML"}%
personalSearch
%STARTSECTION{"personalSearch"}%%SEARCH{ "[F]irstName.*value=.*(%URLPARAM{"q"}%)|[L]astName.*value=.*(%URLPARAM{"q"}%)" web="%MAINWEB%" type="regex" nonoise="on" excludetopic="UserForm,PersonalInfo,PersonalInfoDocumentation,TWikiContributor,TWikiGuest,UnknownUser" format=" * [[$web.$topic][$topic]] $formfield(WorkPhone)"}%%ENDSECTION{"personalSearch"}%
vCard
%STARTSECTION{"vCard"}%%SEARCH{ "[F]irstName.*value=.*();[W]orkStatus.*value=.*(Current)" web="%MAINWEB%" type="regex" nonoise="on" excludetopic="UserForm,PersonalInfo,PersonalInfoDocumentation,TWikiContributor,TWikiGuest,UnknownUser" format="begin:vcard
fn:$formfield(FirstName) $formfield(LastName)
n:$formfield(LastName);$formfield(FirstName)
tel;type=work:$formfield(WorkPhone)
tel;type=cell:$formfield(WorkPhoneMobile)
email;type=WORK:$formfield(WorkEmail)
end:vcard"}%%ENDSECTION{"vCard"}%
directSearch
%STARTSECTION{"directSearch" title="%title%" maxresults="%maxresults%" layout="%layout%" showpictures="%showpictures%" inputfieldsize="%inputfieldsize%" pictureheight="%PICTUREHEIGHT%"}% <div> %title% </div>
<input type="text" class="twikiInputField" size="%IF{"defined inputfieldsize" then="%inputfieldsize%" else="12"}%" id="personalInfoSearchBox" name="personalInfoSearchBox" />
<div id="personalInfoSearchResults"><!-- search results will be displayed here --></div>
%IF{"context AttachContentPluginEnabled" then='%INCLUDE{"PersonalInfo" section="directSearchScriptFile"}%' else='%INCLUDE{"PersonalInfo" section="directSearchScript" raw="on" literal="on"}%'}%
%INCLUDE{"PersonalInfoModules" section="initSearchBox" raw="on" literal="on"}%
<style type="text/css" media="all">
#personalInfoSearchResults td {
padding:.1em .5em .1em 0;
vertical-align:middle;
border-bottom:1px solid #eee;
}
</style>%ENDSECTION{"directSearch"}%
%STARTSECTION{"initSearchBox"}%<script language="javascript" type="text/javascript">
// <![CDATA[
function personalInfoHandleKeyUp() {
pISearch.showResults(this.value);
return false;
}
function initSearchBox() {
var box = document.getElementById('personalInfoSearchBox');
if (box) {
box.onkeyup = personalInfoHandleKeyUp;
box.focus();
pISearch.showResults(box.value);
}
}
twiki.Event.addLoadEvent(initSearchBox);
// ]]>
</script>%ENDSECTION{"initSearchBox"}%
%STARTSECTION{"directSearchScript"}%<script language="javascript" type="text/javascript">
// <![CDATA[
var MAX_RESULTS=%IF{"defined maxresults" then="%maxresults%" else="12"}%;
%INCLUDE{"PersonalInfoModules" section="directSearchScriptCode"}%
// ]]>
</script>%ENDSECTION{"directSearchScript"}%
%STARTSECTION{"directSearchScriptFile"}%<script language="javascript" type="text/javascript" src="%PUBURL%/%WEB%/PersonalInfo/directSearch.js"></script>%ENDSECTION{"directSearchScriptFile"}%
%STARTSECTION{"directSearchScriptCode"}%var pISearch = {};
var userData = new Array(%INCLUDE{"PersonalInfo" section="directSearchData"}%);
var MAX_RESULTS;
if (MAX_RESULTS == undefined) MAX_RESULTS = 12;
pISearch.initSearch = function() {}
pISearch.startSearch = function() {}
pISearch.endSearch = function(inOutput) {
var outputElem = document.getElementById("personalInfoSearchResults");
if (outputElem) outputElem.innerHTML = inOutput;
}
pISearch.processResult = function(inName, inUserData) {
var url = "%SCRIPTURL{view}%/" + inUserData.topic;
var phone = inUserData.phone;
var output = "";
output += "<tr>";
output += "<td><a href=\u0027" + url + "\u0027>" + inName + "</a></td>";
output += "<td>" + phone + "</td>";
output += "</tr>";
return output;
}
pISearch.processZeroResults = function() {}
pISearch.withinBounds = function(inCount) {
if (MAX_RESULTS == -1) return true;
return inCount < MAX_RESULTS;
}
pISearch.outputHtmlStart = function() {
return "<table cellpadding=\u00270\u0027 cellspacing=\u00270\u0027>";
}
pISearch.outputHtmlEnd = function() {
return "</table>";
}
pISearch.showResults = function(inValue) {
var output = "";
var resultCount = 0;
var query = inValue.toLowerCase();
if (query.length != 0) {
var regex = new RegExp("\\b" + query, "gi");
pISearch.startSearch();
output = pISearch.outputHtmlStart();
var i = 0;
while ( i < userData.length && pISearch.withinBounds(resultCount)) {
var name = userData[i].name;
if (name.match(regex)) {
output += pISearch.processResult(name, userData[i]);
resultCount++;
}
i++;
}
output += pISearch.outputHtmlEnd();
} else {
pISearch.processZeroResults();
}
if (query.length > 0 && resultCount == 0) {
output = "";
}
pISearch.endSearch(output);
}%ENDSECTION{"directSearchScriptCode"}%
directSearchData
%STARTSECTION{"directSearchData"}%%SEARCH{ "[F]irstName.*value=.*();[W]orkStatus.*value=.*(Current)" web="%MAINWEB%" type="regex" nonoise="on" excludetopic="UserForm,PersonalInfo,PersonalInfoDocumentation,TWikiContributor,TWikiGuest,UnknownUser" format="{name:\"$formfield(FirstName) $formfield(LastName)\",phone:\"$formfield(WorkPhone)\",topic:\"$web/$topic\",pictureName:\"$formfield(Image)\"}" separator=", "}%%ENDSECTION{"directSearchData"}%
tableOfAllUsers
%STARTSECTION{"tableOfAllUsers"}%<style type="text/css" media="all">
#compact table {
font-size:86%;
}
#compact td {
padding-top:0;
padding-bottom:0;
margin:0;
}
#compact a:link,
#compact a:visited {
color:#000;
text-decoration:none;
}
#compact a:hover {
color:#fff;
}
</style>
<div id="compact">
| *Personal page* | *Phone* | *E-mail* | *Location* |
%SEARCH{ "[F]irstName.*value=.*();[W]orkStatus.*value=.*(Current)" web="%MAINWEB%" type="regex" nonoise="on" excludetopic="UserForm,PersonalInfo,PersonalInfoDocumentation,TWikiContributor,TWikiGuest,UnknownUser" format="|[[%SCRIPTURL{view}%/$web/$topic][$formfield(FirstName) $formfield(LastName)]] |$formfield(WorkPhone) |$formfield(WorkEmail) |$formfield(WorkLocation) |" "}%
</div>%ENDSECTION{"tableOfAllUsers"}%
Pictures
%STARTSECTION{"pictures"}%<style type="text/css" media="all">
#pISearchResultsGrid {
margin:1em 0;
}
#pISearchResultsGrid .twikiImage a img {
border:none;
margin:0 0 .35em 0;
padding:0;
}
#pISearchResultsGrid a.pISearchResultsGridItem {
display:block;
float:left;
text-align:center;
border:1px solid #eee;
text-decoration:none;
margin:0 .5em 1em 0;
padding:3px;
overflow:hidden;
width:auto;%IF{"defined gridWidth" then="width:%gridWidth%px;"}%
height:100%;%IF{"defined gridHeight" then="height:%gridHeight%px;"}%
}
#pISearchResultsGrid a.pISearchResultsGridItem img {
overflow:hidden;
width:auto;%IF{"defined imgWidth and '%imgWidth%'!=''" then="width:%imgWidth%px;"}%
}
#pISearchResultsGrid .pISearchResultsGridInfo {
display:block;
font-size:94%;
line-height:100%;
overflow:hidden;
}
#pISearchResultsGrid a:link .pISearchResultsGridInfo,
#pISearchResultsGrid a:visited .pISearchResultsGridInfo {
text-decoration:none;
color:#06c;
}
#pISearchResultsGrid .twikiImage a:hover {
border:1px solid #06c;
}
#pISearchResultsGrid a:hover .pISearchResultsGridInfo {
text-decoration:none;
color:#06c;
background:none;
}
</style>
<div id="pISearchResultsGrid">%SEARCH{ "[W]orkStatus.*value=.*(Current)" web="%MAINWEB%" type="regex" nonoise="on" excludetopic="PresentationForm,UserForm,PersonalInfo,PersonalInfoDocumentation,PersonalInfoFaceBook,TWikiContributor,TWikiGuest,UnknownUser%IF{'defined exclude' then=',%exclude%'}%" order="topic" format="<div class='twikiImage'><a href='%SCRIPTURL{view}%/$web/$topic' class='pISearchResultsGridItem' id='pISearch$topic' title='$formfield(FirstName) $formfield(LastName)'>$percntINCLUDE{$quotPersonalInfoLayoutModules$quot section=$quotimage$quot imgType=$quotnolink$quot imgWeb=$quot$web$quot imgTopic=$quot$topic$quot imgTitle=$quot$formfield(FirstName) $formfield(LastName)$quot imgName=$quot$percntFORMFIELD{$quotImage$quot topic=$quot$web.$topic$quot format=$quot$value$quot default=$quot$quot alttext=$quot$quot}$percnt$quot}$percnt<span class='pISearchResultsGridInfo'>$formfield(FirstName) $formfield(LastName)</span></a></div>" "}%<br class="twikiClear" /></div>%ENDSECTION{"pictures"}%
pictureFilterSearch
%STARTSECTION{"pictureFilterSearch"}%%IF{"context AttachContentPluginEnabled" then='%INCLUDE{"PersonalInfo" section="directSearchScriptFile"}%' else='%INCLUDE{"PersonalInfo" section="directSearchScript" raw="on" literal="on"}%'}%<script language="javascript" type="text/javascript">
// <![CDATA[
var MAX_RESULTS=%IF{"defined maxresults" then="%maxresults%" else="12"}%;
pISearch.pictureSet = {};
pISearch.initSearch = function() {
MAX_RESULTS = -1;
var pictureElems = document.getElementById('pISearchResultsGrid').getElementsByTagName('a');
var i=0;
while ( i < userData.length) {
var name = userData[i].name;
var re = new RegExp(/(.*?)\//g);
var topic = userData[i].topic.replace(re, "");
pISearch.pictureSet[topic] = document.getElementById("pISearch" + topic);
i++;
}
}
pISearch.startSearch = function() {
if (pISearch.pictureSet == null) return;
for (var s in pISearch.pictureSet) {
if (pISearch.pictureSet[s] != null) {
pISearch.pictureSet[s].style.display = 'none';
}
}
}
pISearch.processZeroResults = function() {
if (pISearch.pictureSet == null) return;
for (var s in pISearch.pictureSet) {
if (pISearch.pictureSet[s] != null) {
pISearch.pictureSet[s].style.display = 'inline';
}
}
}
pISearch.endSearch = function() {}
pISearch.processResult = function(inName, inUserData) {
if (pISearch.pictureSet == null) return;
var re = new RegExp(/(.*?)\//g);
var topic = inUserData.topic.replace(re, "");
if (pISearch.pictureSet[topic] != null) {
pISearch.pictureSet[topic].style.display = 'inline';
}
}
twiki.Event.addLoadEvent(pISearch.initSearch);
// ]]>
</script>
%INCLUDE{"PersonalInfoModules" section="initSearchBox" raw="on" literal="on"}%%ENDSECTION{"pictureFilterSearch"}%
(try to find John Doe - the
PersonalInfoDemoUser - by either first or last name)
phoneList
Creates a bullet list of users. Listed users have a field
WorkPhone
and have the value
Current
at field
WorkStatus
.
Usage:
%INCLUDE{"PersonalInfo" section="phoneList"}%
View phoneList
phoneListXML
Creates a list of user data in XML format. Listed users have a field
WorkPhone
and have the value
Current
at field
WorkStatus
.
The auto-generation of an XML attachment is turned off for performance. To create the XML file, remove the
<nop>
from the beginning of
STARTATTACH
at
PersonalInfo:createPhoneListXMLAttachment .
Usage:
PersonalInfo?section=phoneListXML;skin=xml
View phoneList XML
If the XML has been saved as file:
%PUBURL%/%WEB%/PersonalInfo/phoneList.xml
PhoneList XML file
personalSearch
Creates a bullet list of all users in an empty page. This might be useful for live searches using AJAX.
Call the topic with url:
PersonalInfo?section=personalSearch;skin=text;q=
... where the search characters come after the
q=
View personalSearch with the letter 'a'
tableOfAllUsers
Creates a table of all users.
Usage: create a topic and write the line:
%INCLUDE{"PersonalInfo" section="tableOfAllUsers"}%
or use the url:
PersonalInfo?section=tableOfAllUsers;template=viewplain
Printable list
pictures
Creates a grid view of all user pictures.
Parameters:
imgHeight
- height of the pictures
Usage: create a topic and write the line:
%INCLUDE{"PersonalInfo" section="pictures" title="Face book" imgHeight="100"}%
or use the url:
PersonalInfo?section=pictures;template=viewplain
See
PersonalInfoFaceBook
Note: for performance this topic uses
TWiki:Plugins/VarCachePlugin if installed and enabled.
pictureFilterSearch
Quickly sift through user pictures.
This module adds a search box to the picture grid.
See the example on
PersonalInfoFaceBook