add types to atoms

This commit is contained in:
Sidney Alcantara
2022-04-25 15:23:48 +10:00
parent d664a04ef9
commit 7a12588531
6 changed files with 129 additions and 7 deletions

View File

@@ -1,6 +1,7 @@
import { atom } from "jotai";
import type { User } from "firebase/auth";
// undefined means loading
/** Currently signed in user. `undefined` means loading. */
export const currentUserAtom = atom<User | null | undefined>(undefined);
export const userRolesAtom = atom<string[]>([]);

View File

@@ -1 +1,2 @@
/** Scope for atoms stored at the root of the app */
export const globalScope = Symbol("globalScope");

View File

@@ -1,6 +1,92 @@
import { atom } from "jotai";
import { DocumentData } from "firebase/firestore";
import { sortBy } from "lodash-es";
import { ThemeOptions } from "@mui/material";
import { userRolesAtom } from "./auth";
export const projectIdAtom = atom<string>("");
export const publicSettingsAtom = atom<DocumentData>({});
export const projectSettingsAtom = atom<DocumentData>({});
/** Public settings are visible to unauthenticated users */
export type PublicSettings = Partial<{
signInOptions: Array<
| "google"
| "twitter"
| "facebook"
| "github"
| "microsoft"
| "apple"
| "yahoo"
| "email"
| "phone"
| "anonymous"
>;
theme: Record<"base" | "light" | "dark", ThemeOptions>;
}>;
/** Public settings are visible to unauthenticated users */
export const publicSettingsAtom = atom<PublicSettings>({});
/** Project settings are visible to authenticated users */
export type ProjectSettings = Partial<{
tables: Array<TableSettings>;
setupCompleted: boolean;
rowyRunUrl: string;
rowyRunRegion: string;
rowyRunBuildStatus: "BUILDING" | "COMPLETE";
services: Partial<{
hooks: string;
terminal: string;
}>;
}>;
/** Project settings are visible to authenticated users */
export const projectSettingsAtom = atom<ProjectSettings>({});
/** Table settings stored in project settings */
export type TableSettings = {
id: string;
collection: string;
name: string;
roles: string[];
description: string;
section: string;
tableType: "primaryCollection" | "collectionGroup";
audit?: boolean;
auditFieldCreatedBy?: string;
auditFieldUpdatedBy?: string;
readOnly?: boolean;
};
/** Tables visible to the signed-in user based on roles */
export const tablesAtom = atom((get) => {
const userRoles = get(userRolesAtom);
const tables = get(projectSettingsAtom).tables || [];
return sortBy(tables, "name")
.filter(
(table) =>
userRoles.includes("ADMIN") ||
table.roles.some((role) => userRoles.includes(role))
)
.map((table) => ({
...table,
// Ensure id exists for backwards compatibility
id: table.id || table.collection,
// Ensure section exists
section: table.section ? table.section.trim() : "Other",
}));
});
/** Roles used in the project based on table settings */
export const rolesAtom = atom((get) =>
Array.from(
new Set(
get(tablesAtom).reduce(
(a, c) => [...a, ...c.roles],
["ADMIN", "EDITOR", "VIEWER"]
)
)
)
);

7
src/atoms/table.ts Normal file
View File

@@ -0,0 +1,7 @@
import { where } from "firebase/firestore";
export type TableFilter = {
key: Parameters<typeof where>[0];
operator: Parameters<typeof where>[1];
value: Parameters<typeof where>[2];
};

View File

@@ -1,22 +1,49 @@
import { atom } from "jotai";
import { atomWithStorage } from "jotai/utils";
import { DocumentData } from "firebase/firestore";
import { merge } from "lodash-es";
import { ThemeOptions } from "@mui/material";
import themes from "@src/theme";
import { publicSettingsAtom } from "./project";
import { TableFilter } from "./table";
export const userSettingsAtom = atom<DocumentData>({});
/** User info and settings*/
export type UserSettings = Partial<{
/** Synced from user auth info */
user: {
email: string;
displayName?: string;
photoURL?: string;
};
roles: string[];
theme: Record<"base" | "light" | "dark", ThemeOptions>;
favoriteTables: string[];
/** Stores user overrides */
tables: Record<
string,
Partial<{
filters: TableFilter[];
hiddenFields: string[];
}>
>;
}>;
/** User info and settings*/
export const userSettingsAtom = atom<UserSettings>({});
/** Stores which theme is currently active, based on user or OS setting */
export const themeAtom = atomWithStorage<"light" | "dark">(
"__ROWY__THEME",
"light"
);
/** User can override OS theme */
export const themeOverriddenAtom = atomWithStorage(
"__ROWY__THEME_OVERRIDDEN",
false
);
/** Customized base theme based on project and user settings */
export const customizedThemesAtom = atom((get) => {
const publicSettings = get(publicSettingsAtom);
const userSettings = get(userSettingsAtom);

View File

@@ -210,7 +210,7 @@ export default function FirebaseUi(props: IFirebaseUiProps) {
const [firebaseAuth] = useAtom(firebaseAuthAtom, globalScope);
const [publicSettings] = useAtom(publicSettingsAtom, globalScope);
const signInOptions = useMemo(
const signInOptions: typeof publicSettings.signInOptions = useMemo(
() =>
Array.isArray(publicSettings.signInOptions) &&
publicSettings.signInOptions.length > 0