Passing parameters from Dynamic Page List to Semantic Mediawiki - mediawiki

I'm trying to created a template that will output a dynamic report by generating a list of pages with Dynamic Page List and then run queries on each page using Semantic Mediawiki, outputting the whole mess in a table. The structure of the template looks like this:
{| class="wikitable sortable collapsible collapsed" width="100%"
|- valign="bottom"
! width="15%" | Compound ID
! width="15%" | Generic name
! width="15%" | Trade name
! width="15%" | Developer
! width="10%" | Phase of development
! width="30%" | Target
{{#dpl:
| category=compounds
| linksto={{PAGENAME}}{{#dpl: linksto={{PAGENAME}} | redirects=only | mode=userformat | format=,{{!}},%TITLE%, | suppresserrors=true }}
| ignorecase=true
| distinct=strict
| format=,{{!}}- valign="top"\n{{indication-based compound list/row|%TITLE%}}\n
| noresultsheader={{!}}-\n{{!}} colspan="6" align="center" {{!}} ''No compounds have yet been studied for this indication.''
}}
|}
{{indication-based compound list/row}} consists of the following:
<includeonly>{{!}} {{#show: {{{1}}} | ?compound id }}
{{!}}{{!}} {{#show: {{{1}}} | ?compound generic name }}
{{!}}{{!}} {{#show: {{{1}}} | ?compound trade name }}
{{!}}{{!}} {{#show: {{{1}}} | ?developer }}
{{!}}{{!}} {{#ask: [[category:clinical studies]][[compound number::{{{1|}}}]] | ?Study phase=| limit=1| mainlabel=-| searchlabel=| sort=Study phase| order=descending }}
{{!}}{{!}} {{#show: {{{1|}}} | ?target }}</includeonly>
The {{#ask}} query is the reason why this isn't just a straight-forward DPL table: because the current phase of clinical development of a specific compound for a specific indication is a dynamic piece of data that changes frequently, the only option seems to be using an {{#ask}} query to find out the highest value for study phase among the clinical trials that meet the parameters. But this template will be surveying auto-generated pages and I don't have a way of auto-loading a list of indications for each compound (to apply semantic markup to), so instead it's generating based on lists of indication links that are themselves generated by a {{#dpl}} function on each compound page.
I've walked through this step by step, and none of the following are the problem:
The template code is sound, and generates the proper structure.
The table row template is sound, and if I remove the {{#dpl}} function and replace it with the template and a compound page name as a parameter, e.g. {{indication-based compound list/row|infliximab}}, it creates exactly the output I'm looking for.
The {{#dpl}} function produces the correct list of pages when using the default output format.
The {{#dpl}} function passes the list as sequential parameters properly when using format = ,{{template}} with a simply dummy template (just an unordered list).
However, when I put all the pieces together I just get empty table cells. The {{#show}} and {{#ask}} functions can't seem to accept the DPL input as parameters. Is there an additional argument or intermediate step I'm skipping that can sanitize the input and make the whole thing work? Or are DPL and SMW fundamentally incompatible in this way?
DynamicPageList 2.01
Semantic MediaWiki 1.8
MediaWiki 1.20.2
PHP 5.3.19 (apache2handler)
MySQL 5.1.30

Looks like the problem is that Semantic Mediawiki can't parse the PAGE% and %TITLE% variables generated by Dynamic Page List when you use the format argument, and there's no way around that since DPL doesn't render those into real data until the function is completed.

Related

How can I pass some MediaWiki markup (here: a table) to a template?

I'm looking for a way that a user may specify a table - i.e. by specifying it in MediaWiki syntax - to a template. The template should then put this table in the context of some larger output provided by the template.
A simple example. Is there a way a user could specify something like this:
{{MyTemplate
|FooBar
|{| class="wikitable"
| Something
|-
| Useful
|}
}}
and then the template outputs somewhere the specified data FooBar and the table?
If this doesn't work, is there some alternative way of doing this? i.e. by specifying some arbitrary (!) CSV data and outputting it in a formatted way?
The reason it doesn't work is that the pipes in the table are seen by the template as parameter delimiters. The {{!}} magic word exists as a workaround to this, so your example could be done like this:
{{MyTemplate
|FooBar
|{{{!}} class="wikitable"
{{!}} Something
{{!}}-
{{!}} Useful
{{!}}}
}}
This does make it rather less readable though!
As for rendering CSV data as a table, the TableData extension may do what you're looking for.

Reusing components

Can someone please help me to better understand components, queries, etc. I'm struggling with a seemingly trivial task, I need one component with parametrized query. Instances of that component need to be included in a parent component,
for example I want lists of different kinds of fruits that need to be distributed among group of kids and each row would show kid's name and a quantity of fruits of one kind:
(defui FruitsLedger
static om/IQuery
(query [this]
'[(:data/fruits) {:kind ?kind}])
Object (render [this]
(let [{:keys [data/fruits]} (om/props this)]
(dom/ul nil (apply #(dom/li nil (str "for " (% :kid) " " (% :qt))))))))
now I need to have let's say two instances of this component in another component
where :params
for the 1st instance would be: {:kind :apples}
for the 2nd instance would be: {:kind :oranges}
this should render 2 lists similar to this:
| apples | oranges |
|---------------+---------------|
| for Aaron 2 | for Katie 1 |
| for Dan 1 | for Rob 3 |
| for Charles 0 | for Charles 3 |
| | |
|---------------+---------------|
I'm sure that parameterized queries have their uses. But perhaps this problem and other similar ones can be solved without resort to them.
Have :app/fruit-query-kinds in your db (default db format). It will be a list of fruits. You already have the fruit component, but you will need another component that has this idea of being a list of fruit kinds for querying purposes. Give this component a query and an ident. It doesn't matter if it is going to be displayed or not. Most important thing is getting the data structure right. Its ident will just be something like: '[:fruit-query-kind/by-id 1100], and it might consist of '[:fruit/by-id 10] and '[:fruit/by-id 20]. As per your example 10 will be the id for apples and 20 for oranges. That will be the refs value (a vector of idents in default db storage) of the key :app/fruit-query-kinds. 1100 is just a unique number that won't be expected to change.
The data structure is the important thing, and everything can be modelled in it, even query parameters.
You will need mutations and some buttons (or other input) that call transact! somewhere that directly change the fruit query kinds in your db. If you don't need any re-rendering to happen call transact! with the app's reconciler rather than with a component.
The idea is that you can then have component/s that query on the choices previously made by the user. So your first list component there won't know that it is to be for apples - all it knows is that it is to display fruits of the first fruit query kind.
I've found that you can do as much to-ing and fro-ing between the view and the db as you like, having the db not just store data but the current state of the view. So far the only time I got into trouble with this was when I mistakenly transacted on the not of the boolean key in the component's query. That of course ended up in a forever flickery screen.
In my opinion the way to work simply with Om Next on the Client is for all your reads to look exactly the same, all using db->tree. Once you accept this approach the next step is to get rid of them all together, which you can do by switching to the Untangled framework.

Using SMW subobjects without having to duplicate the content

Example for what I want to achieve
I have many patch pages ("Patch 1.4", "Patch 1.5" etc.) that list the changes that were made to a project, where the affected/changed things are linked to their corresponding pages ("confirmation dialog", "foo", etc.):
Patch 1.4
Fixed spelling in the [[confirmation dialog]]
Patch 1.5
Added two options: [[foo]], [[bar]]
On the pages about the things that were changed ("confirmation dialog", "foo", …), I want to automatically show all corresponding changes:
Foo
[[Patch 1.5]]: Added two options: [[foo]], [[bar]]
Semantic MediaWiki’s subobjects can do this
#subobject allows me to create an (anonymous) object for each change on the patch pages:
{{#subobject:|
|Changes=Added two options: [[foo]], [[bar]]
|Affects=Foo|Bar
}}
And on each page ("foo" etc.) I can include an #ask subobject query to list all the matching subobjects:
{{#ask: [[Affects::{{FULLPAGENAME}}]]
|? Changes
}}
Great.
Problem: I have to duplicate the change entry.
On the patch pages, a change entry looks like this:
* Added two options: [[foo]], [[bar]] {{#subobject:|
|Changes=Added two options: [[foo]], [[bar]]
|Affects=Foo|Bar
}}
So I have to specify "Added two options: [[foo]], [[bar]]" two times: one time for the visible content, one time for the invisible subobject.
Is there a way in (Semantic) MediaWiki to do this without having to duplicate the content?
The ideal solution would just require me to enclose the change entry and specify the affected pages next to it, e.g.:
* {{ Added two options: [[foo]], [[bar]] }}((foo|bar))
As each patch page can list hundreds of changes, I don’t want to have to create a separate page for each change.
If I understand your question clearly, it seems you just need a simple query:
{{#ask: [[-Has subobject::{{FULLPAGENAME}}]]
| ?Changes
| format = ul
| headers = hide
| mainlabel = -
}}
Since using SMW markup may be tedious and error-prone, you might also use MediaWiki templates. You can simplify adding patch changes:
Template:Change
<includeonly><!--
-->{{#subobject:|
| Changes = {{{1|}}}
| Affects = {{{2|}}}|+sep=;
}}<!--
--></includeonly><nowiki/>
{{{1}}} and {{{2}}} are positional parameter,s and the Affects subobject property uses the ; separator (as a pipe | is ambiguous and may break templates, parser functions, etc). The <nowiki/> is a sort of a hack saving from whitespace bloating at the call-site pages.
You can also add a special template that would encapsulate the changes query:
Template:Patch changes
<includeonly><!--
-->{{#ask: [[-Has subobject::{{{1|{{FULLPAGENAME}}}}}]]
| ?Changes
| format = ul
| headers = hide
| mainlabel = -
}}<!--
--></includeonly><nowiki/>
By default, the template asks for the changes list for the current page (if the positional parameter #1 argument is empty), or you can explicitly override it at the call-site later (say, {{Patch changes|Patch 1.5}}).
Patch 1.4
{{Change | Fixed spelling in the [[confirmation dialog]] | Confirmation dialog}}
{{Patch changes}}
Patch 1.5
{{Change | Added two options: [[foo]], [[bar]] | Foo; Bar}}
{{Patch changes}}
respectively.
These links might be useful later:
SMW subobjects and queries
SMW standard parameters for inline queries
SMW templates
MW templates anonymous parameters

Possible to have predefined values on a template/only accept some values

Is it possible to have predefined values on a template? I.e.
{{Infobox Employee
|age = {{{age}}}
|gender = {male,female}
|occupation = {nurse, doctor, caretaker}
}}
So whenever someone uses this template they have to chose either male or female and if neither is chosen nothing shows. Very much like a select in html.
In core MediaWiki, you can make the template output an error or ignore unexpected parameters but cannot prevent the user from entering an invalid value. E.g. you can do something like this in the infobox:
{{#switch:{{{gender}}}
| male = Male
| female = Female
| #default = <span style="color:red">Invalid gender</span>[[Category:Pages with invalid template parameters]]
}}
(This example uses #switch from the ParserFunctions extension. You can do the same thing without ParserFunctions but it requires some complex and awkward template code.)
With the TemplateData extension you can specify allowed values, but it will only affect editors which rely on TemplateData (e.g. VisualEditor); it won't influence what someone can do with the template by plaintext editing.
The Semantic Forms extension can display an actual form for editing the infobox, with select boxes and whatever else you specify.

Group Delimited Flat Data using Flex

I've got some delimited data that I need to get into a Flex tree view (or some other kind of control that can display a hierarchy.) The data looks like this:
item1,groupA,mainGroup,root
item2,groupA,mainGroup,root
groupA,mainGroup,root
groupB,mainGroup,root
item3,groupB,mainGroup,root
item4,groupB,mainGroup,root
mainGroup,root
groupC,mainGroup,root
groupD,someOtherGroup,root
root
My flex app is connected to a jboss server that could potentially remove the root element (if necessary), but it really can't build the tree structure (for a variety of reasons unrelated to this question.)
At any rate, that needs to translates to a tree like this (the actual order doesn't matter, just the hierarchy.):
++ root
|-+ mainGroup
| |-+ groupA
| | - item1
| | - item2
| |-+ groupB
| | - item3
| | - item4
| |-+ groupC
|-+ someOtherGroup
| |-+ groupD
I know how to group flat data using a grouping collection, as is described here. But I haven't had any luck figuring out a way to get flex to actually read/interpret the delimited format (without preprocessing it and building the correct structure myself.)
Thanks in advance for any suggestions.
I think pre-processing it is going to be the only way. What I mean by that is having a method you write that creates the GroupingCollection appropriately based on an algorithm which is based on your initial data.
The split method:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/String.html#split()
GroupingCollection:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/collections/GroupingCollection.html#grouping
Grouping:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/collections/Grouping.html#fields
GroupingField:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/collections/GroupingField.html
In looking through the docs they do have those groupingObjectFunction properties though for the life of me I can't understand what that's supposed to do.