TopicGenerator
Jump to navigation
Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
dialog
@// Copyright (c) 2016 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>
@(smwContext.asSiDIF())
</pre>
=== @(contextName) JSON ===
<pre>
@(smwContext.toJson())
</pre>
}