Skip to content

feat(dashboard): create a team from the switcher - #372

Open
harshtandiya wants to merge 1 commit into
version-2-dashboard-minor-sponsor-hidefrom
version-2-dashboard-create-team-2
Open

feat(dashboard): create a team from the switcher#372
harshtandiya wants to merge 1 commit into
version-2-dashboard-minor-sponsor-hidefrom
version-2-dashboard-create-team-2

Conversation

@harshtandiya

Copy link
Copy Markdown
Collaborator

The Create-team button in the team switcher did nothing. It now opens a dialog:
one centred field for the name, a logo dropped onto the avatar through
FileUploader, and on success the user lands on the new team's overview with
that team already selected.

Backend — buzz.api.teams.create_team, POST, rate limited to 5/hour. Buzz Team's
create right belongs to System Manager while any signed-in user may start a team
of their own, so the insert goes past permissions; the controller still derives
the slug and lays down the Owner membership and the team settings. No duplicate
name check — two teams may share a name, and the slug collision is handled by
append_number_if_name_exists.

Two things this flow surfaced, fixed here:

  • useTeamOverview watched currentTeam, an object rebuilt on every teams
    refresh, so it re-fetched for the same team; the second request aborted the
    first and VueUse left that rejection in error after the newer request had
    already succeeded — "signal is aborted without reason" over loaded data. It
    watches the team name now, and teamOverviewError drops AbortError.
  • The manage shell rendered nothing while the teams loaded. It now renders with
    a LoadingPanel (pinging Buzz mark) in the right-hand pane, reused for the
    team overview's own wait.

Gotchas:

  • The rate limiter buckets on frappe.form_dict.cmd, which /api/v2 never sets,
    so the dashboard calls this over createResource (/api/method) like the
    sibling team writes. Move it to a v2 useCall and every rate-limited v2
    endpoint shares one bucket.
  • createResource does not await onSuccess, so the team switch happens in
    createAndSelectTeam before navigation rather than in a success hook.

Not changed: the account tabs, Buzz Team's doctype permissions, or the desk
add-members flow. TeamMembers keeps its own LoadingText.

The switcher's Create-team button had no behaviour. It now opens a dialog with
the only field a team needs — a name — over a logo the uploader drops onto the
avatar, and lands the user on the new team's overview.

Buzz Team's create right belongs to System Manager while any signed-in user may
start a team of their own, so the insert goes past permissions in a rate-limited
endpoint; the controller still lays down the slug, the Owner membership and the
team settings. The limiter buckets on `cmd`, which only /api/method sets, hence
createResource rather than a v2 call.

Two things the flow surfaced: the team overview watched `currentTeam`, an object
rebuilt on every teams refresh, so it re-fetched for the same team and the second
request aborted the first — its rejection then sat in `error` over data that had
already arrived. It watches the name now, and an aborted request no longer counts
as an error. The manage shell also renders while the teams load, with the wait
held in the panel rather than a blank window.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

❌ UI Demo Check failed

This pull request changes the UI (7 file(s) under dashboard/src/),
but the description has no screenshot or demo. Reviewers should be able to see the
change without checking out the branch.

🛠️ How to fix

  • Edit the description and drag a screenshot or a short screen recording into it.
    Before/after images are ideal for visual tweaks.
  • Or apply the skip-demo label if a visual makes no sense here
    (pure refactor, copy change, dependency bump).

Either one re-runs this check automatically.

@greptile-apps

greptile-apps Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds authenticated team creation from the dashboard switcher and routes successful creation into the newly selected team's overview. It also revises team-overview request handling and introduces reusable loading UI.

  • Adds a rate-limited backend team-creation endpoint that seeds the owner membership and team settings through the existing DocType lifecycle.
  • Adds the create-team dialog with logo upload, team selection, and overview navigation.
  • Changes overview watching and abort-error presentation to reduce stale cancellation errors.
  • Renders the manager shell during team-access loading and reuses a common loading panel.

Confidence Score: 4/5

The concurrent-submit defect should be fixed before merging because a repeated Enter submission can persist multiple teams for one intended creation.

The backend intentionally accepts duplicate names, while the new form's submit handler allows another native form submission during an in-flight request, so both requests can insert distinct teams.

Files Needing Attention: dashboard/src/components/dashboard/teams/CreateTeamDialog.vue

Important Files Changed

Filename Overview
buzz/api/teams/init.py Exposes the authenticated POST team-creation method with a five-per-hour rate limit.
buzz/api/teams/services.py Inserts a Buzz Team past DocType create permissions so its controller can seed owner membership and settings.
buzz/api/teams/test_teams.py Covers ownership, switcher visibility, repeated names, and mandatory-name validation for team creation.
dashboard/src/components/dashboard/teams/CreateTeamDialog.vue Implements the creation form and upload UI, but native repeated form submissions can create duplicate teams concurrently.
dashboard/src/data/teams.ts Adds the create/reload/select sequence and changes overview reloading to follow the selected team name.
dashboard/src/components/TeamSwitcher.vue Connects the existing create-team action to the new dialog after closing the focus-trapping popover.
dashboard/src/layouts/ManagerLayout.vue Keeps the shell visible while team access loads and gates routed content behind the pending state.
dashboard/src/pages/manage/teams/TeamOverview.vue Reuses the loading panel and shared filtered overview error.
dashboard/src/pages/manage/teams/TeamMembers.vue Uses the shared overview error while retaining the existing members loading presentation.

Fix all with Greploop Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
### Issue 1
dashboard/src/components/dashboard/teams/CreateTeamDialog.vue:32-34
**Concurrent team submissions create duplicates**

When a user submits the form again while creation is in progress, `submit` starts another request because it does not guard on `createTeam.loading`, causing multiple teams to be persisted for one intended creation.

```suggestion
async function submit() {
	if (createTeam.loading) return;

	showErrors.value = true;
	if (invalid.value) return;
```

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "feat(dashboard): create a team from the ..." | Re-trigger Greptile

Comment on lines +32 to +34
async function submit() {
showErrors.value = true;
if (invalid.value) return;

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.

P1 Concurrent team submissions create duplicates

When a user submits the form again while creation is in progress, submit starts another request because it does not guard on createTeam.loading, causing multiple teams to be persisted for one intended creation.

Suggested change
async function submit() {
showErrors.value = true;
if (invalid.value) return;
async function submit() {
if (createTeam.loading) return;
showErrors.value = true;
if (invalid.value) return;
Prompt To Fix With AI
This is a comment left during a code review.
Path: dashboard/src/components/dashboard/teams/CreateTeamDialog.vue
Line: 32-34

Comment:
**Concurrent team submissions create duplicates**

When a user submits the form again while creation is in progress, `submit` starts another request because it does not guard on `createTeam.loading`, causing multiple teams to be persisted for one intended creation.

```suggestion
async function submit() {
	if (createTeam.loading) return;

	showErrors.value = true;
	if (invalid.value) return;
```

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code Fix in Codex

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.

1 participant