From 90392c1066b7aed631ec3aaa55258e06f18ad013 Mon Sep 17 00:00:00 2001 From: Olmo del Corral Cano Date: Wed, 1 Dec 2021 10:55:05 +0100 Subject: [PATCH] DashboardFilter -> InitialSelectionDashboardFilter and DefaultDashboardFilter --- .../Dashboard/DashboardLogic.cs | 8 ++++--- .../UserQueries/UserQueryEntity.cs | 22 ++++++++++++++----- Signum.Entities/DynamicQuery/Filter.cs | 3 ++- Signum.Entities/EnumMessages.cs | 2 +- .../Dashboard/Admin/Dashboard.tsx | 4 ++-- .../Dashboard/CachedQueryExecutor.ts | 2 +- .../Dashboard/View/UserChartPart.tsx | 19 +++++++++++----- Signum.React/Scripts/FindOptions.ts | 2 +- Signum.React/Scripts/Finder.tsx | 2 +- .../Scripts/Operations/EntityOperations.tsx | 8 +++++-- .../SearchControl/PinnedFilterBuilder.tsx | 5 +++-- .../Scripts/Signum.Entities.DynamicQuery.ts | 3 ++- 12 files changed, 55 insertions(+), 25 deletions(-) diff --git a/Signum.Engine.Extensions/Dashboard/DashboardLogic.cs b/Signum.Engine.Extensions/Dashboard/DashboardLogic.cs index 521aa19c14..f6f3f022ca 100644 --- a/Signum.Engine.Extensions/Dashboard/DashboardLogic.cs +++ b/Signum.Engine.Extensions/Dashboard/DashboardLogic.cs @@ -459,9 +459,9 @@ public static List GetCachedQueryDefinitions(DashboardEnt } } - var cached = definitions.Where(a => a.IsQueryCached); + var cached = definitions.Where(a => a.IsQueryCached).ToList(); - return cached.ToList(); + return cached; } public static List CombineCachedQueryDefinitions(List cachedQueryDefinition) @@ -505,6 +505,8 @@ public CachedQueryDefinition(QueryRequest queryRequest, PanelPartEmbedded panelP public Lite UserAsset { get; set; } public bool IsQueryCached { get; } public bool CanWriteFilters { get; } + + public override string ToString() => $"{UserAsset} IsQueryCached={IsQueryCached} CanWriteFilters={CanWriteFilters}"; } #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. @@ -541,7 +543,7 @@ public bool CombineIfPossible(CachedQueryDefinition definition) if (me.GroupResults) { var meKeys = me.Columns.Select(a => a.Token).Where(t => t is not AggregateToken).ToHashSet(); - var otherKeys = me.Columns.Select(a => a.Token).Where(t => t is not AggregateToken).ToHashSet(); + var otherKeys = other.Columns.Select(a => a.Token).Where(t => t is not AggregateToken).ToHashSet(); if (!meKeys.SetEquals(otherKeys)) return false; } diff --git a/Signum.Entities.Extensions/UserQueries/UserQueryEntity.cs b/Signum.Entities.Extensions/UserQueries/UserQueryEntity.cs index 11b1c60f84..108fd5f0c0 100644 --- a/Signum.Entities.Extensions/UserQueries/UserQueryEntity.cs +++ b/Signum.Entities.Extensions/UserQueries/UserQueryEntity.cs @@ -456,24 +456,36 @@ public static List ToFilterList(this IEnumerable fi { return filters.GroupWhen(filter => filter.Indentation == indent).Select(gr => { + var filter = gr.Key; + + if (filter.Pinned != null) + { + if (filter.Pinned.Active == PinnedFilterActive.Checkbox_StartUnchecked || + filter.Pinned.Active == PinnedFilterActive.DefaultDashboardFilter /*TODO, works for CachedQueries but maybe not in other cases*/ || + filter.Pinned.Active == PinnedFilterActive.InitialSelectionDashboardFilter) + return null; + } + if (!gr.Key.IsGroup) { if (gr.Count() != 0) throw new InvalidOperationException("Unexpected childrens of condition"); - var filter = gr.Key; - var value = FilterValueConverter.Parse(filter.ValueString, filter.Token!.Token.Type, filter.Operation!.Value.IsList()); + if (filter.Pinned?.Active == PinnedFilterActive.WhenHasValue && value == null) + return null; + return (Filter)new FilterCondition(filter.Token.Token, filter.Operation.Value, value); } else { - var group = gr.Key; + if (filter.Pinned?.Active == PinnedFilterActive.WhenHasValue /*TODO, works for empty groups */) + return null; - return (Filter)new FilterGroup(group.GroupOperation!.Value, group.Token?.Token, gr.ToFilterList(indent + 1).ToList()); + return (Filter)new FilterGroup(filter.GroupOperation!.Value, filter.Token?.Token, gr.ToFilterList(indent + 1).ToList()); } - }).ToList(); + }).NotNull().ToList(); } } diff --git a/Signum.Entities/DynamicQuery/Filter.cs b/Signum.Entities/DynamicQuery/Filter.cs index 61a35b3b33..a7ce4ab5e1 100644 --- a/Signum.Entities/DynamicQuery/Filter.cs +++ b/Signum.Entities/DynamicQuery/Filter.cs @@ -268,5 +268,6 @@ public enum PinnedFilterActive Checkbox_StartChecked, [Description("Checkbox (start unchecked)")] Checkbox_StartUnchecked, - DashboardFilter, + InitialSelectionDashboardFilter, + DefaultDashboardFilter, } diff --git a/Signum.Entities/EnumMessages.cs b/Signum.Entities/EnumMessages.cs index d06d9e176e..502bb0d4dd 100644 --- a/Signum.Entities/EnumMessages.cs +++ b/Signum.Entities/EnumMessages.cs @@ -245,7 +245,7 @@ public enum SearchMessage HideHiddenColumns, GroupKey, - DerivedGroupKey + DerivedGroupKey, } public enum SelectorMessage diff --git a/Signum.React.Extensions/Dashboard/Admin/Dashboard.tsx b/Signum.React.Extensions/Dashboard/Admin/Dashboard.tsx index c5f0211496..8604149f9b 100644 --- a/Signum.React.Extensions/Dashboard/Admin/Dashboard.tsx +++ b/Signum.React.Extensions/Dashboard/Admin/Dashboard.tsx @@ -146,8 +146,8 @@ export default function Dashboard(p: { ctx: TypeContext }) {
{!ctx.value.isNew && a.dashboard), value: ctxBasic.value }] }} />}
-
- {!ctx.value.isNew && } +
+ {!ctx.value.isNew && }
} /> diff --git a/Signum.React.Extensions/Dashboard/CachedQueryExecutor.ts b/Signum.React.Extensions/Dashboard/CachedQueryExecutor.ts index cf587720be..a5884a0363 100644 --- a/Signum.React.Extensions/Dashboard/CachedQueryExecutor.ts +++ b/Signum.React.Extensions/Dashboard/CachedQueryExecutor.ts @@ -306,7 +306,7 @@ function getRowKey(rt: ResultTable, keyTokens: string[], parsedTokens: { [token: const index = rt.columns.indexOf(token); if (index == -1) - throw new CachedQueryError("Token " + token + " not found for filtering"); + throw new CachedQueryError("Token " + token + " not found for grouping"); const qt = parsedTokens[token]; diff --git a/Signum.React.Extensions/Dashboard/View/UserChartPart.tsx b/Signum.React.Extensions/Dashboard/View/UserChartPart.tsx index 6c8b62d5e9..5bafe0db12 100644 --- a/Signum.React.Extensions/Dashboard/View/UserChartPart.tsx +++ b/Signum.React.Extensions/Dashboard/View/UserChartPart.tsx @@ -16,21 +16,30 @@ import { PanelPartContentProps } from '../DashboardClient' import { getTypeInfos } from '@framework/Reflection' import SelectorModal from '@framework/SelectorModal' import { DashboardFilter, DashboardFilterController, DashboardFilterRow, equalsDFR } from "./DashboardFilterController" -import { filterOperations, isFilterGroupOptionParsed } from '@framework/FindOptions' +import { filterOperations, FilterOptionParsed, isFilterGroupOption, isFilterGroupOptionParsed, QueryToken } from '@framework/FindOptions' import { CachedQueryJS, executeChartCached } from '../CachedQueryExecutor' export default function UserChartPart(p: PanelPartContentProps) { const qd = useAPI(() => Finder.getQueryDescription(p.part.userChart.query.key), [p.part.userChart.query.key]); const chartRequest = useAPI(() => UserChartClient.Converter.toChartRequest(p.part.userChart, p.entity), [p.part.userChart, p.entity, ...p.deps ?? []]); - const dbFop = React.useMemo(() => chartRequest?.filterOptions.singleOrNull(a => a.pinned?.active == "DashboardFilter"), [chartRequest]); - const originalFilters = React.useMemo(() => chartRequest?.filterOptions.filter(a => a.pinned == null || a.pinned.active != "DashboardFilter"), [chartRequest]); + const dbFop = React.useMemo(() => chartRequest?.filterOptions.singleOrNull(a => a.pinned?.active == "InitialSelectionDashboardFilter"), [chartRequest]); + const originalFilters = React.useMemo(() => chartRequest?.filterOptions.filter(a => a.pinned == null || a.pinned.active != "InitialSelectionDashboardFilter"), [chartRequest]); if (chartRequest != null) { chartRequest.filterOptions.clear(); + + var dashboardFilters = p.filterController.getFilterOptions(p.partEmbedded, chartRequest!.queryKey); + + function allTokens(fs: FilterOptionParsed[]): QueryToken[] { + return fs.flatMap(f => isFilterGroupOptionParsed(f) ? [f.token, ...allTokens(f.filters)].notNull() : [f.token].notNull()) + } + + var tokens = allTokens(dashboardFilters); + chartRequest.filterOptions = [ - ...originalFilters!, - ...p.filterController.getFilterOptions(p.partEmbedded, chartRequest!.queryKey), + ...originalFilters!.filter(a => a.pinned == null || a.pinned.active !== "DefaultDashboardFilter" || !tokens.some(t => t.fullKey == a.token?.fullKey)), + ...dashboardFilters, ]; } diff --git a/Signum.React/Scripts/FindOptions.ts b/Signum.React/Scripts/FindOptions.ts index eff31bf3f8..3b00301fad 100644 --- a/Signum.React/Scripts/FindOptions.ts +++ b/Signum.React/Scripts/FindOptions.ts @@ -88,7 +88,7 @@ export function isFilterGroupOptionParsed(fo: FilterOptionParsed): fo is FilterG } export function isActive(fo: FilterOptionParsed) { - return !(fo.pinned && (fo.pinned.active == "Checkbox_StartUnchecked" || fo.pinned.active == "DashboardFilter" || fo.pinned.active == "WhenHasValue" && fo.value == null)); + return !(fo.pinned && (fo.pinned.active == "Checkbox_StartUnchecked" || fo.pinned.active == "InitialSelectionDashboardFilter" || fo.pinned.active == "WhenHasValue" && fo.value == null)); } export interface FilterConditionOptionParsed { diff --git a/Signum.React/Scripts/Finder.tsx b/Signum.React/Scripts/Finder.tsx index 3dc2c8ef66..6dfe3b44d7 100644 --- a/Signum.React/Scripts/Finder.tsx +++ b/Signum.React/Scripts/Finder.tsx @@ -875,7 +875,7 @@ export function toFilterRequest(fop: FilterOptionParsed, overridenValue?: Overri if (fop.pinned && fop.pinned.active == "Checkbox_StartUnchecked") return undefined; - if (fop.pinned && fop.pinned.active == "DashboardFilter") + if (fop.pinned && fop.pinned.active == "InitialSelectionDashboardFilter") return undefined; if (fop.pinned && overridenValue == null) { diff --git a/Signum.React/Scripts/Operations/EntityOperations.tsx b/Signum.React/Scripts/Operations/EntityOperations.tsx index 5f57a4cad9..134c533e93 100644 --- a/Signum.React/Scripts/Operations/EntityOperations.tsx +++ b/Signum.React/Scripts/Operations/EntityOperations.tsx @@ -129,10 +129,11 @@ interface OperationButtonProps extends ButtonProps { color?: BsColor; avoidAlternatives?: boolean; onOperationClick?: (eoc: EntityOperationContext, event: React.MouseEvent) => void; - children?: React.ReactNode + children?: React.ReactNode; + hideOnCanExecute?: boolean; } -export function OperationButton({ group, onOperationClick, canExecute, eoc: eocOrNull, outline, color, avoidAlternatives, ...props }: OperationButtonProps): React.ReactElement | null { +export function OperationButton({ group, onOperationClick, canExecute, eoc: eocOrNull, outline, color, avoidAlternatives, hideOnCanExecute, ...props }: OperationButtonProps): React.ReactElement | null { if (eocOrNull == null) return null; @@ -144,6 +145,9 @@ export function OperationButton({ group, onOperationClick, canExecute, eoc: eocO const disabled = !!canExecute; + if (hideOnCanExecute && disabled) + return null; + var alternatives = avoidAlternatives ? undefined : eoc.alternatives && eoc.alternatives.filter(a => a.isVisible != false); if (group) { diff --git a/Signum.React/Scripts/SearchControl/PinnedFilterBuilder.tsx b/Signum.React/Scripts/SearchControl/PinnedFilterBuilder.tsx index 256282e6c6..866cf242c2 100644 --- a/Signum.React/Scripts/SearchControl/PinnedFilterBuilder.tsx +++ b/Signum.React/Scripts/SearchControl/PinnedFilterBuilder.tsx @@ -28,12 +28,13 @@ export default function PinnedFilterBuilder(p: PinnedFilterBuilderProps) { if (allPinned.length == 0) return null; + return (
{ allPinned - .filter(fo => fo.pinned?.active != "DashboardFilter") + .filter(fo => fo.pinned?.active != "InitialSelectionDashboardFilter") .groupBy(fo => (fo.pinned!.column ?? 0).toString()) .orderBy(gr => parseInt(gr.key)) .map(gr =>
@@ -81,7 +82,7 @@ export default function PinnedFilterBuilder(p: PinnedFilterBuilderProps) { ); - return createFilterValueControl(ctx, f.token!, () => handleValueChange(f), labelText, f.pinned!.active == "WhenHasValue" || f.pinned!.active == "DashboardFilter"); + return createFilterValueControl(ctx, f.token!, () => handleValueChange(f), labelText, f.pinned!.active == "WhenHasValue" || f.pinned!.active == "InitialSelectionDashboardFilter"); } diff --git a/Signum.React/Scripts/Signum.Entities.DynamicQuery.ts b/Signum.React/Scripts/Signum.Entities.DynamicQuery.ts index 9617ac3340..e3773e43e2 100644 --- a/Signum.React/Scripts/Signum.Entities.DynamicQuery.ts +++ b/Signum.React/Scripts/Signum.Entities.DynamicQuery.ts @@ -67,7 +67,8 @@ export type PinnedFilterActive = "WhenHasValue" | "Checkbox_StartChecked" | "Checkbox_StartUnchecked" | - "DashboardFilter"; + "InitialSelectionDashboardFilter" | + "DefaultDashboardFilter"; export module QueryTokenMessage { export const _0As1 = new MessageKey("QueryTokenMessage", "_0As1");