[sync] fix(app): collapse the expanded chat panel when clicking a sidebar node T6478 - #3620
[sync] fix(app): collapse the expanded chat panel when clicking a sidebar node T6478#3620tea-artist wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5d24ae0c57
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const userCount = members.filter((m) => m.principalType === PrincipalType.User).length; | ||
| if (await confirmSeat({ role: role as IRole, count: userCount, action: 'invite' })) { |
There was a problem hiding this comment.
Count department members in the seat delta
When the organization selection contains only departments, userCount is zero, so useSeatConfirm returns immediately and skips both the cloud billing confirmation and the EE license limit. Department collaborators grant access to their users—the backend includes a user's organization departments when resolving collaborators—so assigning a billable role to a department can consume multiple seats. Resolve the department's newly billable members instead of filtering departments out; the same zero-seat assumption is present in the base invitation and department role-change handlers.
Useful? React with 👍 / 👎.
| onCreate={async (ro) => { | ||
| if (!(await confirmSeat({ role: ro.role, count: ro.emails.length, action: 'invite' }))) { | ||
| return false; |
There was a problem hiding this comment.
Gate email invitations using the actual seat increase
On an EE instance, ro.emails.length is not necessarily the number of new seats. For example, inviting a user who is already billable through another base or space creates a new collaborator without increasing the instance-wide billable-user count. If the instance is at its seat limit, this calculation rejects that valid invitation because seats + emails.length exceeds the limit. The confirmation needs a server-derived count of newly billable users; the base email flow has the same issue.
Useful? React with 👍 / 👎.
| onUpdate={async (invitationId, role) => { | ||
| if (await confirmSeat({ role, count: 1, action: 'link' })) { | ||
| updateInviteLink({ |
There was a problem hiding this comment.
Avoid charging a seat for billable-to-billable link updates
Updating an existing invitation link from one billable role to another, such as Creator to Editor, does not add a collaborator or consume a seat—the backend only updates the invitation row. Nevertheless this always checks with count: 1, so an EE instance at its seat limit cannot make that role adjustment, and cloud users receive an inaccurate bill-increase confirmation. Compare the existing link role and apply a positive delta only when the transition actually introduces billable access; the base-link handler repeats this behavior.
Useful? React with 👍 / 👎.
| const { confirm, alert } = useConfirm(); | ||
| const queryClient = useQueryClient(); | ||
|
|
||
| const isPaidSpace = isCloud && level != null && level !== BillingProductLevel.Free; |
There was a problem hiding this comment.
Wait for the cloud billing level before allowing the action
On Cloud, level is undefined while useBillingLevel is still fetching, and it remains undefined if that query fails. This classifies the space as unpaid; because isEE is also false, the callback falls through to true. A paid customer who submits an invitation or role change before the usage query resolves therefore bypasses the required bill-increase confirmation. Await or block on the billing query rather than treating an unknown level as Free.
Useful? React with 👍 / 👎.
| queryFn: () => getInstanceUsage().then((res) => res.data), | ||
| staleTime: 0, | ||
| }) | ||
| .catch(() => undefined); |
There was a problem hiding this comment.
Do not fail open when the EE usage request fails
When the instance-usage request fails, this catch converts the error to undefined, leaving seatLimit absent and allowing the callback to return true. During any transient usage-service or network failure, the self-hosted seat-limit dialog and the stated hard stop are therefore bypassed, and the billable mutation is attempted without knowing whether capacity remains. Surface the failure or fail closed instead of silently authorizing the action.
Useful? React with 👍 / 👎.
Coverage Report for CI Build 30447417723Coverage at 58.238% (no base build to compare)Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats💛 - Coveralls |
5d24ae0 to
f0f79a9
Compare
f0f79a9 to
e600e6e
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e600e6e93d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return; | ||
| } | ||
| if (knownCount > 0) { | ||
| ctx.nextGroupPoints.push({ type: GroupPointType.Row, count: knownCount }); |
There was a problem hiding this comment.
Restore nested headers when expanding a parent
When a multi-level group's parent is collapsed, its descendant headers are removed from groupPoints; re-expanding that parent here restores only one aggregate row block and cannot reconstruct those headers. The locally patched state therefore flattens the parent, and useGridAsyncRecords subsequently caches that malformed structure, so on a slow or failed fresh delivery the child groups remain missing and cannot be expanded or collapsed. Preserve the cached subtree for parent expansion, or avoid applying the in-place expansion when only an aggregate count is available.
Useful? React with 👍 / 👎.
| // deliveries re-send a structurally identical list on every page (and | ||
| // after an exact local collapse patch): keep the previous reference so | ||
| // the grid does not rebuild its O(total rows) linear layout for nothing | ||
| setGroupPoints((prev) => (isEqual(prev, freshGroupPoints) ? prev : freshGroupPoints)); |
There was a problem hiding this comment.
Refill row counts on equal server deliveries
After a same-view filter, sort, or row-hiding search change, the layout effect clears groupRowCounts; if the authoritative delivery has structurally equal group points—which is common when sorting within groups or when a filter preserves each group's count—this equality branch retains the old state reference, so the effect that collects counts never runs again. Collapsing a group then omits its now-missing count, and re-expanding it takes the unknown-size path that drops every loaded row behind it until another delivery arrives. Refresh the count cache from every authoritative delivery even when the React layout state can retain its reference.
Useful? React with 👍 / 👎.
e600e6e to
49b46d0
Compare
49b46d0 to
d6ab6e0
Compare
d6ab6e0 to
bee7cb1
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bee7cb196b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| }) | ||
| } | ||
| onCreate={async (role) => { | ||
| if (await confirmSeat({ role, count: 1, action: 'link' })) { |
There was a problem hiding this comment.
Do not reserve an EE seat when creating an invitation link
On an EE instance already at its seat limit, this count: 1 makes useSeatConfirm reject creating a billable-role link even though link creation consumes no seat: InvitationService.generateInvitationLink only creates the invitation, while a collaborator is added later by acceptInvitationLink. The eventual accepter may also already be billable, so capacity cannot be determined at link-creation time; retain the Cloud warning but do not apply the EE seat-delta gate here. The space-link creation handler has the same problem.
Useful? React with 👍 / 👎.
| const isInIframe = useIsInIframe(); | ||
| const [dismissed, setDismissed] = useState(false); | ||
|
|
||
| if (!isHydrated || !isMobile || isInIframe || dismissed) { |
There was a problem hiding this comment.
Hide the mobile operation bar for explicit embed URLs
When a ?embed=... share URL is opened outside an actual iframe on a viewport at or below 640px, isInIframe is false and this condition renders the fixed edit/save bar. The share view components consistently treat the query parameter itself as embed mode and suppress their headers, so a direct embed preview or new-tab embed now gains an operation overlay despite requesting chrome-free embed output. Check router.query.embed here in addition to the window iframe state.
Useful? React with 👍 / 👎.
| const handleUpdateRole = useCallback( | ||
| (role: IRole, item: CollaboratorItem) => { | ||
| async (role: IRole, item: CollaboratorItem) => { | ||
| const addedSeats = item.type === PrincipalType.User && !item.billable ? 1 : 0; |
There was a problem hiding this comment.
Derive role-change deltas from populated billing data
For the base and space collaborator-list responses implemented in this tree, CollaboratorService.getListByBase and getListBySpace never populate the optional billable property, so every user reaches this expression with item.billable === undefined and is treated as a new seat. Consequently, changing an already billable user from Creator to Editor shows a false Cloud cost-increase confirmation and is blocked entirely on an EE instance at its seat limit. Populate the billing status or obtain the actual server-side seat delta before gating the role update; the invitation-dialog role handlers repeat this assumption.
Useful? React with 👍 / 👎.
bee7cb1 to
f2f75f1
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f2f75f1457
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (connection?.saveData || connection?.effectiveType === '2g') { | ||
| return; |
There was a problem hiding this comment.
Skip prefetching on slow-2g connections
When the Network Information API reports effectiveType === 'slow-2g' and data saver is disabled, this condition still schedules the heavy Table chunk download. Since slow-2g is an explicit effective-connection type and is slower than 2g, the users most affected by this speculative download bypass the protection described by the hook; exclude both 2g and slow-2g before warming the bundles.
Useful? React with 👍 / 👎.
…ebar node T6478 Synced from teableio/teable-ee@b03c649 Co-authored-by: Aries X <caoxing9@gmail.com> Co-authored-by: Jun Lu <hammond@teable.io> Co-authored-by: SkyHuang <sky.huang.fe@gmail.com> Co-authored-by: nichenqin <nichenqin@hotmail.com>
f2f75f1 to
a937e10
Compare
🔄 Automated sync from EE repository.
8 commit(s) synced since last sync.
Authors
Included commits
Latest source commit: teableio/teable-ee@b03c649
This PR was automatically created by the sync workflow.