Skip to content

CCCT-2542 Add Connect Progress Card View - #3812

Open
OrangeAndGreen wants to merge 9 commits into
masterfrom
CCCT-2542-connect-progress-and-status-card
Open

CCCT-2542 Add Connect Progress Card View#3812
OrangeAndGreen wants to merge 9 commits into
masterfrom
CCCT-2542-connect-progress-and-status-card

Conversation

@OrangeAndGreen

@OrangeAndGreen OrangeAndGreen commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

CCCT-2542

Technical Summary

Adds ConnectProgressCard, a reusable Connect view intended for both the Learning Progress and Delivery Progress screens. It composes existing sub-views — an optional semi-circle indicator, a horizontal progress bar (label, count, caption), and an independently controllable info-message banner with an optional CTA — with appearance driven entirely by content properties rather than a state enum. Not yet wired into any live screen; this PR is the building block only.

Independently-controllable pieces:

  • Title visibility
  • Semi-circle progress visibility
  • Disabled (grayed out) state
  • Blue message appendage at bottom of card
  • CTA visibility in blue message

Screenshots

Learning progress:
image
Delivery progress:
image

Disabled state with message and CTA:
Disabled

Safety Assurance

Safety story

What gives confidence:

  • I added demo cards to the Learning Progress page to test the visible functionality (see screenshots above)
  • I ran the ConnectProgressCardTest Robolectric suite locally and it passed, and rendered the card in a layout preview/harness to check appearance.
  • The sync removal + rename is a self-contained, mostly-deletion change verified by the trimmed test suite; the class has no live-screen consumers, so there is effectively no blast radius for existing users.
  • The rest of the diff is additive and self-contained: a new view class, its layout/attr/style resources, and its test. No existing files change behavior.

Risks to review:

  • Because the card is not yet integrated into a real screen, its behavior in context (layout under real data, interaction with surrounding views) has only been exercised in a preview harness, not in the actual Learning/Delivery flows.

Automated test coverage

ConnectProgressCardTest covers property-to-view bindings, progressCurrent clamping to progressMax (including setting current before max), the contentEnabled gray-out of the progress text and semi-circle, optional-content visibility (title, label, caption, count), the info-message/CTA banner and its click listener, attribute inflation, and per-instance color overrides.

@OrangeAndGreen OrangeAndGreen self-assigned this Jul 15, 2026
@OrangeAndGreen

Copy link
Copy Markdown
Contributor Author

Suggested Review Order

  • app/res/values/attrs.xml — declares the styleable attributes the view exposes; orients the rest
  • app/res/layout/view_connect_progress_and_status_card.xml — the layout structure the view inflates and binds to
  • app/src/org/commcare/views/connect/ConnectProgressAndStatusCard.kt — core logic tying attributes and layout together
  • app/unit-tests/.../ConnectProgressAndStatusCardTest.kt — documents intended property/appearance behavior
  • app/res/drawable/bg_connect_progress_info_message.xml, app/res/drawable/bg_connect_sync_badge.xml, app/res/values/colors.xml, app/res/values/strings.xml (+ translations) — supporting resources, read last

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Introduces a reusable ConnectProgressAndStatusCard custom view with configurable progress, sync status, content state, informational messaging, and CTA behavior. Adds its layout, drawable resources, XML attributes, colors, and localized progress-count strings. The implementation supports XML initialization, progress calculations, conditional visibility, sync warning styling, and content color changes. Robolectric tests cover property updates, progress behavior, styling, CTA clicks, and attribute inflation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant XMLLayout
  participant ConnectProgressAndStatusCard
  participant ProgressStatusViews
  XMLLayout->>ConnectProgressAndStatusCard: inflate attributes and initial content
  ConnectProgressAndStatusCard->>ProgressStatusViews: update text, visibility, and progress
  ConnectProgressAndStatusCard->>ProgressStatusViews: apply sync badge and content colors
Loading

Possibly related PRs

Suggested reviewers: shubham1g5, jignesh-dimagi

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly matches the main change: adding a new Connect progress card view.
Description check ✅ Passed The description covers technical summary, safety story, and tests, but it omits the Product Description and Labels and Review sections from the template.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch CCCT-2542-connect-progress-and-status-card

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 27.29%. Comparing base (3c7f531) to head (ca0462c).
⚠️ Report is 45 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3812      +/-   ##
============================================
+ Coverage     26.85%   27.29%   +0.44%     
- Complexity     4706     4773      +67     
============================================
  Files           988      991       +3     
  Lines         58844    59019     +175     
  Branches       7003     7025      +22     
============================================
+ Hits          15801    16111     +310     
+ Misses        41131    40974     -157     
- Partials       1912     1934      +22     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@OrangeAndGreen
OrangeAndGreen marked this pull request as ready for review July 16, 2026 17:35
@Jignesh-dimagi

Copy link
Copy Markdown
Contributor

Currently, consumers have to manually bind each individual property of the card to configure it correctly:

card.titleText = data.title
card.progressLabel = data.label
card.progressMax = data.total
card.progressCurrent = data.completed
// and so on...

This imperatively coupled approach leaves room for developers to accidentally miss properties, which can easily lead to inconsistent UI states or bugs.

Can we encapsulate this into a single, cohesive UI State model instead? We could introduce a State data class and expose a single bind method on the component:

data class State(
    val title: CharSequence? = null,
    val progressLabel: CharSequence? = null,
    val progressCurrent: Int = 0,
    val progressMax: Int = 0,
    val progressCaption: CharSequence? = null,
    val contentEnabled: Boolean = true,
    val semiCircle: SemiCircle? = null,
    val sync: Sync? = null,
    val info: Info? = null,
) {
    data class SemiCircle(
        val current: Int,
        val max: Int,
        val description: CharSequence? = null,
    )

    data class Sync(
        val status: SyncStatus,
        val text: CharSequence,
        val subtext: CharSequence? = null,
    )

    class Info(
        val message: CharSequence,
        val ctaText: CharSequence? = null,
        val onCtaClick: (() -> Unit)? = null,
    )
}

This allows the consumer to bind the entire view state safely in a single atomic update:

card.bind(
    ConnectProgressAndStatusCard.State(
        title = data.title,
        progressCurrent = data.completed,
        progressMax = data.total,
        contentEnabled = data.isActive,
        semiCircle = if (data.showSemiCircle) {
            State.SemiCircle(data.completed, data.total, data.semiCircleLabel)
        } else null,
        sync = data.syncMessage?.let {
            State.Sync(
                status = if (data.hasSyncProblem) SyncStatus.WARNING else SyncStatus.UP_TO_DATE,
                text = it,
                subtext = data.lastSynced,
            )
        },
        info = data.banner?.let {
            State.Info(it, data.ctaLabel, onCtaClick = { openMoreInfo() })
        },
    ),
)

Comment thread app/src/org/commcare/views/connect/ConnectProgressAndStatusCard.kt Outdated
@shubham1g5

Copy link
Copy Markdown
Contributor

Based on screenshots, think this PR is implementing outdated/under-iteration designs for task and sync cards, both seems to be undergoing changes in latest iterations. Curious if it's not clear from the Solutions Summary that these cards were going through iterations, product is supposed to mark things getting iterated clearly on this doc and if it's not marked correctly think we should be loud and flag it to product on slack that we are repeatedly implementing Outdated designs due to lack of clarity.

@OrangeAndGreen

Copy link
Copy Markdown
Contributor Author

Based on screenshots, think this PR is implementing outdated/under-iteration designs for task and sync cards, both seems to be undergoing changes in latest iterations. Curious if it's not clear from the Solutions Summary that these cards were going through iterations.

@shubham1g5 Ah, the tasks message part is my mistake, I knew that was being discussed and left it out of the initial work, then when testing the implementation saw it missing, forgot it was intentional, and added it in. But for the sync part of the card, I don't see any indication in the Solutions Summary section about that being in flux, and based on your link it seems the only good source for that discussion right now is in the Playground section in Figma (really just a side effect of moving the tasks message around). So maybe there's some room for improvement in communicating which parts aren't finalized.

Should we move this ticket to blocked until the design is finalized?

@shubham1g5

Copy link
Copy Markdown
Contributor

So maybe there's some room for improvement in communicating which parts aren't finalized.

Got it, are you able to flag it to Kim so that she is aware of these gaps.

Should we move this ticket to blocked until the design is finalized?

We should just remove the tasks and syncs card out of scope of this ticket and tackle them as other tickets as we need this work to be merged sooner than later to be able to make progress on the rest of the phase 1 work.

@OrangeAndGreen OrangeAndGreen changed the title CCCT-2542 Add Connect Progress And Status Card View CCCT-2542 Add Connect Progress Card View Jul 22, 2026
Comment thread app/res/layout/view_connect_progress_card.xml Outdated
Comment thread app/src/org/commcare/views/connect/ConnectProgressCard.kt Outdated
Comment thread app/res/values/strings.xml
@shubham1g5

Copy link
Copy Markdown
Contributor

would be nice to clean up commit history on this PR as well

@conroy-ricketts conroy-ricketts left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks fantastic! Just had a few comments

Comment thread app/res/layout/view_connect_progress_card.xml Outdated
Comment thread app/res/values/styles.xml
<item name="descriptionTextColor">@color/connect_text_color</item>
</style>

<style name="Widget.CommCare.ConnectProgressCard" parent="">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Curiosity question: what's the intention behind explicitly defining an empty parent here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I learned a bit here as well. When a style use dot notation like this one, parent styles are automatically inherited from the parent component (i.e. Widget.CommCare here). Setting parent="" disables the behavior so nothing is inherited (preventing possible surprises later if something in the parent widget changes, even though in this case there isn't one right now).

Comment thread app/src/org/commcare/views/connect/ConnectProgressCard.kt Outdated
Comment thread app/src/org/commcare/views/connect/ConnectProgressCard.kt Outdated
Comment thread app/src/org/commcare/views/connect/ConnectProgressCard.kt Outdated
Comment thread app/unit-tests/src/org/commcare/views/connect/ConnectProgressCardTest.kt Outdated
Comment thread app/unit-tests/src/org/commcare/views/connect/ConnectProgressCardTest.kt Outdated
OrangeAndGreen and others added 3 commits July 24, 2026 13:39
Add ProgressUtils.calculateProgress(current, max) and reuse it in
SemiCircleProgressBar and ConnectProgressJobSummaryAdapter, replacing the
duplicated max>0 fraction guard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reusable Connect card composing a semi-circle indicator, a horizontal progress
bar with label/count/caption and an optional info-message banner with a CTA.
The whole card is configured atomically through a single bind(State) so callers
cannot leave it half-configured; out-of-range progress is logged then coerced.
Content colors resolve through a color -> style -> component path and all
dp/sp values live in dimens.xml (LinearProgressBar's corner radius included).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cover title/label/caption visibility, semi-circle and linear progress binding,
count derivation and clamping, contentEnabled recoloring, the info banner and
CTA callback, attribute inflation, and color-attribute overrides.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@OrangeAndGreen
OrangeAndGreen force-pushed the CCCT-2542-connect-progress-and-status-card branch from 02ab984 to 2c0a5fa Compare July 24, 2026 18:47
@OrangeAndGreen
OrangeAndGreen force-pushed the CCCT-2542-connect-progress-and-status-card branch from 4b9f08e to 1843792 Compare July 24, 2026 23:46
…rogress-and-status-card

# Conflicts:
#	app/res/values/styles.xml
shubham1g5
shubham1g5 previously approved these changes Jul 27, 2026
Comment thread app/res/values/dimens.xml
Match node 5940:23149 of the Opportunity Home design: 8dp card corner
radius, 8dp progress bar, 24sp metric, 4dp gaps around the bar, and no
extra top inset when the card has neither a title nor a semi-circle.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

4 participants