Skip to content

Shubham Jakhete - Phase 1: Finishing followup fixes for PR 4558+1953: Fix Dark Mode, Date Selection, Time Selection and Scheduling the post for Mastodon (frontend) - #5593

Merged
one-community merged 5 commits into
developmentfrom
shubham-mastodon-scheduling
Oct 11, 2026
Merged

one-community merged 5 commits into
developmentfrom
shubham-mastodon-scheduling

Conversation

@shubhamjakhete

@shubhamjakhete shubhamjakhete commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Description

Bug list: "Phase 1: Finishing Followup fixes for the PR 4558+1953 Fix Dark Mode, Date Selection, Time Selection and Scheduling the post for Mastodon" (priority high, Yeshwanth).

Issues found when testing the Mastodon composer (Other Links → Send Emails → Mastodon):

  1. Dark mode was not implemented.
  2. Date selection from the calendar was not working.
  3. Time selection could not be completed.
  4. Scheduling a post failed with an error popup.

Causes on the frontend:

  • The composer called fetch('/api/mastodon/...') on the frontend's own address, so requests never reached the backend (locally the Vite proxy also strips /api; on Netlify the request returns index.html).
  • The composer imported SocialMediaComposer.module.css but used plain class names, so none of its styles were applied: the sub-tabs ran together as "ComposerScheduledHistoryDetails", the inputs were unstyled, and the existing dark styles never applied. They also only followed the operating system's dark mode, not the app's.
  • Editing a scheduled post read the date in UTC but the time in local time, so evening posts in Pacific time moved forward a day.

Related PRS (if any):

This frontend PR is related to backend PR OneCommunityGlobal/HGNRest#2373.
To test this frontend PR you need to check out backend PR OneCommunityGlobal/HGNRest#2373.
Builds on #4558 and OneCommunityGlobal/HGNRest#1953.

Main changes explained:

  • src/utils/URL.js: add MASTODON_POST, MASTODON_SCHEDULED_POSTS, MASTODON_SCHEDULED_POST_BY_ID, and MASTODON_POST_HISTORY, following the LinkedIn entries.
  • SocialMediaComposer.jsx:
    • Replace all fetch('/api/mastodon/...') calls with axios and the new endpoints, which sends the logged-in user's token.
    • Show the backend's error message when a request fails (for example "Scheduled time must be in the future").
    • When editing a scheduled post, delete the old version only after the new one is saved, so a failed save never loses the post.
    • Use the CSS module classes throughout (styles['post-card'], etc.). Bootstrap button classes are unchanged.
    • Read dark mode from the app (state.theme.darkMode) and add a composer-dark class.
    • Label the schedule date and time inputs for screen readers.
  • SocialMediaComposer.module.css:
    • Convert the prefers-color-scheme: dark block to .composer-dark rules so dark mode follows the app's setting.
    • Use color-scheme: dark on the date and time inputs so the calendar and clock popups and icons are drawn in dark colors.
    • Make placeholder text readable in dark mode, and move the Confirmation Preferences box's inline white background into module classes with a dark variant.
  • scheduleTime.js: new helper that reads a scheduled post's date and time in local time for editing.
  • Tests: API calls (schedule, backend error message, missing date/time, loading scheduled posts and history), CSS module and dark mode classes, and local date/time conversion. 14 Announcements tests pass.

How to test:

  1. Check out this branch and backend PR Shubham Jakhete - Phase 1: Finishing followup fixes for PR 4558+1953: Fix Dark Mode, Date Selection, Time Selection and Scheduling the post for Mastodon (backend) HGNRest#2373 (see its description for the Mastodon test account and .env setup).
  2. Run npm install, then npm run start:local.
  3. Clear site data/cache and log in as an Admin or Owner.
  4. Go to Other Links → Send Emails → Mastodon.
  5. Verify:
    • Composer, Scheduled, History, and Details show as separate tabs and the composer is styled.
    • The calendar and clock pickers can be used to choose a date and time.
    • Post Now sends a post; it appears on Mastodon and in the History tab.
    • Schedule a post for 2–3 minutes ahead; it shows on the Scheduled tab, then posts to Mastodon at that time.
    • Edit a scheduled post set for the evening; the composer shows the same date.
    • Scheduling with a past time shows the backend's error message.
  6. Log in as a Volunteer and verify the Send Emails page and the Mastodon routes are not available.
  7. Verify every tab (including the date and time popups and the Details box) in [dark mode](https://docs.google.com/document/d/11OXJfBBedK6vV-XvqWR8A9lOH0BsfnaHx01h1NZZXfI).

Screenshots or videos of changes:

Screenshot 2026-09-28 at 4 18 36 PM Screenshot 2026-09-28 at 4 18 22 PM

The Mastodon composer called /api/mastodon/... on the frontend's own
address, so requests never reached the backend and scheduling always
failed with an error popup.

- Add Mastodon endpoints to URL.js and call them with axios, which
  sends the logged-in user's token
- Show the backend's error message when a request fails
- When editing a scheduled post, delete the old version only after
  the new one is saved
- Label the schedule date and time inputs for screen readers
- Add tests for scheduling and loading scheduled posts and history
The composer imported its CSS module but used plain class names, so
none of its styles were applied: the sub-tabs ran together as one
line of text and dark mode never worked.

- Use the CSS module classes throughout the composer
- Switch dark mode on from the app's dark mode setting instead of the
  operating system's
- Draw the date and time pickers in dark colors in dark mode
- Make placeholder text readable in dark mode
- Add tests for the tab classes and dark mode
The preferences box on the Details tab used an inline white
background, so in dark mode its light text was unreadable. Move its
styles into the CSS module with a dark variant.
Editing a scheduled post read the date in UTC but the time in local
time. For evening posts in Pacific time the UTC date is already the
next day, so the post moved forward a day when saved.

- Read the date and time together in local time
- Add tests for evening times and leading zeros
@netlify

netlify Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for highestgoodnetwork-dev ready!

Name Link
🔨 Latest commit a9ac10a
🔍 Latest deploy log https://app.netlify.com/projects/highestgoodnetwork-dev/deploys/6ac82e12032dc200081803ed
😎 Deploy Preview https://deploy-preview-5593--highestgoodnetwork-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

AaditTrivedi
AaditTrivedi previously approved these changes Sep 30, 2026

@AaditTrivedi AaditTrivedi left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reviewed by Aadit Trivedi.

How I verified
Checked out shubham-mastodon-scheduling and tested locally against the staging backend as Admin and Volunteer, reviewed the diff, and ran the new tests. I did not test Post Now or scheduling a real post end to end: that needs backend #2373 and the Mastodon test account, and staging does not have #2373.

Verified working

  • Scope matches the description: 7 files, all in the Mastodon composer, its CSS module, its tests, and URL.js.
  • Tests: npx vitest run src/components/Announcements/platforms/social passes 11/11 across the three new test files.
  • Composer, Scheduled, History, and Details show as separate, styled tabs.
  • The date and time pickers work.
  • Scheduling with a past date shows "Scheduled time must be in the future."
  • Dark mode follows the app setting: all four tabs, the date and time popups, and the Details preferences box are readable.
  • Volunteer accounts do not see Send Emails in the menu.
  • Time zone handling: toScheduleInputValues reads the saved time with local getters, and scheduling builds the time with new Date(\${scheduleDate}T${scheduleTime}`)before converting withtoISOString()`, so both reading and saving use local time correctly.
  • On staging without #2373, History shows "Failed to load post history," as expected.

Pointers, not blocking

  1. Test step 1 still says "HGNRest#BACKEND"; it should reference HGNRest #2373.
  2. The past-time check runs in the browser before any request (line 258), so the message comes from the frontend, not the backend as test step 5 describes. Same wording, so users see the same thing.
  3. When editing a scheduled post, the new version is saved and then the old one is deleted. If the delete fails after the save succeeds, both versions remain scheduled and both would publish. Consider telling the user or retrying the delete.
  4. On staging, History shows a load error but Scheduled shows "No scheduled posts yet." If the scheduled request can fail the same way, the Scheduled tab may be showing an empty list instead of an error. Worth confirming.

Evidence
Tabs and composer, light mode:
image
Dark mode with the date picker open:
image
Past-time error:
image

Approving.

@adit24dhaya adit24dhaya left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I reviewed 2896010 with its explicitly paired backend #2373 at 9fb3ee10. The frontend request routing, CSS-module binding, app-controlled dark mode and local-time conversion check out. I haven't repeated AaditTrivedi's existing edit/delete and scheduled-load feedback.

I'm holding approval of the paired scheduling feature for a separate backend integration blocker: #2373 starts the existing minute scheduler in server.js, but overlapping callbacks can publish the same due record twice. A successful publication followed by a failed delete also leaves it eligible for a second publication on the next tick. Both paths reproduce with the real scheduler, while the frontend browser fixture sends just one correctly formed scheduling request. The fix belongs in #2373; this is not a second diagnosis of the frontend edit/delete issue.

Please address the paired scheduler's claim/idempotency and post-success recovery before this scheduling feature is considered merge-ready. I've put the concrete source-level feedback on the backend review rather than repeating an inline comment here.

Validation: 11/11 existing frontend tests in three files passed on Node 20.19.4. I checked the actual composer in light/dark browser fixtures: separate tab labels, app-controlled dark class, dark native date control, one request to /api/mastodon/schedule, correct content and local-to-UTC time. Frontend build passed with 9,176 modules; changed-JS ESLint zero errors/three warnings, CSS Stylelint and git diff --check passed. Paired backend: 13/13 existing tests and ten additional scheduler reproduction/control assertions; Babel compiled 773 files and ESLint had zero errors/18 warnings. Requests, persistence and external publications were mocked. No backend server, database write or real Mastodon post was used; live account/scopes and authenticated role navigation remain unverified.

scheduler-evidence

Commit audit: the four commits are focused, imperative, under 72 characters, without trailing periods, and have blank-separated what/why bodies. Optional documentation cleanup: add the relevant issue/PR reference to future commit bodies; the placeholder #BACKEND test-step issue is already noted by Aadit.

@RichaSapre RichaSapre left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Tested locally together with backend PR #2373. The main Mastodon flows worked as expected: Composer/Scheduled/History/Details tabs and styling, light/dark mode, date/time pickers, Post Now, scheduled posting, past-time validation, editing an evening scheduled post without shifting the date, failed-edit preservation of the original scheduled post, deletion, and Volunteer access restrictions.

I found two code-review concerns:

  1. The newly added console.error calls are being flagged by the PR check as unexpected console statements.
  2. During an edit, the new scheduled post is created before the old scheduled post is deleted. If creation succeeds but deletion of the old post fails, it looks possible for both versions to remain scheduled while the UI reports “Failed to schedule post.” Could that partial-failure case be handled separately or recovered from?

Testing/setup note: following the Mastodon setup instructions with only write:statuses and write:media caused an “outside the authorised scope” error when opening History. Adding the required read scope resolved it. It would be helpful to update the testing instructions with the complete required scopes.

Attached screenshots from local testing showing the Mastodon UI in light/dark mode and successful posting/scheduling behavior.

Image Image Image

setScheduledPosts(data || []);
} catch (err) {
if (process.env.NODE_ENV === 'development') {
console.error('Error loading scheduled posts:', err);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Could we remove this console.error or use the project’s existing logging approach instead? The PR check is currently flagging it as an unexpected console statement. Same applies to the similar console.error below.

// so a failed save never loses the original post.
if (editingPostId) {
await fetch(`/api/mastodon/schedule/${editingPostId}`, { method: 'DELETE' });
await axios.delete(ENDPOINTS.MASTODON_SCHEDULED_POST_BY_ID(editingPostId));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What happens if the new scheduled post is saved successfully but deleting the old post fails? It looks like both versions could remain scheduled, while the catch block reports “Failed to schedule post.” Should the delete failure be handled separately so we avoid duplicate scheduled posts or provide a more accurate recovery/error state?

@iAbhi001
iAbhi001 self-requested a review October 3, 2026 20:58

@iAbhi001 iAbhi001 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

PR Review & Testing Feedback

I tested this locally alongside backend PR #2373, and the core Mastodon flows worked as expected.

✅ Verified Working Flows

  • Tabs & Styling: Composer, Scheduled, History, and Details tabs, along with styling and light/dark mode.
  • Functionality: Date/time pickers, Post Now, scheduled posting, past-time validation, and deletion.
  • Edge Cases: Editing an evening scheduled post without shifting the date, preserving the original scheduled post on failed edits, and Volunteer access restrictions.

🔍 Code-Review Concerns & Questions

  1. Unexpected Console Statements: The newly added console.error calls are currently being flagged by PR checks.
  2. Scheduled Post Edit Race Condition / Partial Failure: During an edit, the new scheduled post is created before the old one is deleted. If creation succeeds but deletion fails, both versions could potentially remain scheduled while the UI reports a "Failed to schedule post" error. Can this partial-failure case be handled separately or rolled back/recovered from?

📝 Documentation Note

Following the Mastodon setup instructions with only write:statuses and write:media triggered an “outside the authorised scope” error when opening the History tab. Adding the required read scope resolved the issue.

Suggestion: It would be helpful to update the setup instructions to include the complete set of required scopes.


(Attached screenshots from local testing showing the Mastodon UI in light/dark mode and successful posting/scheduling behavior.)

Image Image

shubhamjakhete pushed a commit to OneCommunityGlobal/HGNRest that referenced this pull request Oct 4, 2026
The scheduler found due posts, published each one and then deleted it,
with no claim. This PR starts the scheduler on every server process, so
an overlapping run or a second server could publish the same post again,
and a failed delete after a successful post left it due for the next
run.

- Claim each due post atomically with findOneAndUpdate, moving it from
  pending to publishing with a lease, so only one worker sends it
- Record a successful post as posted with its Mastodon status ID instead
  of deleting it
- Mark a post failed, not resent, if its claim expires before delivery
  is recorded or the request times out
- Retry clear Mastodon rejections (429, 5xx) on later runs, up to three
  attempts
- Send a stable Idempotency-Key with each post
- Hide posted records from the Scheduled list and only allow deleting
  pending or failed posts
- Add tests for overlapping runs, two workers and a failed save after a
  successful post

Related to OneCommunityGlobal/HighestGoodNetworkApp#5593

@PrajwalpGM256 PrajwalpGM256 left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reviewed by Prajwal.

Tested locally on Windows with backend PR #2373. Works well; requesting one small fix to the testing steps.

What I verified

  1. Tabs and styling. Composer, Scheduled, History, and Details render as separate styled tabs, and the DOM shows CSS Module classes applied (for example _tab-button_16wgl_59, _active_16wgl_103).
Image

html

<div class="_tabs-container_16wgl_41">
  <button class="_tab-button_16wgl_59 ">Composer</button>
  <button class="_tab-button_16wgl_59 _active_16wgl_103">Scheduled</button>
  ...
</div>
  1. Requests reach the backend with login. Calls go to localhost:4500/api/mastodon/... with the Authorization header.

  2. Functional flows work: Post Now, scheduling, editing, and deleting.

  3. Error handling: scheduling in the past shows the backend's message; stopping the backend during an edit shows an error and keeps the original post; empty, whitespace only, and over 500 characters show clear messages.

  4. Duplicates: rapid repeated edits and double clicks produce a single scheduled post and one Mastodon post.

  5. Dark mode: works on all tabs, both pickers, the Details box, and modals, and switches live without a reload.

  6. No CSS leakage: other pages look unchanged after using the composer.

  7. Tests pass: 4 files, 14 tests.

Test Files 4 passed (4)
Tests 14 passed (14)

Required change

Placeholder in How to test. Step 1 says HGNRest#BACKEND; please replace it with #2373.

Note :

The History tab shows "This action is outside the authorized scopes". This is a Mastodon token scope issue in the backend setup steps, documented on backend PR #2373, not a frontend bug.

Image

shubhamjakhete added a commit to OneCommunityGlobal/HGNRest that referenced this pull request Oct 8, 2026
Two failure cases could still publish a scheduled post twice or after
it was deleted (review on #2373):

- A slow image upload could outlast the claim. Another run then marked
  the post failed, the user could delete it, and the original worker
  still published it once the upload finished.
- A gateway or server error (5xx) can come back after Mastodon has
  accepted the post. It was put back in pending and retried, so a
  retry sent after the Idempotency-Key expired (Mastodon keeps it for
  up to one hour) could publish it a second time.

Changes:

- Renew the claim right before the status request and skip the post
  if the claim was lost, so an expired or deleted post is never sent
- Pass the 30-second request timeout to the image upload and alt text
  requests, which had no timeout
- Retry only 429 responses, where nothing was posted. Mark 5xx
  responses failed with lastError, like timeouts, so the user can
  reschedule instead of risking a duplicate
- Add regression tests for the expired-and-deleted post, each 5xx
  status, a retry after the key window, and the 429 retry limit

Refs #2373, OneCommunityGlobal/HighestGoodNetworkApp#5593
Follow-up to review on #5593 and the scheduler changes in
OneCommunityGlobal/HGNRest#2373.

- Editing a scheduled post saves the new version, then deletes the
  old one. If the delete failed, both stayed scheduled while the UI
  said "Failed to schedule post." Report that case on its own: the
  changes were saved and the older version must be deleted
- Show an error on the Scheduled tab when the list fails to load,
  instead of "No scheduled posts yet"
- The backend now marks a post failed when delivery can't be
  confirmed and does not retry it. Show failed posts with their
  error so the user can reschedule, and disable actions on a post
  that is being published
- Remove the console.error calls flagged by the lint check
- Add tests for the edit cases, the load error, and failed and
  publishing posts

Refs #5593, OneCommunityGlobal/HGNRest#2373
@sonarqubecloud

sonarqubecloud Bot commented Oct 8, 2026

Copy link
Copy Markdown

@shubhamjakhete

Copy link
Copy Markdown
Contributor Author

Pushed to address the review feedback:

17/17 tests pass in the Mastodon composer suites. The new tests mock the API calls.

@Niket07pathak Niket07pathak left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reviewed by Niket Pathak

How I verified

Checked out frontend PR #5593 and tested the Mastodon composer locally with the required frontend/backend setup. Tested the functionality using Admin/Owner and Volunteer roles, verified post creation and scheduling, date/time selection, scheduled post editing, validation scenarios, and UI behavior in light and dark modes.

Verified working

  • Composer, Scheduled, History, and Details tabs are properly styled, separated, and functional.
  • Calendar and time pickers work correctly and retain selected values.
  • Light and dark modes display correctly across all tabs, input fields, calendar/clock popups, and Confirmation Preferences.
  • Future posts can be scheduled successfully, appear in the Scheduled tab, and publish at the scheduled time.
  • Editing an evening scheduled post preserves the correct local date and time, and changes persist.
  • Scheduling a post in the past displays the appropriate backend validation message.
  • Missing date/time inputs are handled with proper validation without crashes.
  • Failed edits do not delete or overwrite the original scheduled post.
  • Volunteer users cannot access the restricted Send Emails page or Mastodon routes, including through direct URLs.

Issues found

No issues were observed during the completed tests.

Evidence

Image Image

Required action

No changes requested based on the completed tests.

Approved

@adit24dhaya adit24dhaya left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks, Shubham. I rechecked a9ac10a7 with backend #2373 at 86f04fc5. The scheduler blockers from my earlier review are fixed.

The frontend now gives a clear warning when the new version saves but the original cannot be deleted, and keeps the original when saving fails. Scheduled-list failures show an error, failed posts show the delivery message, and publishing posts have their actions disabled. Evening edits keep the same local date and time.

Validation: 17/17 frontend tests passed, plus 10 actual-component browser scenarios with 78 assertions across light and dark modes. The build, changed-file ESLint, Stylelint and whitespace checks passed. Paired backend: 27 tests and 10 independent scheduler scenarios passed. API calls and persistence were mocked; no real posts or shared database writes were made, and this was not a live authenticated account test.

Approving. The partial-edit warning still requires the user to remove the older version; it does not automatically roll back the edit.

Commit audit: the follow-up is focused, has a 62-character imperative subject without a final period, and explains what/why in a blank-separated body with references to both PRs.

@iAbhi001
iAbhi001 self-requested a review October 11, 2026 05:09

@iAbhi001 iAbhi001 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Rechecked the branch alongside backend PR #2373, and the scheduler blockers from before are resolved.

The frontend handles save failures cleanly now, showing a clear warning if an older version cannot be removed while preserving the original when saves fail. Error messaging on the scheduled list looks good, failed posts display the delivery note properly, publishing states lock action buttons, and evening edits keep the right local timestamps.

All frontend and backend unit tests pass, browser checks hold up across light and dark themes, and linting passes with zero issues. Tested everything with mocked APIs so dev data stayed untouched.

Quick note that the partial edit alert prompts the user to delete the previous version manually rather than auto reverting, but the flow itself is solid. Approving! Thanks, Shubham.

Image

@AaditTrivedi AaditTrivedi left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Re-reviewed by Aadit Trivedi.

The Oct 8 commit "Report partial edits and failed scheduled posts" addresses two pointers from my earlier review:

  • When loading scheduled posts fails, the Scheduled tab now shows an error (scheduledLoadError) instead of an empty list that could be mistaken for having no scheduled posts.
  • Edits now report failures, including the partial case where the new version saves but the old one isn't removed.

Ran npx vitest run src/components/Announcements/platforms/social: 17/17 passing, including the new tests for these cases. Everything else from my earlier approval still holds.

Approving.

@one-community

Copy link
Copy Markdown
Member

Thank you all, merging!

@one-community
one-community merged commit 26ed14d into development Oct 11, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

High Priority - Please Review First This is an important PR we'd like to get merged as soon as possible

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants