TopicGenerator

From BITPlan royal-family Wiki
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+="&params=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>
}