@genspectrum/dashboard-components 0.6.19 → 0.7.0

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.
Files changed (26) hide show
  1. package/custom-elements.json +18 -18
  2. package/dist/assets/mutationOverTimeWorker-BOCXtKzd.js.map +1 -0
  3. package/dist/dashboard-components.js +96 -99
  4. package/dist/dashboard-components.js.map +1 -1
  5. package/dist/genspectrum-components.d.ts +98 -48
  6. package/package.json +1 -3
  7. package/src/index.ts +1 -0
  8. package/src/preact/dateRangeSelector/computeInitialValues.spec.ts +53 -38
  9. package/src/preact/dateRangeSelector/computeInitialValues.ts +17 -23
  10. package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +46 -32
  11. package/src/preact/dateRangeSelector/date-range-selector.tsx +24 -26
  12. package/src/preact/dateRangeSelector/dateRangeOption.ts +65 -0
  13. package/src/preact/dateRangeSelector/selectableOptions.ts +17 -66
  14. package/src/preact/mutationsOverTime/MutationOverTimeData.ts +20 -0
  15. package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +2 -3
  16. package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +2 -2
  17. package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +3 -3
  18. package/src/preact/mutationsOverTime/mutations-over-time.tsx +7 -18
  19. package/src/query/queryMutationsOverTime.ts +3 -5
  20. package/src/utils/map2d.spec.ts +52 -13
  21. package/src/utils/map2d.ts +3 -4
  22. package/src/web-components/input/gs-date-range-selector.stories.ts +16 -28
  23. package/src/web-components/input/gs-date-range-selector.tsx +17 -32
  24. package/standalone-bundle/dashboard-components.js +11687 -12463
  25. package/standalone-bundle/dashboard-components.js.map +1 -1
  26. package/dist/assets/mutationOverTimeWorker-BdzqDqvO.js.map +0 -1
@@ -4,20 +4,29 @@ import { Map2dBase, Map2dView } from './map2d';
4
4
 
5
5
  describe('Map2dBase', () => {
6
6
  it('should add a value and return it', () => {
7
- const map2d = new Map2dBase<string, string, number>();
7
+ const map2d = new Map2dBase<string, string, number>(
8
+ (value) => value,
9
+ (value) => value,
10
+ );
8
11
  map2d.set('a', 'b', 2);
9
12
  expect(map2d.get('a', 'b')).toBe(2);
10
13
  });
11
14
 
12
15
  it('should update a value', () => {
13
- const map2d = new Map2dBase<string, string, number>();
16
+ const map2d = new Map2dBase<string, string, number>(
17
+ (value) => value,
18
+ (value) => value,
19
+ );
14
20
  map2d.set('a', 'b', 2);
15
21
  map2d.set('a', 'b', 3);
16
22
  expect(map2d.get('a', 'b')).toBe(3);
17
23
  });
18
24
 
19
25
  it('should return the data as an array', () => {
20
- const map2d = new Map2dBase<string, string, number>();
26
+ const map2d = new Map2dBase<string, string, number>(
27
+ (value) => value,
28
+ (value) => value,
29
+ );
21
30
  map2d.set('a', 'b', 1);
22
31
  map2d.set('a', 'd', 2);
23
32
  map2d.set('c', 'b', 3);
@@ -30,7 +39,10 @@ describe('Map2dBase', () => {
30
39
  });
31
40
 
32
41
  it('should fill empty values with the given value', () => {
33
- const map2d = new Map2dBase<string, string, number>();
42
+ const map2d = new Map2dBase<string, string, number>(
43
+ (value) => value,
44
+ (value) => value,
45
+ );
34
46
  map2d.set('a', 'b', 2);
35
47
  map2d.set('c', 'd', 4);
36
48
  expect(map2d.getAsArray(0)).toEqual([
@@ -40,7 +52,10 @@ describe('Map2dBase', () => {
40
52
  });
41
53
 
42
54
  it('should return the keys from the first axis', () => {
43
- const map2d = new Map2dBase<string, string, number>();
55
+ const map2d = new Map2dBase<string, string, number>(
56
+ (value) => value,
57
+ (value) => value,
58
+ );
44
59
  map2d.set('a', 'b', 2);
45
60
  map2d.set('c', 'd', 4);
46
61
 
@@ -48,7 +63,10 @@ describe('Map2dBase', () => {
48
63
  });
49
64
 
50
65
  it('should return the keys from the second axis', () => {
51
- const map2d = new Map2dBase<string, string, number>();
66
+ const map2d = new Map2dBase<string, string, number>(
67
+ (value) => value,
68
+ (value) => value,
69
+ );
52
70
  map2d.set('a', 'b', 2);
53
71
  map2d.set('c', 'd', 4);
54
72
 
@@ -56,7 +74,10 @@ describe('Map2dBase', () => {
56
74
  });
57
75
 
58
76
  it('should work with objects as keys', () => {
59
- const map2d = new Map2dBase<{ a: string }, { b: string }, number>();
77
+ const map2d = new Map2dBase<{ a: string }, { b: string }, number>(
78
+ ({ a }) => a,
79
+ ({ b }) => b,
80
+ );
60
81
  map2d.set({ a: 'a' }, { b: 'b' }, 2);
61
82
  map2d.set({ a: 'second' }, { b: 'second' }, 3);
62
83
 
@@ -65,14 +86,20 @@ describe('Map2dBase', () => {
65
86
  });
66
87
 
67
88
  it('should update a value with objects as keys', () => {
68
- const map2d = new Map2dBase<{ a: string }, { b: string }, number>();
89
+ const map2d = new Map2dBase<{ a: string }, { b: string }, number>(
90
+ ({ a }) => a,
91
+ ({ b }) => b,
92
+ );
69
93
  map2d.set({ a: 'a' }, { b: 'b' }, 2);
70
94
  map2d.set({ a: 'a' }, { b: 'b' }, 3);
71
95
  expect(map2d.get({ a: 'a' }, { b: 'b' })).toBe(3);
72
96
  });
73
97
 
74
98
  it('should return a row by key', () => {
75
- const map2d = new Map2dBase<string, string, number>();
99
+ const map2d = new Map2dBase<string, string, number>(
100
+ (value) => value,
101
+ (value) => value,
102
+ );
76
103
  map2d.set('a', 'b', 2);
77
104
  map2d.set('c', 'd', 4);
78
105
 
@@ -81,14 +108,20 @@ describe('Map2dBase', () => {
81
108
  });
82
109
 
83
110
  it('should return an empty array when the row does not exist', () => {
84
- const map2d = new Map2dBase<string, string, number>();
111
+ const map2d = new Map2dBase<string, string, number>(
112
+ (value) => value,
113
+ (value) => value,
114
+ );
85
115
  map2d.set('a', 'b', 2);
86
116
 
87
117
  expect(map2d.getRow('c', 0)).toEqual([]);
88
118
  });
89
119
 
90
120
  it('should return content as object', () => {
91
- const map2d = new Map2dBase<string, string, number>();
121
+ const map2d = new Map2dBase<string, string, number>(
122
+ (value) => value,
123
+ (value) => value,
124
+ );
92
125
  map2d.set('a', 'b', 2);
93
126
  map2d.set('c', 'd', 4);
94
127
 
@@ -99,7 +132,10 @@ describe('Map2dBase', () => {
99
132
  });
100
133
 
101
134
  it('should use initial data', () => {
102
- const map2d = new Map2dBase<string, string, number>();
135
+ const map2d = new Map2dBase<string, string, number>(
136
+ (value) => value,
137
+ (value) => value,
138
+ );
103
139
  map2d.set('a', 'b', 2);
104
140
  map2d.set('c', 'd', 4);
105
141
 
@@ -174,7 +210,10 @@ describe('Map2dView', () => {
174
210
  });
175
211
 
176
212
  function createBaseContainer() {
177
- const container = new Map2dBase<string, string, number>();
213
+ const container = new Map2dBase<string, string, number>(
214
+ (value) => value,
215
+ (value) => value,
216
+ );
178
217
  container.set('a', 'b', 1);
179
218
  container.set('c', 'b', 3);
180
219
  container.set('c', 'd', 4);
@@ -1,5 +1,3 @@
1
- import hash from 'object-hash';
2
-
3
1
  export interface Map2d<Key1, Key2, Value> {
4
2
  get(keyFirstAxis: Key1, keySecondAxis: Key2): Value | undefined;
5
3
 
@@ -16,6 +14,7 @@ export interface Map2d<Key1, Key2, Value> {
16
14
  getAsArray(fillEmptyWith: Value): Value[][];
17
15
 
18
16
  serializeFirstAxis(key: Key1): string;
17
+
19
18
  serializeSecondAxis(key: Key2): string;
20
19
 
21
20
  readonly keysFirstAxis: Map<string, Key1>;
@@ -36,8 +35,8 @@ export class Map2dBase<Key1 extends object | string, Key2 extends object | strin
36
35
  readonly keysSecondAxis = new Map<string, Key2>();
37
36
 
38
37
  constructor(
39
- readonly serializeFirstAxis: (key: Key1) => string = (key) => (typeof key === 'string' ? key : hash(key)),
40
- readonly serializeSecondAxis: (key: Key2) => string = (key) => (typeof key === 'string' ? key : hash(key)),
38
+ readonly serializeFirstAxis: (key: Key1) => string,
39
+ readonly serializeSecondAxis: (key: Key2) => string,
41
40
  initialContent?: Map2DContents<Key1, Key2, Value>,
42
41
  ) {
43
42
  if (initialContent) {
@@ -9,29 +9,21 @@ import { type DateRangeSelectorProps } from '../../preact/dateRangeSelector/date
9
9
  import './gs-date-range-selector';
10
10
  import '../app';
11
11
  import { toYYYYMMDD } from '../../preact/dateRangeSelector/dateConversion';
12
- import {
13
- PRESET_VALUE_ALL_TIMES,
14
- PRESET_VALUE_CUSTOM,
15
- PRESET_VALUE_LAST_2_MONTHS,
16
- PRESET_VALUE_LAST_2_WEEKS,
17
- PRESET_VALUE_LAST_3_MONTHS,
18
- PRESET_VALUE_LAST_6_MONTHS,
19
- PRESET_VALUE_LAST_MONTH,
20
- } from '../../preact/dateRangeSelector/selectableOptions';
12
+ import { dateRangeOptionPresets } from '../../preact/dateRangeSelector/dateRangeOption';
21
13
  import { withinShadowRoot } from '../withinShadowRoot.story';
22
14
 
23
15
  const codeExample = String.raw`
24
16
  <gs-date-range-selector
25
- customSelectOptions='[{ "label": "Year 2021", "dateFrom": "2021-01-01", "dateTo": "2021-12-31" }]'
17
+ dateRangeOptions='[{ "label": "Year 2021", "dateFrom": "2021-01-01", "dateTo": "2021-12-31" }]'
26
18
  earliestDate="1970-01-01"
27
- initialValue="${PRESET_VALUE_LAST_6_MONTHS}"
19
+ initialValue="Year 2021"
28
20
  initialDateFrom="2020-01-01"
29
21
  initialDateTo="2021-01-01"
30
22
  width="100%"
31
23
  dateColumn="myDateColumn"
32
24
  ></gs-date-range-selector>`;
33
25
 
34
- const meta: Meta<Required<DateRangeSelectorProps<'CustomDateRange'>>> = {
26
+ const meta: Meta<Required<DateRangeSelectorProps>> = {
35
27
  title: 'Input/DateRangeSelector',
36
28
  component: 'gs-date-range-selector',
37
29
  parameters: withComponentDocs({
@@ -50,19 +42,10 @@ const meta: Meta<Required<DateRangeSelectorProps<'CustomDateRange'>>> = {
50
42
  control: {
51
43
  type: 'select',
52
44
  },
53
- options: [
54
- PRESET_VALUE_CUSTOM,
55
- PRESET_VALUE_ALL_TIMES,
56
- PRESET_VALUE_LAST_2_WEEKS,
57
- PRESET_VALUE_LAST_MONTH,
58
- PRESET_VALUE_LAST_2_MONTHS,
59
- PRESET_VALUE_LAST_3_MONTHS,
60
- PRESET_VALUE_LAST_6_MONTHS,
61
- 'CustomDateRange',
62
- ],
45
+ options: [dateRangeOptionPresets.lastMonth.label, dateRangeOptionPresets.allTimes.label, 'CustomDateRange'],
63
46
  },
64
47
  dateColumn: { control: { type: 'text' } },
65
- customSelectOptions: {
48
+ dateRangeOptions: {
66
49
  control: {
67
50
  type: 'object',
68
51
  },
@@ -79,9 +62,14 @@ const meta: Meta<Required<DateRangeSelectorProps<'CustomDateRange'>>> = {
79
62
  },
80
63
  },
81
64
  args: {
82
- customSelectOptions: [{ label: 'CustomDateRange', dateFrom: '2021-01-01', dateTo: '2021-12-31' }],
65
+ dateRangeOptions: [
66
+ dateRangeOptionPresets.lastMonth,
67
+ dateRangeOptionPresets.last3Months,
68
+ dateRangeOptionPresets.allTimes,
69
+ { label: 'CustomDateRange', dateFrom: '2021-01-01', dateTo: '2021-12-31' },
70
+ ],
83
71
  earliestDate: '1970-01-01',
84
- initialValue: PRESET_VALUE_LAST_6_MONTHS,
72
+ initialValue: dateRangeOptionPresets.lastMonth.label,
85
73
  dateColumn: 'aDateColumn',
86
74
  width: '100%',
87
75
  initialDateFrom: '',
@@ -92,12 +80,12 @@ const meta: Meta<Required<DateRangeSelectorProps<'CustomDateRange'>>> = {
92
80
 
93
81
  export default meta;
94
82
 
95
- export const DateRangeSelectorStory: StoryObj<Required<DateRangeSelectorProps<'CustomDateRange'>>> = {
83
+ export const DateRangeSelectorStory: StoryObj<Required<DateRangeSelectorProps>> = {
96
84
  render: (args) =>
97
85
  html` <gs-app lapis="${LAPIS_URL}">
98
86
  <div class="max-w-screen-lg">
99
87
  <gs-date-range-selector
100
- .customSelectOptions=${args.customSelectOptions}
88
+ .dateRangeOptions=${args.dateRangeOptions}
101
89
  .earliestDate=${args.earliestDate}
102
90
  .initialValue=${args.initialValue}
103
91
  .initialDateFrom=${args.initialDateFrom}
@@ -112,7 +100,7 @@ export const DateRangeSelectorStory: StoryObj<Required<DateRangeSelectorProps<'C
112
100
  const dateTo = () => canvas.getByPlaceholderText('Date to');
113
101
 
114
102
  await step('Expect last 6 months to be selected', async () => {
115
- await expect(canvas.getByRole('combobox')).toHaveValue('last6Months');
103
+ await expect(canvas.getByRole('combobox')).toHaveValue('Last month');
116
104
  await waitFor(() => {
117
105
  expect(dateTo()).toHaveValue(toYYYYMMDD(new Date()));
118
106
  });
@@ -37,13 +37,14 @@ import { PreactLitAdapter } from '../PreactLitAdapter';
37
37
  @customElement('gs-date-range-selector')
38
38
  export class DateRangeSelectorComponent extends PreactLitAdapter {
39
39
  /**
40
- * An array of custom options that the select field should provide,
41
- * in addition to the predefined options.
40
+ * An array of date range options that the select field should provide.
42
41
  * The `label` will be shown to the user, and it will be available as `initialValue`.
43
42
  * The dates must be in the format `YYYY-MM-DD`.
43
+ *
44
+ * If dateFrom or dateTo is not set, the component will default to the `earliestDate` or the current date.
44
45
  */
45
46
  @property({ type: Array })
46
- customSelectOptions: { label: string; dateFrom: string; dateTo: string }[] = [];
47
+ dateRangeOptions: { label: string; dateFrom?: string; dateTo?: string }[] = [];
47
48
 
48
49
  /**
49
50
  * The `dateFrom` value to use in the `allTimes` preset in the format `YYYY-MM-DD`.
@@ -51,26 +52,18 @@ export class DateRangeSelectorComponent extends PreactLitAdapter {
51
52
  @property({ type: String })
52
53
  earliestDate: string = '1900-01-01';
53
54
 
54
- // prettier-ignore
55
- // The multiline union type must not start with `| 'custom'` - Storybook will list "" as the first type which is wrong
56
55
  /**
57
56
  * The initial value to use for this date range selector.
58
- * Must be a valid label from the preset labels or a `label` given in the `customSelectOptions`.
57
+ * Must be a valid label from the `dateRangeOptions`.
59
58
  *
60
- * If the value is invalid, the component will default to `'last6Months'`.
59
+ * If the value is not set, the component will default to the range `earliestDate` until today.
61
60
  *
62
61
  * It will be overwritten if `initialDateFrom` or `initialDateTo` is set.
62
+ *
63
+ * We provide some options in `dateRangeOptionPresets` for convenience.
63
64
  */
64
65
  @property()
65
- initialValue:
66
- 'custom'
67
- | 'allTimes'
68
- | 'last2Weeks'
69
- | 'lastMonth'
70
- | 'last2Months'
71
- | 'last3Months'
72
- | 'last6Months'
73
- | string = 'last6Months';
66
+ initialValue: string | undefined = undefined;
74
67
 
75
68
  /**
76
69
  * A date string in the format `YYYY-MM-DD`.
@@ -105,7 +98,7 @@ export class DateRangeSelectorComponent extends PreactLitAdapter {
105
98
  override render() {
106
99
  return (
107
100
  <DateRangeSelector
108
- customSelectOptions={this.customSelectOptions}
101
+ dateRangeOptions={this.dateRangeOptions}
109
102
  earliestDate={this.earliestDate}
110
103
  initialValue={this.initialValue}
111
104
  initialDateFrom={this.initialDateFrom}
@@ -138,30 +131,22 @@ declare global {
138
131
 
139
132
  /* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars */
140
133
  type CustomSelectOptionsMatches = Expect<
141
- Equals<
142
- typeof DateRangeSelectorComponent.prototype.customSelectOptions,
143
- DateRangeSelectorProps<string>['customSelectOptions']
144
- >
134
+ Equals<typeof DateRangeSelectorComponent.prototype.dateRangeOptions, DateRangeSelectorProps['dateRangeOptions']>
145
135
  >;
146
136
  type EarliestDateMatches = Expect<
147
- Equals<typeof DateRangeSelectorComponent.prototype.earliestDate, DateRangeSelectorProps<string>['earliestDate']>
137
+ Equals<typeof DateRangeSelectorComponent.prototype.earliestDate, DateRangeSelectorProps['earliestDate']>
148
138
  >;
149
139
  type InitialValueMatches = Expect<
150
- Equals<typeof DateRangeSelectorComponent.prototype.initialValue, DateRangeSelectorProps<string>['initialValue']>
140
+ Equals<typeof DateRangeSelectorComponent.prototype.initialValue, DateRangeSelectorProps['initialValue']>
151
141
  >;
152
142
  type InitialDateFromMatches = Expect<
153
- Equals<
154
- typeof DateRangeSelectorComponent.prototype.initialDateFrom,
155
- DateRangeSelectorProps<string>['initialDateFrom']
156
- >
143
+ Equals<typeof DateRangeSelectorComponent.prototype.initialDateFrom, DateRangeSelectorProps['initialDateFrom']>
157
144
  >;
158
145
  type InitialDateToMatches = Expect<
159
- Equals<typeof DateRangeSelectorComponent.prototype.initialDateTo, DateRangeSelectorProps<string>['initialDateTo']>
160
- >;
161
- type WidthMatches = Expect<
162
- Equals<typeof DateRangeSelectorComponent.prototype.width, DateRangeSelectorProps<string>['width']>
146
+ Equals<typeof DateRangeSelectorComponent.prototype.initialDateTo, DateRangeSelectorProps['initialDateTo']>
163
147
  >;
148
+ type WidthMatches = Expect<Equals<typeof DateRangeSelectorComponent.prototype.width, DateRangeSelectorProps['width']>>;
164
149
  type DateColumnMatches = Expect<
165
- Equals<typeof DateRangeSelectorComponent.prototype.dateColumn, DateRangeSelectorProps<string>['dateColumn']>
150
+ Equals<typeof DateRangeSelectorComponent.prototype.dateColumn, DateRangeSelectorProps['dateColumn']>
166
151
  >;
167
152
  /* eslint-enable @typescript-eslint/no-unused-vars, no-unused-vars */