Skip to content

Commit

Permalink
add external links column hyperlink support (#1475, #1476)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkonie committed Sep 28, 2022
1 parent 7166a21 commit f56272b
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 26 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Added
- ``LandingZone.can_display_files()`` helper (#1401)
- **Samplesheets**
- Statistics badge in iRODS dir modal (#1434)
- External links column hyperlink support (#1475, #1476)
- **Taskflowbackend**
- Add app from SODAR Core (#691)
- Add Taskflow functionality from SODAR Taskflow (#691, #1464)
Expand Down
6 changes: 5 additions & 1 deletion docs_manual/source/admin_settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,11 @@ Sample Sheets Settings
Skip URL template modification if substring is found in the ``accession``
attribute (list).
``SHEETS_EXTERNAL_LINK_LABELS``
Labels for external link columns (dict).
Labels for external link columns (dict). Each item the dict should contain
an ID descriptor such as ``x-generic-remote`` as its key. The item should
contain a ``label`` parameter containing a display-friendly description of
the ID. If linking out to an external resource is needed, add a ``url``
parameter containing a URL pattern in form of ``https://example.com/{id}``.
``SHEETS_SYNC_INTERVAL``
Interval for remote sheet synchronization in minutes (integer).

Expand Down
3 changes: 2 additions & 1 deletion docs_manual/source/app_samplesheets_browse.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ HPO Terms
displayed in the cell for users.
External Links
The "external links" columns are a special case where key-value pairs are
displayed as badges.
displayed as badges. If configured on the server side for a specific key,
the badges will link out to the ID on the appropriate service.
Simple Links
Generic text cells may also contain arbitrary hyperlinks which can target
either internal or external resources.
Expand Down
5 changes: 5 additions & 0 deletions docs_manual/source/app_samplesheets_edit.rst
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ following syntax: ``id_type:id;id_type:id``

External links cell editing

If configured on the server side for a specific key, the badges will link out to
the ID on the appropriate external web service. This has to be configured by an
administrator in the ``SHEETS_EXTERNAL_LINK_LABELS`` variable. For more
information, see :ref:`admin_settings`.


Row Editing
===========
Expand Down
1 change: 1 addition & 0 deletions docs_manual/source/sodar_release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Release for integrating SODAR Taskflow with SODAR.
- Add Taskflowbackend app from SODAR Core
- Add Taskflow functionality from SODAR Taskflow v0.6.2
- Implement SODAR Core v0.11 project modify API
- Add hyperlink support for "external links" sample sheet columns


v0.11.3 (2022-07-20)
Expand Down
50 changes: 34 additions & 16 deletions samplesheets/constants.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,40 @@
"""Constants for the samplesheets app"""

# Default external link labels used at CUBI
# Default external link labels
# Each entry should have a "label" and an optional "url"
# The url should be a pattern containing "{id}" for the ID
# TODO: Move internal CUBI labels from repo to env (see issue #1477)
DEFAULT_EXTERNAL_LINK_LABELS = {
'x-bih-buch-genomics-wetlab-id': 'Wetlab-ID assigned by BIH genomics unit '
'in Buch',
'x-bih-cvk-genomics-wetlab-id': 'Wetlab-ID assigned by BIH genomics unit '
'in CVK',
'x-bih-tcell2015-id': 'ID assigned in "T-CELL 2015" project ran at BIH',
'x-cegat-sequencing-id': 'CeGaT Sequencing ID',
'x-charite-bcrt-genomics-wetlab-id': 'BCRT Genomics Wet-Lab ID',
'x-charite-medgen-array-id': 'Charite Medical Genetics Array ID',
'x-charite-medgen-blood-book-id': 'Charite Medical Genetics Blood Book ID',
'x-dkfz-1touch-id': 'ID assigned through Heidelberg one-touch pipeline',
'x-dkfz-ilse-id': 'ID assigned through DFKZ sequencing',
'x-dkfz-mtk-id': 'ID assigned through DFKZ sequencing for the Molecular '
'Tumor Conference project',
'x-labor-berlin-blood-book-id': 'Labor Berlin Blood Book ID',
'x-generic-remote': 'External ID',
'x-bih-buch-genomics-wetlab-id': {
'label': 'Wetlab-ID assigned by BIH genomics unit in Buch'
},
'x-bih-cvk-genomics-wetlab-id': {
'label': 'Wetlab-ID assigned by BIH genomics unit in CVK'
},
'x-bih-tcell2015-id': {
'label': 'ID assigned in "T-CELL 2015" project ran at BIH'
},
'x-cegat-sequencing-id': {'label': 'CeGaT Sequencing ID'},
'x-charite-bcrt-genomics-wetlab-id': {'label': 'BCRT Genomics Wet-Lab ID'},
'x-charite-medgen-array-id': {'label': 'Charite Medical Genetics Array ID'},
'x-charite-medgen-blood-book-id': {
'label': 'Charite Medical Genetics Blood Book ID'
},
'x-dkfz-1touch-id': {
'label': 'ID assigned through Heidelberg one-touch pipeline'
},
'x-dkfz-ilse-id': {'label': 'ID assigned through DFKZ sequencing'},
'x-dkfz-mtk-id': {
'label': 'ID assigned through DFKZ sequencing for the Molecular Tumor '
'Conference project'
},
'x-labor-berlin-blood-book-id': {'label': 'Labor Berlin Blood Book ID'},
'x-generic-remote': {'label': 'External ID'},
'x-sodar-example': {'label': 'Example ID', 'url': None},
'x-sodar-example-link': {
'label': 'Example ID with hyperlink',
'url': 'https://example.com/{id}',
},
}

# Hide template fields listed here from the template UI (see issue #1443)
Expand Down
4 changes: 4 additions & 0 deletions samplesheets/vueapp/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,10 @@ div.sodar-ss-data-hover {
width: 26px !important; /* Quick HACK for uniform button size */
}
a.sodar-ss-data-ext-link {
color: #ffffff;
}
/* Common editor styles */
.sodar-ss-data-cell-popup {
Expand Down
25 changes: 20 additions & 5 deletions samplesheets/vueapp/src/components/renderers/DataCellRenderer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,12 @@
<span v-for="(idRef, index) in renderData.extIds"
class="badge-group"
:key="index"
:title="idRef.key">
<span class="badge badge-secondary">ID</span><span class="badge badge-info">{{ idRef.id }}</span>
:title="idRef.label">
<span class="badge badge-secondary">ID</span>
<span v-if="idRef.url" class="badge badge-info">
<a :href="idRef.url" target="_blank" class="sodar-ss-data-ext-link">{{ idRef.id }}</a>
</span>
<span v-else class="badge badge-info">{{ idRef.id }}</span>
</span>
</span>
<!-- File link -->
Expand Down Expand Up @@ -73,6 +77,7 @@ import Vue from 'vue'
const contactRegex = /(.+?)(?:[<[])(.+?)(?=[>\]])/
const simpleLinkRegex = /([^<>]+)\s*<(https?:\/\/[^<>]+)>/
const extLinkId = '{id}'
export default Vue.extend({
data () {
Expand Down Expand Up @@ -133,9 +138,19 @@ export default Vue.extend({
const extId = this.value.value[i]
const splitId = extId.split(':')
if (splitId.length > 1 && splitId[1] != null) {
let key = splitId[0]
if (key in linkLabels) key = linkLabels[key]
ret.push({ key: key, id: splitId[1] })
const key = splitId[0]
let label = key
let url = null
if (key in linkLabels) {
label = linkLabels[key].label
if ('url' in linkLabels[key] &&
linkLabels[key].url !== null &&
linkLabels[key].url.includes(extLinkId)) {
url = linkLabels[key].url.replace(
extLinkId, encodeURIComponent(splitId[1]))
}
}
ret.push({ label: label, id: splitId[1], url: url })
}
}
return { extIds: ret }
Expand Down
33 changes: 32 additions & 1 deletion samplesheets/vueapp/tests/unit/DataCellRenderer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,38 @@ describe('DataCellRenderer.vue', () => {
const cellData = cell.find('.sodar-ss-data')
expect(cellData.findAll('.badge-group').length).toBe(2)
expect(cellData.text()).toBe(
'ID' + value[0].split(':')[1] + 'ID' + value[1].split(':')[1])
'ID ' + value[0].split(':')[1] + 'ID ' + value[1].split(':')[1])
expect(cellData.find('.sodar-ss-data-ext-link').exists()).toBe(false)
expect(cell.classes()).not.toContain('text-right')
expect(cell.classes()).not.toContain('text-muted')
})

it('renders external links cell with a link', async () => {
const table = copy(studyTablesOneCol).tables.study
table.field_header[0] = {
value: 'External Links',
name: 'External links',
obj_cls: 'GenericMaterial',
item_type: 'SOURCE',
num_col: false,
config_set: false,
col_type: 'EXTERNAL_LINKS',
max_value_len: 2
}
const value = ['x-sodar-example:ID-123', 'x-sodar-example-link:ID-XYZ']
table.table_data[0][0].value = value
const wrapper = mountSheetTable({ table: table })
await waitAG(wrapper)
await waitRAF()

const cell = wrapper.find('.sodar-ss-data-cell')
const cellData = cell.find('.sodar-ss-data')
expect(cellData.findAll('.badge-group').length).toBe(2)
expect(cellData.text()).toBe(
'ID ' + value[0].split(':')[1] + 'ID ' + value[1].split(':')[1])
expect(cellData.find('.sodar-ss-data-ext-link').exists()).toBe(true)
expect(cellData.find('.sodar-ss-data-ext-link').attributes().href).toBe(
'https://example.com/ID-XYZ')
expect(cell.classes()).not.toContain('text-right')
expect(cell.classes()).not.toContain('text-muted')
})
Expand Down
9 changes: 8 additions & 1 deletion samplesheets/vueapp/tests/unit/data/sodarContext.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@
"irods_webdav_enabled": true,
"irods_webdav_url": "http://davrods.local",
"external_link_labels": {
"x-generic-remote": "External ID"
"x-generic-remote": "External ID",
"x-sodar-example": {
"label": "Example ID",
"url": null},
"x-sodar-example-link": {
"label": "Example ID with hyperlink",
"url": "https://example.com/{id}"
}
},
"table_height": 400,
"min_col_width": 100,
Expand Down
9 changes: 8 additions & 1 deletion samplesheets/vueapp/tests/unit/data/sodarContextNoSheet.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@
"irods_webdav_enabled": true,
"irods_webdav_url": "http://davrods.local",
"external_link_labels": {
"x-generic-remote": "External ID"
"x-generic-remote": "External ID",
"x-sodar-example": {
"label": "Example ID",
"url": null},
"x-sodar-example-link": {
"label": "Example ID with hyperlink",
"url": "https://example.com/{id}"
}
},
"table_height": 400,
"min_col_width": 100,
Expand Down

0 comments on commit f56272b

Please sign in to comment.