Skip to content

feat(teams): public team pages, map and communities - #539

Merged
harshtandiya merged 22 commits into
developfrom
feat/team-pages
Oct 7, 2026
Merged

harshtandiya merged 22 commits into
developfrom
feat/team-pages

Conversation

@harshtandiya

@harshtandiya harshtandiya commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

What changed

Teams get a public page, and a team can act as a community that lists other teams' events.

  • Public team page at /community/<slug>: logo, description, links and an Upcoming / Past day timeline. Cards show Live, Attending (the visitor holds a ticket) and Registrations closed, plus co-hosts. Edited from team settings → Public page.
  • Map and calendar: a dot-matrix map pins each upcoming venue; Nearby frames the visitor's country (from their browser time zone), Everywhere frames all pins. Country chips filter the timeline; a mini calendar jumps to a day. Venues get coordinates, city and country from OpenStreetMap Nominatim in the background (a patch backfills existing ones), with a locality fallback for long street addresses.
  • Communities: turn on "Community" in the public page settings. Other teams submit events from event details or the page's Submit event dialog; approved events show on the community page under their own team. One request per (event, community), guarded by a unique index; changes go through buzz.api.communities, which checks roles on both sides. Emails on submit and on review.
  • Review UI is future work: the dashboard page for approving requests is left out of this PR. Its endpoints (approve_request, reject_request, remove_event, add_event) and tests are in; until the page lands, a System Manager reviews in Desk.
  • The event page's "Hosted by" links the team to its page when published.

Demo

Team page (light) Team page (dark)
Team page light Team page dark
Submit event (community page) Event details → Communities
Submit dialog Event communities
Team settings → Public page
Public page settings

Testing

  • New modules: test_team_route, test_team_page, test_team_page_render, test_team_map, test_geocode, buzz.api.communities.test_communities (submit, review, resubmit, withdraw, add, role checks, emails); buzz.api.teams.test_teams extended. All pass locally.
  • Browser-checked: publish / unpublish (404), tabs and arrow keys, map in two time zones, calendar jumps, pin ↔ card hover, Submit event dialog and the event details section, signed-in and guest views, light and dark.

Buzz Team becomes a website generator. A published team gets a
server-rendered page with its logo, short description, about, links and
a day-grouped Upcoming / Past timeline of its own events, built on the
event pages' layout and espresso tab buttons.

Owners, admins and managers edit the page from the team's settings in
the dashboard through buzz.api.teams.update_public_page. The route is
filled on first publish and only a System Manager changes it.

The site header now supplies the visitor's name and avatar, which a
website generator's page does not get, so signed-in visitors can open
the page.
A dot-matrix map strip pins each upcoming event's venue, framed on the
visitor's country (read from their browser time zone) or on every pin.
Dots grow with the zoom so land keeps its shape when framed close.
Country chips filter the timeline, and a mini calendar jumps to a day.

Event Venue gains city and venue_country, filled in the background from
OpenStreetMap Nominatim when a venue's address or coordinates change. A
patch queues the same lookup for existing venues. The field is not named
country: Frappe would fill that from the system default.
A published team can be a community. Another team's owners, admins and
managers submit an event from its details page or from the community
page's Submit event dialog; the community's managers approve, reject,
remove, or add events directly from a new Community page in the
dashboard. Approved events show on the community page under their own
team's name.

Community Event Request holds one row per (event, community), guarded by
a unique index. Changes go through buzz.api.communities, which checks
roles on each side, and emails go to the community on submit and to the
submitter on review. Deleting an event deletes its requests.
Team page cards name the event's co-hosts after its team, read for every
card in one query, and say "Registrations closed" on upcoming events
whose registrations have closed, using espresso's badge.

The event page's "Hosted by" row links the team to its public page while
that page is published.
Smaller dots (20% of the grid gap, 2.5 to 6px) in fixed colours chosen
by eye for each mode: #969696 on #0f0f0f in dark mode and #404040 on
#fafafa in light, both at 60% opacity, under a 12% glow from the top.
@NagariaHussain

Copy link
Copy Markdown
Contributor

Let's show the country flags if country wise filter? 👀

…im misses

Nominatim finds nothing for many street-level addresses, Google's
especially ("No. 374, ..., situated at, Koramangala, Bengaluru, ...").
The lookup now tries the full address, then its last four and last three
parts, one request a second, so the venue still gets a pin and a country.
It matches the Everywhere chip under the identity bar, which shows the same set of events.
Frappe already turns an empty "not in" list into valid SQL, so not_in_filter goes. The calendar builds YYYY-MM-DD dates with Intl's sv-SE format instead of padding parts by hand.
A running event shows Live in place of its start time, as on the discover page. An event the visitor holds a ticket for shows Attending, the dashboard's rule, read for every card in one query; it replaces Registrations closed, which no longer concerns them.
…ider

Events in one city share a pin, whose tooltip always showed the first of them; hovering a card now shows that card's event. Everywhere frames at least 100 degrees, wider than Nearby's 60, so the two differ even when every event is in one city.
The sidebar narrows from 300px to 248px, giving the event cards the room. The team logo takes frappe-ui's square 3xl Avatar: 46px with 10px corners.
start_time is required on Buzz Event, so the row always has a time to show.
Conflicts with the factory rewrite (#540): its EventVenueFactory replaces this branch's identical one, and the public page tests move onto TeamTestCase and BuzzTeamMembershipFactory.
@harshtandiya harshtandiya changed the title feat(teams): public team pages and communities feat(teams): public team pages, map and communities Oct 6, 2026
@harshtandiya

Copy link
Copy Markdown
Collaborator Author

Let's show the country flags if country wise filter? 👀

Cluttery imo, can experiment

@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Backend test coverage: 91%

Commit 9337198. Test modules are excluded.

Coverage by file
Name Stmts Miss Cover
buzz/__init__.py 5 5 0%
buzz/api/account/__init__.py 30 2 93%
buzz/api/account/exceptions.py 8 0 100%
buzz/api/account/schemas.py 4 0 100%
buzz/api/account/services.py 15 1 93%
buzz/api/auth/__init__.py 11 0 100%
buzz/api/auth/schemas.py 3 0 100%
buzz/api/booking/__init__.py 30 1 97%
buzz/api/booking/coupons.py 30 3 90%
buzz/api/booking/details.py 93 7 92%
buzz/api/booking/event_data.py 42 4 90%
buzz/api/booking/exceptions.py 21 0 100%
buzz/api/booking/guests.py 71 10 86%
buzz/api/booking/my_bookings.py 9 3 67%
buzz/api/booking/schemas.py 38 0 100%
buzz/api/booking/services.py 212 19 91%
buzz/api/campaigns/__init__.py 34 19 44%
buzz/api/campaigns/exceptions.py 11 0 100%
buzz/api/campaigns/schemas.py 2 0 100%
buzz/api/checkin/__init__.py 9 0 100%
buzz/api/checkin/exceptions.py 14 0 100%
buzz/api/checkin/schemas.py 8 0 100%
buzz/api/checkin/services.py 62 1 98%
buzz/api/communications/__init__.py 16 0 100%
buzz/api/communications/exceptions.py 11 0 100%
buzz/api/communications/schemas.py 6 0 100%
buzz/api/communications/services.py 65 1 98%
buzz/api/communities/__init__.py 39 0 100%
buzz/api/communities/exceptions.py 12 0 100%
buzz/api/communities/notifications.py 20 1 95%
buzz/api/communities/queries.py 14 0 100%
buzz/api/communities/reviews.py 36 1 97%
buzz/api/communities/schemas.py 7 0 100%
buzz/api/communities/submissions.py 43 1 98%
buzz/api/events/__init__.py 49 0 100%
buzz/api/events/exceptions.py 20 0 100%
buzz/api/events/schemas.py 85 0 100%
buzz/api/events/services.py 221 13 94%
buzz/api/events/taxes.py 25 0 100%
buzz/api/events/ticket_types.py 43 0 100%
buzz/api/events/zoom.py 15 1 93%
buzz/api/exceptions.py 23 0 100%
buzz/api/filters/conditions.py 99 2 98%
buzz/api/filters/exceptions.py 5 0 100%
buzz/api/filters/schemas.py 6 0 100%
buzz/api/forms/__init__.py 24 0 100%
buzz/api/forms/answers.py 77 14 82%
buzz/api/forms/exceptions.py 27 0 100%
buzz/api/forms/fields.py 82 3 96%
buzz/api/forms/schemas.py 7 0 100%
buzz/api/forms/services.py 119 1 99%
buzz/api/maps/__init__.py 16 0 100%
buzz/api/maps/exceptions.py 11 0 100%
buzz/api/maps/schemas.py 9 0 100%
buzz/api/maps/services.py 57 0 100%
buzz/api/payments/__init__.py 10 1 90%
buzz/api/payments/currencies.py 7 2 71%
buzz/api/payments/schemas.py 2 0 100%
buzz/api/proposals/__init__.py 18 0 100%
buzz/api/proposals/exceptions.py 5 0 100%
buzz/api/proposals/schemas.py 26 0 100%
buzz/api/proposals/services.py 104 1 99%
buzz/api/schemas.py 13 0 100%
buzz/api/sponsorships/__init__.py 37 0 100%
buzz/api/sponsorships/enquiries.py 74 2 97%
buzz/api/sponsorships/exceptions.py 22 0 100%
buzz/api/sponsorships/forms.py 64 2 97%
buzz/api/sponsorships/manage.py 21 1 95%
buzz/api/sponsorships/schemas.py 18 0 100%
buzz/api/sponsorships/services.py 67 1 99%
buzz/api/teams/__init__.py 34 0 100%
buzz/api/teams/exceptions.py 18 0 100%
buzz/api/teams/invitations.py 34 0 100%
buzz/api/teams/schemas.py 8 0 100%
buzz/api/teams/services.py 82 1 99%
buzz/api/tickets/__init__.py 15 0 100%
buzz/api/tickets/emails.py 14 9 36%
buzz/api/tickets/exceptions.py 29 0 100%
buzz/api/tickets/schemas.py 4 0 100%
buzz/api/tickets/services.py 85 0 100%
buzz/api/tickets/windows.py 12 0 100%
buzz/buzz/doctype/buzz_custom_field/buzz_custom_field.py 20 4 80%
buzz/buzz/web_form/apply_for_sponsorship/apply_for_sponsorship.py 3 3 0%
buzz/buzz/web_form/propose_a_talk/propose_a_talk.py 3 3 0%
buzz/buzz_marketing/doctype/buzz_campaign/buzz_campaign.py 21 7 67%
buzz/emails.py 29 3 90%
buzz/events/banner_pattern.py 35 0 100%
buzz/events/doctype/additional_event_page/additional_event_page.py 15 1 93%
buzz/events/doctype/buzz_event/buzz_event.py 267 23 91%
buzz/events/doctype/buzz_event_form/buzz_event_form.py 11 4 64%
buzz/events/doctype/buzz_form_field/buzz_form_field.py 3 0 100%
buzz/events/doctype/buzz_price/buzz_price.py 10 0 100%
buzz/events/doctype/buzz_settings/buzz_settings.py 13 2 85%
buzz/events/doctype/buzz_team/buzz_team.py 73 2 97%
buzz/events/doctype/buzz_team/team_map.py 23 0 100%
buzz/events/doctype/buzz_team/team_page.py 69 2 97%
buzz/events/doctype/buzz_team_membership/buzz_team_membership.py 59 0 100%
buzz/events/doctype/buzz_team_settings/buzz_team_settings.py 44 0 100%
buzz/events/doctype/buzz_theme/buzz_theme.py 42 2 95%
buzz/events/doctype/buzz_theme/tokens.py 29 1 97%
buzz/events/doctype/buzz_theme_token/buzz_theme_token.py 3 0 100%
buzz/events/doctype/community_event_request/community_event_request.py 40 9 78%
buzz/events/doctype/event_category/event_category.py 9 0 100%
buzz/events/doctype/event_check_in/event_check_in.py 10 1 90%
buzz/events/doctype/event_cohost/event_cohost.py 4 0 100%
buzz/events/doctype/event_communication/event_communication.py 16 0 100%
buzz/events/doctype/event_external_link/event_external_link.py 4 0 100%
buzz/events/doctype/event_featured_speaker/event_featured_speaker.py 4 0 100%
buzz/events/doctype/event_feedback/event_feedback.py 4 4 0%
buzz/events/doctype/event_host/event_host.py 4 0 100%
buzz/events/doctype/event_payment_gateway/event_payment_gateway.py 4 0 100%
buzz/events/doctype/event_sponsor/event_sponsor.py 15 3 80%
buzz/events/doctype/event_talk/event_talk.py 8 0 100%
buzz/events/doctype/event_template/event_template.py 38 4 89%
buzz/events/doctype/event_template_add_on/event_template_add_on.py 4 0 100%
buzz/events/doctype/event_template_custom_field/event_template_custom_field.py 4 0 100%
buzz/events/doctype/event_template_ticket_type/event_template_ticket_type.py 4 0 100%
buzz/events/doctype/event_track/event_track.py 4 4 0%
buzz/events/doctype/event_user_preferences/event_user_preferences.py 4 4 0%
buzz/events/doctype/event_venue/event_venue.py 53 1 98%
buzz/events/doctype/event_venue/geocode.py 69 9 87%
buzz/events/doctype/event_venue/map_link.py 106 5 95%
buzz/events/doctype/offline_payment_method/offline_payment_method.py 11 0 100%
buzz/events/doctype/schedule_item/schedule_item.py 4 0 100%
buzz/events/doctype/social_media_link/social_media_link.py 3 0 100%
buzz/events/doctype/speaker_profile/speaker_profile.py 8 1 88%
buzz/events/doctype/sponsor_enquiry_form/sponsor_enquiry_form.py 54 5 91%
buzz/events/doctype/sponsorship_tier/sponsorship_tier.py 27 1 96%
buzz/events/doctype/talk_speaker/talk_speaker.py 3 0 100%
buzz/events/doctype/utm_parameter/utm_parameter.py 4 0 100%
buzz/events/og_image.py 141 7 95%
buzz/events/og_text.py 66 1 98%
buzz/events/online_meeting.py 42 1 98%
buzz/events/report/event_attendance_summary/event_attendance_summary.py 61 61 0%
buzz/events/report/event_overview/event_overview.py 25 25 0%
buzz/hooks.py 28 0 100%
buzz/install.py 60 28 53%
buzz/integrations/zoom.py 3 3 0%
buzz/payments.py 96 33 66%
buzz/permissions.py 137 12 91%
buzz/proposals/doctype/event_proposal/event_proposal.py 71 5 93%
buzz/proposals/doctype/proposal_speaker/proposal_speaker.py 4 0 100%
buzz/proposals/doctype/sponsorship_deck_item/sponsorship_deck_item.py 4 0 100%
buzz/proposals/doctype/sponsorship_enquiry/sponsorship_enquiry.py 81 5 94%
buzz/proposals/doctype/talk_proposal/talk_proposal.py 92 6 93%
buzz/proposals/doctype/talk_proposal_status/talk_proposal_status.py 4 0 100%
buzz/tasks.py 4 4 0%
buzz/telemetry.py 46 0 100%
buzz/telemetry_scan.py 55 8 85%
buzz/ticketing/doctype/additional_field/additional_field.py 4 0 100%
buzz/ticketing/doctype/attendee_ticket_add_on/attendee_ticket_add_on.py 3 0 100%
buzz/ticketing/doctype/buzz_coupon_code/buzz_coupon_code.py 99 4 96%
buzz/ticketing/doctype/coupon_free_add_on/coupon_free_add_on.py 3 0 100%
buzz/ticketing/doctype/event_booking/event_booking.py 355 28 92%
buzz/ticketing/doctype/event_booking_attendee/event_booking_attendee.py 20 7 65%
buzz/ticketing/doctype/event_booking_refund/event_booking_refund.py 56 0 100%
buzz/ticketing/doctype/event_booking_refund_ticket/event_booking_refund_ticket.py 4 0 100%
buzz/ticketing/doctype/event_payment/event_payment.py 4 0 100%
buzz/ticketing/doctype/event_ticket/event_ticket.py 80 10 88%
buzz/ticketing/doctype/event_ticket_type/event_ticket_type.py 69 0 100%
buzz/ticketing/doctype/ticket_add_on/ticket_add_on.py 9 1 89%
buzz/ticketing/doctype/ticket_add_on_value/ticket_add_on_value.py 3 0 100%
buzz/ticketing/doctype/ticket_cancellation_item/ticket_cancellation_item.py 4 0 100%
buzz/ticketing/doctype/ticket_cancellation_request/ticket_cancellation_request.py 19 1 95%
buzz/ticketing/report/detailed_event_registrations/detailed_event_registrations.py 111 5 95%
buzz/ticketing/report/event_add_ons_overview/event_add_ons_overview.py 20 20 0%
buzz/uninstall.py 10 2 80%
buzz/utils.py 138 22 84%
buzz/www/dashboard.py 24 3 88%
buzz/www/event/date_range.py 42 16 62%
buzz/www/event/index.py 140 8 94%
buzz/www/event/link_icons.py 1 0 100%
buzz/www/event/meta.py 65 6 91%
buzz/www/event/venue_map.py 35 1 97%
buzz/www/events.py 69 6 91%
buzz/www/site_header.py 25 0 100%
TOTAL 6600 580 91%

89 empty files skipped.

The dashboard's Community page, its route and sidebar item, and the data calls only it used go. Submitting stays: the Community switch, the Communities section on event details and the page's Submit event dialog. The review endpoints in buzz.api.communities and their tests remain for the page's return; until then a System Manager reviews in Desk. The submit email loses its link to the removed page.
CI never runs bench build, so bundled_asset fails without assets.json.
@harshtandiya
harshtandiya marked this pull request as ready for review October 6, 2026 15:18

@greptile-apps greptile-apps Bot 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.

Your trial has ended. Reactivate Greptile to resume code reviews.

…d batches

Batches run one after another so lookups stay at Nominatim's one request a second.
…view it

Removes the team page's Submit event dialog, the event page's Communities section, and the unused search_addable_events endpoint and TeamOption field.

@greptile-apps greptile-apps Bot 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.

Your trial has ended. Reactivate Greptile to resume code reviews.

@harshtandiya
harshtandiya merged commit 1e3977e into develop Oct 7, 2026
8 checks passed
@harshtandiya
harshtandiya deleted the feat/team-pages branch October 7, 2026 04:54
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.

2 participants