Changing dataset table metadata

LabKey Support Forum (Inactive)
Changing dataset table metadata Anthony Corbett  2012-10-23 08:11
Status: Closed
 
I've implemented electionic CRF forms using wiki pages. Now I'm trying to update a dataset's metadata so that the updateURL points to a wiki page; this way the edit link on the grid will do straight to the wiki page. I tried following https://www.labkey.org/wiki/home/Documentation/page.view?name=tableMetadata which says to use the following xml:

<ns:table tableName="DOB" tableDbType="TABLE">
  <ns:updateUrl>/wiki/page.view?name=Enrollment&action=dob&pid=${ParticipantId}</ns:updateUrl>
</ns:table>


However, when I save I get the message 'saved with parse errors'. There is no feedback as to what the parse error was, maybe it isn't validate xml against the tableInfo XSD? I did notice in other table definitions had the columns specified, but when I click the edit metadata button below the field properties nothing populates in the xml view.

Thanks in advance!

-
Anthony Corbett
 
 
Matthew Bellew responded:  2012-10-23 08:25
You need to encode the '&' character as '&amp;' in xml.
 
Anthony Corbett responded:  2012-10-23 08:37
I'm aware of the encoding issue but usually when I trip over that I get an error message like:

error: Unexpected character encountered (lex state 3): 'p' (line 3, column 47)
Metadata XML error: Unexpected character encountered (lex state 3): 'p' (line 3, column 47)

See https://www.labkey.org/announcements/home/Developer/Forum/thread.view?entityId=4598d895-d83d-102e-a683-987439a6f368&_docid=thread%3A4598d895-d83d-102e-a683-987439a6f368 as an example.


I tried using the following xml:

<ns:table tableName="DOB" tableDbType="TABLE">
  <ns:updateUrl>/wiki/page.view?name=Enrollment&amp;action=dob&amp;pid=${ParticipantId}</ns:updateUrl>
</ns:table>


and it still has parse error on save.
 
jeckels responded:  2012-10-23 09:24
Hi Anthony,

Try wrapping your XML with:

<ns:tables xmlns:ns="http://labkey.org/data/xml">

</ns:tables>

I know it's silly to have <tables> be the root element when the XML is scoped to a single table, but it's historically been expecting it to be set up like that.

Thanks,
Josh
 
Anthony Corbett responded:  2012-10-23 10:22
Thanks Josh, I was able to save after adding the root element with the namespace declaration.

I am now wondering if the URL can be a child of the current container. For example, the datasets live in the parent study folder and the wiki pages live in a child container called eCRFs. This is because we want different permissions on being able to edit/insert into datasets and the ability to delete/edit wiki pages. We have had incidences where a clinical personnel has been known to delete them when they are in the same container as the datasets.

Would it be possible to have the URL be:

controller/containerPath/action -> wiki/eCRFs/page.view?name= . . .

Thanks for the quick responses!
 
Matthew Bellew responded:  2012-10-23 11:09
You can't use a container using this syntax. You can however specify a full url starting with "https://"
 
Anthony Corbett responded:  2012-10-23 12:30
We have a requirement to be able to export the study and datasets from dev to production and they have different hostnames in the URL. Will the URL automatically be updated to the new system's URL?
 
Anthony Corbett responded:  2012-10-23 13:45
I have found a workaround for this. I created a wiki page in the study container called 'Redirect to eCRF'. It reads the appropriate query parameters then sets the window.location to the correct wiki page in the child container.


/labkey/wiki/study/page.view?name=RedirecteCRF&eCRF=XXX&action=YYYY&pid=ZZZ will redirect to /labkey/wiki/study/eCRFs/page.view?name=XXX#/YYYY/ZZZ

Note: the javascript framework I'm using uses anchor tags (#/YYYY/ZZZ part of URL) to manage browser history so each wiki page is a single page javascript app with multiple views.



This leads me to another question.... Now that I have the updateURL set in the metadata is there a way using a query to get to the updateURL or does the updateURL come back in the JSON returned by LABKEY.Query.selectRows() API?

Thanks,

Anthony
 
kevink responded:  2012-10-23 14:02
Unfortunately, we don't currently include the update url for each row in the selectRows API response. We could add that to the selectRows response format or add a redirect action on the query controller that forwards the table's updateURL action.
 
Anthony Corbett responded:  2012-10-29 08:59
Thanks for the replies everyone! Wanted to share my solution for others to see and possibly get feedback from anyone interested.


My Solution to mapping a dataset row to a specific section (view) of a 'wiki' eCRF using the updateURL metadata:


Logical model:

1. An eCRF is composed of one or more sections (views); each section is a 1 to 1 mapping to a dataset.
2. At each visit (sequenceNum) 1 or more eCRFs are completed.
3. An eCRF can be used at 1 or more visits.


So, the relationship between an eCRFs and visits is many-to-many and at each valid cross product is a set of eCRF sections (datasets) to be displayed/populated.

The physical model for this then becomes a list (an associative entity) where each row represents a unique quadruple of the following pieces of information:

DataSetId, SequenceNum, eCRFwiki (Name), section (Name)

Example: 5001, -1, 'Enrollment', 'demographics'

This effectively mapping a visit/Dataset to an eCRF's section. With this mapping it is now possible to ask the question: For this LSID (dataset row) what eCRF section should be displayed?

And this is exactly how I've implemented my updateURL for all datasets:

<ns:tables xmlns:ns="http://labkey.org/data/xml">
  <ns:table tableName="Demographics" tableDbType="TABLE">
    <ns:updateUrl>wiki/page.view?name=eCRFRedirect&amp;lsid=${lsid}</ns:updateUrl>
  </ns:table>
</ns:tables>


As you can see the updateURL goes to a wiki page called 'eCRFRedirect' passing just the LSID of the row. This wiki page then does a lookup using the following query:

PARAMETERS (LSID VARCHAR)
SELECT
  crf.eCRFwiki, -- The wiki page name that represents the eCRF
  crf.section, -- The section (view) of the eCRF to be displayed
  CASE WHEN( crf.requiresParticipantId ) THEN( StudyData.ParticipantId ) ELSE( null ) END as ParticipantId, -- context for the view
  CASE WHEN( crf.requiresSequenceNum ) THEN( CAST(StudyData.SequenceNum as INTEGER) ) ELSE( null ) END as SequenceNum, -- context for the view
FROM StudyData
JOIN lists.eCRF_datasets crf on StudyData.DataSet.DataSetId = crf.DataSetId AND StudyData.SequenceNum = crf.SequenceNum
WHERE StudyData.lsid = LSID

This returns the eCRF (wiki page) name, the section, and 2 peices of optional context to be passed to the view: the ParticipantId and SequenceNum

After the query returns the row it will then build the URL and set window.location to this URL:

window.location = '/labkey/wiki/[containerPathToCRFs]/page.view?name=[eCRFwiki]#/[section]/[ParticipantId]/[SequenceNum]';

Following the example above: /labkey/wiki/myStudy/eCRFs/page.view?name=Enrollment#/demographics/B001
(SequenceNum is not used for this eCRF as it collected only demographic type data designated/hardcoded by SeqNum -1. If this was an eCRf that is used on more than one visit then I'd pass the SequenceNum also)



There is more abstraction that can be done here; for example, putting the controller as a column in the eCRF_datasets associate list so that the controller (say a different module) can be used for opening CRFs.

This is a start for us and I have hope that same day (when things settle down here) this can be added to a module with its own controller, schema, views instead of lists and wiki pages.


Would love to hear some feedback from anyone with better/cleaner ways to do something like this.


-
Anthony Corbett
 
jeckels responded:  2012-11-19 17:31
Hi Anthony,

I thought you might be interested to know that last week I added the capability to request the update and details URLs when using LABKEY.Query.selectRows() and LABKEY.Query.executeSql(). There are two new config parameters, "includeUpdateColumn" and "includeDetailsColumns". They default to false. If set to true, you'll get additional columns in each result row that include the URLs. It's described in the JavaScript API documentation for the 12.3 release.

Thanks,
Josh
 
Anthony Corbett responded:  2012-11-20 05:14
Thanks Josh! This will be a great feature and will help reduce the overhead and complexity of the solution above.


I have one more question. It is actually regarding the updateURLs and substitution.

I am able to substitute query parameters:

/wiki/page.view?name=Enrollment&pid=${ParticipantId}&vid=${SequenceNum}


But I can't substitute any where else, for example, in the anchor:

/wiki/page.view?name=Enrollment#pid/${ParticipantId}/vid/${SequenceNum}

Can this be done or is there some adverse effect to allowing substitution outside of query params?


I would like to Thank everyone at Labkey. You all are very helpful and responsive!

Much appreciated,

Anthony
 
jeckels responded:  2012-11-20 09:32
Hi Anthony,

As you've noted, right now it's not possible to substitute arbitrarily in the URL. I believe we're limited to GET parameters values. As far as I know there's no technical reason why we couldn't relax this restriction, but it's not how the parsing code works right now. We have an open issue in our bug tracker to make this change, but I don't think that it's going to be part of 12.3.

Thanks,
Josh