@genspectrum/dashboard-components 0.6.11 → 0.6.13
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/dashboard-components.js +1079 -873
- package/dist/dashboard-components.js.map +1 -1
- package/dist/genspectrum-components.d.ts +3 -3
- package/dist/style.css +117 -24
- package/package.json +2 -2
- package/src/preact/components/checkbox-selector.stories.tsx +93 -11
- package/src/preact/components/checkbox-selector.tsx +19 -0
- package/src/preact/components/color-scale-selector-dropdown.tsx +5 -3
- package/src/preact/components/dropdown.tsx +3 -3
- package/src/preact/components/loading-display.tsx +8 -1
- package/src/preact/components/mutation-type-selector.stories.tsx +115 -0
- package/src/preact/components/mutation-type-selector.tsx +33 -8
- package/src/preact/components/percent-input.stories.tsx +93 -0
- package/src/preact/components/percent-intput.tsx +4 -0
- package/src/preact/components/proportion-selector-dropdown.stories.tsx +2 -2
- package/src/preact/components/proportion-selector-dropdown.tsx +9 -7
- package/src/preact/components/proportion-selector.stories.tsx +4 -4
- package/src/preact/components/proportion-selector.tsx +46 -12
- package/src/preact/components/segment-selector.stories.tsx +151 -0
- package/src/preact/components/{SegmentSelector.tsx → segment-selector.tsx} +29 -20
- package/src/preact/mutationComparison/mutation-comparison.stories.tsx +1 -1
- package/src/preact/mutationComparison/mutation-comparison.tsx +1 -1
- package/src/preact/mutationComparison/queryMutationData.ts +1 -1
- package/src/preact/mutations/mutations-grid.tsx +5 -1
- package/src/preact/mutations/mutations.tsx +1 -1
- package/src/preact/mutations/queryMutations.ts +1 -1
- package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +4 -4
- package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +3 -2
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +1 -1
- package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +3 -2
- package/src/preact/useQuery.ts +1 -1
- package/src/query/queryMutationsOverTime.ts +3 -3
- package/src/utils/map2d.spec.ts +83 -22
- package/src/utils/map2d.ts +158 -0
- package/src/utils/Map2d.ts +0 -75
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
type SubstitutionOrDeletionEntry,
|
|
13
13
|
type TemporalGranularity,
|
|
14
14
|
} from '../types';
|
|
15
|
-
import { Map2d } from '../utils/
|
|
15
|
+
import { Map2dBase, type Map2d } from '../utils/map2d';
|
|
16
16
|
import { type Deletion, type Substitution } from '../utils/mutations';
|
|
17
17
|
import {
|
|
18
18
|
dateRangeCompare,
|
|
@@ -154,7 +154,7 @@ function fetchAndPrepareSubstitutionsOrDeletions(filter: LapisFilter, sequenceTy
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
export function groupByMutation(data: MutationOverTimeData[]) {
|
|
157
|
-
const dataArray = new
|
|
157
|
+
const dataArray = new Map2dBase<Substitution | Deletion, Temporal, MutationOverTimeMutationValue>(
|
|
158
158
|
(mutation) => mutation.code,
|
|
159
159
|
(date) => date.toString(),
|
|
160
160
|
);
|
|
@@ -174,7 +174,7 @@ export function groupByMutation(data: MutationOverTimeData[]) {
|
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
function addZeroValuesForDatesWithNoMutationData(
|
|
177
|
-
dataArray:
|
|
177
|
+
dataArray: Map2dBase<Substitution | Deletion, Temporal, MutationOverTimeMutationValue>,
|
|
178
178
|
data: MutationOverTimeData[],
|
|
179
179
|
) {
|
|
180
180
|
if (dataArray.getFirstAxisKeys().length !== 0) {
|
package/src/utils/map2d.spec.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { Map2dBase, Map2dView } from './map2d';
|
|
4
4
|
|
|
5
|
-
describe('
|
|
5
|
+
describe('Map2dContainer', () => {
|
|
6
6
|
it('should add a value and return it', () => {
|
|
7
|
-
const map2d = new
|
|
7
|
+
const map2d = new Map2dBase<string, string, number>();
|
|
8
8
|
map2d.set('a', 'b', 2);
|
|
9
9
|
expect(map2d.get('a', 'b')).toBe(2);
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
it('should update a value', () => {
|
|
13
|
-
const map2d = new
|
|
13
|
+
const map2d = new Map2dBase<string, string, number>();
|
|
14
14
|
map2d.set('a', 'b', 2);
|
|
15
15
|
map2d.set('a', 'b', 3);
|
|
16
16
|
expect(map2d.get('a', 'b')).toBe(3);
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
it('should return the data as an array', () => {
|
|
20
|
-
const map2d = new
|
|
20
|
+
const map2d = new Map2dBase<string, string, number>();
|
|
21
21
|
map2d.set('a', 'b', 1);
|
|
22
22
|
map2d.set('a', 'd', 2);
|
|
23
23
|
map2d.set('c', 'b', 3);
|
|
@@ -30,7 +30,7 @@ describe('Map2d', () => {
|
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
it('should fill empty values with the given value', () => {
|
|
33
|
-
const map2d = new
|
|
33
|
+
const map2d = new Map2dBase<string, string, number>();
|
|
34
34
|
map2d.set('a', 'b', 2);
|
|
35
35
|
map2d.set('c', 'd', 4);
|
|
36
36
|
expect(map2d.getAsArray(0)).toEqual([
|
|
@@ -40,7 +40,7 @@ describe('Map2d', () => {
|
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
it('should return the keys from the first axis', () => {
|
|
43
|
-
const map2d = new
|
|
43
|
+
const map2d = new Map2dBase<string, string, number>();
|
|
44
44
|
map2d.set('a', 'b', 2);
|
|
45
45
|
map2d.set('c', 'd', 4);
|
|
46
46
|
|
|
@@ -48,7 +48,7 @@ describe('Map2d', () => {
|
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
it('should return the keys from the second axis', () => {
|
|
51
|
-
const map2d = new
|
|
51
|
+
const map2d = new Map2dBase<string, string, number>();
|
|
52
52
|
map2d.set('a', 'b', 2);
|
|
53
53
|
map2d.set('c', 'd', 4);
|
|
54
54
|
|
|
@@ -56,7 +56,7 @@ describe('Map2d', () => {
|
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
it('should work with objects as keys', () => {
|
|
59
|
-
const map2d = new
|
|
59
|
+
const map2d = new Map2dBase<{ a: string }, { b: string }, number>();
|
|
60
60
|
map2d.set({ a: 'a' }, { b: 'b' }, 2);
|
|
61
61
|
map2d.set({ a: 'second' }, { b: 'second' }, 3);
|
|
62
62
|
|
|
@@ -65,30 +65,91 @@ describe('Map2d', () => {
|
|
|
65
65
|
});
|
|
66
66
|
|
|
67
67
|
it('should update a value with objects as keys', () => {
|
|
68
|
-
const map2d = new
|
|
68
|
+
const map2d = new Map2dBase<{ a: string }, { b: string }, number>();
|
|
69
69
|
map2d.set({ a: 'a' }, { b: 'b' }, 2);
|
|
70
70
|
map2d.set({ a: 'a' }, { b: 'b' }, 3);
|
|
71
71
|
expect(map2d.get({ a: 'a' }, { b: 'b' })).toBe(3);
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
it('should
|
|
75
|
-
const map2d = new
|
|
74
|
+
it('should return a row by key', () => {
|
|
75
|
+
const map2d = new Map2dBase<string, string, number>();
|
|
76
76
|
map2d.set('a', 'b', 2);
|
|
77
|
-
|
|
77
|
+
map2d.set('c', 'd', 4);
|
|
78
|
+
|
|
79
|
+
expect(map2d.getRow('a', 0)).toEqual([2, 0]);
|
|
80
|
+
expect(map2d.getRow('c', 0)).toEqual([0, 4]);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('should return an empty array when the row does not exist', () => {
|
|
84
|
+
const map2d = new Map2dBase<string, string, number>();
|
|
85
|
+
map2d.set('a', 'b', 2);
|
|
86
|
+
|
|
87
|
+
expect(map2d.getRow('c', 0)).toEqual([]);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
78
90
|
|
|
79
|
-
|
|
80
|
-
|
|
91
|
+
describe('Map2dView', () => {
|
|
92
|
+
it('should show the same data as the container', () => {
|
|
93
|
+
const container = createBaseContainer();
|
|
81
94
|
|
|
82
|
-
|
|
83
|
-
|
|
95
|
+
const view = new Map2dView<string, string, number>(container);
|
|
96
|
+
|
|
97
|
+
expect(view.get('a', 'b')).toBe(container.get('a', 'b'));
|
|
98
|
+
expect(view.get('a', 'd')).toBe(container.get('a', 'd'));
|
|
99
|
+
expect(view.get('c', 'b')).toBe(container.get('c', 'b'));
|
|
100
|
+
expect(view.get('c', 'd')).toBe(container.get('c', 'd'));
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('should remove a row', () => {
|
|
104
|
+
const container = createBaseContainer();
|
|
105
|
+
|
|
106
|
+
const view = new Map2dView<string, string, number>(container);
|
|
107
|
+
|
|
108
|
+
view.deleteRow('a');
|
|
109
|
+
|
|
110
|
+
expect(view.get('a', 'b')).toBeUndefined();
|
|
111
|
+
expect(view.get('a', 'd')).toBeUndefined();
|
|
112
|
+
expect(view.get('c', 'b')).toBe(container.get('c', 'b'));
|
|
113
|
+
expect(view.get('c', 'd')).toBe(container.get('c', 'd'));
|
|
114
|
+
expect(view.getFirstAxisKeys().length).toBe(1);
|
|
115
|
+
expect(view.getFirstAxisKeys()[0]).toBe('c');
|
|
116
|
+
expect(view.getSecondAxisKeys().length).toBe(2);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should return the view of the data as an array', () => {
|
|
120
|
+
const container = createBaseContainer();
|
|
121
|
+
const view = new Map2dView<string, string, number>(container);
|
|
122
|
+
view.deleteRow('c');
|
|
123
|
+
|
|
124
|
+
expect(view.getAsArray(0)).toEqual([[1, 0]]);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should throw an error when trying to set a value', () => {
|
|
128
|
+
const container = createBaseContainer();
|
|
129
|
+
const view = new Map2dView<string, string, number>(container);
|
|
130
|
+
expect(() => view.set()).toThrowError();
|
|
84
131
|
});
|
|
85
132
|
|
|
86
133
|
it('should return a row by key', () => {
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
map2d.set('c', 'd', 4);
|
|
134
|
+
const container = createBaseContainer();
|
|
135
|
+
const view = new Map2dView<string, string, number>(container);
|
|
90
136
|
|
|
91
|
-
expect(
|
|
92
|
-
expect(map2d.getRow('c', 0)).toEqual([0, 4]);
|
|
137
|
+
expect(view.getRow('a', 0)).toEqual([1, 0]);
|
|
93
138
|
});
|
|
139
|
+
|
|
140
|
+
it('should return an empty array when the row does not exist', () => {
|
|
141
|
+
const container = createBaseContainer();
|
|
142
|
+
const view = new Map2dView<string, string, number>(container);
|
|
143
|
+
view.deleteRow('c');
|
|
144
|
+
|
|
145
|
+
expect(view.getRow('c', 0)).toEqual([]);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
function createBaseContainer() {
|
|
149
|
+
const container = new Map2dBase<string, string, number>();
|
|
150
|
+
container.set('a', 'b', 1);
|
|
151
|
+
container.set('c', 'b', 3);
|
|
152
|
+
container.set('c', 'd', 4);
|
|
153
|
+
return container;
|
|
154
|
+
}
|
|
94
155
|
});
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import hash from 'object-hash';
|
|
2
|
+
|
|
3
|
+
export interface Map2d<Key1, Key2, Value> {
|
|
4
|
+
get(keyFirstAxis: Key1, keySecondAxis: Key2): Value | undefined;
|
|
5
|
+
|
|
6
|
+
set(keyFirstAxis: Key1, keySecondAxis: Key2, value: Value): void;
|
|
7
|
+
|
|
8
|
+
getRow(key: Key1, fillEmptyWith: Value): Value[];
|
|
9
|
+
|
|
10
|
+
deleteRow(key: Key1): void;
|
|
11
|
+
|
|
12
|
+
getFirstAxisKeys(): Key1[];
|
|
13
|
+
|
|
14
|
+
getSecondAxisKeys(): Key2[];
|
|
15
|
+
|
|
16
|
+
getAsArray(fillEmptyWith: Value): Value[][];
|
|
17
|
+
|
|
18
|
+
serializeFirstAxis(key: Key1): string;
|
|
19
|
+
serializeSecondAxis(key: Key2): string;
|
|
20
|
+
|
|
21
|
+
readonly keysFirstAxis: Map<string, Key1>;
|
|
22
|
+
readonly keysSecondAxis: Map<string, Key2>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class Map2dBase<Key1 extends object | string, Key2 extends object | string, Value>
|
|
26
|
+
implements Map2d<Key1, Key2, Value>
|
|
27
|
+
{
|
|
28
|
+
readonly data: Map<string, Map<string, Value>> = new Map<string, Map<string, Value>>();
|
|
29
|
+
readonly keysFirstAxis = new Map<string, Key1>();
|
|
30
|
+
readonly keysSecondAxis = new Map<string, Key2>();
|
|
31
|
+
|
|
32
|
+
constructor(
|
|
33
|
+
readonly serializeFirstAxis: (key: Key1) => string = (key) => (typeof key === 'string' ? key : hash(key)),
|
|
34
|
+
readonly serializeSecondAxis: (key: Key2) => string = (key) => (typeof key === 'string' ? key : hash(key)),
|
|
35
|
+
) {}
|
|
36
|
+
|
|
37
|
+
get(keyFirstAxis: Key1, keySecondAxis: Key2) {
|
|
38
|
+
const serializedKeyFirstAxis = this.serializeFirstAxis(keyFirstAxis);
|
|
39
|
+
const serializedKeySecondAxis = this.serializeSecondAxis(keySecondAxis);
|
|
40
|
+
return this.data.get(serializedKeyFirstAxis)?.get(serializedKeySecondAxis);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getRow(key: Key1, fillEmptyWith: Value) {
|
|
44
|
+
const serializedKeyFirstAxis = this.serializeFirstAxis(key);
|
|
45
|
+
const row = this.data.get(serializedKeyFirstAxis);
|
|
46
|
+
if (row === undefined) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
return Array.from(this.keysSecondAxis.keys()).map((key) => row.get(key) ?? fillEmptyWith);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
set(keyFirstAxis: Key1, keySecondAxis: Key2, value: Value) {
|
|
53
|
+
const serializedKeyFirstAxis = this.serializeFirstAxis(keyFirstAxis);
|
|
54
|
+
const serializedKeySecondAxis = this.serializeSecondAxis(keySecondAxis);
|
|
55
|
+
|
|
56
|
+
if (!this.data.has(serializedKeyFirstAxis)) {
|
|
57
|
+
this.data.set(serializedKeyFirstAxis, new Map<string, Value>());
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
this.data.get(serializedKeyFirstAxis)!.set(serializedKeySecondAxis, value);
|
|
61
|
+
|
|
62
|
+
this.keysFirstAxis.set(serializedKeyFirstAxis, keyFirstAxis);
|
|
63
|
+
this.keysSecondAxis.set(serializedKeySecondAxis, keySecondAxis);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
deleteRow(key: Key1) {
|
|
67
|
+
const serializedKeyFirstAxis = this.serializeFirstAxis(key);
|
|
68
|
+
this.data.delete(serializedKeyFirstAxis);
|
|
69
|
+
this.keysFirstAxis.delete(serializedKeyFirstAxis);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getFirstAxisKeys() {
|
|
73
|
+
return Array.from(this.keysFirstAxis.values());
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getSecondAxisKeys() {
|
|
77
|
+
return Array.from(this.keysSecondAxis.values());
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
getAsArray(fillEmptyWith: Value) {
|
|
81
|
+
return this.getFirstAxisKeys().map((firstAxisKey) => {
|
|
82
|
+
return this.getSecondAxisKeys().map((secondAxisKey) => {
|
|
83
|
+
return this.get(firstAxisKey, secondAxisKey) ?? fillEmptyWith;
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export class Map2dView<Key1 extends object | string, Key2 extends object | string, Value>
|
|
90
|
+
implements Map2d<Key1, Key2, Value>
|
|
91
|
+
{
|
|
92
|
+
readonly keysFirstAxis;
|
|
93
|
+
readonly keysSecondAxis;
|
|
94
|
+
|
|
95
|
+
readonly baseMap: Map2d<Key1, Key2, Value>;
|
|
96
|
+
|
|
97
|
+
constructor(map: Map2d<Key1, Key2, Value>) {
|
|
98
|
+
this.keysFirstAxis = new Map(map.keysFirstAxis);
|
|
99
|
+
this.keysSecondAxis = new Map(map.keysSecondAxis);
|
|
100
|
+
|
|
101
|
+
if (map instanceof Map2dView) {
|
|
102
|
+
this.baseMap = map.baseMap;
|
|
103
|
+
}
|
|
104
|
+
this.baseMap = map;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
serializeFirstAxis(key: Key1) {
|
|
108
|
+
return this.baseMap.serializeFirstAxis(key);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
serializeSecondAxis(key: Key2) {
|
|
112
|
+
return this.baseMap.serializeSecondAxis(key);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
deleteRow(key: Key1) {
|
|
116
|
+
this.keysFirstAxis.delete(this.serializeFirstAxis(key));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
get(keyFirstAxis: Key1, keySecondAxis: Key2) {
|
|
120
|
+
const firstAxisKey = this.serializeFirstAxis(keyFirstAxis);
|
|
121
|
+
const secondAxisKey = this.serializeSecondAxis(keySecondAxis);
|
|
122
|
+
|
|
123
|
+
if (!this.keysFirstAxis.has(firstAxisKey) || !this.keysSecondAxis.has(secondAxisKey)) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return this.baseMap.get(keyFirstAxis, keySecondAxis);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
set() {
|
|
131
|
+
throw new Error('Cannot set value on a Map2dView');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
getFirstAxisKeys() {
|
|
135
|
+
return Array.from(this.keysFirstAxis.values());
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
getSecondAxisKeys() {
|
|
139
|
+
return Array.from(this.keysSecondAxis.values());
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
getAsArray(fillEmptyWith: Value) {
|
|
143
|
+
return this.getFirstAxisKeys().map((firstAxisKey) => {
|
|
144
|
+
return this.getSecondAxisKeys().map((secondAxisKey) => {
|
|
145
|
+
return this.baseMap.get(firstAxisKey, secondAxisKey) ?? fillEmptyWith;
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
getRow(key: Key1, fillEmptyWith: Value) {
|
|
151
|
+
const serializedKeyFirstAxis = this.serializeFirstAxis(key);
|
|
152
|
+
if (!this.keysFirstAxis.has(serializedKeyFirstAxis)) {
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return this.baseMap.getRow(key, fillEmptyWith);
|
|
157
|
+
}
|
|
158
|
+
}
|
package/src/utils/Map2d.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import hash from 'object-hash';
|
|
2
|
-
|
|
3
|
-
export class Map2d<Key1 extends object | string, Key2 extends object | string, Value> {
|
|
4
|
-
readonly data: Map<string, Map<string, Value>> = new Map<string, Map<string, Value>>();
|
|
5
|
-
readonly keysFirstAxis = new Map<string, Key1>();
|
|
6
|
-
readonly keysSecondAxis = new Map<string, Key2>();
|
|
7
|
-
|
|
8
|
-
constructor(
|
|
9
|
-
readonly serializeFirstAxis: (key: Key1) => string = (key) => (typeof key === 'string' ? key : hash(key)),
|
|
10
|
-
readonly serializeSecondAxis: (key: Key2) => string = (key) => (typeof key === 'string' ? key : hash(key)),
|
|
11
|
-
) {}
|
|
12
|
-
|
|
13
|
-
get(keyFirstAxis: Key1, keySecondAxis: Key2) {
|
|
14
|
-
const serializedKeyFirstAxis = this.serializeFirstAxis(keyFirstAxis);
|
|
15
|
-
const serializedKeySecondAxis = this.serializeSecondAxis(keySecondAxis);
|
|
16
|
-
return this.data.get(serializedKeyFirstAxis)?.get(serializedKeySecondAxis);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
getRow(key: Key1, fillEmptyWith: Value) {
|
|
20
|
-
const serializedKeyFirstAxis = this.serializeFirstAxis(key);
|
|
21
|
-
const row = this.data.get(serializedKeyFirstAxis);
|
|
22
|
-
if (row === undefined) {
|
|
23
|
-
return [];
|
|
24
|
-
}
|
|
25
|
-
return Array.from(this.keysSecondAxis.keys()).map((key) => row.get(key) ?? fillEmptyWith);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
set(keyFirstAxis: Key1, keySecondAxis: Key2, value: Value) {
|
|
29
|
-
const serializedKeyFirstAxis = this.serializeFirstAxis(keyFirstAxis);
|
|
30
|
-
const serializedKeySecondAxis = this.serializeSecondAxis(keySecondAxis);
|
|
31
|
-
|
|
32
|
-
if (!this.data.has(serializedKeyFirstAxis)) {
|
|
33
|
-
this.data.set(serializedKeyFirstAxis, new Map<string, Value>());
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
this.data.get(serializedKeyFirstAxis)!.set(serializedKeySecondAxis, value);
|
|
37
|
-
|
|
38
|
-
this.keysFirstAxis.set(serializedKeyFirstAxis, keyFirstAxis);
|
|
39
|
-
this.keysSecondAxis.set(serializedKeySecondAxis, keySecondAxis);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
deleteRow(key: Key1) {
|
|
43
|
-
const serializedKeyFirstAxis = this.serializeFirstAxis(key);
|
|
44
|
-
this.data.delete(serializedKeyFirstAxis);
|
|
45
|
-
this.keysFirstAxis.delete(serializedKeyFirstAxis);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
getFirstAxisKeys() {
|
|
49
|
-
return Array.from(this.keysFirstAxis.values());
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
getSecondAxisKeys() {
|
|
53
|
-
return Array.from(this.keysSecondAxis.values());
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
getAsArray(fillEmptyWith: Value) {
|
|
57
|
-
return this.getFirstAxisKeys().map((firstAxisKey) => {
|
|
58
|
-
return this.getSecondAxisKeys().map((secondAxisKey) => {
|
|
59
|
-
return this.get(firstAxisKey, secondAxisKey) ?? fillEmptyWith;
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
copy() {
|
|
65
|
-
const copy = new Map2d<Key1, Key2, Value>(this.serializeFirstAxis, this.serializeSecondAxis);
|
|
66
|
-
this.data.forEach((value, key) => {
|
|
67
|
-
const keyFirstAxis = this.keysFirstAxis.get(key);
|
|
68
|
-
value.forEach((value, key) => {
|
|
69
|
-
const keySecondAxis = this.keysSecondAxis.get(key);
|
|
70
|
-
copy.set(keyFirstAxis!, keySecondAxis!, value);
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
return copy;
|
|
74
|
-
}
|
|
75
|
-
}
|