mirror of
https://github.com/rowyio/rowy.git
synced 2025-12-29 00:16:39 +01:00
allow all users to override table filters
This commit is contained in:
@@ -43,6 +43,7 @@ export default function Filters() {
|
||||
const userDocData = userDoc.state.doc;
|
||||
const tableSchemaDoc = tableState?.config?.tableConfig?.doc;
|
||||
const tableFilters = tableSchemaDoc?.filters;
|
||||
const tableFiltersOverridable = Boolean(tableSchemaDoc?.filtersOverridable);
|
||||
const userFilters = tableId
|
||||
? userDocData.tables?.[tableId]?.filters
|
||||
: undefined;
|
||||
@@ -64,17 +65,15 @@ export default function Filters() {
|
||||
? userFilters[0]
|
||||
: INITIAL_QUERY
|
||||
);
|
||||
setCanOverrideCheckbox(tableFiltersOverridable);
|
||||
|
||||
if (!tableActions) return;
|
||||
|
||||
let filtersToApply: TableFilter[] = [];
|
||||
|
||||
// Allow admin to override table-level filters with their own
|
||||
// Set to null to show all filters for the admin user
|
||||
if (
|
||||
userClaims?.roles.includes("ADMIN") &&
|
||||
(hasUserFilters || userFilters === null)
|
||||
) {
|
||||
// Allow override table-level filters with their own
|
||||
// Set to null to completely ignore table filters
|
||||
if (tableFiltersOverridable && (hasUserFilters || userFilters === null)) {
|
||||
filtersToApply = userFilters ?? [];
|
||||
} else if (hasTableFilters) {
|
||||
filtersToApply = tableFilters;
|
||||
@@ -85,7 +84,7 @@ export default function Filters() {
|
||||
tableActions.table.filter(filtersToApply);
|
||||
// Reset order so we don’t have to make a new index
|
||||
tableActions.table.orderBy();
|
||||
}, [tableFilters, userFilters, userClaims?.roles]);
|
||||
}, [tableFilters, tableFiltersOverridable, userFilters, userClaims?.roles]);
|
||||
|
||||
// Helper booleans for local table filter state
|
||||
const appliedFilters = tableState?.filters || [];
|
||||
@@ -93,11 +92,14 @@ export default function Filters() {
|
||||
appliedFilters && appliedFilters.length > 0
|
||||
);
|
||||
const tableFiltersOverridden =
|
||||
userClaims?.roles.includes("ADMIN") &&
|
||||
(tableFiltersOverridable || userClaims?.roles.includes("ADMIN")) &&
|
||||
(hasUserFilters || userFilters === null) &&
|
||||
hasTableFilters;
|
||||
|
||||
// ADMIN overrides
|
||||
// Override table filters
|
||||
const [canOverrideCheckbox, setCanOverrideCheckbox] = useState(
|
||||
tableFiltersOverridable
|
||||
);
|
||||
const [tab, setTab] = useState<"user" | "table">(
|
||||
hasTableFilters && !tableFiltersOverridden ? "table" : "user"
|
||||
);
|
||||
@@ -108,9 +110,10 @@ export default function Filters() {
|
||||
// Save table filters to table schema document
|
||||
const setTableFilters = (filters: TableFilter[]) => {
|
||||
tableActions?.table.updateConfig("filters", filters);
|
||||
tableActions?.table.updateConfig("filtersOverridable", canOverrideCheckbox);
|
||||
};
|
||||
// Save user filters to user document
|
||||
// null overrides table filters - only available to ADMINs
|
||||
// null overrides table filters
|
||||
const setUserFilters = (filters: TableFilter[] | null) => {
|
||||
userDoc.dispatch({
|
||||
action: DocActions.update,
|
||||
@@ -129,79 +132,225 @@ export default function Filters() {
|
||||
availableFilters={availableFilters}
|
||||
setUserFilters={setUserFilters}
|
||||
>
|
||||
{({ handleClose }) =>
|
||||
{({ handleClose }) => {
|
||||
// ADMIN
|
||||
userClaims?.roles.includes("ADMIN") ? (
|
||||
<TabContext value={tab}>
|
||||
<TabList
|
||||
onChange={(_, v) => setTab(v)}
|
||||
variant="fullWidth"
|
||||
aria-label="Filter tabs"
|
||||
>
|
||||
<Tab
|
||||
label={
|
||||
<>
|
||||
Your filter
|
||||
{tableFiltersOverridden && (
|
||||
<Badge
|
||||
aria-label="(overrides table filters)"
|
||||
color="primary"
|
||||
variant="inlineDot"
|
||||
invisible={false}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
value="user"
|
||||
style={{ flexDirection: "row" }}
|
||||
/>
|
||||
<Tab
|
||||
label={
|
||||
<>
|
||||
Table filter
|
||||
{tableFiltersOverridden ? (
|
||||
<Badge
|
||||
aria-label="(overridden by your filters)"
|
||||
color="primary"
|
||||
variant="inlineDot"
|
||||
invisible={false}
|
||||
sx={{
|
||||
"& .MuiBadge-badge": {
|
||||
bgcolor: "transparent",
|
||||
border: "1px solid currentColor",
|
||||
color: "inherit",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
) : hasTableFilters ? (
|
||||
<Badge
|
||||
aria-label="(active)"
|
||||
color="primary"
|
||||
variant="inlineDot"
|
||||
invisible={false}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
}
|
||||
value="table"
|
||||
style={{ flexDirection: "row" }}
|
||||
/>
|
||||
</TabList>
|
||||
<Divider style={{ marginTop: -1 }} />
|
||||
if (userClaims?.roles.includes("ADMIN")) {
|
||||
return (
|
||||
<TabContext value={tab}>
|
||||
<TabList
|
||||
onChange={(_, v) => setTab(v)}
|
||||
variant="fullWidth"
|
||||
aria-label="Filter tabs"
|
||||
>
|
||||
<Tab
|
||||
label={
|
||||
<>
|
||||
Your filter
|
||||
{tableFiltersOverridden && (
|
||||
<Badge
|
||||
aria-label="(overrides table filters)"
|
||||
color="primary"
|
||||
variant="inlineDot"
|
||||
invisible={false}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
value="user"
|
||||
style={{ flexDirection: "row" }}
|
||||
/>
|
||||
<Tab
|
||||
label={
|
||||
<>
|
||||
Table filter
|
||||
{tableFiltersOverridden ? (
|
||||
<Badge
|
||||
aria-label="(overridden by your filters)"
|
||||
color="primary"
|
||||
variant="inlineDot"
|
||||
invisible={false}
|
||||
sx={{
|
||||
"& .MuiBadge-badge": {
|
||||
bgcolor: "transparent",
|
||||
border: "1px solid currentColor",
|
||||
color: "inherit",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
) : hasTableFilters ? (
|
||||
<Badge
|
||||
aria-label="(active)"
|
||||
color="primary"
|
||||
variant="inlineDot"
|
||||
invisible={false}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
}
|
||||
value="table"
|
||||
style={{ flexDirection: "row" }}
|
||||
/>
|
||||
</TabList>
|
||||
<Divider style={{ marginTop: -1 }} />
|
||||
|
||||
<TabPanel value="user" className="content">
|
||||
<TabPanel value="user" className="content">
|
||||
<FilterInputs {...userFilterInputs} />
|
||||
|
||||
{hasTableFilters && (
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={overrideTableFilters}
|
||||
onChange={(e) =>
|
||||
setOverrideTableFilters(e.target.checked)
|
||||
}
|
||||
/>
|
||||
}
|
||||
label="Override table filters"
|
||||
sx={{ justifyContent: "center", mb: 1, mr: 0 }}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Stack
|
||||
direction="row"
|
||||
sx={{ "& .MuiButton-root": { minWidth: 100 } }}
|
||||
justifyContent="center"
|
||||
spacing={1}
|
||||
>
|
||||
<Button
|
||||
disabled={
|
||||
!overrideTableFilters &&
|
||||
!tableFiltersOverridden &&
|
||||
userFilterInputs.query.key === ""
|
||||
}
|
||||
onClick={() => {
|
||||
setUserFilters(overrideTableFilters ? null : []);
|
||||
userFilterInputs.resetQuery();
|
||||
}}
|
||||
>
|
||||
Clear
|
||||
{overrideTableFilters
|
||||
? " (ignore table filter)"
|
||||
: " (use table filter)"}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
disabled={
|
||||
(!overrideTableFilters && hasTableFilters) ||
|
||||
shouldDisableApplyButton(userFilterInputs.query.value)
|
||||
}
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
setUserFilters([userFilterInputs.query]);
|
||||
handleClose();
|
||||
}}
|
||||
>
|
||||
Apply
|
||||
</Button>
|
||||
</Stack>
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel value="table" className="content">
|
||||
<FilterInputs {...tableFilterInputs} />
|
||||
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={canOverrideCheckbox}
|
||||
onChange={(e) => setCanOverrideCheckbox(e.target.checked)}
|
||||
/>
|
||||
}
|
||||
label="All users can override table filters"
|
||||
sx={{ justifyContent: "center", mb: 1, mr: 0 }}
|
||||
/>
|
||||
|
||||
<Alert severity="info" style={{ width: "auto" }} sx={{ mb: 3 }}>
|
||||
<ul style={{ margin: 0, paddingLeft: "1.5em" }}>
|
||||
<li>
|
||||
The filter above will be set
|
||||
{canOverrideCheckbox && " by default"} for all users who
|
||||
view this table.
|
||||
</li>
|
||||
{canOverrideCheckbox ? (
|
||||
<>
|
||||
<li>All users can override this.</li>
|
||||
<li>Only ADMIN users can edit table filters.</li>
|
||||
</>
|
||||
) : (
|
||||
<li>Only ADMIN users can override or edit this.</li>
|
||||
)}
|
||||
</ul>
|
||||
</Alert>
|
||||
|
||||
<Stack
|
||||
direction="row"
|
||||
sx={{ "& .MuiButton-root": { minWidth: 100 } }}
|
||||
justifyContent="center"
|
||||
spacing={1}
|
||||
>
|
||||
<Button
|
||||
disabled={tableFilterInputs.query.key === ""}
|
||||
onClick={() => {
|
||||
setTableFilters([]);
|
||||
tableFilterInputs.resetQuery();
|
||||
}}
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
disabled={shouldDisableApplyButton(
|
||||
tableFilterInputs.query.value
|
||||
)}
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
setTableFilters([tableFilterInputs.query]);
|
||||
handleClose();
|
||||
}}
|
||||
>
|
||||
Apply
|
||||
</Button>
|
||||
</Stack>
|
||||
</TabPanel>
|
||||
</TabContext>
|
||||
);
|
||||
}
|
||||
|
||||
// Non-ADMIN, override disabled
|
||||
if (hasTableFilters && !tableFiltersOverridable) {
|
||||
return (
|
||||
<div className="content">
|
||||
<FilterInputs {...tableFilterInputs} disabled />
|
||||
|
||||
<Alert severity="info" style={{ width: "auto" }}>
|
||||
An ADMIN user has set the filter for this table
|
||||
</Alert>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Non-ADMIN, override enabled
|
||||
if (hasTableFilters && tableFiltersOverridable) {
|
||||
return (
|
||||
<div className="content">
|
||||
<FilterInputs {...userFilterInputs} />
|
||||
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={overrideTableFilters}
|
||||
onChange={(e) => setOverrideTableFilters(e.target.checked)}
|
||||
/>
|
||||
}
|
||||
label="Override table filters"
|
||||
sx={{ justifyContent: "center", mb: 1, mr: 0 }}
|
||||
/>
|
||||
{hasTableFilters && (
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={overrideTableFilters}
|
||||
onChange={(e) =>
|
||||
setOverrideTableFilters(e.target.checked)
|
||||
}
|
||||
/>
|
||||
}
|
||||
label="Override table filters"
|
||||
sx={{ justifyContent: "center", mb: 1, mr: 0 }}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Stack
|
||||
direction="row"
|
||||
@@ -241,59 +390,12 @@ export default function Filters() {
|
||||
Apply
|
||||
</Button>
|
||||
</Stack>
|
||||
</TabPanel>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<TabPanel value="table" className="content">
|
||||
<FilterInputs {...tableFilterInputs} />
|
||||
|
||||
<Alert severity="info" style={{ width: "auto" }} sx={{ mb: 3 }}>
|
||||
The filter above will be set for all users who view this table.
|
||||
Only ADMIN users can override or edit this.
|
||||
</Alert>
|
||||
|
||||
<Stack
|
||||
direction="row"
|
||||
sx={{ "& .MuiButton-root": { minWidth: 100 } }}
|
||||
justifyContent="center"
|
||||
spacing={1}
|
||||
>
|
||||
<Button
|
||||
disabled={tableFilterInputs.query.key === ""}
|
||||
onClick={() => {
|
||||
setTableFilters([]);
|
||||
tableFilterInputs.resetQuery();
|
||||
}}
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
disabled={shouldDisableApplyButton(
|
||||
tableFilterInputs.query.value
|
||||
)}
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
setTableFilters([tableFilterInputs.query]);
|
||||
handleClose();
|
||||
}}
|
||||
>
|
||||
Apply
|
||||
</Button>
|
||||
</Stack>
|
||||
</TabPanel>
|
||||
</TabContext>
|
||||
) : // Non-ADMIN cannot override table filters
|
||||
hasTableFilters ? (
|
||||
<div className="content">
|
||||
<FilterInputs {...tableFilterInputs} disabled />
|
||||
|
||||
<Alert severity="info" style={{ width: "auto" }}>
|
||||
An ADMIN user has set the filter for this table
|
||||
</Alert>
|
||||
</div>
|
||||
) : (
|
||||
// Non-ADMIN can set own filters, since there are no table filters
|
||||
// Non-ADMIN, no table filters
|
||||
return (
|
||||
<div className="content">
|
||||
<FilterInputs {...userFilterInputs} />
|
||||
|
||||
@@ -328,8 +430,8 @@ export default function Filters() {
|
||||
</Button>
|
||||
</Stack>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
}}
|
||||
</FiltersPopover>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user