Skip to content

Commit ae94f1b

Browse files
authored
feat: toggle empty/null rendering (#1778)
- Adds #1646 - Add a new state in Redux for if empty and null should be rendered - Add a check in `IrisGridTableModelTemplate` to check for if the setting is enabled
1 parent e1c1585 commit ae94f1b

8 files changed

Lines changed: 119 additions & 6 deletions

File tree

packages/code-studio/src/settings/FormattingSectionContent.tsx

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import {
2626
getShowTimeZone,
2727
getShowTSeparator,
2828
getTruncateNumbersWithPound,
29+
getShowEmptyStrings,
30+
getShowNullStrings,
2931
updateSettings as updateSettingsAction,
3032
RootState,
3133
WorkspaceSettings,
@@ -52,6 +54,8 @@ interface FormattingSectionContentProps {
5254
showTSeparator: boolean;
5355
timeZone: string;
5456
truncateNumbersWithPound: boolean;
57+
showEmptyStrings: boolean;
58+
showNullStrings: boolean;
5559
updateSettings: (settings: Partial<WorkspaceSettings>) => void;
5660
defaultDecimalFormatOptions: FormatOption;
5761
defaultIntegerFormatOptions: FormatOption;
@@ -66,6 +70,8 @@ interface FormattingSectionContentState {
6670
defaultDecimalFormatOptions: FormatOption;
6771
defaultIntegerFormatOptions: FormatOption;
6872
truncateNumbersWithPound: boolean;
73+
showEmptyStrings: boolean;
74+
showNullStrings: boolean;
6975
timestampAtMenuOpen: Date;
7076
}
7177

@@ -103,6 +109,10 @@ export class FormattingSectionContent extends PureComponent<
103109
this.handleResetTimeZone = this.handleResetTimeZone.bind(this);
104110
this.handleTruncateNumbersWithPoundChange =
105111
this.handleTruncateNumbersWithPoundChange.bind(this);
112+
this.handleShowEmptyStringsChange =
113+
this.handleShowEmptyStringsChange.bind(this);
114+
this.handleShowNullStringsChange =
115+
this.handleShowNullStringsChange.bind(this);
106116

107117
const {
108118
defaultDateTimeFormat,
@@ -112,6 +122,8 @@ export class FormattingSectionContent extends PureComponent<
112122
showTSeparator,
113123
timeZone,
114124
truncateNumbersWithPound,
125+
showEmptyStrings,
126+
showNullStrings,
115127
} = props;
116128

117129
this.containerRef = React.createRef();
@@ -125,6 +137,8 @@ export class FormattingSectionContent extends PureComponent<
125137
defaultDecimalFormatOptions,
126138
defaultIntegerFormatOptions,
127139
truncateNumbersWithPound,
140+
showEmptyStrings,
141+
showNullStrings,
128142
timestampAtMenuOpen: new Date(),
129143
};
130144
}
@@ -298,6 +312,24 @@ export class FormattingSectionContent extends PureComponent<
298312
this.queueUpdate(update);
299313
}
300314

315+
handleShowEmptyStringsChange(): void {
316+
const { showEmptyStrings } = this.state;
317+
const update = {
318+
showEmptyStrings: !showEmptyStrings,
319+
};
320+
this.setState(update);
321+
this.queueUpdate(update);
322+
}
323+
324+
handleShowNullStringsChange(): void {
325+
const { showNullStrings } = this.state;
326+
const update = {
327+
showNullStrings: !showNullStrings,
328+
};
329+
this.setState(update);
330+
this.queueUpdate(update);
331+
}
332+
301333
commitChanges(): void {
302334
const { updateSettings } = this.props;
303335
const updates = this.pendingUpdates.reduce(
@@ -322,6 +354,8 @@ export class FormattingSectionContent extends PureComponent<
322354
showTimeZone,
323355
showTSeparator,
324356
truncateNumbersWithPound,
357+
showEmptyStrings,
358+
showNullStrings,
325359
} = this.state;
326360

327361
const {
@@ -527,7 +561,7 @@ export class FormattingSectionContent extends PureComponent<
527561
/>
528562
</div>
529563
</div>
530-
<div className="form-row mb-3">
564+
<div className="form-row mb-2">
531565
<div className="offset-3 col-9">
532566
<Checkbox
533567
checked={truncateNumbersWithPound ?? null}
@@ -537,6 +571,31 @@ export class FormattingSectionContent extends PureComponent<
537571
</Checkbox>
538572
</div>
539573
</div>
574+
575+
<div className="form-row mb-3">
576+
<label
577+
className="col-form-label col-3"
578+
htmlFor="default-integer-format-input"
579+
>
580+
String
581+
</label>
582+
<div className="col pr-0 pt-2">
583+
<Checkbox
584+
checked={showEmptyStrings ?? null}
585+
onChange={this.handleShowEmptyStringsChange}
586+
>
587+
Show empty strings as{' '}
588+
<span className="font-italic text-muted">empty</span>
589+
</Checkbox>
590+
<Checkbox
591+
checked={showNullStrings ?? null}
592+
onChange={this.handleShowNullStringsChange}
593+
>
594+
Show null strings as{' '}
595+
<span className="font-italic text-muted">null</span>
596+
</Checkbox>
597+
</div>
598+
</div>
540599
</div>
541600
</div>
542601
);
@@ -553,6 +612,8 @@ const mapStateToProps = (
553612
showTimeZone: getShowTimeZone(state),
554613
showTSeparator: getShowTSeparator(state),
555614
truncateNumbersWithPound: getTruncateNumbersWithPound(state),
615+
showEmptyStrings: getShowEmptyStrings(state),
616+
showNullStrings: getShowNullStrings(state),
556617
timeZone: getTimeZone(state),
557618
defaults: getDefaultSettings(state),
558619
});

packages/code-studio/src/storage/LocalWorkspaceStorage.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ export class LocalWorkspaceStorage implements WorkspaceStorage {
5454
defaultFormatString: IntegerColumnFormatter.DEFAULT_FORMAT_STRING,
5555
},
5656
truncateNumbersWithPound: false,
57+
showEmptyStrings: true,
58+
showNullStrings: true,
5759
defaultNotebookSettings: {
5860
isMinimapEnabled: false,
5961
},
@@ -90,6 +92,14 @@ export class LocalWorkspaceStorage implements WorkspaceStorage {
9092
serverConfigValues,
9193
'truncateNumbersWithPound'
9294
),
95+
showEmptyStrings: LocalWorkspaceStorage.getBooleanServerConfig(
96+
serverConfigValues,
97+
'showEmptyStrings'
98+
),
99+
showNullStrings: LocalWorkspaceStorage.getBooleanServerConfig(
100+
serverConfigValues,
101+
'showNullStrings'
102+
),
93103
defaultNotebookSettings:
94104
serverConfigValues?.get('isMinimapEnabled') !== undefined
95105
? {

packages/iris-grid/src/IrisGrid.tsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,8 @@ export class IrisGrid extends Component<IrisGridProps, IrisGridState> {
514514
showTimeZone: false,
515515
showTSeparator: true,
516516
truncateNumbersWithPound: false,
517+
showEmptyStrings: true,
518+
showNullStrings: true,
517519
formatter: EMPTY_ARRAY,
518520
decimalFormatOptions: PropTypes.shape({
519521
defaultFormatString: PropTypes.string,
@@ -620,6 +622,8 @@ export class IrisGrid extends Component<IrisGridProps, IrisGridState> {
620622
this.decimalFormatOptions = {};
621623
this.integerFormatOptions = {};
622624
this.truncateNumbersWithPound = false;
625+
this.showEmptyStrings = true;
626+
this.showNullStrings = true;
623627

624628
// When the loading scrim started/when it should extend to the end of the screen.
625629
this.renderer = new IrisGridRenderer();
@@ -997,6 +1001,10 @@ export class IrisGrid extends Component<IrisGridProps, IrisGridState> {
9971001

9981002
truncateNumbersWithPound: boolean;
9991003

1004+
showEmptyStrings: boolean;
1005+
1006+
showNullStrings: boolean;
1007+
10001008
// When the loading scrim started/when it should extend to the end of the screen.
10011009
loadingScrimStartTime?: number;
10021010

@@ -1793,6 +1801,9 @@ export class IrisGrid extends Component<IrisGridProps, IrisGridState> {
17931801
const truncateNumbersWithPound =
17941802
settings?.truncateNumbersWithPound ?? false;
17951803

1804+
const showEmptyStrings = settings?.showEmptyStrings ?? true;
1805+
const showNullStrings = settings?.showNullStrings ?? true;
1806+
17961807
const isColumnFormatChanged = !deepEqual(
17971808
this.globalColumnFormats,
17981809
globalColumnFormats
@@ -1811,18 +1822,26 @@ export class IrisGrid extends Component<IrisGridProps, IrisGridState> {
18111822
);
18121823
const isTruncateNumbersChanged =
18131824
this.truncateNumbersWithPound !== truncateNumbersWithPound;
1825+
const isShowEmptyStringsChanged =
1826+
this.showEmptyStrings !== showEmptyStrings;
1827+
const isShowNullStringsChanged = this.showNullStrings !== showNullStrings;
1828+
18141829
if (
18151830
isColumnFormatChanged ||
18161831
isDateFormattingChanged ||
18171832
isDecimalFormattingChanged ||
18181833
isIntegerFormattingChanged ||
1819-
isTruncateNumbersChanged
1834+
isTruncateNumbersChanged ||
1835+
isShowEmptyStringsChanged ||
1836+
isShowNullStringsChanged
18201837
) {
18211838
this.globalColumnFormats = globalColumnFormats;
18221839
this.dateTimeFormatterOptions = dateTimeFormatterOptions;
18231840
this.decimalFormatOptions = defaultDecimalFormatOptions;
18241841
this.integerFormatOptions = defaultIntegerFormatOptions;
18251842
this.truncateNumbersWithPound = truncateNumbersWithPound;
1843+
this.showEmptyStrings = showEmptyStrings;
1844+
this.showNullStrings = showNullStrings;
18261845
this.updateFormatter({}, forceUpdate);
18271846

18281847
if (isDateFormattingChanged && forceUpdate) {
@@ -1889,7 +1908,9 @@ export class IrisGrid extends Component<IrisGridProps, IrisGridState> {
18891908
this.dateTimeFormatterOptions,
18901909
this.decimalFormatOptions,
18911910
this.integerFormatOptions,
1892-
this.truncateNumbersWithPound
1911+
this.truncateNumbersWithPound,
1912+
this.showEmptyStrings,
1913+
this.showNullStrings
18931914
);
18941915

18951916
log.debug('updateFormatter', this.globalColumnFormats, mergedColumnFormats);

packages/iris-grid/src/IrisGridTableModelTemplate.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -547,11 +547,11 @@ class IrisGridTableModelTemplate<
547547

548548
if (TableUtils.isTextType(this.columns[x]?.type)) {
549549
if (text === null) {
550-
return 'null';
550+
return this.formatter.showNullStrings ? 'null' : '';
551551
}
552552

553553
if (text === '') {
554-
return 'empty';
554+
return this.formatter.showEmptyStrings ? 'empty' : '';
555555
}
556556
}
557557

packages/jsapi-utils/src/Formatter.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ export class Formatter {
8383
integerFormatOptions?: ConstructorParameters<
8484
typeof IntegerColumnFormatter
8585
>[1],
86-
truncateNumbersWithPound = false
86+
truncateNumbersWithPound = false,
87+
showEmptyStrings = true,
88+
showNullStrings = true
8789
) {
8890
// Formatting order:
8991
// - columnFormatMap[type][name]
@@ -114,6 +116,9 @@ export class Formatter {
114116
// Formats indexed by data type and column name
115117
this.columnFormatMap = Formatter.makeColumnFormatMap(columnFormattingRules);
116118
this.truncateNumbersWithPound = truncateNumbersWithPound;
119+
120+
this.showEmptyStrings = showEmptyStrings;
121+
this.showNullStrings = showNullStrings;
117122
}
118123

119124
defaultColumnFormatter: TableColumnFormatter;
@@ -124,6 +129,10 @@ export class Formatter {
124129

125130
truncateNumbersWithPound: boolean;
126131

132+
showEmptyStrings: boolean;
133+
134+
showNullStrings: boolean;
135+
127136
/**
128137
* Gets columnFormatMap indexed by name for a given column type, creates new Map entry if necessary
129138
* @param columnType column type

packages/jsapi-utils/src/Settings.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ export interface NumberFormatSettings {
1919
defaultFormatString?: string;
2020
};
2121
truncateNumbersWithPound?: boolean;
22+
showEmptyStrings?: boolean;
23+
showNullStrings?: boolean;
2224
}
2325

2426
export interface Settings

packages/redux/src/selectors.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ export const getTruncateNumbersWithPound = <
118118
): Settings<State>['truncateNumbersWithPound'] =>
119119
getSettings(store).truncateNumbersWithPound;
120120

121+
export const getShowEmptyStrings = <State extends RootState = RootState>(
122+
store: State
123+
): Settings<State>['showEmptyStrings'] => getSettings(store).showEmptyStrings;
124+
125+
export const getShowNullStrings = <State extends RootState = RootState>(
126+
store: State
127+
): Settings<State>['showNullStrings'] => getSettings(store).showNullStrings;
128+
121129
export const getDisableMoveConfirmation = <State extends RootState>(
122130
store: State
123131
): Settings<State>['disableMoveConfirmation'] =>

packages/redux/src/store.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ export interface WorkspaceSettings {
4747
showTimeZone: boolean;
4848
showTSeparator: boolean;
4949
truncateNumbersWithPound: boolean;
50+
showEmptyStrings: boolean;
51+
showNullStrings: boolean;
5052
disableMoveConfirmation: boolean;
5153
shortcutOverrides?: {
5254
windows?: { [id: string]: ValidKeyState };

0 commit comments

Comments
 (0)