-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[$500] Status - Error message & emoji status remains when clear status timer has elapsed #33128
Comments
👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:
|
Triggered auto assignment to @deetergp ( |
Looking into this |
If you are the assigned CME please investigate whether the linked PR caused a regression and leave a comment with the results. If a regression has occurred and you are the assigned CM follow the instructions here. If this regression could have been avoided please consider also proposing a recommendation to the PR checklist so that we can avoid it in the future. |
ProposalPlease re-state the problem that we are trying to solve in this issue.The status is not sent to the backend in UTC format What is the root cause of that problem?we dont convert the What changes do you think we should make in order to solve the problem?There is two ways here:
with that being said the changes of the second solution should not introduce breaking change so lets dig into it: first, when writing the data to the server we need to convert it into UTC format so we need to change the update function to: function updateCustomStatus(status) {
const clearAfterInUtc = DateUtils.formatWithUTCTimeZone(status.clearAfter, 'yyyy-MM-dd HH:mm:ss');
const newStatus = {
text: status.text,
emojiCode: status.emojiCode,
clearAfter: clearAfterInUtc,
};
API.write('UpdateStatus', newStatus, {
optimisticData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
value: {
[currentUserAccountID]: {
status: newStatus,
},
},
},
],
});
} then for the reading part, we need to add a new function inside the DateUtils file that converts the UTC string into a local date string given a certain format (this is the opposite of so i have defined this funciton : function formatUTCToLocal(dateString: string, dateFormat: string = CONST.DATE.FNS_FORMAT_STRING) {
if (dateString === '' || !dateString) {
return dateString;
}
const date = parse(dateString, dateFormat, new Date());
// Check if the date is valid
if (!isValid(date)) {
return '';
}
const utcDate = zonedTimeToUtc(date, 'UTC');
const localDate = zonedTimeToUtc(utcDate, timezone.selected);
// the timezone.selected is the timezone that the user selected at profile/timezone
return tzFormat(localDate, dateFormat, {timeZone: timezone.selected});
} then we have two solutions:
to do so we need to add a new middleware to this folder: https://github.com/Expensify/App/blob/82b76c1a36cf1a01b00c14510a5812a591e7f2fd/src/libs/Middleware FormatStatusClearAfter.ts import DateUtils from '@libs/DateUtils';
import type {Middleware} from '@libs/Request';
import ONYXKEYS from '@src/ONYXKEYS';
import type {PersonalDetailsList} from '@src/types/onyx';
/**
* Middleware function to format the 'clearAfter' field in personal details list.
*
* @param {any} requestResponse - The response from the request.
* @param {any} request - The original request data.
* @param {boolean} isFromSequentialQueue - Flag to indicate if the request is from a sequential queue.
* @returns {Promise<any>} - The processed request response.
*/
const formatStatusClearAfter: Middleware = (requestResponse) =>
requestResponse.then((response) => {
const responseOnyxData = response?.onyxData ?? [];
responseOnyxData.forEach((onyxData) => {
if (onyxData.key !== ONYXKEYS.PERSONAL_DETAILS_LIST) {
return;
}
const personalDetailsList = onyxData.value as PersonalDetailsList;
Object.keys(personalDetailsList).forEach((accountID) => {
const status = personalDetailsList[accountID]?.status;
const clearAfter = status?.clearAfter;
if (!clearAfter || clearAfter === '') {
return;
}
if (status) {
status.clearAfter = DateUtils.formatUTCToLocal(clearAfter, 'yyyy-MM-dd HH:mm:ss');
}
});
});
return response;
});
export default formatStatusClearAfter; then we need to add the new middleware to the index file, then we need to register it in the app file: Request.use(Middleware.FormatClearAfterInPersonalDetails); this will convert the value returned from the backend to a local date in the middle without the need to update the time in each component that uses it
like this: const clearAfter = DateUtils.formatUTCToLocal(lodashGet(currentUserPersonalDetails, 'status.clearAfter', ''), 'yyyy-MM-dd HH:mm:ss'); AlternativelyConverting the date inside DateUtilsThis will require quite a lot of change here are the areas where we need to consider converting from UTC to local when showing the data to the user and visa versa when writing the date into the database: will introduce two functions Here are the places where we need to convert the input string from utc to local time :
And here are the places where we need to convert the UTC to localtime to show the date to the user:
|
@abzokhattab have you tested that? I don't think that is the correct cause. We don't need to set the status when we are just creating a draft, and when you actually click save it looks like the request is working properly. When you refresh the page after your timer, the status disappears. That leads me to believe that the issue is that we are not pushing the updates to all users properly. IMO this is not a blocker even though it is genuinely broken. The Status feature that we merged was massive, and reverting it is not feasible. I will work on a fix in web-e first thing next week |
@stitesExpensify , I found out the comment wasn't working, so I hid it. After testing, I think the problem is related to time zones. I tried using a date from 6 hours ago, but the status was not cleared after that time had passed. However, when I checked it just now, the status was updated. It seems there's a mismatch in how the time zone is interpreted. I suspect the server, where the backend is running, is in the USA, causing the entered date to be parsed as a US date. This might be delaying the job trigger by a few hours. My suggestion is to send the date from the frontend as UTC. This way, the backend can accurately parse and handle it. Additionally, it's worth noting that the backend doesn't have information about the client's timezone. The time string is sent to the backend without specifying the zone. In the provided data sample for updating the status, there is no information about the client's browser timezone: ![]() To address this, two actions are recommended:
|
Just tried to test it again .. this time the status is not cleared 😂 even after almost 11 hours of the custom date .. so i guess the backend doesnt clear it. If we dont want to tackle the clearing process in the frontend we can prevent the status from being shown up in case the clearTime has passed. |
If we have decided to tackle the status clearing process in the frontend, here is a blueprint for how we can achieve that : inside the User.js file we need to add this function that would return the current status and (update it if the clear date has passed): function getUserStatus(userPersonalDetails) {
const statusEmojiCode = lodashGet(userPersonalDetails, 'status.emojiCode', '');
const statusText = lodashGet(userPersonalDetails, 'status.text', '');
const statusClearAfter = lodashGet(userPersonalDetails, 'status.clearAfter', '');
if (statusClearAfter !== '' && new Date(statusClearAfter) < new Date()) {
if (userPersonalDetails.accountID === currentUserAccountID) {
clearCustomStatus();
clearDraftCustomStatus();
}
return {
emojiCode: '',
text: '',
clearAfter: '',
};
}
return {
emojiCode: statusEmojiCode,
text: statusText,
clearAfter: statusClearAfter,
};
} then we need to replace this: with: const statusData = User.getUserStatus(currentUserPersonalDetails);
const currentUserEmojiCode = lodashGet(statusData, "emojiCode", "");
const currentUserStatusText = lodashGet(statusData, "text", "");
const currentUserClearAfter = lodashGet(statusData, "clearAfter", ""); same here: change it to: const status = User.getUserStatus(currentUserDetails);
const emojiCode = status.emojiCode; and here change this: to: const { avatar, login, pendingFields, fallbackIcon } = personalDetails[actorAccountID] || {};
const status = User.getUserStatus(personalDetails[actorAccountID]); and change this: to: const emojiStatus = User.getUserStatus(currentUserPersonalDetails).emojiCode; and finally change this: to const statusData = User.getUserStatus(optionItem);
const emojiCode = lodashGet(statusData, "emojiCode", "");
const statusText = lodashGet(statusData, "text", "");
const statusClearAfterDate = lodashGet(statusData, "clearAfter", ""); OR alternatively we can make the above change on connecting to the App so it will update status if needed as we currently do with the timezone ResultScreen.Recording.2023-12-17.at.2.26.59.AM.mov |
Seems a backend issue where the status is not cleared after time expiration and the pusher event isn't receieved. |
I agree |
I think there are actually 2 issues here. One is that we aren't sending the time to the server in UTC (frontend bug), and the second is that the user who set the status does not get a pusher notification (backend bug). When the bedrock job gets created on the server, it uses local time so if you are west of UTC it runs instantly and clears your status, and if you are east of UTC it happens late. Your status also disappears for other users, but not you. |
Job added to Upwork: https://www.upwork.com/jobs/~013df2712d0a3d5327 |
will be ready tonight i believe |
Nice! @abdulrahuman5196 to get ready for review |
PR changes are ready .. will post the videos today. |
bump @abzokhattab |
The pr is ready.. thanks |
Nice, thank you! @abdulrahuman5196 to review! |
bump @abdulrahuman5196 |
We are working on PR review. Still issues to solve. |
Any progress on that PR? |
We are facing issues currently, Waiting on @stitesExpensify response for here #35976 (comment) |
@stitesExpensify any chance you've been able to tackle/ @abdulrahuman5196 ETA? |
Not yet. This is held on me but it is not a priority at the moment unfortunately |
Closing as low priority |
@dylanexpensify I think that we should pay out for this issue. There was a lot of back and forth as well as development/reviewing time |
Apologies both! Yes, will do! |
Payment summary:
Please request/apply! |
Thank you @dylanexpensify i have just applied |
offer sent @abzokhattab |
Awesome .. just accepted the offer |
@dylanexpensify I have also applied. |
@dylanexpensify Gentle ping on the above |
Received payment |
If you haven’t already, check out our contributing guidelines for onboarding and email [email protected] to request to join our Slack channel!
Version Number: 1.4.13-0
Reproducible in staging?: Y
Reproducible in production?: N
If this was caught during regression testing, add the test name, ID and link from TestRail:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Expensify/Expensify Issue URL:
Issue reported by: Applause - Internal Team
Slack conversation:
Issue found when executing PR #24620
Action Performed:
Precondition: user should be Signed In
Expected Result:
The status should be cleared when the clear timer has elapsed
Actual Result:
Please choose a time at least one minute ahead" error message is displayed, and the emoji status remains when the clear status timer has elapsed
Workaround:
Unknown
Platforms:
Which of our officially supported platforms is this issue occurring on?
Screenshots/Videos
Add any screenshot/video evidence
Bug6313647_1702589216993.Screen_Recording_2023-12-14_at_19.48.49.mp4
View all open jobs on GitHub
Upwork Automation - Do Not Edit
The text was updated successfully, but these errors were encountered: