Skip to content

Move refresh button and show last refresh timestamp#1361

Merged
sadiqkhoja merged 4 commits intogetodk:masterfrom
sadiqkhoja:features/last-refresh-timestamp
Oct 20, 2025
Merged

Move refresh button and show last refresh timestamp#1361
sadiqkhoja merged 4 commits intogetodk:masterfrom
sadiqkhoja:features/last-refresh-timestamp

Conversation

@sadiqkhoja
Copy link
Contributor

@sadiqkhoja sadiqkhoja commented Oct 10, 2025

Closes getodk/central#1106

What has been done to verify that this works as intended?

Added assertion in the existing tests and manual verification

Why is this the best possible solution? Were any other approaches considered?

I considered creating now in SubmissionList and pass it to the children view components as prop but view components also update data independently (using watchers on filter change). Emitting timestamp on refresh felt better approach.

Using Luxon DateTime so that it is easy to show timestamp in local timezone and send UTC for snapshot filter.

How does this change affect users? Describe intentional changes to behavior and behavior that could have accidentally been affected by code changes. In other words, what are the regression risks?

No

Does this change require updates to user documentation? If so, please file an issue here and include the link below.

No

Before submitting this PR, please make sure you have:

  • run npm run test and npm run lint and confirmed all checks still pass OR confirm CircleCI build passes
  • verified that any code or assets from external sources are properly credited in comments or that everything is internally sourced

@sadiqkhoja sadiqkhoja changed the title Feature getodk/central#1106: Move refresh button and show last refres… Move refresh button and show last refresh timestamp Oct 10, 2025
@sadiqkhoja sadiqkhoja force-pushed the features/last-refresh-timestamp branch 2 times, most recently from ca35e54 to bedd4f9 Compare October 10, 2025 20:22
@sadiqkhoja sadiqkhoja marked this pull request as ready for review October 10, 2025 20:31
Copy link
Member

@matthew-white matthew-white left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the main question I have is which timestamp to show: the time that the request was sent or the time that the response was received.

Originally, I was thinking that we would show the time that the response was received. I added setAt and patchedAt to requestData in #1341, and I was thinking that we could use something like max(odata.setAt, odata.patchedAt) here. That would work for SubmissionMapView as well, since SubmissionMapView sets odata after the GeoJSON response is received. The main benefit of that approach is that SubmissionList and EntityList can avoid managing an additional piece of state that requires coordination with child components (the now data property).

Now that I think more about it though, maybe there is a way that showing the time that the response was received could be confusing. If the request takes a long time, then new data could theoretically come in between when the request was sent and the response was received. In that case, if we show the time that the response was received, the user might think that they've received all submissions created before that time — when actually that isn't the case. That would kind of be an assumption on the user's part though: I don't think the wording of "Data last refreshed at..." implies that exactly.

This is just my intuition, but I personally feel like it's a little confusing to immediately update the timestamp that's shown (to update it as soon as the Refresh button is clicked). If the request takes a long time, I wouldn't expect the timestamp to change until after the request completes. It's only then that the data has actually been successfully refreshed. Similarly, if the request fails, I wouldn't expect the timestamp to change at all. If we used max(setAt, patchedAt), that wouldn't change if the request fails.

I feel like both approaches have pros and cons; I can see both sides to it. I'm personally more in favor of showing the time that the response was received. That seems reasonably clear to me, and it'd also help simplify SubmissionList and EntityList, since they wouldn't have to manage now.

"search": "Search",
// Text shown above the data tables to tell users when data was last fetched / refreshed.
// {date} is only the date component and {time} is only the time component.
"dataRefreshTime": "Data last refreshed at {date} on {time}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"dataRefreshTime": "Data last refreshed at {date} on {time}"
"dataRefreshTime": "Data last refreshed on {date} at {time}"

@sadiqkhoja
Copy link
Contributor Author

If the request takes a long time, then new data could theoretically come in between when the request was sent and the response was received. In that case, if we show the time that the response was received, the user might think that they've received all submissions created before that time — when actually that isn't the case.

this was my worry when I used now for showing when data was refreshed but I agree with your suggestion to use request success time is simpler and above case probably be tolerable to users. Only difference in my latest commit is that I have used only setAt instead of max(setAt, patchedAt) because I don't want to change the timestamp on page changes.

Comment on lines +27 to +37
<div class="table-refresh-info">
<span v-show="odataEntities.dataExists">
{{ $t('common.dataRefreshTime', { date: formatDate(dataRefreshedAt), time: formatTime(dataRefreshedAt) }) }}
</span>
<button id="entity-list-refresh-button" type="button"
class="btn btn-link" :aria-disabled="refreshing || bulkOperationInProgress"
@click="fetchChunk(false, true)">
<span class="icon-refresh"></span>{{ $t('action.refresh') }}
<spinner :state="refreshing"/>
</button>
</div>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about turning this into a component? It could emit a click event and receive the following props:

  • The OData resource — either odata or odataEntities (needed for the timestamp and also for v-show="odataEntities.dataExists")
  • refreshing
  • disabled

I like the idea of a component for a few reasons:

  • A single file component would centralize the HTML, .table-refresh-info styles, and common.dataRefreshTime message in a single file.
  • SubmissionList and EntityList are already pretty complicated. If they can offload things like date/time formatting to a child component, that sounds nice to me.
  • Looking ahead to the next release, I'm thinking that this component would be the one responsible for the logic for Inform user of new submissions/entities central#1332
    • Fetching the latest count
    • Adjusting the appearance of the refresh button when there are new submissions to pull

It would be a pretty tiny component (at least for now), so I could also see the argument that it's not worth adding one more component. I don't think it'd be any smaller than the OdataLoadingMessage component though.

@sadiqkhoja sadiqkhoja force-pushed the features/last-refresh-timestamp branch 2 times, most recently from 65bb83a to 120eae7 Compare October 16, 2025 19:31
@sadiqkhoja sadiqkhoja marked this pull request as draft October 16, 2025 19:47
@sadiqkhoja sadiqkhoja force-pushed the features/last-refresh-timestamp branch 2 times, most recently from ee7cfd4 to 4ae8c60 Compare October 16, 2025 20:26
@sadiqkhoja sadiqkhoja force-pushed the features/last-refresh-timestamp branch from 4ae8c60 to 92a1529 Compare October 16, 2025 20:27
Comment on lines +35 to +36
refreshing: Boolean,
disabled: Boolean
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can use just one here or maybe in future we might need two?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I think it could just be one for now.

@sadiqkhoja sadiqkhoja marked this pull request as ready for review October 16, 2025 20:33
Comment on lines +464 to +466
// Text shown above the data tables to tell users when data was last fetched / refreshed.
// {date} is only the date component and {time} is only the time component.
"dataRefreshTime": "Data last refreshed on {date} at {time}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about moving this into the TableRefreshBar component?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's some CSS here that could probably go away:

// Further increase the space between the dropdown and the refresh button.
margin-right: 10px;

@sadiqkhoja sadiqkhoja merged commit 62ddd30 into getodk:master Oct 20, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Move refresh button and add timestamp

2 participants