From 08e6559bf57e7f93785e00afaca4e246430aa88f Mon Sep 17 00:00:00 2001 From: David Manthey Date: Mon, 28 Oct 2024 12:31:14 -0400 Subject: [PATCH 1/2] Format dates in item lists --- CHANGELOG.md | 6 +++++ docs/girder_annotation_config_options.rst | 7 +++--- docs/girder_config_options.rst | 9 ++++--- .../web_client/templates/itemList.pug | 25 ++++++++++++++++--- .../templates/annotationListWidget.pug | 10 ++++++-- sources/dicom/setup.py | 2 +- 6 files changed, 46 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d7fc4f6b..adf5fad9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 1.30.3 + +### Improvements + +- Format dates in item lists ([#1706](../../pull/1706)) + ## 1.30.2 ### Features diff --git a/docs/girder_annotation_config_options.rst b/docs/girder_annotation_config_options.rst index 07caefb38..6ed44a372 100644 --- a/docs/girder_annotation_config_options.rst +++ b/docs/girder_annotation_config_options.rst @@ -32,7 +32,7 @@ This can be used to specify how annotations are listed on the item page. columns: - # The "record" type is from the default annotation record. The value - # is one of "name", "creator", "created", "updatedId", "updated", + # is one of "name", "creator", "created", "updatedId", "updated". type: record value: name - @@ -43,8 +43,9 @@ This can be used to specify how annotations are listed on the item page. - type: record value: created - # A format of date will use the browser's default date format - format: date + # A format of datetime, date, or time will use the browser's default + # date and/or time format + format: datetime - # The "metadata" type is taken from the annotations's # "annotation.attributes" contents. It can be a nested key by using diff --git a/docs/girder_config_options.rst b/docs/girder_config_options.rst index 77b313357..78898a8a6 100644 --- a/docs/girder_config_options.rst +++ b/docs/girder_config_options.rst @@ -125,7 +125,8 @@ This is used to specify how items appear in item lists. There are two settings, title: Slide Label - # The "record" type is from the default item record. The value is - # one of "name", "size", or "controls". + # one of "name", "description", "created", "updated", "size", or + # "controls". type: record value: name - @@ -139,8 +140,10 @@ This is used to specify how items appear in item lists. There are two settings, # can be a nested key by using dots in its name. type: metadata value: Stain - # "format" can be "text", "number", "category". Other values may be - # specified later. + # "format" can be "text", "number", "category", "datetime", "date", + # "time". "datetime", "date", and "time" use the user's browser's + # locale to convert the date and/or time to their browser's preferred + # format. Other values may be specified later. format: text - type: metadata diff --git a/girder/girder_large_image/web_client/templates/itemList.pug b/girder/girder_large_image/web_client/templates/itemList.pug index c272bf1bf..ec81f97ca 100644 --- a/girder/girder_large_image/web_client/templates/itemList.pug +++ b/girder/girder_large_image/web_client/templates/itemList.pug @@ -16,7 +16,7 @@ ul.g-item-list.li-item-list(layout_mode=(itemList.layout || {}).mode || '', meta - colNames[colidx] = `${column.value.substr(0, 1).toUpperCase()}${column.value.substr(1)}` = colNames[colidx] each item in items - li.g-item-list-entry(class=(highlightItem && item.id === selectedItemId ? 'g-selected' : ''), public=(isParentPublic ? 'true' : 'false'), style=(itemList.layout || {}).mode == 'grid' ? ('max-width: ' + parseInt((itemList.layout || {})['max-width'] || 250) + 'px') : '') + li.g-item-list-entry(class=(highlightItem && item.id === selectedItemId ? 'g-selected' : ''), public=(isParentPublic ? 'true' : 'false'), style=(itemList.layout || {}).mode === 'grid' ? ('max-width: ' + parseInt((itemList.layout || {})['max-width'] || 250) + 'px') : '') if checkboxes label.li-item-list-cell(for='g-item-cid-' + item.cid) input.g-list-checkbox(type="checkbox", g-item-cid=item.cid, id='g-item-cid-' + item.cid) @@ -24,7 +24,7 @@ ul.g-item-list.li-item-list(layout_mode=(itemList.layout || {}).mode || '', meta if column.type !== 'image' || hasAnyLargeImage - var divtype = column.type !== 'record' || column.value !== 'controls' ? 'a' : 'span'; - var classes = divtype == 'a' ? ['g-item-list-link']: []; + var classes = divtype === 'a' ? ['g-item-list-link']: []; if (('' + column.type + column.value).match(/^[a-zA-Z][a-zA-Z0-9-_]*$/)) classes.push(`li-column-${column.type}-${column.value}`); if (('' + column.type).match(/^[a-zA-Z][a-zA-Z0-9-_]*$/)) classes.push(`li-column-${column.type}`); var skip = false; @@ -69,8 +69,19 @@ ul.g-item-list.li-item-list(layout_mode=(itemList.layout || {}).mode || '', meta i.icon-link-ext else if column.value === 'size' .g-item-size= formatSize(item.get('size')) - else if column.value === 'description' - = item.get(column.value) + else if column.value === 'updated' && item.get('created') + .g-item-datetime= new Date(item.get(column.value) || item.get('created')).toLocaleString() + else if column.value === 'created' && item.get('created') + .g-item-datetime= new Date(item.get('created')).toLocaleString() + else + if column.format === 'datetime' && item.get(column.value) + = new Date(item.get(column.value)).toLocaleString() + else if column.format === 'date' && item.get(column.value) + = new Date(item.get(column.value)).toLocaleDateString() + else if column.format === 'time' && item.get(column.value) + = new Date(item.get(column.value)).toLocaleTimeString() + else + = item.get(column.value) else if column.type === 'image' && item.get('largeImage') .large_image_thumbnail(extra-image=column.value !== 'thumbnail' ? column.value : undefined, style=`width: ${column.width || 160}px; height: ${column.height || 100}px`, g-item-cid=column.value === 'thumbnail' ? item.cid : undefined) - var imageName = column.value === 'thumbnail' ? column.value : `images/${column.value}`; @@ -96,6 +107,12 @@ ul.g-item-list.li-item-list(layout_mode=(itemList.layout || {}).mode || '', meta if column.format === 'text' && value //- allow long strings to be hyphenated at periods and underscores != String(value).replace(/&/g, '&').replace(//, '>').replace(/"/, '"').replace(/'/, ''').replace(/\./g, '.­').replace(/_/g, '_­') + else if column.format === 'datetime' && value + = new Date(value).toLocaleString() + else if column.format === 'date' && value + = new Date(value).toLocaleDateString() + else if column.format === 'time' && value + = new Date(value).toLocaleTimeString() else = value if value && column.format !== 'count' diff --git a/girder_annotation/girder_large_image_annotation/web_client/templates/annotationListWidget.pug b/girder_annotation/girder_large_image_annotation/web_client/templates/annotationListWidget.pug index 3e5918e7d..79f72c6b8 100644 --- a/girder_annotation/girder_large_image_annotation/web_client/templates/annotationListWidget.pug +++ b/girder_annotation/girder_large_image_annotation/web_client/templates/annotationListWidget.pug @@ -60,7 +60,9 @@ if annotations.length if (column.type === 'record' && column.value === 'creator') { value = creator; } else if (column.type === 'record' && column.value === 'updatedId') { - value = updater; + value = updater || creator; + } else if (column.type === 'record' && column.value === 'updated') { + value = value || annotation.get('created') } else if (column.type === 'metadata') { value = annotation.get('annotation').attributes || {}; column.value.split('.').forEach((part) => { @@ -73,8 +75,12 @@ if annotations.length if column.format === 'user' a(href=`#user/${annotation.get(column.value) || annotation.get(column.value + 'Id')}`) = value - else if column.format === 'date' + else if column.format === 'datetime' = (new Date(value)).toLocaleString() + else if column.format === 'date' + = (new Date(value)).toLocaleDateString() + else if column.format === 'time' + = (new Date(value)).toLocaleTimeString() else = value td.g-annotation-actions diff --git a/sources/dicom/setup.py b/sources/dicom/setup.py index 29235721d..1e2c7a0b7 100644 --- a/sources/dicom/setup.py +++ b/sources/dicom/setup.py @@ -73,7 +73,7 @@ def prerelease_local_scheme(version): ], install_requires=[ f'large-image{limit_version}', - 'wsidicom>=0.9.0', + 'wsidicom>=0.9.0,!=0.21.3', 'pydicom<3; python_version < "3.10"', 'pydicom; python_version >= "3.10"', ], From 648cdf7ed1687f6453ae09c26e082fe59d2b1e64 Mon Sep 17 00:00:00 2001 From: David Manthey Date: Mon, 28 Oct 2024 15:31:57 -0400 Subject: [PATCH 2/2] Avoid a version of wsidicom that doesn't work with some tests --- CHANGELOG.md | 6 ----- docs/girder_annotation_config_options.rst | 7 +++--- docs/girder_config_options.rst | 9 +++---- .../web_client/templates/itemList.pug | 25 +++---------------- .../templates/annotationListWidget.pug | 10 ++------ 5 files changed, 12 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index adf5fad9c..4d7fc4f6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,5 @@ # Change Log -## 1.30.3 - -### Improvements - -- Format dates in item lists ([#1706](../../pull/1706)) - ## 1.30.2 ### Features diff --git a/docs/girder_annotation_config_options.rst b/docs/girder_annotation_config_options.rst index 6ed44a372..07caefb38 100644 --- a/docs/girder_annotation_config_options.rst +++ b/docs/girder_annotation_config_options.rst @@ -32,7 +32,7 @@ This can be used to specify how annotations are listed on the item page. columns: - # The "record" type is from the default annotation record. The value - # is one of "name", "creator", "created", "updatedId", "updated". + # is one of "name", "creator", "created", "updatedId", "updated", type: record value: name - @@ -43,9 +43,8 @@ This can be used to specify how annotations are listed on the item page. - type: record value: created - # A format of datetime, date, or time will use the browser's default - # date and/or time format - format: datetime + # A format of date will use the browser's default date format + format: date - # The "metadata" type is taken from the annotations's # "annotation.attributes" contents. It can be a nested key by using diff --git a/docs/girder_config_options.rst b/docs/girder_config_options.rst index 78898a8a6..77b313357 100644 --- a/docs/girder_config_options.rst +++ b/docs/girder_config_options.rst @@ -125,8 +125,7 @@ This is used to specify how items appear in item lists. There are two settings, title: Slide Label - # The "record" type is from the default item record. The value is - # one of "name", "description", "created", "updated", "size", or - # "controls". + # one of "name", "size", or "controls". type: record value: name - @@ -140,10 +139,8 @@ This is used to specify how items appear in item lists. There are two settings, # can be a nested key by using dots in its name. type: metadata value: Stain - # "format" can be "text", "number", "category", "datetime", "date", - # "time". "datetime", "date", and "time" use the user's browser's - # locale to convert the date and/or time to their browser's preferred - # format. Other values may be specified later. + # "format" can be "text", "number", "category". Other values may be + # specified later. format: text - type: metadata diff --git a/girder/girder_large_image/web_client/templates/itemList.pug b/girder/girder_large_image/web_client/templates/itemList.pug index ec81f97ca..c272bf1bf 100644 --- a/girder/girder_large_image/web_client/templates/itemList.pug +++ b/girder/girder_large_image/web_client/templates/itemList.pug @@ -16,7 +16,7 @@ ul.g-item-list.li-item-list(layout_mode=(itemList.layout || {}).mode || '', meta - colNames[colidx] = `${column.value.substr(0, 1).toUpperCase()}${column.value.substr(1)}` = colNames[colidx] each item in items - li.g-item-list-entry(class=(highlightItem && item.id === selectedItemId ? 'g-selected' : ''), public=(isParentPublic ? 'true' : 'false'), style=(itemList.layout || {}).mode === 'grid' ? ('max-width: ' + parseInt((itemList.layout || {})['max-width'] || 250) + 'px') : '') + li.g-item-list-entry(class=(highlightItem && item.id === selectedItemId ? 'g-selected' : ''), public=(isParentPublic ? 'true' : 'false'), style=(itemList.layout || {}).mode == 'grid' ? ('max-width: ' + parseInt((itemList.layout || {})['max-width'] || 250) + 'px') : '') if checkboxes label.li-item-list-cell(for='g-item-cid-' + item.cid) input.g-list-checkbox(type="checkbox", g-item-cid=item.cid, id='g-item-cid-' + item.cid) @@ -24,7 +24,7 @@ ul.g-item-list.li-item-list(layout_mode=(itemList.layout || {}).mode || '', meta if column.type !== 'image' || hasAnyLargeImage - var divtype = column.type !== 'record' || column.value !== 'controls' ? 'a' : 'span'; - var classes = divtype === 'a' ? ['g-item-list-link']: []; + var classes = divtype == 'a' ? ['g-item-list-link']: []; if (('' + column.type + column.value).match(/^[a-zA-Z][a-zA-Z0-9-_]*$/)) classes.push(`li-column-${column.type}-${column.value}`); if (('' + column.type).match(/^[a-zA-Z][a-zA-Z0-9-_]*$/)) classes.push(`li-column-${column.type}`); var skip = false; @@ -69,19 +69,8 @@ ul.g-item-list.li-item-list(layout_mode=(itemList.layout || {}).mode || '', meta i.icon-link-ext else if column.value === 'size' .g-item-size= formatSize(item.get('size')) - else if column.value === 'updated' && item.get('created') - .g-item-datetime= new Date(item.get(column.value) || item.get('created')).toLocaleString() - else if column.value === 'created' && item.get('created') - .g-item-datetime= new Date(item.get('created')).toLocaleString() - else - if column.format === 'datetime' && item.get(column.value) - = new Date(item.get(column.value)).toLocaleString() - else if column.format === 'date' && item.get(column.value) - = new Date(item.get(column.value)).toLocaleDateString() - else if column.format === 'time' && item.get(column.value) - = new Date(item.get(column.value)).toLocaleTimeString() - else - = item.get(column.value) + else if column.value === 'description' + = item.get(column.value) else if column.type === 'image' && item.get('largeImage') .large_image_thumbnail(extra-image=column.value !== 'thumbnail' ? column.value : undefined, style=`width: ${column.width || 160}px; height: ${column.height || 100}px`, g-item-cid=column.value === 'thumbnail' ? item.cid : undefined) - var imageName = column.value === 'thumbnail' ? column.value : `images/${column.value}`; @@ -107,12 +96,6 @@ ul.g-item-list.li-item-list(layout_mode=(itemList.layout || {}).mode || '', meta if column.format === 'text' && value //- allow long strings to be hyphenated at periods and underscores != String(value).replace(/&/g, '&').replace(//, '>').replace(/"/, '"').replace(/'/, ''').replace(/\./g, '.­').replace(/_/g, '_­') - else if column.format === 'datetime' && value - = new Date(value).toLocaleString() - else if column.format === 'date' && value - = new Date(value).toLocaleDateString() - else if column.format === 'time' && value - = new Date(value).toLocaleTimeString() else = value if value && column.format !== 'count' diff --git a/girder_annotation/girder_large_image_annotation/web_client/templates/annotationListWidget.pug b/girder_annotation/girder_large_image_annotation/web_client/templates/annotationListWidget.pug index 79f72c6b8..3e5918e7d 100644 --- a/girder_annotation/girder_large_image_annotation/web_client/templates/annotationListWidget.pug +++ b/girder_annotation/girder_large_image_annotation/web_client/templates/annotationListWidget.pug @@ -60,9 +60,7 @@ if annotations.length if (column.type === 'record' && column.value === 'creator') { value = creator; } else if (column.type === 'record' && column.value === 'updatedId') { - value = updater || creator; - } else if (column.type === 'record' && column.value === 'updated') { - value = value || annotation.get('created') + value = updater; } else if (column.type === 'metadata') { value = annotation.get('annotation').attributes || {}; column.value.split('.').forEach((part) => { @@ -75,12 +73,8 @@ if annotations.length if column.format === 'user' a(href=`#user/${annotation.get(column.value) || annotation.get(column.value + 'Id')}`) = value - else if column.format === 'datetime' - = (new Date(value)).toLocaleString() else if column.format === 'date' - = (new Date(value)).toLocaleDateString() - else if column.format === 'time' - = (new Date(value)).toLocaleTimeString() + = (new Date(value)).toLocaleString() else = value td.g-annotation-actions