TopicGenerator
Jump to navigation
Jump to search
dialog
@// Copyright (c) 2015 BITPlan GmbH
@//
@// This is a Wikitask / Rythm template that
@// displays an AJAX GUI for generating SmartMediaWiki results
@//
@import org.sidif.wiki.Reference
@import org.sidif.wiki.ReferenceManager
@import org.sidif.wiki.Source
@import org.sidif.wiki.PageCache
@import org.sidif.wiki.WikiTask
@import com.bitplan.mediawiki.japi.api.Page
@import com.bitplan.mediawiki.japi.api.Rev
@include(wiki.SiDIFTemplates.defs)
@include(wiki.SiDIFTemplates.dialogdefs)
@// get a link for the given pagetitle
@def String getLink(String pageTitle, int revid) {
String link=wikiTask.getServer()+wikiTask.getScriptpath()+"/index.php?title="+urlEncode(pageTitle);
if (revid>0) {
link+="&oldid="+revid;
}
return link;
}
@// get the parameters for the wikitask
@def String getWikiTaskParams(String engine) {
String params="?server="+urlEncode(wikiTask.getServer());
params+="&scriptpath="+urlEncode(wikiTask.getScriptpath());
params+="&page="+urlEncode(wikiTask.getPageTitle());
params+="&engine="+engine;
return params;
}
@// run the given wikitask command
@def doWikiTaskCmd(String cmd, String param) {
@{
String icon="component";
String engine="Freemarker";
if ("runtemplate".equals(cmd)){ icon="media_play_green.png"; }
if ("reset".equals(cmd)) { icon="refresh"; }
if ("help".equals(cmd)) { icon="help"; }
if ("debug".equals(cmd)) { icon="wrench"; }
if ("refreshRef".equals(cmd)) { icon="refresh"; }
String params=getWikiTaskParams(engine);
}
<a href='@(cmd)@(params)'>@(stockicon(icon,48,cmd,cmd))</a>
}
@// run the given wikitask command
@def wikiTaskCmd(String cmd) {
@doWikiTaskCmd(cmd,null)
}
@// run the given wikitask command with a parameter
@def wikiTaskCmd(String cmd, String param) {
@doWikiTaskCmd(cmd,param)
}
@// add styles for the generator
@def generatorStyle(String i_____) {
@(i_____) <style type="text/css">
@(i_____) // progress text that comes with progress bars
@(i_____) // see http://stackoverflow.com/questions/12452594/how-can-i-add-label-inside-a-progress-bar-tag
@(i_____) span.progresstext {
@(i_____) font-family:'Arial';
@(i_____) position:relative;
@(i_____) top:-1.5em;
@(i_____) margin-left:50%;;
@(i_____) font-size:small;
@(i_____) }
@(i_____) </style>
}
@// scripts for generators
@def generatorScript() {
<script>
// JavaScript support for Y-Principle TopicGenerator
// convert a string to make the first char lower case
function firstToLower(string) {
return string.charAt(0).toLowerCase() + string.slice(1);
}
// get the div where responses are shown
function getResponseDiv() {
var result=document.getElementById("response");
return result;
}
// get the div where errors are shown
function getErrorDiv() {
var result=document.getElementById("errorMessage");
return result;
}
// get the checkBox jquery object with the given id
function getGeneratorElement(generatorId,postfix) {
var result=$("#"+generatorId+postfix);
return result;
}
// clear the given div
function clearDiv(div) {
div.innerHTML='';
}
// add a TextElement with the given tag and message to the given parent
function newTextElement(tag,msg) {
var newElement=document.createElement(tag);
var content = document.createTextNode(msg);
newElement.appendChild(content);
return newElement;
}
// add a message to the given div
function addMessage(div, msg) {
var newElement=newTextElement('pre',msg);
div.appendChild(newElement);
return newElement;
}
// progress on transfers from the server to the client (downloads)
// see https://developer.mozilla.org/de/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
function updateProgress (oEvent) {
if (oEvent.lengthComputable) {
var percentComplete = oEvent.loaded / oEvent.total;
// ...
} else {
// Unable to compute progress information since the total size is unknown
}
}
// show an error Message
// param errMsg: the message to show
function errorMessage(errMsg) {
var errDiv=getErrorDiv();
if (errDiv!=null) {
addMessage(errDiv,errMsg);
errDiv.style.display = 'block';
} else {
alert(errMsg);
}
}
// flag an error for the given id
function flagError(id,msg) {
setProgress(id,0,"");
var checkBox=getGeneratorElement(id,"");
var progresstext=getGeneratorElement(id,"_progress_pc");
var errorSpan=newTextElement('span','⚠ '+msg);
errorSpan.style='color:red;font-size:14px';
progresstext[0].appendChild(errorSpan);
return checkBox;
}
// handle an error that has been thrown
function handleError(err,id) {
flagError(id,err.message);
// abusing checkBox as data lookup
var checkBox=getGeneratorElement(id,"");
var errMessage=checkBox[0].name+" ERROR:"+err.code+" "+err.name+" '"+err.message+"' line:"+err.lineNumber;
errorMessage(errMessage);
}
// get the class name of the given object
function getClass(obj) {
if (typeof obj === "undefined")
return "undefined";
if (obj === null)
return "null";
return Object.prototype.toString.call(obj)
.match(/^\[object\s(.*)\]$/)[1];
}
// send the given form
function sendForm(formData,action,id) {
try {
var oReq = new XMLHttpRequest();
oReq.addEventListener('progress', updateProgress, false);
oReq.addEventListener('load', transferComplete, false);
oReq.addEventListener('error', transferFailed, false);
oReq.addEventListener('abort', transferCanceled, false);
oReq.onload = ajaxSuccess;
// http://stackoverflow.com/questions/921198/get-request-url-from-xhr-object
var xhrProto = XMLHttpRequest.prototype,
origOpen = xhrProto.open;
xhrProto.open = function (method, url, async) {
this._url = url;
this._id = id;
return origOpen.apply(this,arguments);
};
var async=true;
oReq.open('POST', action, async,id);
// important - this makes the request a non-simple request with CORS
// oReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// user defined header forces CORS?
oReq.setRequestHeader('Header-Custom-WikitaskCORS', 'OK');
oReq.setRequestHeader('Accept','application/json');
oReq.send(formData);
} catch(err) {
handleError(err,id);
}
return false; // Prevent direct form page button submit action
}
// set the progress for the given check box id
// and return the progress bar
function setProgress(checkBoxId,progress,percent) {
var checkBox=getGeneratorElement(checkBoxId,"");
var progressbar=getGeneratorElement(checkBoxId,"_progress");
var progresstext=getGeneratorElement(checkBoxId,"_progress_pc");
// console.log(progressbar);
// FIXME - do a true progress
// progressbar.val(progress);
if (progress==0) {
progressbar[0].style.display = 'none';
} else {
progressbar[0].style.display = 'block';
}
progresstext[0].textContent=percent;
return progressbar;
}
// start the generator for the given form, contextSetting, contextname, template and targetpage
function startGenerator(form,contextSettingTxt,contextname,topic,template,targetpage,id) {
var formData = new FormData(form);
formData.append('server', "@(wikiTask.getServer())");
formData.append('scriptpath', "/@(wikiTask.getScriptpath())");
formData.append('engine', 'Rythm');
formData.append('input', 'sidif');
formData.append('page','Topic');
var action=form.action;
// action=
// action="http://phobos.bitplan.com:9089/wikiserver/task/runtemplate";
formData.append('template',template);
formData.append('targetpage',targetpage);
formData.append('id',id);
// set the params from the contextSettings
// e.g. wikiId:capri,sidifInput:Topic#sidif,contextName:MetaModel,maintopicName:Topic
var contextSetting=JSON.parse(contextSettingTxt);
contextSetting.maintopicName=topic;
var contextSettingJson=JSON.stringify(contextSetting)
formData.append('params',contextSettingJson);
sendForm(formData,action,id);
}
// start the generators for the given form
function startGenerators(form) {
clearDiv(getErrorDiv());
clearDiv(getResponseDiv());
var generatorchecks= $(".checkBoxClass:checked");
generatorchecks.each(function(){
setProgress(this.id,1,"");
// targetPage is the name of the checkbox
var template=this.value;
var ytname=$(this).attr("yt")
var target=$(this).attr("target");
var contextname=$(this).attr("context");
var contextSetting=$(this).attr("contextsetting");
var id=this.id;
// split e.g. Template_Context;
var split = id.split('__');
// FIXME use yt and topic and generator objects instead
var topic=split[1];
startGenerator(form,contextSetting,contextname,topic,template,target,id);
});
return false;
}
// get SiDIF
function getSiDIF(lbutton) {
// {{wikitask
// |cmd=runtemplate
// |engine=Rythm
// |input=sidif
// |dialog=TopicGenerator#dialog
// |template=TopicGenerator#template
// |params=tripleStoreMode:SMW,contextName:{{{context|}}}
// |targetpage=TopicGenerator2015/{{{context|}}}}}
var contextSetting=JSON.parse(lbutton.value);
var params='@(getWikiTaskParams("Rythm"))';
var wikiTaskLink="runtemplate"+params;
wikiTaskLink+="&input="+encodeURIComponent(contextSetting.sidifInput);
wikiTaskLink+="&dialog="+encodeURIComponent("TopicGenerator#dialog");
wikiTaskLink+="&template="+encodeURIComponent("TopicGenerator#template");
wikiTaskLink+="&targetpage="+encodeURIComponent("TopicGenerator2015/"+contextSetting.contextName);
wikiTaskLink+="¶ms=tripleStoreMode:"+contextSetting.tripleStoreMode;
wikiTaskLink+=",contextName:"+encodeURIComponent(contextSetting.contextName);
wikiTaskLink+=",sidifInput:"+encodeURIComponent(contextSetting.sidifInput);
// console.log(wikiTaskLink);
window.location.replace(wikiTaskLink);
}
// show the given event with the given message
function showEvent(evt, msg) {
var doshow=true;
if (evt.target instanceof XMLHttpRequest) {
var xhr=evt.target;
msg+=" target="+xhr._url;
msg+=" responseType="+xhr.responseType;
msg+=" status="+xhr.status;
if (xhr.status==200) {
doshow=false;
}
}
if (doshow) {
errorMessage(evt.type+" "+getClass(evt.target)+": "+msg);
}
return evt.target;
}
// event when the transfer was successfully completed
function ajaxSuccess () {
var json=this.responseText;
// console.log(json);
try {
var jsonResult=JSON.parse(json);
// console.log(jsonResult);
var errorMsg=jsonResult.errorMsg;
if (errorMsg!=null) {
setProgress(jsonResult.id,100,"");
addMessage(getResponseDiv(),errorMsg);
} else {
setProgress(jsonResult.id,0,"");
var checkBox=getGeneratorElement(jsonResult.id,"");
var progresstext=getGeneratorElement(jsonResult.id,"_progress_pc");
var target=$("#"+jsonResult.id).attr("target");
var targetRef=newTextElement('a',target);
targetRef.href=jsonResult.targetUrl;
targetRef.style='font-size:12px';
var doneSpan=newTextElement('span','✓');
doneSpan.style='color:green;font-size:14px';
progresstext[0].appendChild(targetRef);
progresstext[0].appendChild(doneSpan);
var deltaRef=newTextElement('a','Δ');
deltaRef.style='font-size:12px';
var revid=$("#"+jsonResult.id+"_rev").attr("revid");
deltaRef.href=jsonResult.targetUrl+"?diff=cur&oldid="+revid;
progresstext[0].appendChild(deltaRef);
}
} catch (ex) {
alert(ex.message+"\njson="+json);
}
}
// event when transfer is complete
function transferComplete(evt) {
showEvent(evt,"transfer complete");
}
// event when the transfer failed
function transferFailed(evt) {
var xhr=showEvent(evt,"transfer failed");
if (xhr instanceof XMLHttpRequest) {
flagError(xhr._id,"transfer failed");
}
}
// event when the transer was cancelled
function transferCanceled(evt) {
showEvent(evt,"transfer canceled");
}
</script>
}
@// run the selected generators
@def runGenerators() {
@{
String icon="media_play_green";
String cmd="run";
}
<button type='submit' name='@cmd' value='@cmd' title='@cmd' onclick="return startGenerators(this.form);">
@(stockicon(icon,32,cmd,cmd))
</button>
}
@// display the given Reference as a row
@def referenceRow(Reference ref) {
<tr>
<td>@(wikiTaskCmd("refreshRef",ref.getReferenceId()))</td>
<td><a href='@(ref.getUrl())'>@(ref.getReferenceId())</a></td>
<td>@(ref.getReferenceType().toString())</td>
<td>@(ref.getAge())</td>
<td>@(ref.isAvailable())</td>
<td>@if(ref.getContent()) { @(ref.getContent().length()) } else { - }</td>
</tr>
}
@// display the given Source as a row
@def sourceRow(Source source) {
<tr><td></td><td>@(source.getId())</td><td>@(source.getPageTitle())</td><td>@(source.getAge())</td><td>@(source.isCache())</td><td>@(source.getSource().length())</td></tr>
}
@// display the table of PageCache entries
@def pageCacheTable(PageCache pageCache,String indent) {
@(indent)<table class="table tablesorter sortable">
@(indent)<thead>
@(indent) <tr><th>page</th><th>rev</th><th>timestamp</th></tr>
@(indent)</thead>
@(indent)<tbody>
@{
List<String> pageTitles = new ArrayList<String>(pageCache.getCachedPages().keySet());
}
@for (String pageTitle:pageTitles) {
@{
Page page=pageCache.getCachedPages().get(pageTitle);
Rev rev = PageCache.getPageRevision(page);
int revid=-1;
String timeStamp="?";
if (rev!=null) {
revid=rev.getRevid();
timeStamp=rev.getTimestamp();
}
}
@(indent) <tr><td>@showLink(pageTitle, 0, "Cache0_"+revid, "")</td><td>@showLink(pageTitle, revid, "Cache_"+revid, "")</td><td>@(timeStamp)</td></tr>
}
@(indent)</tbody>
@(indent)</table>
}
@// display the table of references and sources
@def referenceTable(ReferenceManager rm) {
<table class="table tablesorter sortable">
<thead>
<tr><th></th><th>id</th><th>type</th><th>age</th><th>cache</th><th>size</th></tr>
</thead>
<tbody>
@for (Reference reference:rm.referenceByReferenceId.values()) {
@referenceRow(reference)
@if (rm.getSourceById().get(reference.getReferenceId())!=null) {
<tr><th colspan='3'>Sources by Id</th>
@for (Source source:wikiTask.referenceManager.getSourceById().get(reference.getReferenceId()).values()) {
@sourceRow(source)
}
}
@if (rm.getSourceBySection().get(reference.getAnchor())!=null) {
<tr><th colspan='3'>Sources by Section</th>
@for (Source source:wikiTask.referenceManager.getSourceBySection().get(reference.getAnchor()).values()) {
@sourceRow(source)
}
}
}
</tbody>
</table>
}
@// show a link for the given pageTitle and revision id
@def showLink(String pageTitle,int revid, String id, String indent) {
@{
// default is unknown revision red link / create page approach
String revname="click to create";
String style="style='color:red'";
if (revid>=0) {
style="style='font-size: 12px'"; // normal link but small font
revname="Rev "+revid;
}
String link=getLink(pageTitle,revid);
}
@(indent)<a href='@(link)' id='@(id)' revid='@(revid)' title='@(revname)' @(style)>@(pageTitle)</a>
}
@// show the page status link
@def pageStatusLink(Topic topic,YT yt,Map<String, Page> statusMap) {
@{
String pageTitle=yt.getPageTitle(topic);
Page page=statusMap.get(pageTitle);
int revid = -1;
if (page != null) {
Rev rev = PageCache.getPageRevision(page);
if (rev!=null) {
revid = rev.getRevid();
}
}
}
@showLink(pageTitle, revid, yt.name+"__"+topic.name+"_rev", " ")
}
@// show a single row of generators for a given domain topic
@def topicRow(ContextSetting contextSetting,Context context,Topic topic,Map<String, Page> statusMap,YT[] yts, int rownum) {
<tr>
<th>@(topic.name)<div style="margin: 0 auto; width: 48px"><img src='@(wikiTask.getServer())@(wikiTask.getScriptpath())@(topic.iconUrl)' alt='@(topic.name)'></div></th><th><label><input class='checkboxSelect' type='checkbox' id="select_row_@(rownum)" title='select row'/>→</label></th>
@{ int colnum=0;}
@for(YT yt:yts) {
<td>
<label for='@(yt.name)_@(topic.name)'>
<input type="checkbox" class="checkBoxClass row_@(rownum) col_@(colnum)" contextsetting='@contextSetting.toJson()' context='@(context.name)' target='@yt.getPageTitle(topic)' yt='@(yt.name)' topic='@(topic.name)' id='@(yt.name)__@(topic.name)' name='@(yt.name):@(topic.name)' title='generate @(yt.getPageTitle(topic))' value="SiDIFTemplates#@(yt.template)">
</label>
</td>
<td>
@pageStatusLink(topic,yt,statusMap)
<progress id='@(yt.name)__@(topic.name)_progress' max='10' title='@(yt.name):@(topic.name)' style='display:none'></progress>
<span id='@(yt.name)__@(topic.name)_progress_pc' class='progresstext'></span>
</td>
@{ colnum++;}
}
</tr>
}
@// display the generators
@// sortable disabled - doesn't seem to work with selectAll logic
@def showGeneratorTasks(WikiTask wikiTask,ContextSetting contextSetting) {
@{
Context context=ContextFactory.getInstance().getContext(contextSetting);
List<String> pageTitles = new ArrayList<String>();
if (context!=null) {
for (YT yt : YT.yts) {
for (Topic topic : context.getTopics()) {
pageTitles.add(yt.getPageTitle(topic));
}
}
}
Map<String, Page> statusMap = wikiTask.referenceManager.getPageCache()
.updatePageStatus(pageTitles, true);
}
<h3>@(contextSetting.getTripleStoreMode())</h3>
@if (context) {
<form action='#'>
<table class="table tablesorter tablesorter-blue">
<thead>
<tr>
<th width='12%'>@(runGenerators())</th>
<th>Targets
</th>
@for(YT yt:YT.yts) {
<th colspan='2' style="text-align:center">@(yt.label)</th>
}
</tr>
@{ int colnum=0;}
<tr>
<th class='{sorter: false}'>Topics<br>
<div id='reloadbuttoncontainer' style='width:80px;display:inline-block' >
<button onclick='getSiDIF(this);return false;' value='@ContextSetting.fromWikiTaskAsSiDIF(wikiTask).toJson()' title='reload from SiDIF' style='display:inline-block'>
<img src='/stockicons/16x16/shadow/arrow_down_blue.png'/>
</button>
<button onclick='getSiDIF(this);return false;' value='@contextSetting.asSMWContextSetting().toJson()' title='reload from SMW Triples' style='display:inline-block' >
<img src='/stockicons/16x16/shadow/arrow_down_green.png'/>
</button>
</div>
</th>
<th class='{sorter: false}'><label><input type="checkbox" id="selectall" name="selectall" title='select all'/>↘</label></th>
@for(YT yt:YT.yts) {
<th class='{sorter: false}' width='14px'><label><input class='checkboxSelect' type='checkbox' id='select_col_@(colnum)' title='select all @(yt.label)'/>↓</label></th><th width='10%'><div style="margin: 0 auto; width: 48px"><img src='@(wikiTask.getServer())@(wikiTask.getScriptpath())@(yt.iconUrl)' alt='@(yt.label)'></div></th>
@{ colnum++;}
}
</tr>
</thead>
<tbody id='generatortasktable'>
@{ int rownum=0;}
@for (Topic topic:context.getTopics()) {
@topicRow(contextSetting,context,topic,statusMap,YT.yts,rownum++)
}
</tbody>
</table>
</form>
}
}
@// show the HTML Page for the given context
@def showHtml(ContextSetting contextSetting) {
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8'/>
<title>@(title)</title>
@jquery(" ")
@style(" ")
@selectall()
@generatorStyle(" ")
@generatorScript()
</head>
<body>
<div id='container' class='container'>
<div id="dialog" title="@(title)" >
@(wikiTaskCmd("reset"))@(wikiTaskCmd("help"))@(wikiTaskCmd("debug"))
<a href='@(wikiTask.getTargetLink().getUrl())'>@(wikiTask.getTargetpage())</a>
called from <a href='@(wikiTask.getServer())@(wikiTask.getScriptpath())/index.php/@(wikiTask.getPageTitle())'>@(wikiTask.getPageTitle())</a> (@(wikiTask.getDuration()) msecs)
<div id="tabs">
<ul>
<li><a href="#generators">Generators</a></li>
<li><a href="#pagecache">Page-Cache</a></li>
<li><a href="#references">References</a></li>
</ul>
<div id="generators">
@(showGeneratorTasks(wikiTask,contextSetting))
</div>
<div id="pagecache">
@pageCacheTable(wikiTask.referenceManager.getPageCache()," ")
</div>
<div id="references">
@referenceTable(wikiTask.referenceManager)
</div>
</div>
<div id='errorMessage' style='color:red;font-size: 14px;border:1px solid red;display:none'></div>
<div id='response' style='font-size: 14px;border:1px solid blue'></div>
</div>
</div>
@dialog(" ")
</body>
</html>
}
@{
ContextSetting contextSetting=ContextSetting.fromWikiTask(wikiTask);
}
@showHtml(contextSetting)
template
@include(wiki.SiDIFTemplates.defs)
@// handle error
@def handleError(Throwable error) {
error @(error.getClass().getName()): @(error.getMessage())
=== stacktrace ===
<pre>
@getStackTrace(error)
</pre>
}
@{
ContextSetting contextSetting=ContextSetting.fromWikiTask(wikiTask);
Context context=ContextFactory.getInstance().getContext(contextSetting);
Context smwContext=ContextFactory.getInstance().getContext(contextSetting.asSMWContextSetting());
String contextName=contextSetting.getContextName();
}
@if (context==null) {
Context (sidif): @(contextName) not found in SiDIF
} else {== SiDIF ==
=== @(contextName) SiDIF ===
<pre>
@(context.asSiDIF())
</pre>
=== @(contextName) JSON ===
<pre>
@(context.toJson())
</pre>
}
@if (smwContext==null) {
Context (smw): @(contextName) not found in SMW triples of Wiki
} else {
== SMW ==
=== @(contextName) SiDIF ===
<pre>
@(context.asSiDIF())
</pre>
=== @(contextName) JSON ===
<pre>
@(context.toJson())
</pre>
}