From dcdbbafec72edbf34541ddc7a7ffa0d425ded8ec Mon Sep 17 00:00:00 2001 From: David Manthey Date: Mon, 28 Oct 2024 12:31:14 -0400 Subject: [PATCH] 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 ++++++-- 5 files changed, 45 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d7fc4f6b..5d0c46902 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 1.30.3 + +### Improvements + +- Format dates in item lists ([#1707](../../pull/1707)) + ## 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