Use auth.availableTeams endpoint for workspace switching (#4585)

This commit is contained in:
Tom Moor
2022-12-17 17:17:02 -08:00
committed by GitHub
parent 1995a3fb19
commit f8ba393f7c
4 changed files with 61 additions and 73 deletions

View File

@ -2,42 +2,46 @@ import { PlusIcon } from "outline-icons";
import * as React from "react";
import styled from "styled-components";
import { stringToColor } from "@shared/utils/color";
import RootStore from "~/stores/RootStore";
import TeamNew from "~/scenes/TeamNew";
import TeamLogo from "~/components/TeamLogo";
import { createAction } from "~/actions";
import { loadSessionsFromCookie } from "~/hooks/useSessions";
import { TeamSection } from "../sections";
export const switchTeamList = getSessions().map((session) => {
return createAction({
name: session.name,
section: TeamSection,
keywords: "change switch workspace organization team",
icon: () => (
<StyledTeamLogo
alt={session.name}
model={{
initial: session.name[0],
avatarUrl: session.logoUrl,
id: session.teamId,
color: stringToColor(session.teamId),
}}
size={24}
/>
),
visible: ({ currentTeamId }) => currentTeamId !== session.teamId,
perform: () => (window.location.href = session.url),
});
});
export const createTeamsList = ({ stores }: { stores: RootStore }) => {
return (
stores.auth.availableTeams?.map((session) =>
createAction({
name: session.name,
section: TeamSection,
keywords: "change switch workspace organization team",
icon: () => (
<StyledTeamLogo
alt={session.name}
model={{
initial: session.name[0],
avatarUrl: session.avatarUrl,
id: session.id,
color: stringToColor(session.id),
}}
size={24}
/>
),
visible: ({ currentTeamId }) => currentTeamId !== session.id,
perform: () => (window.location.href = session.url),
})
) ?? []
);
};
const switchTeam = createAction({
export const switchTeam = createAction({
name: ({ t }) => t("Switch workspace"),
placeholder: ({ t }) => t("Select a workspace"),
keywords: "change switch workspace organization team",
section: TeamSection,
visible: ({ currentTeamId }) =>
getSessions({ exclude: currentTeamId }).length > 0,
children: switchTeamList,
visible: ({ stores }) =>
!!stores.auth.availableTeams && stores.auth.availableTeams?.length > 1,
children: createTeamsList,
});
export const createTeam = createAction({
@ -60,14 +64,6 @@ export const createTeam = createAction({
},
});
function getSessions(params?: { exclude?: string }) {
const sessions = loadSessionsFromCookie();
const otherSessions = sessions.filter(
(session) => session.teamId !== params?.exclude
);
return otherSessions;
}
const StyledTeamLogo = styled(TeamLogo)`
border-radius: 2px;
border: 0;

View File

@ -1,25 +0,0 @@
import * as React from "react";
import { getCookie } from "tiny-cookie";
type Session = {
url: string;
logoUrl: string;
name: string;
teamId: string;
};
export function loadSessionsFromCookie(): Session[] {
const sessions = JSON.parse(getCookie("sessions") || "{}");
return Object.keys(sessions).map((teamId) => ({
teamId,
...sessions[teamId],
}));
}
export default function useSessions(): [Session[], () => void] {
const [sessions, setSessions] = React.useState(loadSessionsFromCookie);
const reload = React.useCallback(() => {
setSessions(loadSessionsFromCookie());
}, []);
return [sessions, reload];
}

View File

@ -5,23 +5,19 @@ import { MenuButton, useMenuState } from "reakit/Menu";
import ContextMenu from "~/components/ContextMenu";
import Template from "~/components/ContextMenu/Template";
import { navigateToSettings, logout } from "~/actions/definitions/navigation";
import { createTeam, switchTeamList } from "~/actions/definitions/teams";
import useCurrentTeam from "~/hooks/useCurrentTeam";
import { createTeam, createTeamsList } from "~/actions/definitions/teams";
import usePrevious from "~/hooks/usePrevious";
import useSessions from "~/hooks/useSessions";
import useStores from "~/hooks/useStores";
import separator from "~/menus/separator";
const OrganizationMenu: React.FC = ({ children }) => {
const [sessions] = useSessions();
const menu = useMenuState({
unstable_offset: [4, -4],
placement: "bottom-start",
modal: true,
});
const { ui } = useStores();
const { theme } = ui;
const team = useCurrentTeam();
const stores = useStores();
const { theme } = stores.ui;
const previousTheme = usePrevious(theme);
const { t } = useTranslation();
@ -35,13 +31,13 @@ const OrganizationMenu: React.FC = ({ children }) => {
// menu is not cached at all.
const actions = React.useMemo(() => {
return [
...switchTeamList,
...createTeamsList({ stores }),
createTeam,
separator(),
navigateToSettings,
logout,
];
}, [team.id, sessions]);
}, [stores]);
return (
<>

View File

@ -19,6 +19,13 @@ const NO_REDIRECT_PATHS = ["/", "/create", "/home"];
type PersistedData = {
user?: User;
team?: Team;
availableTeams?: {
id: string;
name: string;
avatarUrl: string;
url: string;
isSignedIn: boolean;
}[];
policies?: Policy[];
};
@ -37,19 +44,28 @@ export type Config = {
export default class AuthStore {
@observable
user: User | null | undefined;
user?: User | null;
@observable
team: Team | null | undefined;
team?: Team | null;
@observable
token: string | null | undefined;
availableTeams?: {
id: string;
name: string;
avatarUrl: string;
url: string;
isSignedIn: boolean;
}[];
@observable
token?: string | null;
@observable
policies: Policy[] = [];
@observable
lastSignedIn: string | null | undefined;
lastSignedIn?: string | null;
@observable
isSaving = false;
@ -58,7 +74,7 @@ export default class AuthStore {
isSuspended = false;
@observable
suspendedContactEmail: string | null | undefined;
suspendedContactEmail?: string | null;
@observable
config: Config | null | undefined;
@ -133,6 +149,7 @@ export default class AuthStore {
return {
user: this.user,
team: this.team,
availableTeams: this.availableTeams,
policies: this.policies,
};
}
@ -156,6 +173,7 @@ export default class AuthStore {
const { user, team } = res.data;
this.user = new User(user, this);
this.team = new Team(team, this);
this.availableTeams = res.data.availableTeams;
if (env.SENTRY_DSN) {
Sentry.configureScope(function (scope) {
@ -214,6 +232,9 @@ export default class AuthStore {
runInAction("AuthStore#updateUser", () => {
this.user = null;
this.team = null;
this.availableTeams = this.availableTeams?.filter(
(team) => team.id !== this.team?.id
);
this.policies = [];
this.token = null;
});