fix(ui): invalidate organization queries after team mutations

Team create/delete/update can change which teams belong to an organization
(via teamCreateCall, teamDeleteCall, and teamUpdateCall when organization_id
changes). Without invalidating the React Query cache for organizations, the
org info page's teams list and any useOrganizations() consumer (e.g. the
team edit form's organization dropdown) stay stale until a hard reload.

Export organizationKeys from useOrganizations and invalidate
organizationKeys.all after each successful team mutation, matching the
pattern used in hooks/projects, hooks/budgets, and hooks/accessGroups.
This commit is contained in:
Ryan Crabbe 2026-04-15 12:55:08 -07:00
parent 72a461ba4a
commit c8496a2767
No known key found for this signature in database
4 changed files with 13 additions and 2 deletions

View file

@ -3,7 +3,7 @@ import { Organization, organizationInfoCall, organizationListCall } from "@/comp
import { useQuery, useQueryClient, UseQueryResult } from "@tanstack/react-query";
import { createQueryKeys } from "../common/queryKeysFactory";
const organizationKeys = createQueryKeys("organizations");
export const organizationKeys = createQueryKeys("organizations");
export const useOrganizations = (): UseQueryResult<Organization[]> => {
const { accessToken, userId, userRole } = useAuthorized();
return useQuery<Organization[]>({

View file

@ -1,4 +1,6 @@
import React, { useState, useEffect } from "react";
import { useQueryClient } from "@tanstack/react-query";
import { organizationKeys } from "@/app/(dashboard)/hooks/organizations/useOrganizations";
import { teamDeleteCall, Organization } from "@/components/networking";
import { fetchTeams } from "@/components/common_components/fetch_teams";
import { Form } from "antd";
@ -54,6 +56,7 @@ const TeamsView: React.FC<TeamProps> = ({
organizations,
premiumUser = false,
}) => {
const queryClient = useQueryClient();
const [currentOrg, setCurrentOrg] = useState<Organization | null>(null);
const [showFilters, setShowFilters] = useState(false);
const [filters, setFilters] = useState<FilterState>({
@ -138,6 +141,7 @@ const TeamsView: React.FC<TeamProps> = ({
try {
await teamDeleteCall(accessToken, teamToDelete);
queryClient.invalidateQueries({ queryKey: organizationKeys.all });
// Successfully completed the deletion. Update the state to trigger a rerender.
fetchTeams(accessToken, userID, userRole, currentOrg, setTeams);
} catch (error) {

View file

@ -13,9 +13,11 @@ import AgentSelector from "@/components/agent_management/AgentSelector";
import PremiumLoggingSettings from "@/components/common_components/PremiumLoggingSettings";
import ModelAliasManager from "@/components/common_components/ModelAliasManager";
import React, { useEffect, useState } from "react";
import { useQueryClient } from "@tanstack/react-query";
import NotificationsManager from "@/components/molecules/notifications_manager";
import { fetchMCPAccessGroups, getGuardrailsList, getPoliciesList, Organization, Team, teamCreateCall } from "@/components/networking";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
import { organizationKeys } from "@/app/(dashboard)/hooks/organizations/useOrganizations";
import MCPToolPermissions from "@/components/mcp_server_management/MCPToolPermissions";
interface ModelAliases {
@ -71,6 +73,7 @@ const CreateTeamModal = ({
setIsTeamModalVisible,
}: CreateTeamModalProps) => {
const { userId: userID, userRole, accessToken, premiumUser } = useAuthorized();
const queryClient = useQueryClient();
const [form] = Form.useForm();
const [userModels, setUserModels] = useState<string[]>([]);
const [currentOrgForCreateTeam, setCurrentOrgForCreateTeam] = useState<Organization | null>(null);
@ -273,6 +276,7 @@ const CreateTeamModal = ({
}
const response: any = await teamCreateCall(accessToken, formValues);
queryClient.invalidateQueries({ queryKey: organizationKeys.all });
if (teams !== null) {
setTeams([...teams, response]);
} else {

View file

@ -1,5 +1,6 @@
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
import { useOrganizations } from "@/app/(dashboard)/hooks/organizations/useOrganizations";
import { organizationKeys, useOrganizations } from "@/app/(dashboard)/hooks/organizations/useOrganizations";
import { useQueryClient } from "@tanstack/react-query";
import UserSearchModal from "@/components/common_components/user_search_modal";
import {
getPoliciesList,
@ -195,6 +196,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
const [organization, setOrganization] = useState<Organization | null>(null);
const { userRole, userId } = useAuthorized();
const { data: userOrganizations = [] } = useOrganizations();
const queryClient = useQueryClient();
// Check if user is org admin for this team's organization
const isOrgAdminForTeam = useMemo(() => {
@ -611,6 +613,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
}
const response = await teamUpdateCall(accessToken, updateData);
queryClient.invalidateQueries({ queryKey: organizationKeys.all });
NotificationsManager.success("Team settings updated successfully");
setIsEditing(false);