'1'
This commit is contained in:
1 parent
cfb6afcdce
commit
178a3e656f
4 files changed
+272
-270
No files matched your search
+158
-31
@@ -6,11 +6,13 @@ import {
|
||||
ModuleRegistry as AgGridModuleRegistry,
|
||||
type ColDef,
|
||||
type ColGroupDef,
|
||||
type GridApi,
|
||||
type GridReadyEvent,
|
||||
type ValueFormatterParams,
|
||||
} from 'ag-grid-community';
|
||||
import type { AgCartesianChartOptions } from 'ag-charts-community';
|
||||
import { ModuleRegistry } from 'ag-charts-community';
|
||||
import { Building2, Construction, LayoutGrid, Library, LocateFixed, MapPinned, SquareFunction, Waypoints } from 'lucide-react';
|
||||
import { Building2, Construction, LayoutGrid, Library, LocateFixed, MapPinned, PanelRightClose, PanelRightOpen, SquareFunction, Waypoints } from 'lucide-react';
|
||||
import {
|
||||
AnnotationsModule,
|
||||
ContextMenuModule,
|
||||
@@ -140,6 +142,7 @@ const defaultTemplateFilterNode = {
|
||||
filterKey: 'templateLibrary',
|
||||
label: '默认模板',
|
||||
} as const;
|
||||
const overallSummaryKey = 'summary';
|
||||
|
||||
// const mockGeoLocationPayload = {
|
||||
// checkStrictly: true,
|
||||
@@ -196,6 +199,7 @@ type ApiBuildingFunctionStat = {
|
||||
type ApiBuildingFunctionStatBatchItem = {
|
||||
key?: string;
|
||||
data?: ApiBuildingFunctionStat[];
|
||||
summary?: ApiBuildingFunctionStat | null;
|
||||
};
|
||||
type ChartDatum = {
|
||||
groupName: string;
|
||||
@@ -237,6 +241,7 @@ type SelectedFilterNode = {
|
||||
type PivotGridRow = {
|
||||
year: string;
|
||||
name: string;
|
||||
summary: boolean;
|
||||
lowValue: number | null;
|
||||
centerValue: number | null;
|
||||
highValue: number | null;
|
||||
@@ -717,6 +722,7 @@ function renderFilterTreeNodes(
|
||||
function App() {
|
||||
const workspaceRef = useRef<HTMLElement>(null);
|
||||
const chartFrameRef = useRef<HTMLDivElement>(null);
|
||||
const pivotGridApiRef = useRef<GridApi<PivotGridRow> | null>(null);
|
||||
const treeInitialLoadStartedRef = useRef<Record<ContentKey, boolean>>({
|
||||
geoLocation: false,
|
||||
facilityType: false,
|
||||
@@ -738,6 +744,8 @@ function App() {
|
||||
const [metricKey, setMetricKey] = useState<MetricKey>('cost');
|
||||
const [groupKey, setGroupKey] = useState<GroupKey>('year');
|
||||
const [chartViewKey, setChartViewKey] = useState<ChartViewKey>('trend');
|
||||
const [workspaceFullscreen, setWorkspaceFullscreen] = useState(false);
|
||||
const [rightPanelCollapsed, setRightPanelCollapsed] = useState(false);
|
||||
const [statisticMenuOpen, setStatisticMenuOpen] = useState(false);
|
||||
const [metricMenuOpen, setMetricMenuOpen] = useState(false);
|
||||
const [activeContentKey, setActiveContentKey] = useState<ContentKey>('geoLocation');
|
||||
@@ -764,6 +772,7 @@ function App() {
|
||||
});
|
||||
const [selectedContentNodes, setSelectedContentNodes] = useState<SelectedContentNode[]>([]);
|
||||
const [chartDataBySelection, setChartDataBySelection] = useState<Record<string, ChartDatum[]>>({});
|
||||
const [chartSummaryBySelection, setChartSummaryBySelection] = useState<Record<string, ChartDatum>>({});
|
||||
const [chartQueryVersion, setChartQueryVersion] = useState(0);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [loadError, setLoadError] = useState<string | null>(null);
|
||||
@@ -861,6 +870,8 @@ function App() {
|
||||
const currentViewShortLabel = chartViewKey === 'pivot' ? '表' : '趋';
|
||||
const pivotToggleActionLabel = chartViewKey === 'pivot' ? '切换到趋势图' : '切换到表格';
|
||||
const pivotToggleTitle = `${chartViewKey === 'pivot' ? '当前表格' : '当前趋势图'},${pivotToggleActionLabel}`;
|
||||
const fullscreenToggleLabel = workspaceFullscreen ? '退出全屏' : '全屏';
|
||||
const rightPanelToggleLabel = rightPanelCollapsed ? '展开选择区' : '收起选择区';
|
||||
const activeContent = contentOptions.find((option) => option.key === activeContentKey) ?? contentOptions[0];
|
||||
const activeTree = treeByContent[activeContentKey];
|
||||
const activeFilter = filterOptions.find((option) => option.key === filterModalKey);
|
||||
@@ -912,6 +923,7 @@ function App() {
|
||||
return rows.map((datum) => ({
|
||||
year: datum.groupName,
|
||||
name: node.label,
|
||||
summary: false,
|
||||
lowValue: datum.thresholdLowValue,
|
||||
centerValue: datum.thresholdCenterValue,
|
||||
highValue: datum.thresholdHighValue,
|
||||
@@ -927,6 +939,32 @@ function App() {
|
||||
}),
|
||||
[chartDataBySelection, selectedContentNodes],
|
||||
);
|
||||
const pivotGridPinnedBottomRowData = useMemo<PivotGridRow[]>(
|
||||
() => {
|
||||
const datum = chartSummaryBySelection[overallSummaryKey]
|
||||
?? selectedContentNodes
|
||||
.map((node) => chartSummaryBySelection[getSelectionKey(node.contentKey, node.id)])
|
||||
.find(Boolean);
|
||||
if (!datum) return [];
|
||||
return [{
|
||||
year: '',
|
||||
name: '统计',
|
||||
summary: true,
|
||||
lowValue: datum.thresholdLowValue,
|
||||
centerValue: datum.thresholdCenterValue,
|
||||
highValue: datum.thresholdHighValue,
|
||||
maxValue: datum.maxValue,
|
||||
minValue: datum.minValue,
|
||||
avgValue: datum.avgValue,
|
||||
medianValue: datum.medianValue,
|
||||
standardDeviation: datum.standardDeviation,
|
||||
interquartileRange: datum.interquartileRange,
|
||||
coefficientOfVariation: datum.coefficientOfVariation,
|
||||
dataCount: datum.dataCount,
|
||||
}];
|
||||
},
|
||||
[chartSummaryBySelection, selectedContentNodes],
|
||||
);
|
||||
const pivotGridColumnDefs = useMemo<(ColDef<PivotGridRow> | ColGroupDef<PivotGridRow>)[]>(
|
||||
() => {
|
||||
const valueFormatter = ({ value }: ValueFormatterParams<PivotGridRow, number | null>) => (
|
||||
@@ -937,14 +975,15 @@ function App() {
|
||||
{
|
||||
field: 'year',
|
||||
headerName: '年度',
|
||||
minWidth: 68,
|
||||
width: 74,
|
||||
minWidth: 58,
|
||||
width: 64,
|
||||
},
|
||||
{
|
||||
field: 'name',
|
||||
headerName: '名称',
|
||||
flex: 1,
|
||||
minWidth: 108,
|
||||
minWidth: 86,
|
||||
tooltipField: 'name',
|
||||
},
|
||||
{
|
||||
headerName: '基准阀值',
|
||||
@@ -953,21 +992,21 @@ function App() {
|
||||
field: 'lowValue',
|
||||
headerName: '低值',
|
||||
type: 'numericColumn',
|
||||
minWidth: 78,
|
||||
minWidth: 64,
|
||||
valueFormatter,
|
||||
},
|
||||
{
|
||||
field: 'centerValue',
|
||||
headerName: '中心值',
|
||||
type: 'numericColumn',
|
||||
minWidth: 78,
|
||||
minWidth: 68,
|
||||
valueFormatter,
|
||||
},
|
||||
{
|
||||
field: 'highValue',
|
||||
headerName: '高值',
|
||||
type: 'numericColumn',
|
||||
minWidth: 78,
|
||||
minWidth: 64,
|
||||
valueFormatter,
|
||||
},
|
||||
],
|
||||
@@ -979,49 +1018,49 @@ function App() {
|
||||
field: 'maxValue',
|
||||
headerName: '最大值',
|
||||
type: 'numericColumn',
|
||||
minWidth: 78,
|
||||
minWidth: 68,
|
||||
valueFormatter,
|
||||
},
|
||||
{
|
||||
field: 'minValue',
|
||||
headerName: '最小值',
|
||||
type: 'numericColumn',
|
||||
minWidth: 78,
|
||||
minWidth: 68,
|
||||
valueFormatter,
|
||||
},
|
||||
{
|
||||
field: 'avgValue',
|
||||
headerName: '平均值',
|
||||
type: 'numericColumn',
|
||||
minWidth: 78,
|
||||
minWidth: 68,
|
||||
valueFormatter,
|
||||
},
|
||||
{
|
||||
field: 'medianValue',
|
||||
headerName: '中位数',
|
||||
type: 'numericColumn',
|
||||
minWidth: 78,
|
||||
minWidth: 68,
|
||||
valueFormatter,
|
||||
},
|
||||
{
|
||||
field: 'standardDeviation',
|
||||
headerName: '标准差',
|
||||
type: 'numericColumn',
|
||||
minWidth: 78,
|
||||
minWidth: 68,
|
||||
valueFormatter,
|
||||
},
|
||||
{
|
||||
field: 'interquartileRange',
|
||||
headerName: '四分位距',
|
||||
type: 'numericColumn',
|
||||
minWidth: 88,
|
||||
minWidth: 76,
|
||||
valueFormatter,
|
||||
},
|
||||
{
|
||||
field: 'coefficientOfVariation',
|
||||
headerName: '变异系数',
|
||||
type: 'numericColumn',
|
||||
minWidth: 88,
|
||||
minWidth: 76,
|
||||
valueFormatter: ({ value }: ValueFormatterParams<PivotGridRow, number | null>) => (
|
||||
value == null ? '' : formatNumber(Number(value), 4)
|
||||
),
|
||||
@@ -1032,6 +1071,17 @@ function App() {
|
||||
},
|
||||
[requestMetricKey],
|
||||
);
|
||||
const fitPivotGridColumns = useCallback(() => {
|
||||
window.requestAnimationFrame(() => {
|
||||
pivotGridApiRef.current?.sizeColumnsToFit({
|
||||
defaultMinWidth: 58,
|
||||
columnLimits: [
|
||||
{ key: 'year', minWidth: 58, maxWidth: 72 },
|
||||
{ key: 'name', minWidth: 86, maxWidth: 220 },
|
||||
],
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
const selectedNodeKeys = useMemo(
|
||||
() => new Set(selectedContentNodes.map((node) => getSelectionKey(node.contentKey, node.id))),
|
||||
[selectedContentNodes],
|
||||
@@ -1306,6 +1356,10 @@ function App() {
|
||||
const { [selectionKey]: _removed, ...rest } = data;
|
||||
return rest;
|
||||
});
|
||||
setChartSummaryBySelection((data) => {
|
||||
const { [selectionKey]: _removed, ...rest } = data;
|
||||
return rest;
|
||||
});
|
||||
return current.filter((_, index) => index !== existingIndex);
|
||||
}
|
||||
|
||||
@@ -1319,6 +1373,7 @@ function App() {
|
||||
setActiveContentKey(nextContentKey);
|
||||
setSelectedContentNodes([]);
|
||||
setChartDataBySelection({});
|
||||
setChartSummaryBySelection({});
|
||||
setLoadError(null);
|
||||
setLoadingHint('');
|
||||
setLoading(false);
|
||||
@@ -1546,6 +1601,7 @@ function App() {
|
||||
resetIndicatorTreeState();
|
||||
}
|
||||
setChartDataBySelection({});
|
||||
setChartSummaryBySelection({});
|
||||
setLoadError(null);
|
||||
if (selectedContentNodes.length > 0) {
|
||||
setLoadingHint('正在按筛选条件重新计算');
|
||||
@@ -1578,6 +1634,7 @@ function App() {
|
||||
resetIndicatorTreeState();
|
||||
}
|
||||
setChartDataBySelection({});
|
||||
setChartSummaryBySelection({});
|
||||
setLoadError(null);
|
||||
if (selectedContentNodes.length > 0) {
|
||||
setLoadingHint('正在按筛选条件重新计算');
|
||||
@@ -1589,6 +1646,7 @@ function App() {
|
||||
const updateMetricKey = (nextMetricKey: MetricKey) => {
|
||||
setMetricKey(nextMetricKey);
|
||||
setChartDataBySelection({});
|
||||
setChartSummaryBySelection({});
|
||||
setLoadError(null);
|
||||
setLoadingHint('正在重新加载数据');
|
||||
setLoading(true);
|
||||
@@ -1601,12 +1659,33 @@ function App() {
|
||||
setStatisticMenuOpen(false);
|
||||
}, []);
|
||||
|
||||
const toggleWorkspaceFullscreen = useCallback(() => {
|
||||
const fullscreenTarget = workspaceRef.current;
|
||||
if (!fullscreenTarget) return;
|
||||
if (document.fullscreenElement === fullscreenTarget) {
|
||||
void document.exitFullscreen();
|
||||
} else {
|
||||
void fullscreenTarget.requestFullscreen();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const openGridFilterModal = (filterKey: 'templateLibrary' | 'indicatorTree') => {
|
||||
setMetricMenuOpen(false);
|
||||
setStatisticMenuOpen(false);
|
||||
openFilterModal(filterKey);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleFullscreenChange = () => {
|
||||
setWorkspaceFullscreen(document.fullscreenElement === workspaceRef.current);
|
||||
};
|
||||
handleFullscreenChange();
|
||||
document.addEventListener('fullscreenchange', handleFullscreenChange);
|
||||
return () => {
|
||||
document.removeEventListener('fullscreenchange', handleFullscreenChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!contentTreeConfigs[activeContentKey]) return;
|
||||
if (treeByContent[activeContentKey].length > 0 || treeInitialLoadStartedRef.current[activeContentKey]) return;
|
||||
@@ -1645,10 +1724,6 @@ function App() {
|
||||
async function loadStats() {
|
||||
if (selectedContentNodes.length === 0) {
|
||||
setChartDataBySelection({});
|
||||
setLoading(false);
|
||||
setLoadingHint('');
|
||||
setLoadError(null);
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
@@ -1656,7 +1731,7 @@ function App() {
|
||||
setLoadError(null);
|
||||
try {
|
||||
const hasAnyMissingNode = selectedContentNodes.some((node) => !chartDataBySelection[getSelectionKey(node.contentKey, node.id)]);
|
||||
if (!hasAnyMissingNode) {
|
||||
if (selectedContentNodes.length > 0 && !hasAnyMissingNode && chartSummaryBySelection[overallSummaryKey]) {
|
||||
setLoading(false);
|
||||
setLoadingHint('');
|
||||
return;
|
||||
@@ -1687,10 +1762,19 @@ function App() {
|
||||
const results = (payload.data ?? [])
|
||||
.filter((item) => item.key)
|
||||
.map((item) => [item.key as string, (item.data ?? []).map(normalizeStat).slice(0, 36)] as const);
|
||||
const summaries = (payload.data ?? [])
|
||||
.filter((item) => item.key && item.summary)
|
||||
.map((item) => [item.key as string, normalizeStat(item.summary as ApiBuildingFunctionStat)] as const);
|
||||
const overallSummary = (payload.data ?? []).find((item) => item.summary)?.summary;
|
||||
setChartDataBySelection((current) => ({
|
||||
...current,
|
||||
...Object.fromEntries(results),
|
||||
}));
|
||||
setChartSummaryBySelection((current) => ({
|
||||
...current,
|
||||
...Object.fromEntries(summaries),
|
||||
...(overallSummary ? { [overallSummaryKey]: normalizeStat(overallSummary) } : {}),
|
||||
}));
|
||||
} catch (error) {
|
||||
if (controller.signal.aborted) return;
|
||||
setLoadError(error instanceof Error ? error.message : '接口请求失败');
|
||||
@@ -1783,20 +1867,12 @@ function App() {
|
||||
}
|
||||
};
|
||||
|
||||
const toggleFullscreen = () => {
|
||||
if (document.fullscreenElement === fullscreenTarget) {
|
||||
void document.exitFullscreen();
|
||||
} else {
|
||||
void fullscreenTarget.requestFullscreen();
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key !== 'F11') return;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
toggleFullscreen();
|
||||
toggleWorkspaceFullscreen();
|
||||
};
|
||||
|
||||
const handleFullscreenChange = () => {
|
||||
@@ -1818,7 +1894,7 @@ function App() {
|
||||
} else if (button.classList.contains('chart-pivot-button')) {
|
||||
togglePivotView();
|
||||
} else {
|
||||
toggleFullscreen();
|
||||
toggleWorkspaceFullscreen();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1891,8 +1967,16 @@ function App() {
|
||||
selectedContentNodes.length,
|
||||
statisticMenuOpen,
|
||||
togglePivotView,
|
||||
toggleWorkspaceFullscreen,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (chartViewKey !== 'pivot') return;
|
||||
|
||||
const timer = window.setTimeout(fitPivotGridColumns, 180);
|
||||
return () => window.clearTimeout(timer);
|
||||
}, [chartViewKey, fitPivotGridColumns, metricKey, pivotGridRowData.length, rightPanelCollapsed]);
|
||||
|
||||
const chartOptions = useMemo<AgCartesianChartOptions>(() => {
|
||||
const visibleData = groupNames.map((groupName) => {
|
||||
const row: Record<string, string | number | null> = { groupName };
|
||||
@@ -2161,7 +2245,11 @@ function App() {
|
||||
))}
|
||||
</div>
|
||||
|
||||
<section className="workspace" aria-label="年度费用模板" ref={workspaceRef}>
|
||||
<section
|
||||
className={`workspace${rightPanelCollapsed ? ' is-right-panel-collapsed' : ''}`}
|
||||
aria-label="年度费用模板"
|
||||
ref={workspaceRef}
|
||||
>
|
||||
{indicatorSelectionLabel ? <div className="chart-indicator-selection-label" title={indicatorSelectionLabel}>{indicatorSelectionLabel}</div> : null}
|
||||
<div className="chart-filter-bar chart-filter-bar--workspace" aria-label="筛选条件">
|
||||
{chartFilterOptions.map((option) => {
|
||||
@@ -2199,6 +2287,7 @@ function App() {
|
||||
planningForm: [],
|
||||
});
|
||||
setChartDataBySelection({});
|
||||
setChartSummaryBySelection({});
|
||||
setLoadError(null);
|
||||
if (selectedContentNodes.length > 0) {
|
||||
setLoadingHint('正在按筛选条件重新计算');
|
||||
@@ -2264,9 +2353,23 @@ function App() {
|
||||
>
|
||||
{currentViewShortLabel}
|
||||
</button>
|
||||
<button
|
||||
className="chart-grid-tool-button chart-grid-tool-button--fullscreen"
|
||||
type="button"
|
||||
title={fullscreenToggleLabel}
|
||||
aria-label={fullscreenToggleLabel}
|
||||
aria-pressed={workspaceFullscreen}
|
||||
onClick={toggleWorkspaceFullscreen}
|
||||
>
|
||||
<i
|
||||
className={`anticon ${workspaceFullscreen ? 'anticon-shrink' : 'anticon-arrow-salt'} ag-charts-myButton-fullScreen ag-charts-diy-button`}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
{renderMetricSwitcher('grid')}
|
||||
<AgGridReact<PivotGridRow>
|
||||
rowData={pivotGridRowData}
|
||||
pinnedBottomRowData={pivotGridPinnedBottomRowData}
|
||||
columnDefs={pivotGridColumnDefs}
|
||||
containerStyle={{ width: '100%', height: '100%' }}
|
||||
theme="legacy"
|
||||
@@ -2274,7 +2377,17 @@ function App() {
|
||||
sortable: true,
|
||||
resizable: true,
|
||||
filter: true,
|
||||
minWidth: 58,
|
||||
}}
|
||||
rowHeight={30}
|
||||
headerHeight={32}
|
||||
groupHeaderHeight={32}
|
||||
onGridReady={(event: GridReadyEvent<PivotGridRow>) => {
|
||||
pivotGridApiRef.current = event.api;
|
||||
fitPivotGridColumns();
|
||||
}}
|
||||
onGridSizeChanged={fitPivotGridColumns}
|
||||
onFirstDataRendered={fitPivotGridColumns}
|
||||
suppressCellFocus
|
||||
overlayNoRowsTemplate={selectedContentNodes.length === 0 ? '请选择右侧分类项' : '暂无透视数据'}
|
||||
/>
|
||||
@@ -2288,7 +2401,21 @@ function App() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<aside className="right-panel" aria-label="选择内容">
|
||||
<button
|
||||
className="right-panel-toggle"
|
||||
type="button"
|
||||
title={rightPanelToggleLabel}
|
||||
aria-label={rightPanelToggleLabel}
|
||||
aria-expanded={!rightPanelCollapsed}
|
||||
onClick={() => setRightPanelCollapsed((collapsed) => !collapsed)}
|
||||
>
|
||||
{rightPanelCollapsed ? (
|
||||
<PanelRightOpen className="right-panel-toggle-icon" aria-hidden="true" strokeWidth={2} />
|
||||
) : (
|
||||
<PanelRightClose className="right-panel-toggle-icon" aria-hidden="true" strokeWidth={2} />
|
||||
)}
|
||||
</button>
|
||||
<aside className="right-panel" aria-label="选择内容" aria-hidden={rightPanelCollapsed}>
|
||||
<div className="content-tabs" role="tablist" aria-label="选择内容切换项">
|
||||
{contentOptions.map((option) => (
|
||||
<button
|
||||
|
||||
+111
-7
@@ -69,10 +69,18 @@ button {
|
||||
gap: 12px 28px;
|
||||
height: 100vh;
|
||||
padding: 30px 28px 18px 64px;
|
||||
transition: grid-template-columns 160ms ease, gap 160ms ease;
|
||||
}
|
||||
|
||||
.workspace.is-right-panel-collapsed {
|
||||
grid-template-columns: minmax(0, 1fr) 34px;
|
||||
gap: 12px 12px;
|
||||
}
|
||||
|
||||
.chart-area {
|
||||
display: grid;
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
grid-template-rows: minmax(0, 1fr);
|
||||
min-width: 0;
|
||||
}
|
||||
@@ -251,6 +259,11 @@ button {
|
||||
background: #f5e8d8;
|
||||
}
|
||||
|
||||
.workspace:fullscreen.is-right-panel-collapsed {
|
||||
grid-template-columns: minmax(0, 1fr) 34px;
|
||||
gap: 12px 12px;
|
||||
}
|
||||
|
||||
.workspace:fullscreen .chart-area {
|
||||
min-height: 0;
|
||||
}
|
||||
@@ -471,6 +484,10 @@ button {
|
||||
top: 80px;
|
||||
}
|
||||
|
||||
.chart-grid-tool-button--fullscreen {
|
||||
top: 114px;
|
||||
}
|
||||
|
||||
.chart-grid-tool-button:hover {
|
||||
color: #0078a8;
|
||||
border-color: rgba(0, 120, 168, 0.36);
|
||||
@@ -482,13 +499,31 @@ button {
|
||||
--ag-active-color: #0078a8;
|
||||
--ag-background-color: #fffaf4;
|
||||
--ag-border-color: rgba(90, 82, 72, 0.18);
|
||||
--ag-cell-horizontal-padding: 6px;
|
||||
--ag-font-family: "Microsoft YaHei", "PingFang SC", "Segoe UI", Arial, sans-serif;
|
||||
--ag-font-size: 12px;
|
||||
--ag-foreground-color: #262a33;
|
||||
--ag-header-cell-horizontal-padding: 6px;
|
||||
--ag-header-background-color: #f6eadc;
|
||||
--ag-row-hover-color: rgba(0, 120, 168, 0.08);
|
||||
}
|
||||
|
||||
.chart-pivot-grid-panel .ag-header-cell,
|
||||
.chart-pivot-grid-panel .ag-header-group-cell {
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
|
||||
.chart-pivot-grid-panel .ag-cell {
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
|
||||
.chart-pivot-grid-panel .ag-header-cell-label,
|
||||
.chart-pivot-grid-panel .ag-header-group-cell-label {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.metric-switcher {
|
||||
position: absolute;
|
||||
z-index: 12;
|
||||
@@ -501,7 +536,7 @@ button {
|
||||
|
||||
.metric-switcher--grid {
|
||||
left: 24px;
|
||||
top: 114px;
|
||||
top: 148px;
|
||||
}
|
||||
|
||||
.metric-switcher-button {
|
||||
@@ -661,15 +696,19 @@ button {
|
||||
box-shadow: 0 1px 5px rgba(69, 54, 36, 0.12);
|
||||
}
|
||||
|
||||
.chart-frame .ag-charts-myButton-fullScreen {
|
||||
.chart-frame .ag-charts-myButton-fullScreen,
|
||||
.chart-grid-tool-button .ag-charts-myButton-fullScreen {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 4px auto;
|
||||
}
|
||||
|
||||
.chart-frame .ag-charts-myButton-fullScreen::before,
|
||||
.chart-frame .ag-charts-myButton-fullScreen::after {
|
||||
.chart-frame .ag-charts-myButton-fullScreen::after,
|
||||
.chart-grid-tool-button .ag-charts-myButton-fullScreen::before,
|
||||
.chart-grid-tool-button .ag-charts-myButton-fullScreen::after {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: block;
|
||||
@@ -678,19 +717,22 @@ button {
|
||||
content: "";
|
||||
}
|
||||
|
||||
.chart-frame .anticon-arrow-salt::before {
|
||||
.chart-frame .anticon-arrow-salt::before,
|
||||
.chart-grid-tool-button .anticon-arrow-salt::before {
|
||||
border-top: 1px solid currentColor;
|
||||
border-right: 1px solid currentColor;
|
||||
clip-path: polygon(54% 0, 100% 0, 100% 46%, 86% 46%, 86% 14%, 54% 14%);
|
||||
}
|
||||
|
||||
.chart-frame .anticon-arrow-salt::after {
|
||||
.chart-frame .anticon-arrow-salt::after,
|
||||
.chart-grid-tool-button .anticon-arrow-salt::after {
|
||||
border-bottom: 1px solid currentColor;
|
||||
border-left: 1px solid currentColor;
|
||||
clip-path: polygon(0 54%, 14% 54%, 14% 86%, 46% 86%, 46% 100%, 0 100%);
|
||||
}
|
||||
|
||||
.chart-frame .anticon-shrink::before {
|
||||
.chart-frame .anticon-shrink::before,
|
||||
.chart-grid-tool-button .anticon-shrink::before {
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
width: 6px;
|
||||
@@ -699,7 +741,8 @@ button {
|
||||
border-bottom: 1px solid currentColor;
|
||||
}
|
||||
|
||||
.chart-frame .anticon-shrink::after {
|
||||
.chart-frame .anticon-shrink::after,
|
||||
.chart-grid-tool-button .anticon-shrink::after {
|
||||
right: 2px;
|
||||
bottom: 2px;
|
||||
left: auto;
|
||||
@@ -722,6 +765,8 @@ button {
|
||||
|
||||
.right-panel {
|
||||
display: grid;
|
||||
grid-column: 2;
|
||||
grid-row: 2;
|
||||
grid-template-rows: auto minmax(0, 1fr);
|
||||
min-width: 0;
|
||||
height: 100%;
|
||||
@@ -730,6 +775,52 @@ button {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.right-panel-toggle {
|
||||
display: inline-grid;
|
||||
grid-column: 2;
|
||||
grid-row: 2;
|
||||
justify-self: end;
|
||||
align-self: start;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
place-items: center;
|
||||
padding: 0;
|
||||
border: 1px solid rgba(90, 82, 72, 0.18);
|
||||
border-radius: 3px;
|
||||
color: #46413b;
|
||||
background: rgba(255, 249, 241, 0.82);
|
||||
cursor: pointer;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.right-panel-toggle:hover,
|
||||
.right-panel-toggle:focus-visible {
|
||||
color: #0078a8;
|
||||
border-color: rgba(0, 120, 168, 0.36);
|
||||
background: rgba(255, 252, 248, 0.96);
|
||||
box-shadow: 0 1px 5px rgba(69, 54, 36, 0.12);
|
||||
}
|
||||
|
||||
.right-panel-toggle:focus-visible {
|
||||
outline: 2px solid rgba(0, 120, 168, 0.28);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.right-panel-toggle-icon {
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.workspace.is-right-panel-collapsed .right-panel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.workspace.is-right-panel-collapsed .right-panel-toggle {
|
||||
position: sticky;
|
||||
top: 24px;
|
||||
}
|
||||
|
||||
.content-tabs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -1100,14 +1191,27 @@ button {
|
||||
padding: 8px 18px 18px 56px;
|
||||
}
|
||||
|
||||
.workspace.is-right-panel-collapsed {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.chart-area {
|
||||
grid-row: 2;
|
||||
min-height: 520px;
|
||||
}
|
||||
|
||||
.right-panel {
|
||||
grid-column: 1;
|
||||
grid-row: 3;
|
||||
min-height: 280px;
|
||||
}
|
||||
|
||||
.right-panel-toggle {
|
||||
grid-column: 1;
|
||||
grid-row: 3;
|
||||
justify-self: end;
|
||||
}
|
||||
|
||||
.content-tabs {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user