@marimo-team/frontend 0.23.2-dev61 → 0.23.2-dev63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{JsonOutput-Cib1YSyW.js → JsonOutput-B7SdSwth.js} +10 -10
- package/dist/assets/{add-connection-dialog-BEPj8ARO.js → add-connection-dialog-eBEz1Rlx.js} +1 -1
- package/dist/assets/{agent-panel-j9gn23Bw.js → agent-panel-DdQIPV4s.js} +1 -1
- package/dist/assets/{cell-editor-DzvGVpZ4.js → cell-editor-DTCP63YJ.js} +1 -1
- package/dist/assets/{column-preview-B9m4l29S.js → column-preview-M5tW9DeW.js} +1 -1
- package/dist/assets/{command-palette-NX0xxB_G.js → command-palette-ExiY3B81.js} +1 -1
- package/dist/assets/{edit-page-Omreus8k.js → edit-page-BTwAqki-.js} +3 -3
- package/dist/assets/{file-explorer-panel-Bep-85KO.js → file-explorer-panel-CuPnqR_c.js} +1 -1
- package/dist/assets/{form-DBaVPTFv.js → form-D76nZZF7.js} +1 -1
- package/dist/assets/{glide-data-editor-n2Pw7Fk9.js → glide-data-editor-CKiZFI5U.js} +16 -16
- package/dist/assets/{hooks-B2ArfcJq.js → hooks-BSyCiOiV.js} +1 -1
- package/dist/assets/{index-D6-su6XF.js → index-BRf5dlJi.js} +4 -4
- package/dist/assets/{layout-Cp0JtSeH.js → layout-BULJlgp-.js} +3 -3
- package/dist/assets/{panels-rhd1T559.js → panels-D7Ix_ZZ-.js} +1 -1
- package/dist/assets/{reveal-component-B_RnD8qR.js → reveal-component-BFqPeIsQ.js} +1 -1
- package/dist/assets/{run-page-DJpwa_b_.js → run-page-LlaD7bx4.js} +1 -1
- package/dist/assets/{scratchpad-panel-Ba0rcWha.js → scratchpad-panel-DEAn87uP.js} +1 -1
- package/dist/assets/{session-panel-DY3Z3ICZ.js → session-panel-DrVK3__u.js} +1 -1
- package/dist/assets/{slide-Bv2zR5_1.js → slide-szdKdcoM.js} +1 -1
- package/dist/assets/{state-DwYUxIVe.js → state-Do4CKYxK.js} +1 -1
- package/dist/assets/{useNotebookActions-BcUD5CgV.js → useNotebookActions-maZjRwJd.js} +1 -1
- package/dist/index.html +5 -5
- package/package.json +1 -1
- package/src/components/data-table/__tests__/chart-spec-model.test.ts +14 -14
- package/src/components/data-table/__tests__/types.test.ts +34 -1
- package/src/components/data-table/column-summary/chart-spec-model.tsx +6 -3
- package/src/components/data-table/column-summary/column-summary.tsx +1 -1
- package/src/components/data-table/types.ts +9 -7
- package/src/plugins/impl/DataEditorPlugin.tsx +7 -3
- package/src/plugins/impl/data-editor/__tests__/data-utils.test.ts +147 -149
- package/src/plugins/impl/data-editor/data-utils.ts +12 -11
- package/src/plugins/impl/data-editor/glide-data-editor.tsx +4 -4
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import type { RowData } from "@tanstack/react-table";
|
|
4
4
|
import type { DataType } from "@/core/kernel/messages";
|
|
5
|
-
import { Objects } from "@/utils/objects";
|
|
6
5
|
|
|
7
6
|
declare module "@tanstack/react-table" {
|
|
8
7
|
interface TableMeta<TData extends RowData> {
|
|
@@ -56,16 +55,19 @@ export type FieldTypesWithExternalType = [
|
|
|
56
55
|
columnName: string,
|
|
57
56
|
[dataType: DataType, externalType: string],
|
|
58
57
|
][];
|
|
59
|
-
|
|
58
|
+
// Ordered map of column name -> data type.
|
|
59
|
+
//
|
|
60
|
+
// `Map` (not `Record`) because JS objects reorder integer-string keys
|
|
61
|
+
// to the front in numeric order per `OrdinaryOwnPropertyKeys`; a
|
|
62
|
+
// DataFrame with a `"2010"` column alongside `"here"` would otherwise
|
|
63
|
+
// lose its column order on iteration (#9269). `Map` preserves insertion
|
|
64
|
+
// order for all keys.
|
|
65
|
+
export type FieldTypes = Map<string, DataType>;
|
|
60
66
|
|
|
61
67
|
export function toFieldTypes(
|
|
62
68
|
fieldTypes: FieldTypesWithExternalType,
|
|
63
69
|
): FieldTypes {
|
|
64
|
-
return
|
|
65
|
-
fieldTypes,
|
|
66
|
-
([columnName]) => columnName,
|
|
67
|
-
([, [type]]) => type,
|
|
68
|
-
);
|
|
70
|
+
return new Map(fieldTypes.map(([columnName, [type]]) => [columnName, type]));
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
interface BinValue {
|
|
@@ -83,19 +83,23 @@ interface Props extends Omit<
|
|
|
83
83
|
|
|
84
84
|
const LoadingDataEditor = (props: Props) => {
|
|
85
85
|
const [data, setData] = useState<unknown[]>([]);
|
|
86
|
-
const [columnFields, setColumnFields] = useState<FieldTypes>(
|
|
86
|
+
const [columnFields, setColumnFields] = useState<FieldTypes>(new Map());
|
|
87
87
|
|
|
88
88
|
// Load the data
|
|
89
89
|
const { error } = useAsyncData(async () => {
|
|
90
90
|
const withoutExternalTypes = toFieldTypes(props.fieldTypes ?? []);
|
|
91
91
|
|
|
92
92
|
// If we already have the data, return it
|
|
93
|
-
// Otherwise, load the data from the URL
|
|
93
|
+
// Otherwise, load the data from the URL. Vega's CSV parser takes a
|
|
94
|
+
// plain `Record`; column order doesn't matter for parsing.
|
|
94
95
|
const localData = Array.isArray(props.data)
|
|
95
96
|
? props.data
|
|
96
97
|
: await vegaLoadData(
|
|
97
98
|
props.data,
|
|
98
|
-
{
|
|
99
|
+
{
|
|
100
|
+
type: "csv",
|
|
101
|
+
parse: getVegaFieldTypes(Object.fromEntries(withoutExternalTypes)),
|
|
102
|
+
},
|
|
99
103
|
{ handleBigIntAndNumberLike: true },
|
|
100
104
|
);
|
|
101
105
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { describe, expect, it } from "vitest";
|
|
4
4
|
import type { FieldTypes } from "@/components/data-table/types";
|
|
5
|
+
import type { DataType } from "@/core/kernel/messages";
|
|
5
6
|
import {
|
|
6
7
|
insertColumn,
|
|
7
8
|
modifyColumnFields,
|
|
@@ -9,6 +10,11 @@ import {
|
|
|
9
10
|
renameColumn,
|
|
10
11
|
} from "../data-utils";
|
|
11
12
|
|
|
13
|
+
// Fixtures are written as object literals for readability; `FieldTypes`
|
|
14
|
+
// is a `Map` (#9269).
|
|
15
|
+
const asFieldTypes = (obj: Record<string, DataType>): FieldTypes =>
|
|
16
|
+
new Map(Object.entries(obj));
|
|
17
|
+
|
|
12
18
|
describe("removeColumn", () => {
|
|
13
19
|
const testData = [
|
|
14
20
|
{ int: 1, string: "a", bool: "True", datetime: "2025-07-12 00:07:13" },
|
|
@@ -481,12 +487,12 @@ describe("renameColumn", () => {
|
|
|
481
487
|
});
|
|
482
488
|
|
|
483
489
|
describe("modifyColumnFields", () => {
|
|
484
|
-
const testFieldTypes: FieldTypes = {
|
|
490
|
+
const testFieldTypes: FieldTypes = asFieldTypes({
|
|
485
491
|
int: "integer",
|
|
486
492
|
string: "string",
|
|
487
493
|
bool: "boolean",
|
|
488
494
|
datetime: "datetime",
|
|
489
|
-
};
|
|
495
|
+
});
|
|
490
496
|
|
|
491
497
|
it("should insert a new column at index 0", () => {
|
|
492
498
|
const result = modifyColumnFields({
|
|
@@ -496,16 +502,15 @@ describe("modifyColumnFields", () => {
|
|
|
496
502
|
newColumnName: "newColumn",
|
|
497
503
|
});
|
|
498
504
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
expect(result).toEqual(expected);
|
|
505
|
+
expect(result).toMatchInlineSnapshot(`
|
|
506
|
+
Map {
|
|
507
|
+
"newColumn" => "string",
|
|
508
|
+
"int" => "integer",
|
|
509
|
+
"string" => "string",
|
|
510
|
+
"bool" => "boolean",
|
|
511
|
+
"datetime" => "datetime",
|
|
512
|
+
}
|
|
513
|
+
`);
|
|
509
514
|
});
|
|
510
515
|
|
|
511
516
|
it("should insert a new column at index 1", () => {
|
|
@@ -516,16 +521,15 @@ describe("modifyColumnFields", () => {
|
|
|
516
521
|
newColumnName: "newColumn",
|
|
517
522
|
});
|
|
518
523
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
expect(result).toEqual(expected);
|
|
524
|
+
expect(result).toMatchInlineSnapshot(`
|
|
525
|
+
Map {
|
|
526
|
+
"int" => "integer",
|
|
527
|
+
"newColumn" => "string",
|
|
528
|
+
"string" => "string",
|
|
529
|
+
"bool" => "boolean",
|
|
530
|
+
"datetime" => "datetime",
|
|
531
|
+
}
|
|
532
|
+
`);
|
|
529
533
|
});
|
|
530
534
|
|
|
531
535
|
it("should insert a new column at index 2", () => {
|
|
@@ -536,16 +540,15 @@ describe("modifyColumnFields", () => {
|
|
|
536
540
|
newColumnName: "newColumn",
|
|
537
541
|
});
|
|
538
542
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
expect(result).toEqual(expected);
|
|
543
|
+
expect(result).toMatchInlineSnapshot(`
|
|
544
|
+
Map {
|
|
545
|
+
"int" => "integer",
|
|
546
|
+
"string" => "string",
|
|
547
|
+
"newColumn" => "string",
|
|
548
|
+
"bool" => "boolean",
|
|
549
|
+
"datetime" => "datetime",
|
|
550
|
+
}
|
|
551
|
+
`);
|
|
549
552
|
});
|
|
550
553
|
|
|
551
554
|
it("should insert a new column at the end", () => {
|
|
@@ -557,16 +560,15 @@ describe("modifyColumnFields", () => {
|
|
|
557
560
|
dataType: "datetime",
|
|
558
561
|
});
|
|
559
562
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
expect(result).toEqual(expected);
|
|
563
|
+
expect(result).toMatchInlineSnapshot(`
|
|
564
|
+
Map {
|
|
565
|
+
"int" => "integer",
|
|
566
|
+
"string" => "string",
|
|
567
|
+
"bool" => "boolean",
|
|
568
|
+
"datetime" => "datetime",
|
|
569
|
+
"newColumn" => "datetime",
|
|
570
|
+
}
|
|
571
|
+
`);
|
|
570
572
|
});
|
|
571
573
|
|
|
572
574
|
it("should insert a new column beyond the array length", () => {
|
|
@@ -577,16 +579,15 @@ describe("modifyColumnFields", () => {
|
|
|
577
579
|
newColumnName: "newColumn",
|
|
578
580
|
});
|
|
579
581
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
expect(result).toEqual(expected);
|
|
582
|
+
expect(result).toMatchInlineSnapshot(`
|
|
583
|
+
Map {
|
|
584
|
+
"int" => "integer",
|
|
585
|
+
"string" => "string",
|
|
586
|
+
"bool" => "boolean",
|
|
587
|
+
"datetime" => "datetime",
|
|
588
|
+
"newColumn" => "string",
|
|
589
|
+
}
|
|
590
|
+
`);
|
|
590
591
|
});
|
|
591
592
|
|
|
592
593
|
it("should remove column at index 0", () => {
|
|
@@ -596,14 +597,13 @@ describe("modifyColumnFields", () => {
|
|
|
596
597
|
type: "remove",
|
|
597
598
|
});
|
|
598
599
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
expect(result).toEqual(expected);
|
|
600
|
+
expect(result).toMatchInlineSnapshot(`
|
|
601
|
+
Map {
|
|
602
|
+
"string" => "string",
|
|
603
|
+
"bool" => "boolean",
|
|
604
|
+
"datetime" => "datetime",
|
|
605
|
+
}
|
|
606
|
+
`);
|
|
607
607
|
});
|
|
608
608
|
|
|
609
609
|
it("should remove column at index 1", () => {
|
|
@@ -613,14 +613,13 @@ describe("modifyColumnFields", () => {
|
|
|
613
613
|
type: "remove",
|
|
614
614
|
});
|
|
615
615
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
expect(result).toEqual(expected);
|
|
616
|
+
expect(result).toMatchInlineSnapshot(`
|
|
617
|
+
Map {
|
|
618
|
+
"int" => "integer",
|
|
619
|
+
"bool" => "boolean",
|
|
620
|
+
"datetime" => "datetime",
|
|
621
|
+
}
|
|
622
|
+
`);
|
|
624
623
|
});
|
|
625
624
|
|
|
626
625
|
it("should remove column at index 2", () => {
|
|
@@ -630,14 +629,13 @@ describe("modifyColumnFields", () => {
|
|
|
630
629
|
type: "remove",
|
|
631
630
|
});
|
|
632
631
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
expect(result).toEqual(expected);
|
|
632
|
+
expect(result).toMatchInlineSnapshot(`
|
|
633
|
+
Map {
|
|
634
|
+
"int" => "integer",
|
|
635
|
+
"string" => "string",
|
|
636
|
+
"datetime" => "datetime",
|
|
637
|
+
}
|
|
638
|
+
`);
|
|
641
639
|
});
|
|
642
640
|
|
|
643
641
|
it("should remove column at index 3", () => {
|
|
@@ -647,14 +645,13 @@ describe("modifyColumnFields", () => {
|
|
|
647
645
|
type: "remove",
|
|
648
646
|
});
|
|
649
647
|
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
expect(result).toEqual(expected);
|
|
648
|
+
expect(result).toMatchInlineSnapshot(`
|
|
649
|
+
Map {
|
|
650
|
+
"int" => "integer",
|
|
651
|
+
"string" => "string",
|
|
652
|
+
"bool" => "boolean",
|
|
653
|
+
}
|
|
654
|
+
`);
|
|
658
655
|
});
|
|
659
656
|
|
|
660
657
|
it("should handle removing non-existent column index", () => {
|
|
@@ -685,15 +682,14 @@ describe("modifyColumnFields", () => {
|
|
|
685
682
|
newColumnName: "number",
|
|
686
683
|
});
|
|
687
684
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
expect(result).toEqual(expected);
|
|
685
|
+
expect(result).toMatchInlineSnapshot(`
|
|
686
|
+
Map {
|
|
687
|
+
"number" => "string",
|
|
688
|
+
"string" => "string",
|
|
689
|
+
"bool" => "boolean",
|
|
690
|
+
"datetime" => "datetime",
|
|
691
|
+
}
|
|
692
|
+
`);
|
|
697
693
|
});
|
|
698
694
|
|
|
699
695
|
it("should rename column at index 1", () => {
|
|
@@ -704,15 +700,14 @@ describe("modifyColumnFields", () => {
|
|
|
704
700
|
newColumnName: "text",
|
|
705
701
|
});
|
|
706
702
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
expect(result).toEqual(expected);
|
|
703
|
+
expect(result).toMatchInlineSnapshot(`
|
|
704
|
+
Map {
|
|
705
|
+
"int" => "integer",
|
|
706
|
+
"text" => "string",
|
|
707
|
+
"bool" => "boolean",
|
|
708
|
+
"datetime" => "datetime",
|
|
709
|
+
}
|
|
710
|
+
`);
|
|
716
711
|
});
|
|
717
712
|
|
|
718
713
|
it("should rename column at index 3", () => {
|
|
@@ -724,15 +719,14 @@ describe("modifyColumnFields", () => {
|
|
|
724
719
|
newColumnName: "timestamp",
|
|
725
720
|
});
|
|
726
721
|
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
expect(result).toEqual(expected);
|
|
722
|
+
expect(result).toMatchInlineSnapshot(`
|
|
723
|
+
Map {
|
|
724
|
+
"int" => "integer",
|
|
725
|
+
"string" => "string",
|
|
726
|
+
"bool" => "boolean",
|
|
727
|
+
"timestamp" => "datetime",
|
|
728
|
+
}
|
|
729
|
+
`);
|
|
736
730
|
});
|
|
737
731
|
|
|
738
732
|
it("should handle renaming non-existent column index", () => {
|
|
@@ -758,7 +752,7 @@ describe("modifyColumnFields", () => {
|
|
|
758
752
|
});
|
|
759
753
|
|
|
760
754
|
it("should preserve original field types structure", () => {
|
|
761
|
-
const originalFieldTypes =
|
|
755
|
+
const originalFieldTypes = new Map(testFieldTypes);
|
|
762
756
|
modifyColumnFields({
|
|
763
757
|
columnFields: testFieldTypes,
|
|
764
758
|
columnIdx: 1,
|
|
@@ -769,7 +763,7 @@ describe("modifyColumnFields", () => {
|
|
|
769
763
|
});
|
|
770
764
|
|
|
771
765
|
it("should handle empty field types object", () => {
|
|
772
|
-
const emptyFieldTypes: FieldTypes =
|
|
766
|
+
const emptyFieldTypes: FieldTypes = new Map();
|
|
773
767
|
|
|
774
768
|
// Insert
|
|
775
769
|
const insertResult = modifyColumnFields({
|
|
@@ -778,7 +772,11 @@ describe("modifyColumnFields", () => {
|
|
|
778
772
|
type: "insert",
|
|
779
773
|
newColumnName: "newColumn",
|
|
780
774
|
});
|
|
781
|
-
expect(insertResult).
|
|
775
|
+
expect(insertResult).toMatchInlineSnapshot(`
|
|
776
|
+
Map {
|
|
777
|
+
"newColumn" => "string",
|
|
778
|
+
}
|
|
779
|
+
`);
|
|
782
780
|
|
|
783
781
|
// Remove
|
|
784
782
|
const removeResult = modifyColumnFields({
|
|
@@ -786,16 +784,16 @@ describe("modifyColumnFields", () => {
|
|
|
786
784
|
columnIdx: 0,
|
|
787
785
|
type: "remove",
|
|
788
786
|
});
|
|
789
|
-
expect(removeResult).
|
|
787
|
+
expect(removeResult).toMatchInlineSnapshot(`Map {}`);
|
|
790
788
|
});
|
|
791
789
|
|
|
792
790
|
it("should handle field types with special characters in column names", () => {
|
|
793
|
-
const specialFieldTypes: FieldTypes = {
|
|
791
|
+
const specialFieldTypes: FieldTypes = asFieldTypes({
|
|
794
792
|
"column-with-dash": "integer",
|
|
795
793
|
column_with_underscore: "string",
|
|
796
794
|
"column.with.dot": "boolean",
|
|
797
795
|
"column with space": "datetime",
|
|
798
|
-
};
|
|
796
|
+
});
|
|
799
797
|
|
|
800
798
|
// Insert
|
|
801
799
|
const insertResult = modifyColumnFields({
|
|
@@ -804,15 +802,15 @@ describe("modifyColumnFields", () => {
|
|
|
804
802
|
type: "insert",
|
|
805
803
|
newColumnName: "new-column",
|
|
806
804
|
});
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
805
|
+
expect(insertResult).toMatchInlineSnapshot(`
|
|
806
|
+
Map {
|
|
807
|
+
"column-with-dash" => "integer",
|
|
808
|
+
"new-column" => "string",
|
|
809
|
+
"column_with_underscore" => "string",
|
|
810
|
+
"column.with.dot" => "boolean",
|
|
811
|
+
"column with space" => "datetime",
|
|
812
|
+
}
|
|
813
|
+
`);
|
|
816
814
|
|
|
817
815
|
// Remove
|
|
818
816
|
const removeResult = modifyColumnFields({
|
|
@@ -820,13 +818,13 @@ describe("modifyColumnFields", () => {
|
|
|
820
818
|
columnIdx: 1,
|
|
821
819
|
type: "remove",
|
|
822
820
|
});
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
821
|
+
expect(removeResult).toMatchInlineSnapshot(`
|
|
822
|
+
Map {
|
|
823
|
+
"column-with-dash" => "integer",
|
|
824
|
+
"column.with.dot" => "boolean",
|
|
825
|
+
"column with space" => "datetime",
|
|
826
|
+
}
|
|
827
|
+
`);
|
|
830
828
|
|
|
831
829
|
// Rename
|
|
832
830
|
const renameResult = modifyColumnFields({
|
|
@@ -835,14 +833,14 @@ describe("modifyColumnFields", () => {
|
|
|
835
833
|
type: "rename",
|
|
836
834
|
newColumnName: "renamed-column",
|
|
837
835
|
});
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
836
|
+
expect(renameResult).toMatchInlineSnapshot(`
|
|
837
|
+
Map {
|
|
838
|
+
"column-with-dash" => "integer",
|
|
839
|
+
"renamed-column" => "string",
|
|
840
|
+
"column.with.dot" => "boolean",
|
|
841
|
+
"column with space" => "datetime",
|
|
842
|
+
}
|
|
843
|
+
`);
|
|
846
844
|
});
|
|
847
845
|
|
|
848
846
|
it("should handle multiple operations in sequence", () => {
|
|
@@ -864,13 +862,13 @@ describe("modifyColumnFields", () => {
|
|
|
864
862
|
newColumnName: "renamed",
|
|
865
863
|
});
|
|
866
864
|
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
865
|
+
expect(result).toMatchInlineSnapshot(`
|
|
866
|
+
Map {
|
|
867
|
+
"renamed" => "string",
|
|
868
|
+
"newColumn" => "string",
|
|
869
|
+
"bool" => "boolean",
|
|
870
|
+
"datetime" => "datetime",
|
|
871
|
+
}
|
|
872
|
+
`);
|
|
875
873
|
});
|
|
876
874
|
});
|
|
@@ -79,24 +79,25 @@ export function modifyColumnFields(opts: {
|
|
|
79
79
|
return columnFields;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
const entries =
|
|
83
|
-
const newEntries = [
|
|
82
|
+
const entries = [...columnFields.entries()];
|
|
83
|
+
const newEntries: Array<[string, DataType]> = [
|
|
84
84
|
...entries.slice(0, columnIdx),
|
|
85
85
|
[newColumnName, dataType || "string"],
|
|
86
86
|
...entries.slice(columnIdx),
|
|
87
87
|
];
|
|
88
|
-
return
|
|
88
|
+
return new Map(newEntries);
|
|
89
89
|
}
|
|
90
90
|
case "remove": {
|
|
91
|
-
if (columnIdx < 0 || columnIdx >=
|
|
91
|
+
if (columnIdx < 0 || columnIdx >= columnFields.size) {
|
|
92
92
|
return columnFields;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
const entries =
|
|
95
|
+
const entries = [...columnFields.entries()];
|
|
96
96
|
const columnName = entries[columnIdx]?.[0];
|
|
97
97
|
if (columnName) {
|
|
98
|
-
const
|
|
99
|
-
|
|
98
|
+
const next = new Map(columnFields);
|
|
99
|
+
next.delete(columnName);
|
|
100
|
+
return next;
|
|
100
101
|
}
|
|
101
102
|
return columnFields;
|
|
102
103
|
}
|
|
@@ -106,18 +107,18 @@ export function modifyColumnFields(opts: {
|
|
|
106
107
|
return columnFields;
|
|
107
108
|
}
|
|
108
109
|
|
|
109
|
-
if (columnIdx < 0 || columnIdx >=
|
|
110
|
+
if (columnIdx < 0 || columnIdx >= columnFields.size) {
|
|
110
111
|
return columnFields;
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
// Rename at the right index
|
|
114
|
-
const entries =
|
|
115
|
-
const newEntries = [
|
|
115
|
+
const entries = [...columnFields.entries()];
|
|
116
|
+
const newEntries: Array<[string, DataType]> = [
|
|
116
117
|
...entries.slice(0, columnIdx),
|
|
117
118
|
[newColumnName, dataType || "string"],
|
|
118
119
|
...entries.slice(columnIdx + 1),
|
|
119
120
|
];
|
|
120
|
-
return
|
|
121
|
+
return new Map(newEntries);
|
|
121
122
|
}
|
|
122
123
|
}
|
|
123
124
|
}
|
|
@@ -102,7 +102,7 @@ export const GlideDataEditor = <T,>({
|
|
|
102
102
|
|
|
103
103
|
const columns: ModifiedGridColumn[] = useMemo(() => {
|
|
104
104
|
const columns: ModifiedGridColumn[] = [];
|
|
105
|
-
for (const [columnName, fieldType] of
|
|
105
|
+
for (const [columnName, fieldType] of columnFields) {
|
|
106
106
|
const editable =
|
|
107
107
|
editableColumns === "all" || editableColumns.includes(columnName);
|
|
108
108
|
|
|
@@ -311,7 +311,7 @@ export const GlideDataEditor = <T,>({
|
|
|
311
311
|
const [col, _row] = cell;
|
|
312
312
|
const key = columns[col].title;
|
|
313
313
|
|
|
314
|
-
const columnType = columnFields
|
|
314
|
+
const columnType = columnFields.get(key);
|
|
315
315
|
// Verify the new value is of the correct type
|
|
316
316
|
switch (columnType) {
|
|
317
317
|
case "number":
|
|
@@ -445,7 +445,7 @@ export const GlideDataEditor = <T,>({
|
|
|
445
445
|
const oldColumnName = columns[menu.col].title;
|
|
446
446
|
|
|
447
447
|
// Validate the new column name
|
|
448
|
-
if (columnFields
|
|
448
|
+
if (columnFields.has(newName)) {
|
|
449
449
|
toastColumnExists(newName);
|
|
450
450
|
return;
|
|
451
451
|
}
|
|
@@ -498,7 +498,7 @@ export const GlideDataEditor = <T,>({
|
|
|
498
498
|
const clampedColumnIdx = Math.max(0, Math.min(columnIdx, columns.length));
|
|
499
499
|
|
|
500
500
|
// Validate the new column name
|
|
501
|
-
if (columnFields
|
|
501
|
+
if (columnFields.has(columnName)) {
|
|
502
502
|
toastColumnExists(columnName);
|
|
503
503
|
return;
|
|
504
504
|
}
|