mirror of
https://github.com/rowyio/rowy.git
synced 2026-02-24 04:01:17 +01:00
Merge pull request #1390 from rowyio/11/improve-multi-filters
add support for multiple filters
This commit is contained in:
@@ -59,6 +59,8 @@ export const tableColumnsReducer = (
|
||||
|
||||
/** Filters applied to the local view */
|
||||
export const tableFiltersAtom = atom<TableFilter[]>([]);
|
||||
/** Join operator applied to mulitple filters */
|
||||
export const tableFiltersJoinAtom = atom<"AND" | "OR">("AND");
|
||||
/** Sorts applied to the local view */
|
||||
export const tableSortsAtom = atom<TableSort[]>([]);
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ import { getFieldProp } from "@src/components/fields";
|
||||
import { analytics, logEvent } from "@src/analytics";
|
||||
import {
|
||||
formatSubTableName,
|
||||
generateId,
|
||||
getTableBuildFunctionPathname,
|
||||
getTableSchemaPath,
|
||||
} from "@src/utils/table";
|
||||
@@ -251,6 +252,7 @@ export default function ColumnMenu({
|
||||
: column.type
|
||||
)!.operators[0]?.value || "==",
|
||||
value: "",
|
||||
id: generateId(),
|
||||
},
|
||||
});
|
||||
handleClose();
|
||||
|
||||
@@ -39,6 +39,7 @@ import {
|
||||
} from "@src/atoms/tableScope";
|
||||
import { FieldType } from "@src/constants/fields";
|
||||
import { TableRow } from "@src/types/table";
|
||||
import { generateId } from "@src/utils/table";
|
||||
|
||||
interface IMenuContentsProps {
|
||||
onClose: () => void;
|
||||
@@ -281,6 +282,7 @@ export default function MenuContents({ onClose }: IMenuContentsProps) {
|
||||
key: selectedColumn.fieldName,
|
||||
operator: columnFilters!.operators[0]?.value || "==",
|
||||
value: cellValue,
|
||||
id: generateId(),
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -316,12 +316,7 @@ export default function Table({
|
||||
// for large screen heights
|
||||
useEffect(() => {
|
||||
fetchMoreOnBottomReached(containerRef.current);
|
||||
}, [
|
||||
fetchMoreOnBottomReached,
|
||||
tablePage,
|
||||
tableNextPage.loading,
|
||||
containerRef,
|
||||
]);
|
||||
}, [fetchMoreOnBottomReached, tableNextPage.loading, containerRef]);
|
||||
|
||||
// apply user default sort on first render
|
||||
const [applySort, setApplySort] = useState(true);
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
Typography,
|
||||
TextField,
|
||||
InputLabel,
|
||||
IconButton,
|
||||
} from "@mui/material";
|
||||
|
||||
import ColumnSelect from "@src/components/Table/ColumnSelect";
|
||||
@@ -17,11 +18,28 @@ import FieldSkeleton from "@src/components/SideDrawer/FieldSkeleton";
|
||||
import IdFilterInput from "./IdFilterInput";
|
||||
import { InlineErrorFallback } from "@src/components/ErrorFallback";
|
||||
|
||||
import type { useFilterInputs } from "./useFilterInputs";
|
||||
import { getFieldType, getFieldProp } from "@src/components/fields";
|
||||
import type { IFieldConfig } from "@src/components/fields/types";
|
||||
|
||||
export interface IFilterInputsProps extends ReturnType<typeof useFilterInputs> {
|
||||
import { TableFilter } from "@src/types/table";
|
||||
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import DragIndicatorOutlinedIcon from "@mui/icons-material/DragIndicatorOutlined";
|
||||
import { useFilterInputs } from "./useFilterInputs";
|
||||
|
||||
export interface IFilterInputsProps {
|
||||
filterColumns: ReturnType<typeof useFilterInputs>["filterColumns"];
|
||||
selectedColumn: ReturnType<typeof useFilterInputs>["filterColumns"][0];
|
||||
availableFilters: IFieldConfig["filter"];
|
||||
disabled?: boolean;
|
||||
query: TableFilter;
|
||||
setQuery: (query: TableFilter) => void;
|
||||
handleDelete: () => void;
|
||||
index: number;
|
||||
noOfQueries: number;
|
||||
handleChangeColumn: (column: string) => void;
|
||||
joinOperator: "AND" | "OR";
|
||||
setJoinOperator: (operator: "AND" | "OR") => void;
|
||||
}
|
||||
|
||||
export default function FilterInputs({
|
||||
@@ -32,6 +50,11 @@ export default function FilterInputs({
|
||||
query,
|
||||
setQuery,
|
||||
disabled,
|
||||
joinOperator,
|
||||
setJoinOperator,
|
||||
handleDelete,
|
||||
index,
|
||||
noOfQueries,
|
||||
}: IFilterInputsProps) {
|
||||
const columnType = selectedColumn ? getFieldType(selectedColumn) : null;
|
||||
|
||||
@@ -76,18 +99,18 @@ export default function FilterInputs({
|
||||
|
||||
return (
|
||||
<Grid container spacing={2} sx={{ mb: 3 }}>
|
||||
<Grid item xs={4}>
|
||||
<Grid item xs={3.5}>
|
||||
<ColumnSelect
|
||||
multiple={false}
|
||||
label="Column"
|
||||
options={filterColumns}
|
||||
value={query.key}
|
||||
onChange={handleChangeColumn}
|
||||
onChange={(newKey: string | null) => handleChangeColumn(newKey ?? "")}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={4}>
|
||||
<Grid item xs={3.5}>
|
||||
<TextField
|
||||
label="Operator"
|
||||
select
|
||||
@@ -98,13 +121,17 @@ export default function FilterInputs({
|
||||
disabled || !query.key || availableFilters?.operators?.length === 0
|
||||
}
|
||||
onChange={(e) => {
|
||||
setQuery((query) => ({
|
||||
const newQuery = {
|
||||
...query,
|
||||
operator: e.target.value as string,
|
||||
}));
|
||||
operator: e.target.value as TableFilter["operator"],
|
||||
};
|
||||
|
||||
setQuery(newQuery);
|
||||
}}
|
||||
SelectProps={{ displayEmpty: true }}
|
||||
sx={{ "& .MuiSelect-select": { display: "flex" } }}
|
||||
sx={{
|
||||
"& .MuiSelect-select": { display: "flex" },
|
||||
}}
|
||||
>
|
||||
<MenuItem disabled value="" style={{ display: "none" }}>
|
||||
Select operator
|
||||
@@ -113,39 +140,107 @@ export default function FilterInputs({
|
||||
</TextField>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={4} key={query.key + query.operator}>
|
||||
{query.key && query.operator && (
|
||||
<ErrorBoundary FallbackComponent={InlineErrorFallback}>
|
||||
<InputLabel
|
||||
variant="filled"
|
||||
id={`filters-label-${query.key}`}
|
||||
htmlFor={`sidedrawer-field-${query.key}`}
|
||||
>
|
||||
Value
|
||||
</InputLabel>
|
||||
<Grid item xs={3.5} key={query.key + query.operator}>
|
||||
{query.key &&
|
||||
query.operator &&
|
||||
query.operator !== "is-empty" &&
|
||||
query.operator != "is-not-empty" && (
|
||||
<ErrorBoundary FallbackComponent={InlineErrorFallback}>
|
||||
<InputLabel
|
||||
variant="filled"
|
||||
id={`filters-label-${query.key}`}
|
||||
htmlFor={`sidedrawer-field-${query.key}`}
|
||||
>
|
||||
Value
|
||||
</InputLabel>
|
||||
|
||||
<Suspense fallback={<FieldSkeleton />}>
|
||||
{columnType &&
|
||||
createElement(
|
||||
query.key === "_rowy_ref.id"
|
||||
? IdFilterInput
|
||||
: getFieldProp("filter.customInput" as any, columnType) ||
|
||||
getFieldProp("SideDrawerField", columnType),
|
||||
{
|
||||
column: selectedColumn,
|
||||
_rowy_ref: {},
|
||||
value: query.value,
|
||||
onChange: (value: any) => {
|
||||
setQuery((query) => ({ ...query, value }));
|
||||
},
|
||||
disabled,
|
||||
operator: query.operator,
|
||||
}
|
||||
)}
|
||||
</Suspense>
|
||||
</ErrorBoundary>
|
||||
)}
|
||||
<Suspense fallback={<FieldSkeleton />}>
|
||||
{columnType &&
|
||||
createElement(
|
||||
query.key === "_rowy_ref.id"
|
||||
? IdFilterInput
|
||||
: getFieldProp("filter.customInput" as any, columnType) ||
|
||||
getFieldProp("SideDrawerField", columnType),
|
||||
{
|
||||
column: selectedColumn,
|
||||
_rowy_ref: {},
|
||||
value: query.value,
|
||||
onChange: (value: any) => {
|
||||
const newQuery = {
|
||||
...query,
|
||||
value,
|
||||
};
|
||||
setQuery(newQuery);
|
||||
},
|
||||
disabled,
|
||||
operator: query.operator,
|
||||
}
|
||||
)}
|
||||
</Suspense>
|
||||
</ErrorBoundary>
|
||||
)}
|
||||
</Grid>
|
||||
|
||||
<Grid
|
||||
item
|
||||
xs={1.5}
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "flex-end",
|
||||
paddingBottom: "5px",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
aria-label="Remove"
|
||||
sx={{ padding: 0 }}
|
||||
onClick={handleDelete}
|
||||
>
|
||||
{<DeleteIcon />}
|
||||
</IconButton>
|
||||
<DragIndicatorOutlinedIcon
|
||||
color="disabled"
|
||||
sx={[
|
||||
{
|
||||
marginRight: "6px",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
{noOfQueries > 1 &&
|
||||
index !== noOfQueries - 1 &&
|
||||
(index === 0 ? (
|
||||
<Grid item xs={12}>
|
||||
<Grid container>
|
||||
<Grid item xs={3.5}>
|
||||
<TextField
|
||||
select
|
||||
variant="filled"
|
||||
fullWidth
|
||||
value={joinOperator}
|
||||
onChange={(e) =>
|
||||
setJoinOperator(e.target.value === "AND" ? "AND" : "OR")
|
||||
}
|
||||
sx={{
|
||||
"& .MuiSelect-select": {
|
||||
display: "flex",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<MenuItem value="AND">And</MenuItem>
|
||||
<MenuItem value="OR">Or</MenuItem>
|
||||
</TextField>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
) : (
|
||||
<Grid item xs={12}>
|
||||
<Typography paddingLeft={1}>
|
||||
{joinOperator === "AND" ? "And" : "Or"}
|
||||
</Typography>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
128
src/components/TableToolbar/Filters/FilterInputsCollection.tsx
Normal file
128
src/components/TableToolbar/Filters/FilterInputsCollection.tsx
Normal file
@@ -0,0 +1,128 @@
|
||||
import FilterInputs from "./FilterInputs";
|
||||
|
||||
import { Button } from "@mui/material";
|
||||
|
||||
import type { useFilterInputs } from "./useFilterInputs";
|
||||
|
||||
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
|
||||
import AddIcon from "@mui/icons-material/Add";
|
||||
import { find } from "lodash-es";
|
||||
import { TableFilter } from "@src/types/table";
|
||||
import { generateId } from "@src/utils/table";
|
||||
|
||||
export interface IFilterInputsCollectionProps
|
||||
extends ReturnType<typeof useFilterInputs> {
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export default function FilterInputsCollection({
|
||||
filterColumns,
|
||||
selectedColumns,
|
||||
handleColumnChange,
|
||||
availableFiltersForEachSelectedColumn,
|
||||
queries,
|
||||
setQueries,
|
||||
disabled,
|
||||
joinOperator,
|
||||
setJoinOperator,
|
||||
}: IFilterInputsCollectionProps) {
|
||||
const onDragEnd = (result: any) => {
|
||||
if (!result.destination) return;
|
||||
|
||||
setQueries((prevQueries) => {
|
||||
const newQueries = [...prevQueries];
|
||||
const [reorderedItem] = newQueries.splice(result.source.index, 1);
|
||||
newQueries.splice(result.destination.index, 0, reorderedItem);
|
||||
return newQueries;
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
<Droppable droppableId="items">
|
||||
{(provided) => (
|
||||
<div {...provided.droppableProps} ref={provided.innerRef}>
|
||||
{queries.map((query, index) => {
|
||||
return (
|
||||
<Draggable
|
||||
key={query.id}
|
||||
draggableId={query.id.toString()}
|
||||
index={index}
|
||||
>
|
||||
{(provided) => (
|
||||
<div
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
ref={provided.innerRef}
|
||||
>
|
||||
<FilterInputs
|
||||
filterColumns={filterColumns}
|
||||
selectedColumn={selectedColumns[index]}
|
||||
handleChangeColumn={(key: string) => {
|
||||
handleColumnChange(query.id, key);
|
||||
}}
|
||||
availableFilters={
|
||||
availableFiltersForEachSelectedColumn[index]
|
||||
}
|
||||
query={query}
|
||||
setQuery={(newQuery: TableFilter) => {
|
||||
setQueries((prevQueries) => {
|
||||
const newQueries = [...prevQueries];
|
||||
newQueries[index] = newQuery;
|
||||
return newQueries;
|
||||
});
|
||||
}}
|
||||
disabled={disabled}
|
||||
joinOperator={joinOperator}
|
||||
setJoinOperator={setJoinOperator}
|
||||
handleDelete={() => {
|
||||
setQueries((prevQueries) => {
|
||||
const newQueries = [...prevQueries];
|
||||
newQueries.splice(index, 1);
|
||||
return newQueries;
|
||||
});
|
||||
}}
|
||||
index={index}
|
||||
noOfQueries={queries.length}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Draggable>
|
||||
);
|
||||
})}
|
||||
{provided.placeholder}
|
||||
</div>
|
||||
)}
|
||||
</Droppable>
|
||||
</DragDropContext>
|
||||
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
const column = find(filterColumns, (column) => {
|
||||
return !find(selectedColumns, { key: column.key });
|
||||
});
|
||||
|
||||
const id = generateId();
|
||||
|
||||
setQueries((prevQueries) => [
|
||||
...prevQueries,
|
||||
{
|
||||
key: "",
|
||||
operator: "is-not-empty",
|
||||
value: "",
|
||||
id,
|
||||
},
|
||||
]);
|
||||
|
||||
handleColumnChange(id, column?.key ?? filterColumns[0].key);
|
||||
}}
|
||||
startIcon={<AddIcon />}
|
||||
>
|
||||
Add Filter
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useState, useEffect } from "react";
|
||||
import { useAtom } from "jotai";
|
||||
import { useAtom, useSetAtom } from "jotai";
|
||||
import useMemoValue from "use-memo-value";
|
||||
import { isEmpty, isDate } from "lodash-es";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import { useSnackbar } from "notistack";
|
||||
|
||||
import {
|
||||
Tab,
|
||||
@@ -21,8 +18,7 @@ import TabList from "@mui/lab/TabList";
|
||||
import TabPanel from "@mui/lab/TabPanel";
|
||||
|
||||
import FiltersPopover from "./FiltersPopover";
|
||||
import FilterInputs from "./FilterInputs";
|
||||
import { changePageUrl, separateOperands } from "./utils";
|
||||
import FilterInputsCollection from "./FilterInputsCollection";
|
||||
|
||||
import {
|
||||
projectScope,
|
||||
@@ -39,16 +35,31 @@ import {
|
||||
tableSortsAtom,
|
||||
updateTableSchemaAtom,
|
||||
tableFiltersPopoverAtom,
|
||||
tableFiltersJoinAtom,
|
||||
} from "@src/atoms/tableScope";
|
||||
import { useFilterInputs, INITIAL_QUERY } from "./useFilterInputs";
|
||||
import { useFilterInputs } from "./useFilterInputs";
|
||||
import { analytics, logEvent } from "@src/analytics";
|
||||
import type { TableFilter } from "@src/types/table";
|
||||
import { generateId } from "@src/utils/table";
|
||||
import { useFilterUrl } from "./useFilterUrl";
|
||||
|
||||
const shouldDisableApplyButton = (value: any) =>
|
||||
isEmpty(value) &&
|
||||
!isDate(value) &&
|
||||
typeof value !== "boolean" &&
|
||||
typeof value !== "number";
|
||||
const shouldDisableApplyButton = (queries: any) => {
|
||||
for (let query of queries) {
|
||||
if (query.operator === "is-empty" || query.operator === "is-not-empty") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
isEmpty(query.value) &&
|
||||
!isDate(query.value) &&
|
||||
typeof query.value !== "boolean" &&
|
||||
typeof query.value !== "number"
|
||||
)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
enum FilterType {
|
||||
yourFilter = "local_filter",
|
||||
@@ -66,17 +77,16 @@ export default function Filters() {
|
||||
const [, setTableSorts] = useAtom(tableSortsAtom, tableScope);
|
||||
const [updateTableSchema] = useAtom(updateTableSchemaAtom, tableScope);
|
||||
const [{ defaultQuery }] = useAtom(tableFiltersPopoverAtom, tableScope);
|
||||
|
||||
const tableFilterInputs = useFilterInputs(tableColumnsOrdered);
|
||||
const setTableQuery = tableFilterInputs.setQuery;
|
||||
const setTableQueries = tableFilterInputs.setQueries;
|
||||
const userFilterInputs = useFilterInputs(tableColumnsOrdered, defaultQuery);
|
||||
const setUserQuery = userFilterInputs.setQuery;
|
||||
const { availableFilters, filterColumns } = userFilterInputs;
|
||||
const [searchParams] = useSearchParams();
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
useEffect(() => {
|
||||
let isFiltered = searchParams.get("filter");
|
||||
if (isFiltered) updateUserFilter(isFiltered);
|
||||
}, [searchParams]);
|
||||
const setUserQueries = userFilterInputs.setQueries;
|
||||
const { availableFiltersForEachSelectedColumn } = userFilterInputs;
|
||||
const availableFiltersForFirstColumn =
|
||||
availableFiltersForEachSelectedColumn[0];
|
||||
|
||||
const setTableFiltersJoin = useSetAtom(tableFiltersJoinAtom, tableScope);
|
||||
|
||||
// Get table filters & user filters from config documents
|
||||
const tableFilters = useMemoValue(
|
||||
@@ -91,58 +101,30 @@ export default function Filters() {
|
||||
const hasTableFilters =
|
||||
Array.isArray(tableFilters) && tableFilters.length > 0;
|
||||
const hasUserFilters = Array.isArray(userFilters) && userFilters.length > 0;
|
||||
function updateUserFilter(str: string) {
|
||||
let { operators, operands = [] } = separateOperands(str);
|
||||
if (!operators.length) return;
|
||||
if (operators.length) {
|
||||
let appliedFilter: TableFilter[] = [];
|
||||
appliedFilter = [
|
||||
{
|
||||
key: operands[0],
|
||||
operator: operators[0],
|
||||
value: Number(operands[1]),
|
||||
},
|
||||
];
|
||||
let isValidFilter = checkFilterValidation(appliedFilter[0]);
|
||||
if (isValidFilter) {
|
||||
setOverrideTableFilters(true);
|
||||
setUserFilters(appliedFilter);
|
||||
} else {
|
||||
enqueueSnackbar("Oops, Invalid filter!!!", { variant: "error" });
|
||||
setUserFilters([]);
|
||||
setOverrideTableFilters(false);
|
||||
userFilterInputs.resetQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
function checkFilterValidation(filter: TableFilter): boolean {
|
||||
let isFilterableColumn = filterColumns?.filter(
|
||||
(item) =>
|
||||
item.key === filter.key ||
|
||||
item.label === filter.key ||
|
||||
item.type === filter.key
|
||||
);
|
||||
if (!isFilterableColumn?.length) return false;
|
||||
filter.key = isFilterableColumn?.[0]?.value;
|
||||
filter.operator = filter.operator === "-is-" ? "id-equal" : filter.operator;
|
||||
filter.value =
|
||||
filter.operator === "id-equal" ? filter.value.toString() : filter.value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set the local table filter
|
||||
useEffect(() => {
|
||||
// Set local state for UI
|
||||
setTableQuery(
|
||||
Array.isArray(tableFilters) && tableFilters[0]
|
||||
? tableFilters[0]
|
||||
: INITIAL_QUERY
|
||||
);
|
||||
setUserQuery(
|
||||
Array.isArray(userFilters) && userFilters[0]
|
||||
? userFilters[0]
|
||||
: INITIAL_QUERY
|
||||
);
|
||||
if (
|
||||
Array.isArray(tableFilters) &&
|
||||
tableFilters &&
|
||||
tableFilters.length > 0
|
||||
) {
|
||||
// Older filters do not have ID. Migrating them here.
|
||||
for (const filter of tableFilters) {
|
||||
if (!filter.id) filter.id = generateId();
|
||||
}
|
||||
setTableQueries(tableFilters);
|
||||
}
|
||||
|
||||
if (Array.isArray(userFilters) && userFilters && userFilters.length > 0) {
|
||||
// Older filters do not have ID. Migrating them here.
|
||||
for (const filter of userFilters) {
|
||||
if (!filter.id) filter.id = generateId();
|
||||
}
|
||||
setUserQueries(userFilters);
|
||||
}
|
||||
|
||||
setCanOverrideCheckbox(tableFiltersOverridable);
|
||||
|
||||
let filtersToApply: TableFilter[] = [];
|
||||
@@ -156,7 +138,7 @@ export default function Filters() {
|
||||
} else if (hasUserFilters) {
|
||||
filtersToApply = userFilters;
|
||||
}
|
||||
updatePageURL(filtersToApply);
|
||||
|
||||
setLocalFilters(filtersToApply);
|
||||
// Reset order so we don’t have to make a new index
|
||||
if (filtersToApply.length) {
|
||||
@@ -167,9 +149,10 @@ export default function Filters() {
|
||||
hasUserFilters,
|
||||
setLocalFilters,
|
||||
setTableSorts,
|
||||
setTableQueries,
|
||||
tableFilters,
|
||||
tableFiltersOverridable,
|
||||
setUserQuery,
|
||||
setUserQueries,
|
||||
userFilters,
|
||||
userRoles,
|
||||
]);
|
||||
@@ -197,50 +180,104 @@ export default function Filters() {
|
||||
// When defaultQuery (from atom) is updated, update the UI
|
||||
useEffect(() => {
|
||||
if (defaultQuery) {
|
||||
setUserQuery(defaultQuery);
|
||||
setUserQueries([defaultQuery]);
|
||||
setTab("user");
|
||||
}
|
||||
}, [setUserQuery, defaultQuery]);
|
||||
}, [setUserQueries, defaultQuery]);
|
||||
|
||||
const [overrideTableFilters, setOverrideTableFilters] = useState(
|
||||
tableFiltersOverridden
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (userSettings.tables?.[tableId]?.joinOperator) {
|
||||
userFilterInputs.setJoinOperator(
|
||||
userSettings.tables?.[tableId]?.joinOperator === "AND" ? "AND" : "OR"
|
||||
);
|
||||
}
|
||||
|
||||
if (tableSchema.joinOperator) {
|
||||
tableFilterInputs.setJoinOperator(
|
||||
tableSchema.joinOperator === "AND" ? "AND" : "OR"
|
||||
);
|
||||
}
|
||||
}, [userSettings.tables?.[tableId]?.joinOperator, tableSchema.joinOperator]);
|
||||
|
||||
useEffect(() => {
|
||||
if (tableFiltersOverridable && (hasUserFilters || userFilters === null)) {
|
||||
setTableFiltersJoin(
|
||||
userSettings.tables?.[tableId]?.joinOperator === "AND" ? "AND" : "OR"
|
||||
);
|
||||
} else if (hasTableFilters) {
|
||||
setTableFiltersJoin(tableSchema.joinOperator === "AND" ? "AND" : "OR");
|
||||
} else if (hasUserFilters) {
|
||||
setTableFiltersJoin(
|
||||
userSettings.tables?.[tableId]?.joinOperator === "AND" ? "AND" : "OR"
|
||||
);
|
||||
}
|
||||
}, [
|
||||
tableFiltersOverridable,
|
||||
hasUserFilters,
|
||||
hasTableFilters,
|
||||
userFilters,
|
||||
tableSchema.joinOperator,
|
||||
userSettings.tables?.[tableId]?.joinOperator,
|
||||
]);
|
||||
|
||||
// Save table filters to table schema document
|
||||
const setTableFilters = (filters: TableFilter[]) => {
|
||||
const setTableFilters = (
|
||||
filters: TableFilter[],
|
||||
op: "AND" | "OR" = "AND"
|
||||
) => {
|
||||
logEvent(analytics, FilterType.tableFilter);
|
||||
if (updateTableSchema)
|
||||
updateTableSchema({ filters, filtersOverridable: canOverrideCheckbox });
|
||||
updateTableSchema({
|
||||
filters,
|
||||
filtersOverridable: canOverrideCheckbox,
|
||||
joinOperator: op,
|
||||
});
|
||||
};
|
||||
// Save user filters to user document
|
||||
// null overrides table filters
|
||||
const setUserFilters = (filters: TableFilter[] | null) => {
|
||||
const setUserFilters = (
|
||||
filters: TableFilter[] | null,
|
||||
op: "AND" | "OR" = "AND"
|
||||
) => {
|
||||
logEvent(analytics, FilterType.yourFilter);
|
||||
if (updateUserSettings && filters)
|
||||
updateUserSettings({ tables: { [`${tableId}`]: { filters } } });
|
||||
updateUserSettings({
|
||||
tables: { [`${tableId}`]: { filters, joinOperator: op } },
|
||||
});
|
||||
};
|
||||
function updatePageURL(filters: TableFilter[]) {
|
||||
if (!filters.length) {
|
||||
changePageUrl();
|
||||
} else {
|
||||
const [filter] = filters;
|
||||
const fieldName = filter.key === "_rowy_ref.id" ? "ID" : filter.key;
|
||||
const operator =
|
||||
filter.operator === "id-equal" ? "-is-" : filter.operator;
|
||||
const formattedValue = availableFilters?.valueFormatter
|
||||
? availableFilters.valueFormatter(filter.value, filter.operator)
|
||||
: filter.value.toString();
|
||||
const queryParams = `?filter=${fieldName}${operator}${formattedValue}`;
|
||||
changePageUrl(queryParams);
|
||||
|
||||
const { filtersUrl, updateFilterQueryParam } = useFilterUrl();
|
||||
|
||||
// If the filter in URL is not the same as currently applied local filter
|
||||
// then update the user filter.
|
||||
useEffect(() => {
|
||||
if (
|
||||
filtersUrl &&
|
||||
JSON.stringify(filtersUrl) !== JSON.stringify(appliedFilters)
|
||||
) {
|
||||
setUserFilters(filtersUrl);
|
||||
setOverrideTableFilters(true);
|
||||
}
|
||||
}
|
||||
}, [filtersUrl]);
|
||||
|
||||
// Update queyy param if the locally applied filter changes
|
||||
useEffect(() => {
|
||||
if (appliedFilters) {
|
||||
updateFilterQueryParam(appliedFilters);
|
||||
}
|
||||
}, [appliedFilters]);
|
||||
|
||||
return (
|
||||
<FiltersPopover
|
||||
appliedFilters={appliedFilters}
|
||||
hasAppliedFilters={hasAppliedFilters}
|
||||
hasTableFilters={hasTableFilters}
|
||||
tableFiltersOverridden={tableFiltersOverridden}
|
||||
availableFilters={availableFilters}
|
||||
availableFilters={availableFiltersForFirstColumn}
|
||||
setUserFilters={setUserFilters}
|
||||
>
|
||||
{({ handleClose }) => {
|
||||
@@ -305,7 +342,7 @@ export default function Filters() {
|
||||
<Divider style={{ marginTop: -1 }} />
|
||||
|
||||
<TabPanel value="user" className="content">
|
||||
<FilterInputs {...userFilterInputs} />
|
||||
<FilterInputsCollection {...userFilterInputs} />
|
||||
|
||||
{hasTableFilters && (
|
||||
<FormControlLabel
|
||||
@@ -330,31 +367,29 @@ export default function Filters() {
|
||||
>
|
||||
<Button
|
||||
disabled={
|
||||
!overrideTableFilters &&
|
||||
!tableFiltersOverridden &&
|
||||
userFilterInputs.query.key === ""
|
||||
(!overrideTableFilters && hasTableFilters) ||
|
||||
userFilterInputs.queries.length === 0
|
||||
}
|
||||
onClick={() => {
|
||||
setUserFilters(overrideTableFilters ? null : []);
|
||||
setUserFilters([]);
|
||||
userFilterInputs.resetQuery();
|
||||
}}
|
||||
>
|
||||
Clear
|
||||
{hasTableFilters &&
|
||||
(overrideTableFilters
|
||||
? " (ignore table filter)"
|
||||
: " (use table filter)")}
|
||||
Clear All
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
disabled={
|
||||
(!overrideTableFilters && hasTableFilters) ||
|
||||
shouldDisableApplyButton(userFilterInputs.query.value)
|
||||
shouldDisableApplyButton(userFilterInputs.queries)
|
||||
}
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
setUserFilters([userFilterInputs.query as TableFilter]);
|
||||
setUserFilters(
|
||||
userFilterInputs.queries as TableFilter[],
|
||||
userFilterInputs.joinOperator
|
||||
);
|
||||
handleClose();
|
||||
}}
|
||||
>
|
||||
@@ -364,7 +399,7 @@ export default function Filters() {
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel value="table" className="content">
|
||||
<FilterInputs {...tableFilterInputs} />
|
||||
<FilterInputsCollection {...tableFilterInputs} />
|
||||
|
||||
<FormControlLabel
|
||||
control={
|
||||
@@ -402,23 +437,26 @@ export default function Filters() {
|
||||
spacing={1}
|
||||
>
|
||||
<Button
|
||||
disabled={tableFilterInputs.query.key === ""}
|
||||
disabled={tableFilterInputs.queries.length === 0}
|
||||
onClick={() => {
|
||||
setTableFilters([]);
|
||||
tableFilterInputs.resetQuery();
|
||||
}}
|
||||
>
|
||||
Clear
|
||||
Clear All
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
disabled={shouldDisableApplyButton(
|
||||
tableFilterInputs.query.value
|
||||
tableFilterInputs.queries
|
||||
)}
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
setTableFilters([tableFilterInputs.query as TableFilter]);
|
||||
setTableFilters(
|
||||
tableFilterInputs.queries as TableFilter[],
|
||||
tableFilterInputs.joinOperator
|
||||
);
|
||||
handleClose();
|
||||
}}
|
||||
>
|
||||
@@ -434,7 +472,7 @@ export default function Filters() {
|
||||
if (hasTableFilters && !tableFiltersOverridable) {
|
||||
return (
|
||||
<div className="content">
|
||||
<FilterInputs {...tableFilterInputs} disabled />
|
||||
<FilterInputsCollection {...tableFilterInputs} disabled />
|
||||
|
||||
<Alert severity="info" style={{ width: "auto" }}>
|
||||
An ADMIN user has set the filter for this table
|
||||
@@ -447,7 +485,7 @@ export default function Filters() {
|
||||
if (hasTableFilters && tableFiltersOverridable) {
|
||||
return (
|
||||
<div className="content">
|
||||
<FilterInputs {...userFilterInputs} />
|
||||
<FilterInputsCollection {...userFilterInputs} />
|
||||
|
||||
<FormControlLabel
|
||||
control={
|
||||
@@ -470,28 +508,28 @@ export default function Filters() {
|
||||
disabled={
|
||||
!overrideTableFilters &&
|
||||
!tableFiltersOverridden &&
|
||||
userFilterInputs.query.key === ""
|
||||
userFilterInputs.queries.length === 0
|
||||
}
|
||||
onClick={() => {
|
||||
setUserFilters(overrideTableFilters ? null : []);
|
||||
setUserFilters([]);
|
||||
userFilterInputs.resetQuery();
|
||||
}}
|
||||
>
|
||||
Clear
|
||||
{overrideTableFilters
|
||||
? " (ignore table filter)"
|
||||
: " (use table filter)"}
|
||||
Clear All
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
disabled={
|
||||
(!overrideTableFilters && hasTableFilters) ||
|
||||
shouldDisableApplyButton(userFilterInputs.query.value)
|
||||
shouldDisableApplyButton(userFilterInputs.queries)
|
||||
}
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
setUserFilters([userFilterInputs.query as TableFilter]);
|
||||
setUserFilters(
|
||||
userFilterInputs.queries as TableFilter[],
|
||||
userFilterInputs.joinOperator
|
||||
);
|
||||
handleClose();
|
||||
}}
|
||||
>
|
||||
@@ -505,7 +543,7 @@ export default function Filters() {
|
||||
// Non-ADMIN, no table filters
|
||||
return (
|
||||
<div className="content">
|
||||
<FilterInputs {...userFilterInputs} />
|
||||
<FilterInputsCollection {...userFilterInputs} />
|
||||
|
||||
<Stack
|
||||
direction="row"
|
||||
@@ -514,23 +552,24 @@ export default function Filters() {
|
||||
spacing={1}
|
||||
>
|
||||
<Button
|
||||
disabled={userFilterInputs.query.key === ""}
|
||||
disabled={userFilterInputs.queries.length === 0}
|
||||
onClick={() => {
|
||||
setUserFilters([]);
|
||||
userFilterInputs.resetQuery();
|
||||
}}
|
||||
>
|
||||
Clear
|
||||
Clear All
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
disabled={shouldDisableApplyButton(
|
||||
userFilterInputs.query.value
|
||||
)}
|
||||
disabled={shouldDisableApplyButton(userFilterInputs.queries)}
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
setUserFilters([userFilterInputs.query as TableFilter]);
|
||||
setUserFilters(
|
||||
userFilterInputs.queries as TableFilter[],
|
||||
userFilterInputs.joinOperator
|
||||
);
|
||||
handleClose();
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -15,7 +15,9 @@ export interface IFiltersPopoverProps {
|
||||
hasAppliedFilters: boolean;
|
||||
hasTableFilters: boolean;
|
||||
tableFiltersOverridden: boolean;
|
||||
availableFilters: ReturnType<typeof useFilterInputs>["availableFilters"];
|
||||
availableFilters: ReturnType<
|
||||
typeof useFilterInputs
|
||||
>["availableFiltersForEachSelectedColumn"][0];
|
||||
setUserFilters: (filters: TableFilter[]) => void;
|
||||
|
||||
children: (props: { handleClose: () => void }) => React.ReactNode;
|
||||
@@ -50,7 +52,7 @@ export default function FiltersPopover({
|
||||
startIcon={<FilterIcon />}
|
||||
active={hasAppliedFilters}
|
||||
style={
|
||||
hasAppliedFilters
|
||||
appliedFilters.length === 1
|
||||
? {
|
||||
borderTopRightRadius: 0,
|
||||
borderBottomRightRadius: 0,
|
||||
@@ -61,60 +63,61 @@ export default function FiltersPopover({
|
||||
}
|
||||
aria-describedby={popoverId}
|
||||
>
|
||||
{hasAppliedFilters ? "Filtered" : "Filter"}
|
||||
{hasAppliedFilters ? `Filtered: ${appliedFilters.length}` : "Filter"}
|
||||
</ButtonWithStatus>
|
||||
|
||||
{appliedFilters.map((filter) => {
|
||||
const fieldName = filter.key === "_rowy_ref.id" ? "ID" : filter.key;
|
||||
const operator = (availableFilters?.operators ?? []).find(
|
||||
(f) => f.value === filter.operator
|
||||
);
|
||||
const operatorLabel = (operator?.label ?? filter.operator).replace(
|
||||
"id-equal",
|
||||
"is"
|
||||
);
|
||||
{appliedFilters.length === 1 &&
|
||||
appliedFilters.map((filter) => {
|
||||
const fieldName = filter.key === "_rowy_ref.id" ? "ID" : filter.key;
|
||||
const operator = (availableFilters?.operators ?? []).find(
|
||||
(f) => f.value === filter.operator
|
||||
);
|
||||
const operatorLabel = (operator?.label ?? filter.operator).replace(
|
||||
"id-equal",
|
||||
"is"
|
||||
);
|
||||
|
||||
const formattedValue = availableFilters?.valueFormatter
|
||||
? availableFilters.valueFormatter(filter.value, filter.operator)
|
||||
: filter.value.toString();
|
||||
const formattedValue = availableFilters?.valueFormatter
|
||||
? availableFilters.valueFormatter(filter.value, filter.operator)
|
||||
: filter.value.toString();
|
||||
|
||||
return (
|
||||
<Chip
|
||||
key={filter.key}
|
||||
label={
|
||||
<Typography variant="inherit" component="span">
|
||||
{fieldName}{" "}
|
||||
<Typography
|
||||
variant="inherit"
|
||||
display="inline"
|
||||
color="text.secondary"
|
||||
fontWeight="normal"
|
||||
>
|
||||
{operatorLabel}
|
||||
</Typography>{" "}
|
||||
{formattedValue}
|
||||
</Typography>
|
||||
}
|
||||
onDelete={
|
||||
hasTableFilters && !tableFiltersOverridden
|
||||
? undefined
|
||||
: () => setUserFilters([])
|
||||
}
|
||||
sx={{
|
||||
borderRadius: 1,
|
||||
borderTopLeftRadius: 0,
|
||||
borderBottomLeftRadius: 0,
|
||||
borderLeft: "none",
|
||||
return (
|
||||
<Chip
|
||||
key={filter.key}
|
||||
label={
|
||||
<Typography variant="inherit" component="span">
|
||||
{fieldName}{" "}
|
||||
<Typography
|
||||
variant="inherit"
|
||||
display="inline"
|
||||
color="text.secondary"
|
||||
fontWeight="normal"
|
||||
>
|
||||
{operatorLabel}
|
||||
</Typography>{" "}
|
||||
{formattedValue}
|
||||
</Typography>
|
||||
}
|
||||
onDelete={
|
||||
hasTableFilters && !tableFiltersOverridden
|
||||
? undefined
|
||||
: () => setUserFilters([])
|
||||
}
|
||||
sx={{
|
||||
borderRadius: 1,
|
||||
borderTopLeftRadius: 0,
|
||||
borderBottomLeftRadius: 0,
|
||||
borderLeft: "none",
|
||||
|
||||
backgroundColor: "background.paper",
|
||||
height: 32,
|
||||
backgroundColor: "background.paper",
|
||||
height: 32,
|
||||
|
||||
"& .MuiChip-label": { px: 1.5 },
|
||||
}}
|
||||
variant="outlined"
|
||||
/>
|
||||
);
|
||||
})}
|
||||
"& .MuiChip-label": { px: 1.5 },
|
||||
}}
|
||||
variant="outlined"
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
|
||||
<Popover
|
||||
|
||||
@@ -5,8 +5,7 @@ import { getFieldType, getFieldProp } from "@src/components/fields";
|
||||
import { FieldType } from "@src/constants/fields";
|
||||
import type { ColumnConfig, TableFilter } from "@src/types/table";
|
||||
import type { IFieldConfig } from "@src/components/fields/types";
|
||||
|
||||
export const INITIAL_QUERY = { key: "", operator: "", value: "" };
|
||||
import { generateId } from "@src/utils/table";
|
||||
|
||||
export const useFilterInputs = (
|
||||
columns: ColumnConfig[],
|
||||
@@ -34,50 +33,112 @@ export const useFilterInputs = (
|
||||
config: {},
|
||||
});
|
||||
|
||||
const INITIAL_QUERY: TableFilter[] =
|
||||
filterColumns && filterColumns.length > 0
|
||||
? [
|
||||
{
|
||||
key: filterColumns[0].key,
|
||||
operator:
|
||||
filterColumns[0].key === "_rowy_ref.id"
|
||||
? "id-equal"
|
||||
: getFieldProp("filter", getFieldType(filterColumns[0]))
|
||||
.operators[0].value,
|
||||
value:
|
||||
filterColumns[0].key === "_rowy_ref.id"
|
||||
? ""
|
||||
: getFieldProp("filter", getFieldType(filterColumns[0]))
|
||||
.defaultValue ?? "",
|
||||
id: generateId(),
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
// State for filter inputs
|
||||
const [query, setQuery] = useState<TableFilter | typeof INITIAL_QUERY>(
|
||||
defaultQuery || INITIAL_QUERY
|
||||
const [queries, setQueries] = useState<TableFilter[]>(
|
||||
defaultQuery ? [{ ...defaultQuery, id: generateId() }] : INITIAL_QUERY
|
||||
);
|
||||
const resetQuery = () => setQuery(INITIAL_QUERY);
|
||||
const resetQuery = () => setQueries([]);
|
||||
|
||||
// State for filter inputs joined by AND/OR
|
||||
const [joinOperator, setJoinOperator] = useState<"AND" | "OR">("AND");
|
||||
|
||||
// When the user sets a new column, automatically set the operator and value
|
||||
const handleChangeColumn = (value: string | null) => {
|
||||
if (value === "_rowy_ref.id") {
|
||||
setQuery({ key: "_rowy_ref.id", operator: "id-equal", value: "" });
|
||||
const handleColumnChange = (oldId: string, newKey: string) => {
|
||||
if (newKey === "_rowy_ref.id") {
|
||||
setQueries((prevQueries) => {
|
||||
return prevQueries.map((q) => {
|
||||
if (q.id === oldId)
|
||||
return {
|
||||
key: newKey,
|
||||
operator: "id-equal",
|
||||
value: "",
|
||||
id: q.id,
|
||||
};
|
||||
|
||||
return q;
|
||||
});
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const column = find(filterColumns, ["key", value]);
|
||||
|
||||
const column = find(filterColumns, ["key", newKey]);
|
||||
if (column) {
|
||||
const filter = getFieldProp("filter", getFieldType(column));
|
||||
setQuery({
|
||||
key: column.key,
|
||||
operator: filter.operators[0].value,
|
||||
value: filter.defaultValue ?? "",
|
||||
setQueries((prevQueries) => {
|
||||
return prevQueries.map((q) => {
|
||||
if (q.id === oldId)
|
||||
return {
|
||||
key: newKey,
|
||||
operator: filter.operators[0].value,
|
||||
value: filter.defaultValue ?? "",
|
||||
id: q.id,
|
||||
};
|
||||
|
||||
return q;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
setQuery(INITIAL_QUERY);
|
||||
setQueries((prevQueries) => {
|
||||
return prevQueries.map((q) => {
|
||||
if (q.id === oldId)
|
||||
return {
|
||||
key: newKey,
|
||||
operator: "is-not-empty",
|
||||
value: "",
|
||||
id: q.id,
|
||||
};
|
||||
|
||||
return q;
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Get the column config
|
||||
const selectedColumn = find(filterColumns, ["key", query?.key]);
|
||||
// Get available filters from selected column type
|
||||
const availableFilters: IFieldConfig["filter"] =
|
||||
query?.key === "_rowy_ref.id"
|
||||
? { operators: [{ value: "id-equal", label: "is" }] }
|
||||
: selectedColumn
|
||||
? getFieldProp("filter", getFieldType(selectedColumn))
|
||||
: undefined;
|
||||
const selectedColumns = [];
|
||||
for (const query of queries) {
|
||||
const column = find(filterColumns, ["key", query.key]);
|
||||
if (column) selectedColumns.push(column);
|
||||
}
|
||||
|
||||
const availableFiltersForEachSelectedColumn: IFieldConfig["filter"][] =
|
||||
selectedColumns.map((column) => {
|
||||
if (column.key === "_rowy_ref.id") {
|
||||
return { operators: [{ value: "id-equal", label: "is" }] };
|
||||
}
|
||||
return getFieldProp("filter", getFieldType(column));
|
||||
});
|
||||
|
||||
return {
|
||||
filterColumns,
|
||||
selectedColumn,
|
||||
handleChangeColumn,
|
||||
availableFilters,
|
||||
query,
|
||||
setQuery,
|
||||
selectedColumns,
|
||||
handleColumnChange,
|
||||
availableFiltersForEachSelectedColumn,
|
||||
queries,
|
||||
setQueries,
|
||||
resetQuery,
|
||||
joinOperator,
|
||||
setJoinOperator,
|
||||
} as const;
|
||||
};
|
||||
|
||||
64
src/components/TableToolbar/Filters/useFilterUrl.tsx
Normal file
64
src/components/TableToolbar/Filters/useFilterUrl.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import { TableFilter } from "@src/types/table";
|
||||
import { useSnackbar } from "notistack";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
|
||||
function isTableFilter(filter: any): filter is TableFilter {
|
||||
if (typeof filter !== "object") return false;
|
||||
if ("key" in filter === false) return false;
|
||||
if ("id" in filter === false) return false;
|
||||
if ("value" in filter === false) return false;
|
||||
if ("operator" in filter === false) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Hook to manage filter as a query parameter */
|
||||
export function useFilterUrl() {
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
const [filters, setFilters] = useState<TableFilter[] | null>(null);
|
||||
|
||||
// Fetch filter from URL and update user filter
|
||||
useEffect(() => {
|
||||
const filterParam = searchParams.get("filter");
|
||||
|
||||
if (filterParam) {
|
||||
try {
|
||||
const _filters = JSON.parse(decodeURIComponent(filterParam));
|
||||
|
||||
if (!Array.isArray(_filters))
|
||||
throw new Error("Filter should be an array");
|
||||
|
||||
for (const _filter of _filters) {
|
||||
if (!isTableFilter(_filter)) throw new Error("Invalid Filter");
|
||||
}
|
||||
|
||||
setFilters(_filters);
|
||||
} catch (err) {
|
||||
enqueueSnackbar("Oops, filter in URL is incorrect!!!", {
|
||||
variant: "error",
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [searchParams]);
|
||||
|
||||
const updateFilterQueryParam = (filter: TableFilter[]) => {
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
if (filter.length === 0) {
|
||||
searchParams.delete("filter");
|
||||
} else {
|
||||
// Due to the nature of searchParams, filter is being encoded twice. Once by
|
||||
// encodeURIComponent and then by searchParams. We can't remove encodeURIComponent
|
||||
// because searchParams uses application/x-www-form-urlencoded which is not URL safe.
|
||||
searchParams.set("filter", encodeURIComponent(JSON.stringify(filter)));
|
||||
}
|
||||
setSearchParams(searchParams, { replace: true });
|
||||
};
|
||||
|
||||
return {
|
||||
/** Table filter present as a query param in the URL */
|
||||
filtersUrl: filters,
|
||||
/** Use this function to update the filter query param */
|
||||
updateFilterQueryParam,
|
||||
};
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
export const URL =
|
||||
window.location.protocol +
|
||||
"//" +
|
||||
window.location.host +
|
||||
window.location.pathname;
|
||||
export function separateOperands(str: string): {
|
||||
operators: any[];
|
||||
operands: string[];
|
||||
} {
|
||||
const operators = findOperators(str);
|
||||
const operands = str.split(
|
||||
new RegExp(operators.map((op) => `\\${op}`).join("|"), "g")
|
||||
);
|
||||
return { operators, operands };
|
||||
}
|
||||
export function changePageUrl(newURL: string | undefined = URL) {
|
||||
if (newURL !== URL) {
|
||||
newURL = URL + newURL;
|
||||
}
|
||||
window.history.pushState({ path: newURL }, "", newURL);
|
||||
}
|
||||
|
||||
function findOperators(str: string) {
|
||||
const operators = [">=", "<=", ">", "<", "==", "!=", "=", "-is-"];
|
||||
const regex = new RegExp(operators.map((op) => `\\${op}`).join("|"), "g");
|
||||
return str.match(regex) || [];
|
||||
}
|
||||
@@ -9,4 +9,12 @@ export const filterOperators: IFilterOperator[] = [
|
||||
label: "not equals",
|
||||
value: "!=",
|
||||
},
|
||||
{
|
||||
label: "is empty",
|
||||
value: "is-empty",
|
||||
},
|
||||
{
|
||||
label: "is not empty",
|
||||
value: "is-not-empty",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -9,4 +9,12 @@ export const filterOperators: IFilterOperator[] = [
|
||||
label: "not equals",
|
||||
value: "!=",
|
||||
},
|
||||
{
|
||||
label: "is empty",
|
||||
value: "is-empty",
|
||||
},
|
||||
{
|
||||
label: "is not empty",
|
||||
value: "is-not-empty",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -19,11 +19,12 @@ import {
|
||||
deleteField,
|
||||
CollectionReference,
|
||||
Query,
|
||||
QueryConstraint,
|
||||
WhereFilterOp,
|
||||
documentId,
|
||||
getCountFromServer,
|
||||
DocumentData,
|
||||
or,
|
||||
QueryFieldFilterConstraint,
|
||||
} from "firebase/firestore";
|
||||
import { useErrorHandler } from "react-error-boundary";
|
||||
|
||||
@@ -66,6 +67,8 @@ interface IUseFirestoreCollectionWithAtomOptions<T> {
|
||||
nextPageAtom?: PrimitiveAtom<NextPageState>;
|
||||
/** Set this atom's value to the number of docs in the collection on each new snapshot */
|
||||
serverDocCountAtom?: PrimitiveAtom<number | undefined>;
|
||||
|
||||
joinOperator?: "AND" | "OR";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,6 +103,7 @@ export function useFirestoreCollectionWithAtom<
|
||||
deleteDocAtom,
|
||||
nextPageAtom,
|
||||
serverDocCountAtom,
|
||||
joinOperator,
|
||||
} = options || {};
|
||||
|
||||
const [firebaseDb] = useAtom(firebaseDbAtom, projectScope);
|
||||
@@ -140,6 +144,7 @@ export function useFirestoreCollectionWithAtom<
|
||||
page,
|
||||
pageSize,
|
||||
filters,
|
||||
joinOperator,
|
||||
sorts,
|
||||
onError
|
||||
),
|
||||
@@ -152,6 +157,9 @@ export function useFirestoreCollectionWithAtom<
|
||||
)
|
||||
return false;
|
||||
|
||||
// If joinOperator is not equal, update the query
|
||||
if (next?.joinOperator !== prev?.joinOperator) return false;
|
||||
|
||||
// If sorts are not equal, update the query
|
||||
// Overrides isLastPage check
|
||||
if (JSON.stringify(next?.sorts) !== JSON.stringify(prev?.sorts))
|
||||
@@ -309,6 +317,7 @@ const getQuery = <T>(
|
||||
page: number,
|
||||
pageSize: number,
|
||||
filters: IUseFirestoreCollectionWithAtomOptions<T>["filters"],
|
||||
joinOperator: "AND" | "OR" | undefined,
|
||||
sorts: IUseFirestoreCollectionWithAtomOptions<T>["sorts"],
|
||||
onError: IUseFirestoreCollectionWithAtomOptions<T>["onError"]
|
||||
) => {
|
||||
@@ -335,19 +344,37 @@ const getQuery = <T>(
|
||||
const limit = (page + 1) * pageSize;
|
||||
const firestoreFilters = tableFiltersToFirestoreFilters(filters || []);
|
||||
|
||||
return {
|
||||
query: query<T>(
|
||||
collectionRef,
|
||||
queryLimit(limit),
|
||||
...firestoreFilters,
|
||||
...(sorts?.map((order) => orderBy(order.key, order.direction)) || [])
|
||||
),
|
||||
page,
|
||||
limit,
|
||||
firestoreFilters,
|
||||
sorts,
|
||||
unlimitedQuery: query<T>(collectionRef, ...firestoreFilters),
|
||||
};
|
||||
return joinOperator === "OR"
|
||||
? {
|
||||
query: query<T>(
|
||||
collectionRef,
|
||||
or(...firestoreFilters),
|
||||
queryLimit(limit),
|
||||
...(sorts?.map((order) => orderBy(order.key, order.direction)) ||
|
||||
[])
|
||||
),
|
||||
page,
|
||||
limit,
|
||||
firestoreFilters,
|
||||
sorts,
|
||||
unlimitedQuery: query<T>(collectionRef, ...firestoreFilters),
|
||||
joinOperator,
|
||||
}
|
||||
: {
|
||||
query: query<T>(
|
||||
collectionRef,
|
||||
queryLimit(limit),
|
||||
...firestoreFilters,
|
||||
...(sorts?.map((order) => orderBy(order.key, order.direction)) ||
|
||||
[])
|
||||
),
|
||||
page,
|
||||
limit,
|
||||
firestoreFilters,
|
||||
sorts,
|
||||
unlimitedQuery: query<T>(collectionRef, ...firestoreFilters),
|
||||
joinOperator,
|
||||
};
|
||||
} catch (e) {
|
||||
if (onError) onError(e as FirestoreError);
|
||||
return null;
|
||||
@@ -361,7 +388,7 @@ const getQuery = <T>(
|
||||
* @returns Array of Firestore query `where` constraints
|
||||
*/
|
||||
export const tableFiltersToFirestoreFilters = (filters: TableFilter[]) => {
|
||||
const firestoreFilters: QueryConstraint[] = [];
|
||||
const firestoreFilters: QueryFieldFilterConstraint[] = [];
|
||||
|
||||
for (const filter of filters) {
|
||||
if (filter.operator.startsWith("date-")) {
|
||||
@@ -405,6 +432,11 @@ export const tableFiltersToFirestoreFilters = (filters: TableFilter[]) => {
|
||||
where(filter.key.concat(".hex"), "!=", filter.value.hex.toString())
|
||||
);
|
||||
continue;
|
||||
} else if (filter.operator === "is-empty") {
|
||||
firestoreFilters.push(where(filter.key, "==", ""));
|
||||
continue;
|
||||
} else if (filter.operator === "is-not-empty") {
|
||||
firestoreFilters.push(where(filter.key, "!=", ""));
|
||||
} else if (filter.operator === "array-contains") {
|
||||
if (!filter.value || !filter.value.length) continue;
|
||||
// make the value as a singular string
|
||||
@@ -413,6 +445,7 @@ export const tableFiltersToFirestoreFilters = (filters: TableFilter[]) => {
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
firestoreFilters.push(
|
||||
where(filter.key, filter.operator as WhereFilterOp, filter.value)
|
||||
);
|
||||
|
||||
@@ -21,6 +21,7 @@ import { firebaseDbAtom } from "@src/sources/ProjectSourceFirebase";
|
||||
import { currentUserAtom, projectScope } from "@src/atoms/projectScope";
|
||||
import { doc, setDoc, updateDoc } from "firebase/firestore";
|
||||
import { TABLE_SCHEMAS } from "@src/config/dbPaths";
|
||||
import { generateId } from "@src/utils/table";
|
||||
|
||||
function TableTestPage() {
|
||||
const [tableId] = useAtom(tableIdAtom, tableScope);
|
||||
@@ -78,7 +79,14 @@ function TableTestPage() {
|
||||
|
||||
<button
|
||||
onClick={() =>
|
||||
setTableFilters([{ key: "signedUp", operator: "==", value: true }])
|
||||
setTableFilters([
|
||||
{
|
||||
key: "signedUp",
|
||||
operator: "==",
|
||||
value: true,
|
||||
id: generateId(),
|
||||
},
|
||||
])
|
||||
}
|
||||
>
|
||||
Set table filters
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
_deleteRowDbAtom,
|
||||
tableNextPageAtom,
|
||||
serverDocCountAtom,
|
||||
tableFiltersJoinAtom,
|
||||
} from "@src/atoms/tableScope";
|
||||
|
||||
import useFirestoreDocWithAtom, {
|
||||
@@ -112,6 +113,8 @@ export const TableSourceFirestore = memo(function TableSourceFirestore() {
|
||||
}
|
||||
);
|
||||
|
||||
const [joinOperator] = useAtom(tableFiltersJoinAtom, tableScope);
|
||||
|
||||
// Get table filters and sorts
|
||||
const [filters] = useAtom(tableFiltersAtom, tableScope);
|
||||
const [sorts] = useAtom(tableSortsAtom, tableScope);
|
||||
@@ -130,6 +133,7 @@ export const TableSourceFirestore = memo(function TableSourceFirestore() {
|
||||
tableSettings.collection,
|
||||
{
|
||||
filters,
|
||||
joinOperator,
|
||||
sorts,
|
||||
page,
|
||||
collectionGroup: isCollectionGroup,
|
||||
|
||||
1
src/types/settings.d.ts
vendored
1
src/types/settings.d.ts
vendored
@@ -57,6 +57,7 @@ export type UserSettings = Partial<{
|
||||
filters: TableFilter[];
|
||||
hiddenFields: string[];
|
||||
sorts: TableSort[];
|
||||
joinOperator: "AND" | "OR";
|
||||
}>
|
||||
>;
|
||||
|
||||
|
||||
6
src/types/table.d.ts
vendored
6
src/types/table.d.ts
vendored
@@ -123,6 +123,8 @@ export type TableSchema = {
|
||||
subTables?: SubTablesSchema;
|
||||
/** @deprecated Migrate to Extensions */
|
||||
sparks?: string;
|
||||
|
||||
joinOperator?: "AND" | "OR";
|
||||
};
|
||||
|
||||
export type SubTablesSchema = {
|
||||
@@ -194,8 +196,10 @@ export type TableFilter = {
|
||||
| "id-equal"
|
||||
| "color-equal"
|
||||
| "color-not-equal"
|
||||
| "-is-";
|
||||
| "is-empty"
|
||||
| "is-not-empty";
|
||||
value: any;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export const TableTools = [
|
||||
|
||||
669
yarn.lock
669
yarn.lock
@@ -1658,176 +1658,174 @@
|
||||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@firebase/analytics-compat@0.1.17":
|
||||
version "0.1.17"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/analytics-compat/-/analytics-compat-0.1.17.tgz#7be65327b3fe8a4dceab636562fc10032064280f"
|
||||
integrity sha512-36ByEDsH6/3YNuD6yig30s2A/+E1pt333r8SJirUE8+aHYl/DGX0PXplKvJWDGamYYjMwet3Kt4XRrB1NY8mLg==
|
||||
"@firebase/analytics-compat@0.2.6":
|
||||
version "0.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/analytics-compat/-/analytics-compat-0.2.6.tgz#50063978c42f13eb800e037e96ac4b17236841f4"
|
||||
integrity sha512-4MqpVLFkGK7NJf/5wPEEP7ePBJatwYpyjgJ+wQHQGHfzaCDgntOnl9rL2vbVGGKCnRqWtZDIWhctB86UWXaX2Q==
|
||||
dependencies:
|
||||
"@firebase/analytics" "0.8.4"
|
||||
"@firebase/analytics-types" "0.7.1"
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/analytics" "0.10.0"
|
||||
"@firebase/analytics-types" "0.8.0"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/analytics-types@0.7.1":
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/analytics-types/-/analytics-types-0.7.1.tgz#21556098e83aa14f192ce84051c81d794b2eb150"
|
||||
integrity sha512-a1INLjelc1Mqrt2CbGmGdlNBj0zsvwBv0K5q5C6Fje8GSXBMc3+iQQQjzYe/4KkK6nL54UP7ZMeI/Q3VEW72FA==
|
||||
"@firebase/analytics-types@0.8.0":
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/analytics-types/-/analytics-types-0.8.0.tgz#551e744a29adbc07f557306530a2ec86add6d410"
|
||||
integrity sha512-iRP+QKI2+oz3UAh4nPEq14CsEjrjD6a5+fuypjScisAh9kXKFvdJOZJDwk7kikLvWVLGEs9+kIUS4LPQV7VZVw==
|
||||
|
||||
"@firebase/analytics@0.8.4":
|
||||
version "0.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/analytics/-/analytics-0.8.4.tgz#596e79258605c8322ef25f47cd4e1ff94579dd90"
|
||||
integrity sha512-Bgr2tMexv0YrL6kjrOF1xVRts8PM6WWmROpfRQjh0xFU4QSoofBJhkVn2NXDXkHWrr5slFfqB5yOnmgAIsHiMw==
|
||||
"@firebase/analytics@0.10.0":
|
||||
version "0.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/analytics/-/analytics-0.10.0.tgz#9c6986acd573c6c6189ffb52d0fd63c775db26d7"
|
||||
integrity sha512-Locv8gAqx0e+GX/0SI3dzmBY5e9kjVDtD+3zCFLJ0tH2hJwuCAiL+5WkHuxKj92rqQj/rvkBUCfA1ewlX2hehg==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/installations" "0.5.16"
|
||||
"@firebase/logger" "0.3.4"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/installations" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/app-check-compat@0.2.17":
|
||||
version "0.2.17"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-check-compat/-/app-check-compat-0.2.17.tgz#c949976e8353156d521a52664d3735d4aa3c4417"
|
||||
integrity sha512-yhiAy6U4MuhbY+DCgvG5FcrXkAL+7YohRzqywycQKr31k/ftelbR5l9Zmo2WJMxdLxfubnnqeG/BYCRHlSvk7A==
|
||||
"@firebase/app-check-compat@0.3.7":
|
||||
version "0.3.7"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-check-compat/-/app-check-compat-0.3.7.tgz#e150f61d653a0f2043a34dcb995616a717161839"
|
||||
integrity sha512-cW682AxsyP1G+Z0/P7pO/WT2CzYlNxoNe5QejVarW2o5ZxeWSSPAiVEwpEpQR/bUlUmdeWThYTMvBWaopdBsqw==
|
||||
dependencies:
|
||||
"@firebase/app-check" "0.5.17"
|
||||
"@firebase/app-check-types" "0.4.1"
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/logger" "0.3.4"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/app-check" "0.8.0"
|
||||
"@firebase/app-check-types" "0.5.0"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/app-check-interop-types@0.1.1":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-check-interop-types/-/app-check-interop-types-0.1.1.tgz#7a6e01f4bc37195e58e62d7e4a2995e54b1957b8"
|
||||
integrity sha512-QpYh5GmiLA9ob8NWAZpHbNNl9TzxxZI4NLevT6MYPRDXKG9BSmBI7FATRfm5uv2QQUVSQrESKog5CCmU16v+7Q==
|
||||
"@firebase/app-check-interop-types@0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.0.tgz#b27ea1397cb80427f729e4bbf3a562f2052955c4"
|
||||
integrity sha512-xAxHPZPIgFXnI+vb4sbBjZcde7ZluzPPaSK7Lx3/nmuVk4TjZvnL8ONnkd4ERQKL8WePQySU+pRcWkh8rDf5Sg==
|
||||
|
||||
"@firebase/app-check-types@0.4.1":
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-check-types/-/app-check-types-0.4.1.tgz#7807e761b119d71562611a14c307ac8ca2981103"
|
||||
integrity sha512-4X79w2X0H5i5qvaho3qkjZg5qdERnKR4gCfy/fxDmdMMP4QgNJHJ9IBk1E+c4cm5HlaZVcLq9K6z8xaRqjZhyw==
|
||||
"@firebase/app-check-types@0.5.0":
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-check-types/-/app-check-types-0.5.0.tgz#1b02826213d7ce6a1cf773c329b46ea1c67064f4"
|
||||
integrity sha512-uwSUj32Mlubybw7tedRzR24RP8M8JUVR3NPiMk3/Z4bCmgEKTlQBwMXrehDAZ2wF+TsBq0SN1c6ema71U/JPyQ==
|
||||
|
||||
"@firebase/app-check@0.5.17":
|
||||
version "0.5.17"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-check/-/app-check-0.5.17.tgz#d24aa73f9ac887711c79986c90f18b0f15cb2c14"
|
||||
integrity sha512-P4bm0lbs+VgS7pns322GC0hyKuTDCqYk2X4FGBf133LZaw1NXJpzOteqPdCT0hBCaR0QSHk49gxx+bdnSdd5Fg==
|
||||
"@firebase/app-check@0.8.0":
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-check/-/app-check-0.8.0.tgz#b531ec40900af9c3cf1ec63de9094a0ddd733d6a"
|
||||
integrity sha512-dRDnhkcaC2FspMiRK/Vbp+PfsOAEP6ZElGm9iGFJ9fDqHoPs0HOPn7dwpJ51lCFi1+2/7n5pRPGhqF/F03I97g==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/logger" "0.3.4"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/app-compat@0.1.39":
|
||||
version "0.1.39"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-compat/-/app-compat-0.1.39.tgz#3ea5465d07855fdb8357a0f63fd113da81468e50"
|
||||
integrity sha512-F5O/N38dVGFzpe6zM//MslYT80rpX0V+MQNMvONPUlXhvDqS5T+8NMSCWOcZ++Z4Hkj8EvgTJk59AMnD8SdyFw==
|
||||
"@firebase/app-compat@0.2.12":
|
||||
version "0.2.12"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-compat/-/app-compat-0.2.12.tgz#90375027edccf2f3782af02014d0eb61ef7fde11"
|
||||
integrity sha512-3EfputoACcXvgi2uN9RUQVDYSmRSR4R4TWJW9Wvs4hTib2I26ldvVhDHaheQq90IwGYrRa+TTWuzr4a5dCRkVQ==
|
||||
dependencies:
|
||||
"@firebase/app" "0.8.4"
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/logger" "0.3.4"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/app" "0.9.12"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/app-types@0.8.1":
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.8.1.tgz#4c7f916281aed570581fc667e3eb6cc730119a95"
|
||||
integrity sha512-p75Ow3QhB82kpMzmOntv866wH9eZ3b4+QbUY+8/DA5Zzdf1c8Nsk8B7kbFpzJt4wwHMdy5LTF5YUnoTc1JiWkw==
|
||||
"@firebase/app-types@0.9.0":
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.9.0.tgz#35b5c568341e9e263b29b3d2ba0e9cfc9ec7f01e"
|
||||
integrity sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==
|
||||
|
||||
"@firebase/app@0.8.4":
|
||||
version "0.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.8.4.tgz#e62b47f909e10627f7f377ecfb7b90b921303d21"
|
||||
integrity sha512-gQntijd+sLaGWjcBQpk33giCEXNzGLB6489NMpypVgEXJwQXYQPSrtb9vUHXot1w1iy/j6xlNl4K8wwwNdRgDg==
|
||||
"@firebase/app@0.9.12":
|
||||
version "0.9.12"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.9.12.tgz#05f83181c54cdab88e054eb0a80d4ec551799b57"
|
||||
integrity sha512-VsE/WHZU8M9BCnHMbOi3FqIVIsoG4FlEehjp+XCDNE0zxn4BGgnpLdBu6/r9Bg565b1ND7dm6LSVRtewmeRb3w==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/logger" "0.3.4"
|
||||
"@firebase/util" "1.7.3"
|
||||
idb "7.0.1"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
idb "7.1.1"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/auth-compat@0.2.24":
|
||||
version "0.2.24"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/auth-compat/-/auth-compat-0.2.24.tgz#7ad914d412d467f181016c88b5a2b398b6e7fba3"
|
||||
integrity sha512-IuZQScjtoOLkUHtmIUJ2F3E2OpDOyap6L/9HL/DX3nzEA1LrX7wlpeU6OF2jS9E0KLueWKIrSkIQOOsKoQj/sA==
|
||||
"@firebase/auth-compat@0.4.2":
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/auth-compat/-/auth-compat-0.4.2.tgz#cb65edc2fbd5f72fff32310409f2fd702b5145e7"
|
||||
integrity sha512-Q30e77DWXFmXEt5dg5JbqEDpjw9y3/PcP9LslDPR7fARmAOTIY9MM6HXzm9KC+dlrKH/+p6l8g9ifJiam9mc4A==
|
||||
dependencies:
|
||||
"@firebase/auth" "0.20.11"
|
||||
"@firebase/auth-types" "0.11.1"
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/auth" "0.23.2"
|
||||
"@firebase/auth-types" "0.12.0"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/util" "1.9.3"
|
||||
node-fetch "2.6.7"
|
||||
selenium-webdriver "4.5.0"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/auth-interop-types@0.1.7":
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.1.7.tgz#82c8d431779916224d2af5cef6cec2042d830f28"
|
||||
integrity sha512-yA/dTveGGPcc85JP8ZE/KZqfGQyQTBCV10THdI8HTlP1GDvNrhr//J5jAt58MlsCOaO3XmC4DqScPBbtIsR/EA==
|
||||
"@firebase/auth-interop-types@0.2.1":
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz#78884f24fa539e34a06c03612c75f222fcc33742"
|
||||
integrity sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg==
|
||||
|
||||
"@firebase/auth-types@0.11.1":
|
||||
version "0.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.11.1.tgz#f5524891653dbe4e22fba7586ef00605f33ce61d"
|
||||
integrity sha512-ud7T39VG9ptTrC2fOy/XlU+ubC+BVuBJPteuzsPZSa9l7gkntvWgVb3Z/3FxqqRPlkVUYiyvmsbRN3DE1He2ow==
|
||||
"@firebase/auth-types@0.12.0":
|
||||
version "0.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.12.0.tgz#f28e1b68ac3b208ad02a15854c585be6da3e8e79"
|
||||
integrity sha512-pPwaZt+SPOshK8xNoiQlK5XIrS97kFYc3Rc7xmy373QsOJ9MmqXxLaYssP5Kcds4wd2qK//amx/c+A8O2fVeZA==
|
||||
|
||||
"@firebase/auth@0.20.11":
|
||||
version "0.20.11"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-0.20.11.tgz#acf40fcf9c64af9d5f29ad9a8cfc2e99aed50237"
|
||||
integrity sha512-cKy91l4URDG3yWfPK7tjUySh2wCLxtTilsR59jiqQJLReBrQsKP79eFDJ6jqWwbEh3+f1lmoH1nKswwbo9XdmA==
|
||||
"@firebase/auth@0.23.2":
|
||||
version "0.23.2"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-0.23.2.tgz#9e6d8dd550a28053c1825fb98c7dc9b37119254d"
|
||||
integrity sha512-dM9iJ0R6tI1JczuGSxXmQbXAgtYie0K4WvKcuyuSTCu9V8eEDiz4tfa1sO3txsfvwg7nOY3AjoCyMYEdqZ8hdg==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/logger" "0.3.4"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
node-fetch "2.6.7"
|
||||
selenium-webdriver "4.5.0"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/component@0.5.21":
|
||||
version "0.5.21"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.5.21.tgz#bb10add24fe2ee59a61163a469d4711d8da4002d"
|
||||
integrity sha512-12MMQ/ulfygKpEJpseYMR0HunJdlsLrwx2XcEs40M18jocy2+spyzHHEwegN3x/2/BLFBjR5247Etmz0G97Qpg==
|
||||
"@firebase/component@0.6.4":
|
||||
version "0.6.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.6.4.tgz#8981a6818bd730a7554aa5e0516ffc9b1ae3f33d"
|
||||
integrity sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA==
|
||||
dependencies:
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/database-compat@0.2.10":
|
||||
version "0.2.10"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/database-compat/-/database-compat-0.2.10.tgz#fa4440db9f41a9a05112642504c1e6557a75b8be"
|
||||
integrity sha512-fK+IgUUqVKcWK/gltzDU+B1xauCOfY6vulO8lxoNTkcCGlSxuTtwsdqjGkFmgFRMYjXFWWJ6iFcJ/vXahzwCtA==
|
||||
"@firebase/database-compat@0.3.4":
|
||||
version "0.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/database-compat/-/database-compat-0.3.4.tgz#4e57932f7a5ba761cd5ac946ab6b6ab3f660522c"
|
||||
integrity sha512-kuAW+l+sLMUKBThnvxvUZ+Q1ZrF/vFJ58iUY9kAcbX48U03nVzIF6Tmkf0p3WVQwMqiXguSgtOPIB6ZCeF+5Gg==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/database" "0.13.10"
|
||||
"@firebase/database-types" "0.9.17"
|
||||
"@firebase/logger" "0.3.4"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/database" "0.14.4"
|
||||
"@firebase/database-types" "0.10.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/database-types@0.9.17":
|
||||
version "0.9.17"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.9.17.tgz#4c248052b0a9ae052ba940e4996a0bfab25dc257"
|
||||
integrity sha512-YQm2tCZyxNtEnlS5qo5gd2PAYgKCy69tUKwioGhApCFThW+mIgZs7IeYeJo2M51i4LCixYUl+CvnOyAnb/c3XA==
|
||||
"@firebase/database-types@0.10.4":
|
||||
version "0.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.10.4.tgz#47ba81113512dab637abace61cfb65f63d645ca7"
|
||||
integrity sha512-dPySn0vJ/89ZeBac70T+2tWWPiJXWbmRygYv0smT5TfE3hDrQ09eKMF3Y+vMlTdrMWq7mUdYW5REWPSGH4kAZQ==
|
||||
dependencies:
|
||||
"@firebase/app-types" "0.8.1"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/app-types" "0.9.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
|
||||
"@firebase/database@0.13.10":
|
||||
version "0.13.10"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.13.10.tgz#c24e0219490b9c1fabfb7b42cb45850e145fe56d"
|
||||
integrity sha512-KRucuzZ7ZHQsRdGEmhxId5jyM2yKsjsQWF9yv0dIhlxYg0D8rCVDZc/waoPKA5oV3/SEIoptF8F7R1Vfe7BCQA==
|
||||
"@firebase/database@0.14.4":
|
||||
version "0.14.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.14.4.tgz#9e7435a16a540ddfdeb5d99d45618e6ede179aa6"
|
||||
integrity sha512-+Ea/IKGwh42jwdjCyzTmeZeLM3oy1h0mFPsTy6OqCWzcu/KFqRAr5Tt1HRCOBlNOdbh84JPZC47WLU18n2VbxQ==
|
||||
dependencies:
|
||||
"@firebase/auth-interop-types" "0.1.7"
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/logger" "0.3.4"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/auth-interop-types" "0.2.1"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
faye-websocket "0.11.4"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/firestore-compat@0.2.3":
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/firestore-compat/-/firestore-compat-0.2.3.tgz#da2f4f9a1da8cdf0a83769ec771f64ad7866363c"
|
||||
integrity sha512-FgJwGCA2K+lsGk6gbJo57qn4iocQSGfOlNi2s4QsEO/WOVIU00yYGm408fN7iAGpr9d5VKyulO4sYcic7cS51g==
|
||||
"@firebase/firestore-compat@0.3.11":
|
||||
version "0.3.11"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/firestore-compat/-/firestore-compat-0.3.11.tgz#010c78990c1a2a4b87d0eff68704baefd43f6f32"
|
||||
integrity sha512-jPhySBBp6+Vt750WmeCK4it/NV9YHQEX+jJ7Va8wHOhVejy0zUhL5TsLF6Bz3hCjb4Dxn6XVgvuSqiuqY16yWw==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/firestore" "3.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/firestore" "3.12.2"
|
||||
"@firebase/firestore-types" "2.5.1"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/firestore-types@2.5.1":
|
||||
@@ -1835,204 +1833,204 @@
|
||||
resolved "https://registry.yarnpkg.com/@firebase/firestore-types/-/firestore-types-2.5.1.tgz#464b2ee057956599ca34de50eae957c30fdbabb7"
|
||||
integrity sha512-xG0CA6EMfYo8YeUxC8FeDzf6W3FX1cLlcAGBYV6Cku12sZRI81oWcu61RSKM66K6kUENP+78Qm8mvroBcm1whw==
|
||||
|
||||
"@firebase/firestore@3.7.3":
|
||||
version "3.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-3.7.3.tgz#c839d6983f81d2853daeac42fba316a86102e5e4"
|
||||
integrity sha512-hnA8hljwJBpejv0SPlt0yiej1wz3VRcLzoNAZujTCI1wLoADkRNsqic5uN/Ge0M0vbmHliLXtet/PDqvEbB9Ww==
|
||||
"@firebase/firestore@3.12.2":
|
||||
version "3.12.2"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-3.12.2.tgz#8f1fbde355bd82b3164a1fac60049a501a1d3fdf"
|
||||
integrity sha512-6EDIJ2V4hlUkPvAb1uH5DAz65ZvhStIM1oYGSUx6mt2UdEDu/0CAVS7xYBY6niTyM/+2r6XBW3hYG/1x1V27vg==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/logger" "0.3.4"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/webchannel-wrapper" "0.8.1"
|
||||
"@grpc/grpc-js" "^1.3.2"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
"@firebase/webchannel-wrapper" "0.10.1"
|
||||
"@grpc/grpc-js" "~1.7.0"
|
||||
"@grpc/proto-loader" "^0.6.13"
|
||||
node-fetch "2.6.7"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/functions-compat@0.2.8":
|
||||
version "0.2.8"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/functions-compat/-/functions-compat-0.2.8.tgz#e6f1c476cdd6c3657d3b6328aebe8a62ace0a7bb"
|
||||
integrity sha512-5w668whT+bm6oVcFqIxfFbn9N77WycpNCfZNg1l0iC+5RLSt53RTVu43pqi43vh23Vp4ad+SRBgZiQGAMen5wA==
|
||||
"@firebase/functions-compat@0.3.5":
|
||||
version "0.3.5"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/functions-compat/-/functions-compat-0.3.5.tgz#7a532d3a9764c6d5fbc1ec5541a989a704326647"
|
||||
integrity sha512-uD4jwgwVqdWf6uc3NRKF8cSZ0JwGqSlyhPgackyUPe+GAtnERpS4+Vr66g0b3Gge0ezG4iyHo/EXW/Hjx7QhHw==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/functions" "0.8.8"
|
||||
"@firebase/functions-types" "0.5.1"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/functions" "0.10.0"
|
||||
"@firebase/functions-types" "0.6.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/functions-types@0.5.1":
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/functions-types/-/functions-types-0.5.1.tgz#7633fd2ade99c1b8c0c5037fa369fc91849e3b15"
|
||||
integrity sha512-olEJnTuULM/ws0pwhHA0Ze5oIdpFbZsdBGCaBhyL4pm1NUR4Moh0cyAsqr+VtqHCNMGquHU1GJ77qITkoonp0w==
|
||||
"@firebase/functions-types@0.6.0":
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/functions-types/-/functions-types-0.6.0.tgz#ccd7000dc6fc668f5acb4e6a6a042a877a555ef2"
|
||||
integrity sha512-hfEw5VJtgWXIRf92ImLkgENqpL6IWpYaXVYiRkFY1jJ9+6tIhWM7IzzwbevwIIud/jaxKVdRzD7QBWfPmkwCYw==
|
||||
|
||||
"@firebase/functions@0.8.8":
|
||||
version "0.8.8"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/functions/-/functions-0.8.8.tgz#a193d5565670bfa9b0e64b00556fae7d183fc895"
|
||||
integrity sha512-weNcDQJcH3/2YFaXd5dF5pUk3IQdZY60QNuWpq7yS+uaPlCRHjT0K989Q3ZcmYwXz7mHTfhlQamXdA4Yobgt+Q==
|
||||
"@firebase/functions@0.10.0":
|
||||
version "0.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/functions/-/functions-0.10.0.tgz#c630ddf12cdf941c25bc8d554e30c3226cd560f6"
|
||||
integrity sha512-2U+fMNxTYhtwSpkkR6WbBcuNMOVaI7MaH3cZ6UAeNfj7AgEwHwMIFLPpC13YNZhno219F0lfxzTAA0N62ndWzA==
|
||||
dependencies:
|
||||
"@firebase/app-check-interop-types" "0.1.1"
|
||||
"@firebase/auth-interop-types" "0.1.7"
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/messaging-interop-types" "0.1.1"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/app-check-interop-types" "0.3.0"
|
||||
"@firebase/auth-interop-types" "0.2.1"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/messaging-interop-types" "0.2.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
node-fetch "2.6.7"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/installations-compat@0.1.16":
|
||||
version "0.1.16"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/installations-compat/-/installations-compat-0.1.16.tgz#b54c2fefaffd49a9f16e84ab5260348197ea9e4e"
|
||||
integrity sha512-Xp7s3iUMZ6/TN0a+g1kpHNEn7h59kSxi44/2I7bd3X6xwHnxMu0TqYB7U9WfqEhqiI9iKulL3g06wIZqaklElw==
|
||||
"@firebase/installations-compat@0.2.4":
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/installations-compat/-/installations-compat-0.2.4.tgz#b5557c897b4cd3635a59887a8bf69c3731aaa952"
|
||||
integrity sha512-LI9dYjp0aT9Njkn9U4JRrDqQ6KXeAmFbRC0E7jI7+hxl5YmRWysq5qgQl22hcWpTk+cm3es66d/apoDU/A9n6Q==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/installations" "0.5.16"
|
||||
"@firebase/installations-types" "0.4.1"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/installations" "0.6.4"
|
||||
"@firebase/installations-types" "0.5.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/installations-types@0.4.1":
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/installations-types/-/installations-types-0.4.1.tgz#3aa99213e39a81a3bbac25b1627169082da289ad"
|
||||
integrity sha512-ac906QcmipomZjSasGDYNS1LDy4JNGzQ4VXHpFtoOrI6U2QGFkRezZpI+5bzfU062JOD+doO6irYC6Uwnv/GnA==
|
||||
"@firebase/installations-types@0.5.0":
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/installations-types/-/installations-types-0.5.0.tgz#2adad64755cd33648519b573ec7ec30f21fb5354"
|
||||
integrity sha512-9DP+RGfzoI2jH7gY4SlzqvZ+hr7gYzPODrbzVD82Y12kScZ6ZpRg/i3j6rleto8vTFC8n6Len4560FnV1w2IRg==
|
||||
|
||||
"@firebase/installations@0.5.16":
|
||||
version "0.5.16"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/installations/-/installations-0.5.16.tgz#ee83f771d36e991335d625dc861ac7d5574044e4"
|
||||
integrity sha512-k3iyjr+yZnDOcJbP+CCZW3/zQJf9gYL2CNBJs9QbmFJoLz7cgIcnAT/XNDMudxcggF1goLfq4+MygpzHD0NzLA==
|
||||
"@firebase/installations@0.6.4":
|
||||
version "0.6.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/installations/-/installations-0.6.4.tgz#20382e33e6062ac5eff4bede8e468ed4c367609e"
|
||||
integrity sha512-u5y88rtsp7NYkCHC3ElbFBrPtieUybZluXyzl7+4BsIz4sqb4vSAuwHEUgCgCeaQhvsnxDEU6icly8U9zsJigA==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/util" "1.9.3"
|
||||
idb "7.0.1"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/logger@0.3.4":
|
||||
version "0.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.3.4.tgz#8822dd3e9168be93c1bce0b4ac235e3b165a6a68"
|
||||
integrity sha512-hlFglGRgZEwoyClZcGLx/Wd+zoLfGmbDkFx56mQt/jJ0XMbfPqwId1kiPl0zgdWZX+D8iH+gT6GuLPFsJWgiGw==
|
||||
"@firebase/logger@0.4.0":
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.4.0.tgz#15ecc03c452525f9d47318ad9491b81d1810f113"
|
||||
integrity sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==
|
||||
dependencies:
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/messaging-compat@0.1.21":
|
||||
version "0.1.21"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/messaging-compat/-/messaging-compat-0.1.21.tgz#1e221cdd186fd48d41a8b9c42fdb912476717939"
|
||||
integrity sha512-oxQCQ8EXqpSaTybryokbEM/LAqkG0L7OJuucllCg5roqRGIHE437Abus0Bn67P8TKJaYjyKxomg8wCvfmInjlg==
|
||||
"@firebase/messaging-compat@0.2.4":
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/messaging-compat/-/messaging-compat-0.2.4.tgz#323ca48deef77065b4fcda3cfd662c4337dffcfd"
|
||||
integrity sha512-lyFjeUhIsPRYDPNIkYX1LcZMpoVbBWXX4rPl7c/rqc7G+EUea7IEtSt4MxTvh6fDfPuzLn7+FZADfscC+tNMfg==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/messaging" "0.11.0"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/messaging" "0.12.4"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/messaging-interop-types@0.1.1":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/messaging-interop-types/-/messaging-interop-types-0.1.1.tgz#03733115df2688786be5f96baa64869fb3914d0c"
|
||||
integrity sha512-7XuY87zPh01EBaeS3s6co31Il5oGbPl5MxAg6Uj3fPv7PqJQlbwQ+B5k7CKSF/Y26tRxp+u+usxIvIWCSEA8CQ==
|
||||
"@firebase/messaging-interop-types@0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.0.tgz#6056f8904a696bf0f7fdcf5f2ca8f008e8f6b064"
|
||||
integrity sha512-ujA8dcRuVeBixGR9CtegfpU4YmZf3Lt7QYkcj693FFannwNuZgfAYaTmbJ40dtjB81SAu6tbFPL9YLNT15KmOQ==
|
||||
|
||||
"@firebase/messaging@0.11.0":
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/messaging/-/messaging-0.11.0.tgz#ab6dbcd8b95f2b65f2290eb44110979261f84399"
|
||||
integrity sha512-V7+Xw4QlB8PgINY7Wml+Uj8A3S2nR0ooVoaqfRJ8ZN3W7A4aO/DCkjPsf6DXehwfqRLA7PGB9Boe8l9Idy7icA==
|
||||
"@firebase/messaging@0.12.4":
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/messaging/-/messaging-0.12.4.tgz#ccb49df5ab97d5650c9cf5b8c77ddc34daafcfe0"
|
||||
integrity sha512-6JLZct6zUaex4g7HI3QbzeUrg9xcnmDAPTWpkoMpd/GoSVWH98zDoWXMGrcvHeCAIsLpFMe4MPoZkJbrPhaASw==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/installations" "0.5.16"
|
||||
"@firebase/messaging-interop-types" "0.1.1"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/installations" "0.6.4"
|
||||
"@firebase/messaging-interop-types" "0.2.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
idb "7.0.1"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/performance-compat@0.1.17":
|
||||
version "0.1.17"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/performance-compat/-/performance-compat-0.1.17.tgz#23774adda07f6af83299517a202f8d98ebc9a70d"
|
||||
integrity sha512-Hci5MrDlRuqwVozq7LaSAufXXElz+AtmEQArix64kLRJqHhOu5K/8TpuZXM/klR6gnLyIrk+01CrAemH3zHpDw==
|
||||
"@firebase/performance-compat@0.2.4":
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/performance-compat/-/performance-compat-0.2.4.tgz#95cbf32057b5d9f0c75d804bc50e6ed3ba486274"
|
||||
integrity sha512-nnHUb8uP9G8islzcld/k6Bg5RhX62VpbAb/Anj7IXs/hp32Eb2LqFPZK4sy3pKkBUO5wcrlRWQa6wKOxqlUqsg==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/logger" "0.3.4"
|
||||
"@firebase/performance" "0.5.17"
|
||||
"@firebase/performance-types" "0.1.1"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/performance" "0.6.4"
|
||||
"@firebase/performance-types" "0.2.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/performance-types@0.1.1":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/performance-types/-/performance-types-0.1.1.tgz#ac37fff87f2e716c18fb78c138dc398d9b9aecd7"
|
||||
integrity sha512-wiJRLBg8EPaYSGJqx7aqkZ3L5fULfZa9zOTs4C06K020g0zzJh9kUUO/0U3wvHz7zRQjJxTO8Jw4SDjxs3EZrA==
|
||||
"@firebase/performance-types@0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/performance-types/-/performance-types-0.2.0.tgz#400685f7a3455970817136d9b48ce07a4b9562ff"
|
||||
integrity sha512-kYrbr8e/CYr1KLrLYZZt2noNnf+pRwDq2KK9Au9jHrBMnb0/C9X9yWSXmZkFt4UIdsQknBq8uBB7fsybZdOBTA==
|
||||
|
||||
"@firebase/performance@0.5.17":
|
||||
version "0.5.17"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/performance/-/performance-0.5.17.tgz#f0aa9724df9e2ef095f176c2ef1accfa75e3bac6"
|
||||
integrity sha512-NDgzI5JYo6Itnj1FWhMkK3LtwKhtOnhC+WBkxezjzFVuCOornQjvu7ucAU1o2dHXh7MFruhHGFPsHyfkkMCljA==
|
||||
"@firebase/performance@0.6.4":
|
||||
version "0.6.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/performance/-/performance-0.6.4.tgz#0ad766bfcfab4f386f4fe0bef43bbcf505015069"
|
||||
integrity sha512-HfTn/bd8mfy/61vEqaBelNiNnvAbUtME2S25A67Nb34zVuCSCRIX4SseXY6zBnOFj3oLisaEqhVcJmVPAej67g==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/installations" "0.5.16"
|
||||
"@firebase/logger" "0.3.4"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/installations" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/remote-config-compat@0.1.16":
|
||||
version "0.1.16"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/remote-config-compat/-/remote-config-compat-0.1.16.tgz#2953f8d556145eb57cb4244eb3e2c4a2c6f19804"
|
||||
integrity sha512-BWonzeqODnGki/fZ17zOnjJFR5CWbIOU0PmYGjWBnbkWxpFDdE3zNsz8JTVd/Mkt7y2PHFMYpLsyZ473E/62FQ==
|
||||
"@firebase/remote-config-compat@0.2.4":
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/remote-config-compat/-/remote-config-compat-0.2.4.tgz#1f494c81a6c9560b1f9ca1b4fbd4bbbe47cf4776"
|
||||
integrity sha512-FKiki53jZirrDFkBHglB3C07j5wBpitAaj8kLME6g8Mx+aq7u9P7qfmuSRytiOItADhWUj7O1JIv7n9q87SuwA==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/logger" "0.3.4"
|
||||
"@firebase/remote-config" "0.3.15"
|
||||
"@firebase/remote-config-types" "0.2.1"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/remote-config" "0.4.4"
|
||||
"@firebase/remote-config-types" "0.3.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/remote-config-types@0.2.1":
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/remote-config-types/-/remote-config-types-0.2.1.tgz#9f7dfb6b0066443592b055dddc57b0c954b0e83c"
|
||||
integrity sha512-1PGx4vKtMMd5uB6G1Nj2b8fOnJx7mIJGzkdyfhIM1oQx9k3dJ+pVu4StrNm46vHaD8ZlOQLr91YfUE43xSXwSg==
|
||||
"@firebase/remote-config-types@0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/remote-config-types/-/remote-config-types-0.3.0.tgz#689900dcdb3e5c059e8499b29db393e4e51314b4"
|
||||
integrity sha512-RtEH4vdcbXZuZWRZbIRmQVBNsE7VDQpet2qFvq6vwKLBIQRQR5Kh58M4ok3A3US8Sr3rubYnaGqZSurCwI8uMA==
|
||||
|
||||
"@firebase/remote-config@0.3.15":
|
||||
version "0.3.15"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/remote-config/-/remote-config-0.3.15.tgz#97e14d08a1065ce1ccd63b13a6eaa0927164556d"
|
||||
integrity sha512-ZCyqoCaftoNvc2r4zPaqNV4OgC4sRHjcQI+agzXESnhDLnTY8DpCaQ0m9j6deHuxxDOgu8QPDb8psLbjR+9CgQ==
|
||||
"@firebase/remote-config@0.4.4":
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/remote-config/-/remote-config-0.4.4.tgz#6a496117054de58744bc9f382d2a6d1e14060c65"
|
||||
integrity sha512-x1ioTHGX8ZwDSTOVp8PBLv2/wfwKzb4pxi0gFezS5GCJwbLlloUH4YYZHHS83IPxnua8b6l0IXUaWd0RgbWwzQ==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/installations" "0.5.16"
|
||||
"@firebase/logger" "0.3.4"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/installations" "0.6.4"
|
||||
"@firebase/logger" "0.4.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/storage-compat@0.1.22":
|
||||
version "0.1.22"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/storage-compat/-/storage-compat-0.1.22.tgz#0eba37444a525fce3854c68eacc1d2b5d87f8b5a"
|
||||
integrity sha512-uv33WnAEcxf2983Z03uhJmKc91LKSsRijFwut8xeoJamJoGAVj1Tc9Mio491aI1KZ+RMkNFghHL2FpxjuvxpPg==
|
||||
"@firebase/storage-compat@0.3.2":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/storage-compat/-/storage-compat-0.3.2.tgz#51a97170fd652a516f729f82b97af369e5a2f8d7"
|
||||
integrity sha512-wvsXlLa9DVOMQJckbDNhXKKxRNNewyUhhbXev3t8kSgoCotd1v3MmqhKKz93ePhDnhHnDs7bYHy+Qa8dRY6BXw==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/storage" "0.9.14"
|
||||
"@firebase/storage-types" "0.6.1"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/storage" "0.11.2"
|
||||
"@firebase/storage-types" "0.8.0"
|
||||
"@firebase/util" "1.9.3"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/storage-types@0.6.1":
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/storage-types/-/storage-types-0.6.1.tgz#76b71b6f6ef5df4cf286e63f58e92638b9dcd62d"
|
||||
integrity sha512-/pkNzKiGCSjdBBZHPvWL1kkPZfM3pFJ38HPJE1xTHwLBwdrFb4JrmY+5/E4ma5ePsbejecIOD1SZhEKDB/JwUQ==
|
||||
"@firebase/storage-types@0.8.0":
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/storage-types/-/storage-types-0.8.0.tgz#f1e40a5361d59240b6e84fac7fbbbb622bfaf707"
|
||||
integrity sha512-isRHcGrTs9kITJC0AVehHfpraWFui39MPaU7Eo8QfWlqW7YPymBmRgjDrlOgFdURh6Cdeg07zmkLP5tzTKRSpg==
|
||||
|
||||
"@firebase/storage@0.9.14":
|
||||
version "0.9.14"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.9.14.tgz#e70a0e6a706df8401acfa9991306b77eb1e32d7d"
|
||||
integrity sha512-he8VAJ4BLkQdebnna15TI1/ymkwQTeKnjA/psKMAJ2+/UswD/68bCMKOlTrMvw6Flv3zc5YZk1xdL9DHR0i6wg==
|
||||
"@firebase/storage@0.11.2":
|
||||
version "0.11.2"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.11.2.tgz#c5e0316543fe1c4026b8e3910f85ad73f5b77571"
|
||||
integrity sha512-CtvoFaBI4hGXlXbaCHf8humajkbXhs39Nbh6MbNxtwJiCqxPy9iH3D3CCfXAvP0QvAAwmJUTK3+z9a++Kc4nkA==
|
||||
dependencies:
|
||||
"@firebase/component" "0.5.21"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/component" "0.6.4"
|
||||
"@firebase/util" "1.9.3"
|
||||
node-fetch "2.6.7"
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/util@1.7.3":
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/util/-/util-1.7.3.tgz#e71640b6b2970b754f947235ceb10cba3f70e62c"
|
||||
integrity sha512-wxNqWbqokF551WrJ9BIFouU/V5SL1oYCGx1oudcirdhadnQRFH5v1sjgGL7cUV/UsekSycygphdrF2lxBxOYKg==
|
||||
"@firebase/util@1.9.3":
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/util/-/util-1.9.3.tgz#45458dd5cd02d90e55c656e84adf6f3decf4b7ed"
|
||||
integrity sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==
|
||||
dependencies:
|
||||
tslib "^2.1.0"
|
||||
|
||||
"@firebase/webchannel-wrapper@0.8.1":
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.8.1.tgz#5fbb3808677aa6b88bf79968237d3bb14595b1ba"
|
||||
integrity sha512-CJW8vxt6bJaBeco2VnlJjmCmAkrrtIdf0GGKvpAB4J5gw8Gi0rHb+qsgKp6LsyS5W6ALPLawLs7phZmw02dvLw==
|
||||
"@firebase/webchannel-wrapper@0.10.1":
|
||||
version "0.10.1"
|
||||
resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.10.1.tgz#60bb2aaf129f9e00621f8d698722ddba6ee1f8ac"
|
||||
integrity sha512-Dq5rYfEpdeel0bLVN+nfD1VWmzCkK+pJbSjIawGE+RY4+NIJqhbUDDQjvV0NUK84fMfwxvtFoCtEe70HfZjFcw==
|
||||
|
||||
"@grpc/grpc-js@^1.3.2":
|
||||
"@grpc/grpc-js@~1.7.0":
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.7.3.tgz#f2ea79f65e31622d7f86d4b4c9ae38f13ccab99a"
|
||||
integrity sha512-H9l79u4kJ2PVSxUNA08HMYAnUBLj9v6KjYQ7SQ71hOZcEXhShE/y5iQCesP8+6/Ik/7i2O0a10bPquIcYfufog==
|
||||
@@ -2052,15 +2050,15 @@
|
||||
yargs "^16.2.0"
|
||||
|
||||
"@grpc/proto-loader@^0.7.0":
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.3.tgz#75a6f95b51b85c5078ac7394da93850c32d36bb8"
|
||||
integrity sha512-5dAvoZwna2Py3Ef96Ux9jIkp3iZ62TUsV00p3wVBPNX5K178UbNi8Q7gQVqwXT1Yq9RejIGG9G2IPEo93T6RcA==
|
||||
version "0.7.7"
|
||||
resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.7.tgz#d33677a77eea8407f7c66e2abd97589b60eb4b21"
|
||||
integrity sha512-1TIeXOi8TuSCQprPItwoMymZXxWT0CPxUhkrkeCUH+D8U7QDwQ6b7SUz2MaLuWM2llT+J/TVFLmQI5KtML3BhQ==
|
||||
dependencies:
|
||||
"@types/long" "^4.0.1"
|
||||
lodash.camelcase "^4.3.0"
|
||||
long "^4.0.0"
|
||||
protobufjs "^7.0.0"
|
||||
yargs "^16.2.0"
|
||||
yargs "^17.7.2"
|
||||
|
||||
"@hookform/resolvers@^2.6.0":
|
||||
version "2.9.10"
|
||||
@@ -3069,11 +3067,16 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
|
||||
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
|
||||
|
||||
"@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0":
|
||||
"@types/node@*":
|
||||
version "18.11.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.9.tgz#02d013de7058cea16d36168ef2fc653464cfbad4"
|
||||
integrity sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==
|
||||
|
||||
"@types/node@>=12.12.47", "@types/node@>=13.7.0":
|
||||
version "20.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.0.tgz#719498898d5defab83c3560f45d8498f58d11938"
|
||||
integrity sha512-cumHmIAf6On83X7yP+LrsEyUOf/YlociZelmpRYaGFydoaPdxdt80MAbu6vWerQT2COCp2nPvHdsbD7tHn/YlQ==
|
||||
|
||||
"@types/node@^17.0.23":
|
||||
version "17.0.45"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190"
|
||||
@@ -4021,6 +4024,15 @@ cliui@^7.0.2:
|
||||
strip-ansi "^6.0.0"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
cliui@^8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
|
||||
integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
|
||||
dependencies:
|
||||
string-width "^4.2.0"
|
||||
strip-ansi "^6.0.1"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
clsx@^1.1.0, clsx@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
|
||||
@@ -5089,36 +5101,36 @@ find-up@^5.0.0:
|
||||
path-exists "^4.0.0"
|
||||
|
||||
firebase@^9.12.1:
|
||||
version "9.14.0"
|
||||
resolved "https://registry.yarnpkg.com/firebase/-/firebase-9.14.0.tgz#407de4855092e607d3ee1fb222294ab2b45c4798"
|
||||
integrity sha512-wePrsf7W33mhT7RVXQavragoAgXb/NDm22vuhwJXkprrQ2Y9alrEKC5LTAtLJL3P2dHdDmeylS6PLZwWPEE79A==
|
||||
version "9.22.2"
|
||||
resolved "https://registry.yarnpkg.com/firebase/-/firebase-9.22.2.tgz#8619bbdf38ab691d6b14da5d863370ab2c7ab6e5"
|
||||
integrity sha512-eBXsaTzXPx3Y0QhuuluG/qR58tlOx2X/W0GKNoF004FcG9L2gHuvGu5/bIczvrPyfNOCqDF+I5I/kOQi8l9m0A==
|
||||
dependencies:
|
||||
"@firebase/analytics" "0.8.4"
|
||||
"@firebase/analytics-compat" "0.1.17"
|
||||
"@firebase/app" "0.8.4"
|
||||
"@firebase/app-check" "0.5.17"
|
||||
"@firebase/app-check-compat" "0.2.17"
|
||||
"@firebase/app-compat" "0.1.39"
|
||||
"@firebase/app-types" "0.8.1"
|
||||
"@firebase/auth" "0.20.11"
|
||||
"@firebase/auth-compat" "0.2.24"
|
||||
"@firebase/database" "0.13.10"
|
||||
"@firebase/database-compat" "0.2.10"
|
||||
"@firebase/firestore" "3.7.3"
|
||||
"@firebase/firestore-compat" "0.2.3"
|
||||
"@firebase/functions" "0.8.8"
|
||||
"@firebase/functions-compat" "0.2.8"
|
||||
"@firebase/installations" "0.5.16"
|
||||
"@firebase/installations-compat" "0.1.16"
|
||||
"@firebase/messaging" "0.11.0"
|
||||
"@firebase/messaging-compat" "0.1.21"
|
||||
"@firebase/performance" "0.5.17"
|
||||
"@firebase/performance-compat" "0.1.17"
|
||||
"@firebase/remote-config" "0.3.15"
|
||||
"@firebase/remote-config-compat" "0.1.16"
|
||||
"@firebase/storage" "0.9.14"
|
||||
"@firebase/storage-compat" "0.1.22"
|
||||
"@firebase/util" "1.7.3"
|
||||
"@firebase/analytics" "0.10.0"
|
||||
"@firebase/analytics-compat" "0.2.6"
|
||||
"@firebase/app" "0.9.12"
|
||||
"@firebase/app-check" "0.8.0"
|
||||
"@firebase/app-check-compat" "0.3.7"
|
||||
"@firebase/app-compat" "0.2.12"
|
||||
"@firebase/app-types" "0.9.0"
|
||||
"@firebase/auth" "0.23.2"
|
||||
"@firebase/auth-compat" "0.4.2"
|
||||
"@firebase/database" "0.14.4"
|
||||
"@firebase/database-compat" "0.3.4"
|
||||
"@firebase/firestore" "3.12.2"
|
||||
"@firebase/firestore-compat" "0.3.11"
|
||||
"@firebase/functions" "0.10.0"
|
||||
"@firebase/functions-compat" "0.3.5"
|
||||
"@firebase/installations" "0.6.4"
|
||||
"@firebase/installations-compat" "0.2.4"
|
||||
"@firebase/messaging" "0.12.4"
|
||||
"@firebase/messaging-compat" "0.2.4"
|
||||
"@firebase/performance" "0.6.4"
|
||||
"@firebase/performance-compat" "0.2.4"
|
||||
"@firebase/remote-config" "0.4.4"
|
||||
"@firebase/remote-config-compat" "0.2.4"
|
||||
"@firebase/storage" "0.11.2"
|
||||
"@firebase/storage-compat" "0.3.2"
|
||||
"@firebase/util" "1.9.3"
|
||||
|
||||
firebaseui@^6.0.1:
|
||||
version "6.0.2"
|
||||
@@ -5577,7 +5589,7 @@ idb@7.0.1:
|
||||
resolved "https://registry.yarnpkg.com/idb/-/idb-7.0.1.tgz#d2875b3a2f205d854ee307f6d196f246fea590a7"
|
||||
integrity sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg==
|
||||
|
||||
idb@^7.0.1:
|
||||
idb@7.1.1, idb@^7.0.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b"
|
||||
integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==
|
||||
@@ -6322,9 +6334,9 @@ long@^4.0.0:
|
||||
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
|
||||
|
||||
long@^5.0.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/long/-/long-5.2.1.tgz#e27595d0083d103d2fa2c20c7699f8e0c92b897f"
|
||||
integrity sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A==
|
||||
version "5.2.3"
|
||||
resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1"
|
||||
integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==
|
||||
|
||||
longest-streak@^3.0.0:
|
||||
version "3.1.0"
|
||||
@@ -7426,9 +7438,9 @@ protobufjs@^6.11.3:
|
||||
long "^4.0.0"
|
||||
|
||||
protobufjs@^7.0.0:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.1.2.tgz#a0cf6aeaf82f5625bffcf5a38b7cd2a7de05890c"
|
||||
integrity sha512-4ZPTPkXCdel3+L81yw3dG6+Kq3umdWKh7Dc7GW/CpNk4SX3hK58iPCWeCyhVTDrbkNeKrYNZ7EojM5WDaEWTLQ==
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.2.3.tgz#01af019e40d9c6133c49acbb3ff9e30f4f0f70b2"
|
||||
integrity sha512-TtpvOqwB5Gdz/PQmOjgsrGH1nHjAQVCN7JG4A6r1sXRWESL5rNMAiRcBQlCAdKxZcAbstExQePYG8xof/JVRgg==
|
||||
dependencies:
|
||||
"@protobufjs/aspromise" "^1.1.2"
|
||||
"@protobufjs/base64" "^1.1.2"
|
||||
@@ -8079,7 +8091,7 @@ rifm@^0.12.1:
|
||||
resolved "https://registry.yarnpkg.com/rifm/-/rifm-0.12.1.tgz#8fa77f45b7f1cda2a0068787ac821f0593967ac4"
|
||||
integrity sha512-OGA1Bitg/dSJtI/c4dh90svzaUPt228kzFsUkJbtA2c964IqEAwWXeL9ZJi86xWv3j5SMqRvGULl7bA6cK0Bvg==
|
||||
|
||||
rimraf@^3.0.0, rimraf@^3.0.2:
|
||||
rimraf@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
|
||||
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
|
||||
@@ -8206,15 +8218,6 @@ seedrandom@^3.0.5:
|
||||
resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7"
|
||||
integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==
|
||||
|
||||
selenium-webdriver@4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.5.0.tgz#7e20d0fc038177970dad81159950c12f7411ac0d"
|
||||
integrity sha512-9mSFii+lRwcnT2KUAB1kqvx6+mMiiQHH60Y0VUtr3kxxi3oZ3CV3B8e2nuJ7T4SPb+Q6VA0swswe7rYpez07Bg==
|
||||
dependencies:
|
||||
jszip "^3.10.0"
|
||||
tmp "^0.2.1"
|
||||
ws ">=8.7.0"
|
||||
|
||||
semver@7.x, semver@^7.3.2, semver@^7.3.7:
|
||||
version "7.3.8"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
|
||||
@@ -8455,7 +8458,7 @@ string-natural-compare@^3.0.1:
|
||||
resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4"
|
||||
integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==
|
||||
|
||||
string-width@^4.1.0, string-width@^4.2.0:
|
||||
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
@@ -8750,13 +8753,6 @@ tinyspy@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-2.1.1.tgz#9e6371b00c259e5c5b301917ca18c01d40ae558c"
|
||||
integrity sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==
|
||||
|
||||
tmp@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
|
||||
integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==
|
||||
dependencies:
|
||||
rimraf "^3.0.0"
|
||||
|
||||
to-fast-properties@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
||||
@@ -8854,11 +8850,16 @@ tslib@^1.8.1:
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0:
|
||||
tslib@^2.0.1, tslib@^2.4.0:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e"
|
||||
integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==
|
||||
|
||||
tslib@^2.1.0:
|
||||
version "2.5.3"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913"
|
||||
integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==
|
||||
|
||||
tss-react@^4.4.4:
|
||||
version "4.4.4"
|
||||
resolved "https://registry.yarnpkg.com/tss-react/-/tss-react-4.4.4.tgz#12207842dfc58676a9f4d0f532741257428a78e7"
|
||||
@@ -9607,11 +9608,6 @@ wrappy@1:
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
|
||||
|
||||
ws@>=8.7.0:
|
||||
version "8.11.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143"
|
||||
integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==
|
||||
|
||||
xtend@~4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
@@ -9647,7 +9643,7 @@ yargs-parser@^20.2.2:
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
|
||||
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
|
||||
|
||||
yargs-parser@^21.0.1:
|
||||
yargs-parser@^21.0.1, yargs-parser@^21.1.1:
|
||||
version "21.1.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
|
||||
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
|
||||
@@ -9665,6 +9661,19 @@ yargs@^16.2.0:
|
||||
y18n "^5.0.5"
|
||||
yargs-parser "^20.2.2"
|
||||
|
||||
yargs@^17.7.2:
|
||||
version "17.7.2"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"
|
||||
integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
|
||||
dependencies:
|
||||
cliui "^8.0.1"
|
||||
escalade "^3.1.1"
|
||||
get-caller-file "^2.0.5"
|
||||
require-directory "^2.1.1"
|
||||
string-width "^4.2.3"
|
||||
y18n "^5.0.5"
|
||||
yargs-parser "^21.1.1"
|
||||
|
||||
yn@3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
|
||||
|
||||
Reference in New Issue
Block a user