Skip to content

Commit c8d09cb

Browse files
authored
de: Remove unused widgets and merge others (#5208)
1 parent c8c6133 commit c8d09cb

File tree

8 files changed

+246
-691
lines changed

8 files changed

+246
-691
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// Copyright (C) 2026 The Android Open Source Project
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import m from 'mithril';
16+
import {ColumnInfo} from './column_info';
17+
import {Button, ButtonVariant} from '../../../widgets/button';
18+
import {Checkbox} from '../../../widgets/checkbox';
19+
import {DraggableItem} from './widgets';
20+
21+
/**
22+
* Reusable column selector widget with checkboxes, optional drag reorder,
23+
* and optional per-row extra content.
24+
*
25+
* Used by ModifyColumnsNode, UnionNode, and JoinColumnSelector to replace
26+
* the duplicated column-selection-with-checkboxes pattern.
27+
*/
28+
export interface ColumnSelectorAttrs {
29+
// The columns to display with their checked state.
30+
columns: ColumnInfo[];
31+
// Called when columns change (check/uncheck, reorder).
32+
onColumnsChange: (columns: ColumnInfo[]) => void;
33+
// Optional help text shown above the list.
34+
helpText?: string;
35+
// Enable drag-and-drop reordering. Default: false.
36+
draggable?: boolean;
37+
// Optional per-row extra content (e.g., alias input, type selector).
38+
renderExtra?: (col: ColumnInfo, index: number) => m.Children;
39+
// Optional empty state when columns is empty.
40+
emptyState?: m.Child;
41+
}
42+
43+
export class ColumnSelector implements m.ClassComponent<ColumnSelectorAttrs> {
44+
view({attrs}: m.CVnode<ColumnSelectorAttrs>) {
45+
const {
46+
columns,
47+
onColumnsChange,
48+
helpText,
49+
draggable,
50+
renderExtra,
51+
emptyState,
52+
} = attrs;
53+
54+
// If columns is empty and emptyState is provided, show that instead.
55+
if (columns.length === 0 && emptyState !== undefined) {
56+
return emptyState;
57+
}
58+
59+
return m(
60+
'.pf-modify-columns-content',
61+
// Select All / Deselect All buttons
62+
m(
63+
'.pf-select-deselect-all-buttons',
64+
m(Button, {
65+
label: 'Select All',
66+
onclick: () => {
67+
onColumnsChange(columns.map((col) => ({...col, checked: true})));
68+
},
69+
variant: ButtonVariant.Outlined,
70+
compact: true,
71+
}),
72+
m(Button, {
73+
label: 'Deselect All',
74+
onclick: () => {
75+
onColumnsChange(columns.map((col) => ({...col, checked: false})));
76+
},
77+
variant: ButtonVariant.Outlined,
78+
compact: true,
79+
}),
80+
),
81+
// Column list
82+
m(
83+
'.pf-modify-columns-node',
84+
m(
85+
'.pf-column-list-container',
86+
helpText !== undefined && m('.pf-column-list-help', helpText),
87+
m(
88+
'.pf-column-list',
89+
columns.map((col, index) => {
90+
const checkbox = m(Checkbox, {
91+
checked: col.checked,
92+
label: col.column.name,
93+
onchange: (e) => {
94+
const newColumns = [...columns];
95+
newColumns[index] = {
96+
...newColumns[index],
97+
checked: (e.target as HTMLInputElement).checked,
98+
};
99+
onColumnsChange(newColumns);
100+
},
101+
});
102+
103+
const extra = renderExtra?.(col, index);
104+
105+
if (draggable) {
106+
return m(
107+
DraggableItem,
108+
{
109+
index,
110+
onReorder: (from: number, to: number) => {
111+
const newColumns = [...columns];
112+
const [removed] = newColumns.splice(from, 1);
113+
newColumns.splice(to, 0, removed);
114+
onColumnsChange(newColumns);
115+
},
116+
},
117+
checkbox,
118+
extra,
119+
);
120+
}
121+
122+
return m('.pf-column-selector-row', checkbox, extra);
123+
}),
124+
),
125+
),
126+
),
127+
);
128+
}
129+
}

ui/src/plugins/dev.perfetto.DataExplorer/query_builder/common.scss

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,6 @@
5757
border: 1px solid var(--pf-color-border);
5858
}
5959

60-
.pf-exp-section {
61-
display: flex;
62-
flex-direction: column;
63-
gap: 0.5rem;
64-
padding: 0.75rem;
65-
border: 1px solid var(--pf-color-border);
66-
border-radius: 4px;
67-
}
68-
6960
// Shared styling for all round action buttons (undo/redo/add node/dashboard).
7061
.pf-qb-round-action-button {
7162
width: 40px;

ui/src/plugins/dev.perfetto.DataExplorer/query_builder/join_widgets.ts

Lines changed: 46 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,8 @@
1414

1515
import m from 'mithril';
1616
import {ColumnInfo} from './column_info';
17-
import {
18-
OutlinedField,
19-
ResultsPanelEmptyState,
20-
SelectDeselectAllButtons,
21-
} from './widgets';
17+
import {OutlinedField, ResultsPanelEmptyState} from './widgets';
18+
import {ColumnSelector} from './column_selector';
2219
import {classNames} from '../../../base/classnames';
2320
import {Card} from '../../../widgets/card';
2421
import {Checkbox} from '../../../widgets/checkbox';
@@ -279,65 +276,46 @@ export interface JoinColumnSelectorAttrs {
279276
rightAlias: string;
280277
leftColumns: ColumnInfo[];
281278
rightColumns: ColumnInfo[];
282-
onLeftColumnToggle: (index: number, checked: boolean) => void;
283-
onRightColumnToggle: (index: number, checked: boolean) => void;
284-
onLeftColumnAlias: (index: number, alias: string) => void;
285-
onRightColumnAlias: (index: number, alias: string) => void;
286-
onSelectAllLeft: () => void;
287-
onDeselectAllLeft: () => void;
288-
onSelectAllRight: () => void;
289-
onDeselectAllRight: () => void;
279+
onLeftColumnsChange: (columns: ColumnInfo[]) => void;
280+
onRightColumnsChange: (columns: ColumnInfo[]) => void;
290281
}
291282

292283
export class JoinColumnSelector
293284
implements m.ClassComponent<JoinColumnSelectorAttrs>
294285
{
295-
private renderColumnRow(
296-
col: ColumnInfo,
297-
index: number,
298-
onToggle: (index: number, checked: boolean) => void,
299-
onAlias: (index: number, alias: string) => void,
300-
): m.Child {
301-
return m(
302-
'.pf-join-column-row',
303-
m(Checkbox, {
304-
checked: col.checked,
305-
label: col.column.name,
306-
onchange: (e) => {
307-
onToggle(index, (e.target as HTMLInputElement).checked);
308-
},
309-
}),
310-
m(TextInput, {
311-
oninput: (e: Event) => {
312-
const inputValue = (e.target as HTMLInputElement).value;
313-
// Normalize empty strings to undefined (no alias)
314-
onAlias(index, inputValue.trim() === '' ? '' : inputValue);
315-
},
316-
placeholder: 'alias',
317-
value: col.alias ?? '',
318-
}),
319-
);
320-
}
321-
322286
view({attrs}: m.Vnode<JoinColumnSelectorAttrs>) {
323287
const {
324288
leftAlias,
325289
rightAlias,
326290
leftColumns,
327291
rightColumns,
328-
onLeftColumnToggle,
329-
onRightColumnToggle,
330-
onLeftColumnAlias,
331-
onRightColumnAlias,
332-
onSelectAllLeft,
333-
onDeselectAllLeft,
334-
onSelectAllRight,
335-
onDeselectAllRight,
292+
onLeftColumnsChange,
293+
onRightColumnsChange,
336294
} = attrs;
337295

338296
const leftSelectedCount = leftColumns.filter((c) => c.checked).length;
339297
const rightSelectedCount = rightColumns.filter((c) => c.checked).length;
340298

299+
const renderAliasInput = (
300+
col: ColumnInfo,
301+
index: number,
302+
columns: ColumnInfo[],
303+
onColumnsChange: (columns: ColumnInfo[]) => void,
304+
) =>
305+
m(TextInput, {
306+
oninput: (e: Event) => {
307+
const inputValue = (e.target as HTMLInputElement).value;
308+
const newColumns = [...columns];
309+
newColumns[index] = {
310+
...newColumns[index],
311+
alias: inputValue.trim() === '' ? undefined : inputValue,
312+
};
313+
onColumnsChange(newColumns);
314+
},
315+
placeholder: 'alias',
316+
value: col.alias ?? '',
317+
});
318+
341319
return m('.pf-join-column-selector', [
342320
// Left columns section
343321
m('.pf-join-column-section', [
@@ -347,27 +325,17 @@ export class JoinColumnSelector
347325
'h4',
348326
`${leftAlias} (${leftSelectedCount} / ${leftColumns.length} selected)`,
349327
),
350-
m(SelectDeselectAllButtons, {
351-
onSelectAll: onSelectAllLeft,
352-
onDeselectAll: onDeselectAllLeft,
353-
}),
354-
),
355-
m(
356-
'.pf-join-column-list',
357-
leftColumns.length === 0
358-
? m(ResultsPanelEmptyState, {
359-
icon: 'cable',
360-
title: 'Connect left source',
361-
})
362-
: leftColumns.map((col, i) =>
363-
this.renderColumnRow(
364-
col,
365-
i,
366-
onLeftColumnToggle,
367-
onLeftColumnAlias,
368-
),
369-
),
370328
),
329+
m(ColumnSelector, {
330+
columns: leftColumns,
331+
onColumnsChange: onLeftColumnsChange,
332+
renderExtra: (col, index) =>
333+
renderAliasInput(col, index, leftColumns, onLeftColumnsChange),
334+
emptyState: m(ResultsPanelEmptyState, {
335+
icon: 'cable',
336+
title: 'Connect left source',
337+
}),
338+
}),
371339
]),
372340
// Right columns section
373341
m('.pf-join-column-section', [
@@ -377,27 +345,17 @@ export class JoinColumnSelector
377345
'h4',
378346
`${rightAlias} (${rightSelectedCount} / ${rightColumns.length} selected)`,
379347
),
380-
m(SelectDeselectAllButtons, {
381-
onSelectAll: onSelectAllRight,
382-
onDeselectAll: onDeselectAllRight,
383-
}),
384-
),
385-
m(
386-
'.pf-join-column-list',
387-
rightColumns.length === 0
388-
? m(ResultsPanelEmptyState, {
389-
icon: 'cable',
390-
title: 'Connect right source',
391-
})
392-
: rightColumns.map((col, i) =>
393-
this.renderColumnRow(
394-
col,
395-
i,
396-
onRightColumnToggle,
397-
onRightColumnAlias,
398-
),
399-
),
400348
),
349+
m(ColumnSelector, {
350+
columns: rightColumns,
351+
onColumnsChange: onRightColumnsChange,
352+
renderExtra: (col, index) =>
353+
renderAliasInput(col, index, rightColumns, onRightColumnsChange),
354+
emptyState: m(ResultsPanelEmptyState, {
355+
icon: 'cable',
356+
title: 'Connect right source',
357+
}),
358+
}),
401359
]),
402360
]);
403361
}

0 commit comments

Comments
 (0)