diff --git a/Signum.React.Extensions/Chart/ChartClient.tsx b/Signum.React.Extensions/Chart/ChartClient.tsx index fab55c8c97..11ccfd2731 100644 --- a/Signum.React.Extensions/Chart/ChartClient.tsx +++ b/Signum.React.Extensions/Chart/ChartClient.tsx @@ -487,7 +487,6 @@ export module Encoder { return p.element.value != defaultParameterValue(scriptParam, c?.token && c.token.token); }) .map(p => ({ name: p.element.name, value: p.element.value }) as ChartParameterOption), - customDrilldowns: cr.customDrilldowns, }; } diff --git a/Signum.React.Extensions/Chart/Templates/ChartRenderer.tsx b/Signum.React.Extensions/Chart/Templates/ChartRenderer.tsx index a8111a4a9d..f5cd628ac9 100644 --- a/Signum.React.Extensions/Chart/Templates/ChartRenderer.tsx +++ b/Signum.React.Extensions/Chart/Templates/ChartRenderer.tsx @@ -3,7 +3,7 @@ import { DomUtils, Dic } from '@framework/Globals' import * as Finder from '@framework/Finder' import * as Navigator from '@framework/Navigator' import { FilterOptionParsed, ColumnOption, hasAggregate, withoutAggregate, FilterOption, FindOptions, withoutPinned } from '@framework/FindOptions' -import { ChartRequestModel, ChartMessage } from '../Signum.Entities.Chart' +import { ChartRequestModel, ChartMessage, UserChartEntity } from '../Signum.Entities.Chart' import * as ChartClient from '../ChartClient' import { toFilterOptions } from '@framework/Finder'; @@ -19,8 +19,10 @@ import { toAbsoluteUrl } from '@framework/AppContext' import * as UserQueryClient from '../../UserQueries/UserQueryClient' import { DynamicTypeConditionSymbolEntity } from '../../Dynamic/Signum.Entities.Dynamic' import { extractFindOptions } from '../../UserQueries/UserQueryClient' +import { Lite } from '@framework/Signum.Entities' export interface ChartRendererProps { + userChart?: Lite; chartRequest: ChartRequestModel; loading: boolean; @@ -56,7 +58,7 @@ export default function ChartRenderer(p: ChartRendererProps) { data={p.data} dashboardFilter={p.dashboardFilter} loading={p.loading} - onDrillDown={p.onDrillDown ?? ((r, e) => handleDrillDown(r, e, p.lastChartRequest!, p.autoRefresh ? p.onReload : undefined))} + onDrillDown={p.onDrillDown ?? ((r, e) => handleDrillDown(r, e, p.lastChartRequest!, p.userChart, p.autoRefresh ? p.onReload : undefined))} onBackgroundClick={p.onBackgroundClick} parameters={parameters} onReload={p.onReload} @@ -69,12 +71,12 @@ export default function ChartRenderer(p: ChartRendererProps) { ); } -export function handleDrillDown(r: ChartRow, e: React.MouseEvent | MouseEvent, cr: ChartRequestModel, onReload?: () => void) { +export function handleDrillDown(r: ChartRow, e: React.MouseEvent | MouseEvent, cr: ChartRequestModel, uc?: Lite, onReload?: () => void) { e.stopPropagation(); var newWindow = e.ctrlKey || e.button == 1; - UserQueryClient.onDrilldownUserChart(cr, r, { openInNewTab: newWindow, onReload }) + UserQueryClient.onDrilldownUserChart(cr, r, uc, { openInNewTab: newWindow, onReload }) .then(done => { if (done == false) { if (r.entity) { diff --git a/Signum.React.Extensions/Chart/Templates/ChartRendererCombined.tsx b/Signum.React.Extensions/Chart/Templates/ChartRendererCombined.tsx index 66e6d7c8c2..1a85da2b12 100644 --- a/Signum.React.Extensions/Chart/Templates/ChartRendererCombined.tsx +++ b/Signum.React.Extensions/Chart/Templates/ChartRendererCombined.tsx @@ -3,7 +3,7 @@ import { DomUtils, Dic } from '@framework/Globals' import * as Finder from '@framework/Finder' import * as Navigator from '@framework/Navigator' import { FilterOptionParsed, ColumnOption, hasAggregate, withoutAggregate, FilterOption, FindOptions, withoutPinned } from '@framework/FindOptions' -import { ChartRequestModel, ChartMessage } from '../Signum.Entities.Chart' +import { ChartRequestModel, ChartMessage, UserChartEntity } from '../Signum.Entities.Chart' import * as ChartClient from '../ChartClient' import { toFilterOptions } from '@framework/Finder'; @@ -17,6 +17,7 @@ import { TypeInfo } from '@framework/Reflection' import { FullscreenComponent } from './FullscreenComponent' import { handleDrillDown } from './ChartRenderer' import { ReactChartCombined } from '../D3Scripts/Components/ReactChartCombined' +import { Lite } from '@framework/Signum.Entities' @@ -28,6 +29,7 @@ export interface ChartRendererCombinedProps { } export interface ChartRendererCombinedInfo { + userChart: Lite; chartRequest: ChartRequestModel; chartScript: ChartScript; data?: ChartClient.ChartTable; @@ -41,7 +43,7 @@ export default function ChartRendererCombined(p: ChartRendererCombinedProps) { a.data)}> ({ chartRequest: info.chartRequest, - onDrillDown: (r, e) => handleDrillDown(r, e, info.chartRequest), + onDrillDown: (r, e) => handleDrillDown(r, e, info.chartRequest, info.userChart), parameters: ChartClient.API.getParameterWithDefault(info.chartRequest, info.chartScript), data: info.data, memo: info.memo diff --git a/Signum.React.Extensions/Chart/Templates/ChartRequestView.tsx b/Signum.React.Extensions/Chart/Templates/ChartRequestView.tsx index 70e952eb65..e5e9aeb947 100644 --- a/Signum.React.Extensions/Chart/Templates/ChartRequestView.tsx +++ b/Signum.React.Extensions/Chart/Templates/ChartRequestView.tsx @@ -24,7 +24,6 @@ import { ChartScript, cleanedChartRequest, getCustomDrilldownsFindOptions, hasAg import { useForceUpdate, useAPI } from '@framework/Hooks' import { AutoFocus } from '@framework/Components/AutoFocus'; import PinnedFilterBuilder from '@framework/SearchControl/PinnedFilterBuilder'; -import { EntityStrip } from '../../../Signum.React/Scripts/Lines'; interface ChartRequestViewProps { chartRequest: ChartRequestModel; @@ -58,19 +57,6 @@ export default function ChartRequestView(p: ChartRequestViewProps) { loading: boolean; } | undefined>(undefined); - const hasAggregatesRef = React.useRef(hasAggregates(p.chartRequest)); - - React.useEffect(() => { - const ha = hasAggregates(p.chartRequest); - if (ha == hasAggregatesRef.current) - return; - - hasAggregatesRef.current = ha; - p.chartRequest.customDrilldowns = []; - p.chartRequest.modified = true; - forceUpdate(); - }); - const queryDescription = useAPI(signal => p.chartRequest ? Finder.getQueryDescription(p.chartRequest.queryKey) : Promise.resolve(undefined), [p.chartRequest.queryKey]); @@ -215,11 +201,6 @@ export default function ChartRequestView(p: ChartRequestViewProps) { forceUpdate(); }} /> - e.customDrilldowns)} - findOptions={getCustomDrilldownsFindOptions(p.chartRequest.queryKey, qd, hasAggregatesRef.current)} - avoidDuplicates={true} - vertical={true} - iconStart={true} /> }
@@ -239,7 +220,7 @@ export default function ChartRequestView(p: ChartRequestViewProps) {
- + {result && {ChartMessage.Data.niceToString()} ( diff --git a/Signum.React.Extensions/Chart/UserChart/UserChartClient.tsx b/Signum.React.Extensions/Chart/UserChart/UserChartClient.tsx index fbadb14fa4..5c4198d1ee 100644 --- a/Signum.React.Extensions/Chart/UserChart/UserChartClient.tsx +++ b/Signum.React.Extensions/Chart/UserChart/UserChartClient.tsx @@ -73,7 +73,6 @@ export module Converter { export async function applyUserChart(cr: ChartRequestModel, uc: UserChartEntity, entity?: Lite): Promise { cr.chartScript = uc.chartScript; cr.maxRows = uc.maxRows; - cr.customDrilldowns = uc.customDrilldowns; const filters = await UserAssetsClient.API.parseFilters({ queryKey: uc.query.key, diff --git a/Signum.React.Extensions/Chart/UserChart/UserChartMenu.tsx b/Signum.React.Extensions/Chart/UserChart/UserChartMenu.tsx index e44eb7bdbf..aad71e187a 100644 --- a/Signum.React.Extensions/Chart/UserChart/UserChartMenu.tsx +++ b/Signum.React.Extensions/Chart/UserChart/UserChartMenu.tsx @@ -153,7 +153,6 @@ export default function UserChartMenu(p: UserChartMenuProps) { filters: qfs.map(f => newMListElement(UserAssetClient.Converter.toQueryFilterEmbedded(f))), columns: cr.columns.map(a => newMListElement(JSON.parse(JSON.stringify(a.element)))), parameters: cr.parameters.map(p => newMListElement(JSON.parse(JSON.stringify(p.element)))), - customDrilldowns: cr.customDrilldowns.map(p => newMListElement(JSON.parse(JSON.stringify(p.element)))), }); return uc; diff --git a/Signum.React.Extensions/Dashboard/View/CombinedUserChartPart.tsx b/Signum.React.Extensions/Dashboard/View/CombinedUserChartPart.tsx index 29048b8a21..a774233519 100644 --- a/Signum.React.Extensions/Dashboard/View/CombinedUserChartPart.tsx +++ b/Signum.React.Extensions/Dashboard/View/CombinedUserChartPart.tsx @@ -175,7 +175,7 @@ export default function CombinedUserChartPart(p: PanelPartContentProps { e.preventDefault(); c.makeQuery!(); }} />) : ({ chartRequest: c.chartRequest!, data: c.result?.chartTable, chartScript: c.chartScript!, memo: c.memo }))} + infos={infos.map(c => ({ userChart: toLite(c.userChart, true), chartRequest: c.chartRequest!, data: c.result?.chartTable, chartScript: c.chartScript!, memo: c.memo }))} onReload={e => { infos.forEach(a => a.makeQuery!()) }} useSameScale={p.content.useSameScale} minHeigh={p.content.minHeight} diff --git a/Signum.React.Extensions/Dashboard/View/UserChartPart.tsx b/Signum.React.Extensions/Dashboard/View/UserChartPart.tsx index d3a64767cd..eae109db4a 100644 --- a/Signum.React.Extensions/Dashboard/View/UserChartPart.tsx +++ b/Signum.React.Extensions/Dashboard/View/UserChartPart.tsx @@ -148,13 +148,14 @@ export default function UserChartPart(p: PanelPartContentProps) { e?.preventDefault(); reloadQuery(); } + const result = resultOrError?.result; + const userChart = toLite(p.content.userChart, true); + return (
reloadQuery()} pinnedFilterVisible={fop => fop.dashboardBehaviour == null} extraSmall={true} /> @@ -175,6 +176,7 @@ export default function UserChartPart(p: PanelPartContentProps) : { e.stopPropagation(); if (e.altKey || p.partEmbedded.interactionGroup == null) - handleDrillDown(row, e, chartRequest, handleReload); + handleDrillDown(row, e, chartRequest, userChart, handleReload); else { const dashboardFilter = p.dashboardController.filters.get(p.partEmbedded); const filterRow = toDashboardFilterRow(row, chartRequest); diff --git a/Signum.React.Extensions/UserQueries/UserQueryClient.tsx b/Signum.React.Extensions/UserQueries/UserQueryClient.tsx index 908f5443ee..b81fe39095 100644 --- a/Signum.React.Extensions/UserQueries/UserQueryClient.tsx +++ b/Signum.React.Extensions/UserQueries/UserQueryClient.tsx @@ -27,7 +27,7 @@ import SearchControlLoaded, { OnDrilldownOptions } from '@framework/SearchContro import SelectorModal from '@framework/SelectorModal'; import { DynamicTypeConditionSymbolEntity } from '../Dynamic/Signum.Entities.Dynamic'; import { Dic } from '@framework/Globals'; -import { ChartRequestModel } from '../Chart/Signum.Entities.Chart'; +import { ChartRequestModel, UserChartEntity } from '../Chart/Signum.Entities.Chart'; import { ChartRow, hasAggregates } from '../Chart/ChartClient'; export function start(options: { routes: RouteObject[] }) { @@ -164,22 +164,28 @@ export async function onDrilldownSearchControl(scl: SearchControlLoaded, row: Re return drilldownToUserQuery(val.fo, val.uq, options); } -export function onDrilldownUserChart(cr: ChartRequestModel, row: ChartRow, options?: OnDrilldownOptions): Promise { - if (cr.customDrilldowns.length == 0) - return Promise.resolve(false); +export async function onDrilldownUserChart(cr: ChartRequestModel, row: ChartRow, uc?: Lite, options?: OnDrilldownOptions): Promise { + if (uc == null) + return false; + + await Navigator.API.fetchAndRemember(uc); + + if (uc.entity!.customDrilldowns.length == 0 || hasAggregates(uc.entity!) != hasAggregates(cr)) + return false; + debugger; const fo = extractFindOptions(cr, row); const entity = row.entity ?? (hasAggregates(cr) ? undefined : fo.filterOptions?.singleOrNull(f => f?.token == "Entity")?.value); - const filters = fo.filterOptions?.notNull(); - const promise = entity ? onDrilldownEntity(cr.customDrilldowns, entity) : onDrilldownGroup(cr.customDrilldowns, filters); - return promise - .then(val => { - if (!val) - return undefined; - return drilldownToUserQuery(val.fo, val.uq, options); - }); + const val = entity ? + await onDrilldownEntity(uc.entity!.customDrilldowns, entity) : + await onDrilldownGroup(uc.entity!.customDrilldowns, filters); + + if (!val) + return undefined; + + return drilldownToUserQuery(val.fo, val.uq, options); } export function onDrilldownEntity(items: MList>, entity: Lite) { diff --git a/Signum.React/Scripts/SearchControl/SearchControlLoaded.tsx b/Signum.React/Scripts/SearchControl/SearchControlLoaded.tsx index 8cadae18fe..caa6c66bc4 100644 --- a/Signum.React/Scripts/SearchControl/SearchControlLoaded.tsx +++ b/Signum.React/Scripts/SearchControl/SearchControlLoaded.tsx @@ -173,10 +173,10 @@ export class SearchControlLoaded extends React.Component { @@ -301,11 +301,11 @@ export class SearchControlLoaded extends React.Component { + doSearch(opts : { dataChanged?: boolean, force?: boolean}): Promise { if (this.isUnmounted || (this.isManualRefreshOrAllPagination() && !opts.force)) return Promise.resolve(); @@ -328,7 +328,7 @@ export class SearchControlLoaded extends React.Component(undefined) + qrSummary ? this.abortableSearchSummary.getData({ request: qrSummary, fop, customRequest }) : Promise.resolve(undefined) ]).then(([rt, summaryRt]) => { this.setState({ resultTable: rt, @@ -459,7 +459,7 @@ export class SearchControlLoaded extends React.Component { @@ -516,17 +516,17 @@ export class SearchControlLoaded extends React.Component { this.state.showFilters ? : - sfb &&
{sfb}
} + sfb &&
{sfb}
}
} {p.showHeader == true && !this.state.showFilters && !sfb && this.renderPinnedFilters(true)} @@ -567,7 +567,7 @@ export class SearchControlLoaded extends React.Component this.containerDiv = d} +
this.containerDiv = d} className="sf-scroll-table-container" style={{ maxHeight: this.props.maxResultsHeight }}>
@@ -689,7 +689,7 @@ export class SearchControlLoaded extends React.Component Ʃ - + }, p.showSystemTimeButton && { @@ -713,7 +713,7 @@ export class SearchControlLoaded extends React.Component + button: }, @@ -768,7 +768,7 @@ export class SearchControlLoaded extends React.Component) => { if (!this.props.create) @@ -823,7 +823,7 @@ export class SearchControlLoaded extends React.Component this.handleCreated(entity)); } - + }); } } @@ -915,7 +915,7 @@ export class SearchControlLoaded extends React.Component this.setMarkedRows(dic)); } - setMarkedRows(dic: MarkedRowsDictionary) { + setMarkedRows(dic: MarkedRowsDictionary){ this.setState({ markedRows: { ...this.state.markedRows, ...dic } as MarkedRowsDictionary }) } @@ -1081,7 +1081,7 @@ export class SearchControlLoaded extends React.Component { const cm = this.state.contextualMenu!; const fo = this.props.findOptions; - + const col = fo.columnOptions[cm.columnIndex!]; fo.columnOptions.clear(); fo.columnOptions.push(...Dic.getValues(this.props.queryDescription.columns).filter(a => a.name != "Entity").map(cd => softCast({ displayName: cd.displayName, token: toQueryToken(cd) }))); @@ -1165,7 +1165,7 @@ export class SearchControlLoaded extends React.Component this.setState({ showHiddenColumns: undefined })}> + menuItems.push( this.setState({ showHiddenColumns : undefined })}>  {SearchMessage.HideHiddenColumns.niceToString()} ); } else { @@ -1173,7 +1173,7 @@ export class SearchControlLoaded extends React.Component {SearchMessage.ShowHiddenColumns.niceToString()} ); } - } + } } if (cm.rowIndex != undefined) { @@ -1213,7 +1213,7 @@ export class SearchControlLoaded extends React.Component{prefix} {formatter.formatter(val, { - columns: rt.columns, - row: rt.rows[0], - rowIndex: 0, - refresh: () => scl.dataChanged(), + columns: rt.columns, + row: rt.rows[0], + rowIndex: 0, + refresh: () => scl.dataChanged(), systemTime: scl.props.findOptions.systemTime, searchControl: scl, }, summaryToken)} @@ -1375,7 +1375,7 @@ export class SearchControlLoaded extends React.Component co.token && co.token.queryTokenType != "Aggregate" && !hasToArray(co.token))); - function isDerivedKey(token: QueryToken | undefined): boolean { + function isDerivedKey(token: QueryToken | undefined) : boolean { if (token == null) return false; @@ -1415,7 +1415,7 @@ export class SearchControlLoaded extends React.Component } + title={rootKeys.contains(co) ? SearchMessage.GroupKey.niceToString() : SearchMessage.DerivedGroupKey.niceToString() } />} {co.displayName}
@@ -1724,7 +1724,7 @@ export class SearchControlLoaded extends React.Component{noResultsElement}; const entityFormatter = this.getEntityFormatter(); @@ -1735,8 +1735,8 @@ export class SearchControlLoaded extends React.Component; return ( @@ -1893,7 +1893,7 @@ export class SearchControlLoaded extends React.Component ); } - + handleOnNavigated = (lite: Lite) => { if (this.props.onNavigated)