@jbrowse/plugin-data-management 2.16.1 → 2.17.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.
@@ -108,7 +108,9 @@ const ConfirmTrack = (0, mobx_react_1.observer)(function ConfirmTrack({ model, }
108
108
  warningMessage ? (react_1.default.createElement(material_1.Typography, { style: { color: 'orange' } }, warningMessage)) : null,
109
109
  react_1.default.createElement(material_1.TextField, { className: classes.spacing, label: "trackName", helperText: "A name for this track", fullWidth: true, value: trackName, onChange: event => {
110
110
  model.setTrackName(event.target.value);
111
- }, inputProps: { 'data-testid': 'trackNameInput' } }),
111
+ }, slotProps: {
112
+ htmlInput: { 'data-testid': 'trackNameInput' },
113
+ } }),
112
114
  react_1.default.createElement(TrackAdapterSelector_1.default, { model: model }),
113
115
  react_1.default.createElement(TrackTypeSelector_1.default, { model: model }),
114
116
  react_1.default.createElement(ui_1.AssemblySelector, { session: session, helperText: "Select assembly to add track to", selected: model.assembly, onChange: asm => {
@@ -71,18 +71,20 @@ const TextIndexingConfig = (0, mobx_react_1.observer)(function ({ model, }) {
71
71
  section.values.map((val, idx) => (
72
72
  /* biome-ignore lint/suspicious/noArrayIndexKey: */
73
73
  react_1.default.createElement(material_1.ListItem, { key: `${val}-${idx}`, disableGutters: true },
74
- react_1.default.createElement(material_1.TextField, { value: val, InputProps: {
75
- endAdornment: (react_1.default.createElement(material_1.InputAdornment, { position: "end" },
76
- react_1.default.createElement(material_1.IconButton, { onClick: () => {
77
- const newAttr = section.values.filter((_, i) => i !== idx);
78
- if (index === 0) {
79
- setAttributes(newAttr);
80
- }
81
- else {
82
- setExclude(newAttr);
83
- }
84
- } },
85
- react_1.default.createElement(Delete_1.default, null)))),
74
+ react_1.default.createElement(material_1.TextField, { value: val, slotProps: {
75
+ input: {
76
+ endAdornment: (react_1.default.createElement(material_1.InputAdornment, { position: "end" },
77
+ react_1.default.createElement(material_1.IconButton, { onClick: () => {
78
+ const newAttr = section.values.filter((_, i) => i !== idx);
79
+ if (index === 0) {
80
+ setAttributes(newAttr);
81
+ }
82
+ else {
83
+ setExclude(newAttr);
84
+ }
85
+ } },
86
+ react_1.default.createElement(Delete_1.default, null)))),
87
+ },
86
88
  } })))),
87
89
  react_1.default.createElement(material_1.ListItem, { disableGutters: true },
88
90
  react_1.default.createElement(material_1.TextField, { value: index === 0 ? value1 : value2, placeholder: "add new", onChange: event => {
@@ -92,19 +94,21 @@ const TextIndexingConfig = (0, mobx_react_1.observer)(function ({ model, }) {
92
94
  else {
93
95
  setValue2(event.target.value);
94
96
  }
95
- }, InputProps: {
96
- endAdornment: (react_1.default.createElement(material_1.InputAdornment, { position: "end" },
97
- react_1.default.createElement(material_1.IconButton, { onClick: () => {
98
- if (index === 0) {
99
- setAttributes([...attributes, value1]);
100
- setValue1('');
101
- }
102
- else {
103
- setExclude([...exclude, value2]);
104
- setValue2('');
105
- }
106
- }, disabled: index === 0 ? value1 === '' : value2 === '', "data-testid": "stringArrayAdd-Feat" },
107
- react_1.default.createElement(Add_1.default, null)))),
97
+ }, slotProps: {
98
+ input: {
99
+ endAdornment: (react_1.default.createElement(material_1.InputAdornment, { position: "end" },
100
+ react_1.default.createElement(material_1.IconButton, { onClick: () => {
101
+ if (index === 0) {
102
+ setAttributes([...attributes, value1]);
103
+ setValue1('');
104
+ }
105
+ else {
106
+ setExclude([...exclude, value2]);
107
+ setValue2('');
108
+ }
109
+ }, disabled: index === 0 ? value1 === '' : value2 === '', "data-testid": "stringArrayAdd-Feat" },
110
+ react_1.default.createElement(Add_1.default, null)))),
111
+ },
108
112
  } })))))))));
109
113
  });
110
114
  exports.default = TextIndexingConfig;
@@ -34,9 +34,11 @@ const TrackAdapterSelector = (0, mobx_react_1.observer)(({ model }) => {
34
34
  const { pluginManager } = (0, util_1.getEnv)(model);
35
35
  return (react_1.default.createElement(material_1.TextField, { className: classes.spacing, value: (trackAdapter === null || trackAdapter === void 0 ? void 0 : trackAdapter.type) !== 'UNKNOWN' ? trackAdapter === null || trackAdapter === void 0 ? void 0 : trackAdapter.type : '', label: "Adapter type", variant: "outlined", helperText: "Select an adapter type", select: true, fullWidth: true, onChange: event => {
36
36
  model.setAdapterHint(event.target.value);
37
- }, SelectProps: {
38
- // @ts-expect-error
39
- SelectDisplayProps: { 'data-testid': 'adapterTypeSelect' },
37
+ }, slotProps: {
38
+ select: {
39
+ // @ts-expect-error
40
+ SelectDisplayProps: { 'data-testid': 'adapterTypeSelect' },
41
+ },
40
42
  } }, Object.entries(categorizeAdapters(pluginManager
41
43
  .getAdapterElements()
42
44
  .filter(e => { var _a; return !((_a = e.adapterMetadata) === null || _a === void 0 ? void 0 : _a.hiddenFromGUI); }))).map(([key, val]) => {
@@ -20,9 +20,11 @@ const TrackTypeSelector = (0, mobx_react_1.observer)(({ model }) => {
20
20
  const trackTypes = pluginManager.getTrackElements();
21
21
  return (react_1.default.createElement(material_1.TextField, { className: classes.spacing, value: trackType, variant: "outlined", label: "Track type", helperText: "Select track type", select: true, fullWidth: true, onChange: event => {
22
22
  model.setTrackType(event.target.value);
23
- }, SelectProps: {
24
- // @ts-expect-error
25
- SelectDisplayProps: { 'data-testid': 'trackTypeSelect' },
23
+ }, slotProps: {
24
+ select: {
25
+ // @ts-expect-error
26
+ SelectDisplayProps: { 'data-testid': 'trackTypeSelect' },
27
+ },
26
28
  } }, trackTypes.map(({ name, displayName }) => (react_1.default.createElement(material_1.MenuItem, { key: name, value: name }, displayName)))));
27
29
  });
28
30
  exports.default = TrackTypeSelector;
@@ -139,11 +139,15 @@ const AssemblyAddForm = (0, mobx_react_1.observer)(function ({ rootModel, setFor
139
139
  }
140
140
  return (react_1.default.createElement("div", null,
141
141
  react_1.default.createElement(material_1.Paper, null,
142
- react_1.default.createElement(material_1.TextField, { id: "assembly-name", inputProps: { 'data-testid': 'assembly-name' }, label: "Assembly name", helperText: "The assembly name e.g. hg38", variant: "outlined", value: assemblyName, onChange: event => {
142
+ react_1.default.createElement(material_1.TextField, { id: "assembly-name", label: "Assembly name", helperText: "The assembly name e.g. hg38", variant: "outlined", value: assemblyName, onChange: event => {
143
143
  setAssemblyName(event.target.value);
144
+ }, slotProps: {
145
+ htmlInput: { 'data-testid': 'assembly-name' },
144
146
  } }),
145
- react_1.default.createElement(material_1.TextField, { id: "assembly-name", inputProps: { 'data-testid': 'assembly-display-name' }, label: "Assembly display name", helperText: 'A human readable display name for the assembly e.g. "Homo sapiens (hg38)"', variant: "outlined", value: assemblyDisplayName, onChange: event => {
147
+ react_1.default.createElement(material_1.TextField, { id: "assembly-name", label: "Assembly display name", helperText: 'A human readable display name for the assembly e.g. "Homo sapiens (hg38)"', variant: "outlined", value: assemblyDisplayName, onChange: event => {
146
148
  setAssemblyDisplayName(event.target.value);
149
+ }, slotProps: {
150
+ htmlInput: { 'data-testid': 'assembly-display-name' },
147
151
  } }),
148
152
  react_1.default.createElement(AdapterSelector, { adapterSelection: adapterSelection, adapterTypes: adapterTypes, setAdapterSelection: setAdapterSelection }),
149
153
  react_1.default.createElement(AdapterInput, { adapterSelection: adapterSelection, fastaLocation: fastaLocation, faiLocation: faiLocation, gziLocation: gziLocation, twoBitLocation: twoBitLocation, chromSizesLocation: chromSizesLocation, setFaiLocation: setFaiLocation, setGziLocation: setGziLocation, setTwoBitLocation: setTwoBitLocation, setFastaLocation: setFastaLocation, setChromSizesLocation: setChromSizesLocation })),
@@ -44,12 +44,14 @@ function FacetedHeader({ model, }) {
44
44
  react_1.default.createElement(material_1.Grid, { item: true },
45
45
  react_1.default.createElement(material_1.TextField, { label: "Search...", value: faceted.filterText, onChange: event => {
46
46
  faceted.setFilterText(event.target.value);
47
- }, InputProps: {
48
- endAdornment: (react_1.default.createElement(material_1.InputAdornment, { position: "end" },
49
- react_1.default.createElement(material_1.IconButton, { onClick: () => {
50
- faceted.setFilterText('');
51
- } },
52
- react_1.default.createElement(Clear_1.default, null)))),
47
+ }, slotProps: {
48
+ input: {
49
+ endAdornment: (react_1.default.createElement(material_1.InputAdornment, { position: "end" },
50
+ react_1.default.createElement(material_1.IconButton, { onClick: () => {
51
+ faceted.setFilterText('');
52
+ } },
53
+ react_1.default.createElement(Clear_1.default, null)))),
54
+ },
53
55
  } })),
54
56
  react_1.default.createElement(material_1.Grid, { item: true },
55
57
  react_1.default.createElement(material_1.IconButton, { onClick: event => {
@@ -23,12 +23,14 @@ const SearchTracksTextField = (0, mobx_react_1.observer)(function ({ model, }) {
23
23
  const { classes } = useStyles();
24
24
  return (react_1.default.createElement(material_1.TextField, { className: classes.searchBox, label: "Filter tracks", value: filterText, onChange: event => {
25
25
  model.setFilterText(event.target.value);
26
- }, fullWidth: true, InputProps: {
27
- endAdornment: (react_1.default.createElement(material_1.InputAdornment, { position: "end" },
28
- react_1.default.createElement(material_1.IconButton, { onClick: () => {
29
- model.clearFilterText();
30
- } },
31
- react_1.default.createElement(Clear_1.default, null)))),
26
+ }, fullWidth: true, slotProps: {
27
+ input: {
28
+ endAdornment: (react_1.default.createElement(material_1.InputAdornment, { position: "end" },
29
+ react_1.default.createElement(material_1.IconButton, { onClick: () => {
30
+ model.clearFilterText();
31
+ } },
32
+ react_1.default.createElement(Clear_1.default, null)))),
33
+ },
32
34
  } }));
33
35
  });
34
36
  const HierarchicalTrackSelectorHeader = (0, mobx_react_1.observer)(function ({ model, setHeaderHeight, }) {
@@ -82,12 +82,14 @@ const PluginStoreWidget = (0, mobx_react_1.observer)(function ({ model, }) {
82
82
  }, model: model }))) : null)),
83
83
  react_1.default.createElement(material_1.TextField, { label: "Filter plugins", value: model.filterText, onChange: event => {
84
84
  model.setFilterText(event.target.value);
85
- }, fullWidth: true, InputProps: {
86
- endAdornment: (react_1.default.createElement(material_1.InputAdornment, { position: "end" },
87
- react_1.default.createElement(material_1.IconButton, { onClick: () => {
88
- model.clearFilterText();
89
- } },
90
- react_1.default.createElement(Clear_1.default, null)))),
85
+ }, fullWidth: true, slotProps: {
86
+ input: {
87
+ endAdornment: (react_1.default.createElement(material_1.InputAdornment, { position: "end" },
88
+ react_1.default.createElement(material_1.IconButton, { onClick: () => {
89
+ model.clearFilterText();
90
+ } },
91
+ react_1.default.createElement(Clear_1.default, null)))),
92
+ },
91
93
  } }),
92
94
  react_1.default.createElement(material_1.Accordion, { defaultExpanded: true },
93
95
  react_1.default.createElement(material_1.AccordionSummary, { expandIcon: react_1.default.createElement(ExpandMore_1.default, { className: classes.expandIcon }) },
@@ -80,7 +80,9 @@ const ConfirmTrack = observer(function ConfirmTrack({ model, }) {
80
80
  warningMessage ? (React.createElement(Typography, { style: { color: 'orange' } }, warningMessage)) : null,
81
81
  React.createElement(TextField, { className: classes.spacing, label: "trackName", helperText: "A name for this track", fullWidth: true, value: trackName, onChange: event => {
82
82
  model.setTrackName(event.target.value);
83
- }, inputProps: { 'data-testid': 'trackNameInput' } }),
83
+ }, slotProps: {
84
+ htmlInput: { 'data-testid': 'trackNameInput' },
85
+ } }),
84
86
  React.createElement(TrackAdapterSelector, { model: model }),
85
87
  React.createElement(TrackTypeSelector, { model: model }),
86
88
  React.createElement(AssemblySelector, { session: session, helperText: "Select assembly to add track to", selected: model.assembly, onChange: asm => {
@@ -43,18 +43,20 @@ const TextIndexingConfig = observer(function ({ model, }) {
43
43
  section.values.map((val, idx) => (
44
44
  /* biome-ignore lint/suspicious/noArrayIndexKey: */
45
45
  React.createElement(ListItem, { key: `${val}-${idx}`, disableGutters: true },
46
- React.createElement(TextField, { value: val, InputProps: {
47
- endAdornment: (React.createElement(InputAdornment, { position: "end" },
48
- React.createElement(IconButton, { onClick: () => {
49
- const newAttr = section.values.filter((_, i) => i !== idx);
50
- if (index === 0) {
51
- setAttributes(newAttr);
52
- }
53
- else {
54
- setExclude(newAttr);
55
- }
56
- } },
57
- React.createElement(DeleteIcon, null)))),
46
+ React.createElement(TextField, { value: val, slotProps: {
47
+ input: {
48
+ endAdornment: (React.createElement(InputAdornment, { position: "end" },
49
+ React.createElement(IconButton, { onClick: () => {
50
+ const newAttr = section.values.filter((_, i) => i !== idx);
51
+ if (index === 0) {
52
+ setAttributes(newAttr);
53
+ }
54
+ else {
55
+ setExclude(newAttr);
56
+ }
57
+ } },
58
+ React.createElement(DeleteIcon, null)))),
59
+ },
58
60
  } })))),
59
61
  React.createElement(ListItem, { disableGutters: true },
60
62
  React.createElement(TextField, { value: index === 0 ? value1 : value2, placeholder: "add new", onChange: event => {
@@ -64,19 +66,21 @@ const TextIndexingConfig = observer(function ({ model, }) {
64
66
  else {
65
67
  setValue2(event.target.value);
66
68
  }
67
- }, InputProps: {
68
- endAdornment: (React.createElement(InputAdornment, { position: "end" },
69
- React.createElement(IconButton, { onClick: () => {
70
- if (index === 0) {
71
- setAttributes([...attributes, value1]);
72
- setValue1('');
73
- }
74
- else {
75
- setExclude([...exclude, value2]);
76
- setValue2('');
77
- }
78
- }, disabled: index === 0 ? value1 === '' : value2 === '', "data-testid": "stringArrayAdd-Feat" },
79
- React.createElement(AddIcon, null)))),
69
+ }, slotProps: {
70
+ input: {
71
+ endAdornment: (React.createElement(InputAdornment, { position: "end" },
72
+ React.createElement(IconButton, { onClick: () => {
73
+ if (index === 0) {
74
+ setAttributes([...attributes, value1]);
75
+ setValue1('');
76
+ }
77
+ else {
78
+ setExclude([...exclude, value2]);
79
+ setValue2('');
80
+ }
81
+ }, disabled: index === 0 ? value1 === '' : value2 === '', "data-testid": "stringArrayAdd-Feat" },
82
+ React.createElement(AddIcon, null)))),
83
+ },
80
84
  } })))))))));
81
85
  });
82
86
  export default TextIndexingConfig;
@@ -29,9 +29,11 @@ const TrackAdapterSelector = observer(({ model }) => {
29
29
  const { pluginManager } = getEnv(model);
30
30
  return (React.createElement(TextField, { className: classes.spacing, value: (trackAdapter === null || trackAdapter === void 0 ? void 0 : trackAdapter.type) !== 'UNKNOWN' ? trackAdapter === null || trackAdapter === void 0 ? void 0 : trackAdapter.type : '', label: "Adapter type", variant: "outlined", helperText: "Select an adapter type", select: true, fullWidth: true, onChange: event => {
31
31
  model.setAdapterHint(event.target.value);
32
- }, SelectProps: {
33
- // @ts-expect-error
34
- SelectDisplayProps: { 'data-testid': 'adapterTypeSelect' },
32
+ }, slotProps: {
33
+ select: {
34
+ // @ts-expect-error
35
+ SelectDisplayProps: { 'data-testid': 'adapterTypeSelect' },
36
+ },
35
37
  } }, Object.entries(categorizeAdapters(pluginManager
36
38
  .getAdapterElements()
37
39
  .filter(e => { var _a; return !((_a = e.adapterMetadata) === null || _a === void 0 ? void 0 : _a.hiddenFromGUI); }))).map(([key, val]) => {
@@ -15,9 +15,11 @@ const TrackTypeSelector = observer(({ model }) => {
15
15
  const trackTypes = pluginManager.getTrackElements();
16
16
  return (React.createElement(TextField, { className: classes.spacing, value: trackType, variant: "outlined", label: "Track type", helperText: "Select track type", select: true, fullWidth: true, onChange: event => {
17
17
  model.setTrackType(event.target.value);
18
- }, SelectProps: {
19
- // @ts-expect-error
20
- SelectDisplayProps: { 'data-testid': 'trackTypeSelect' },
18
+ }, slotProps: {
19
+ select: {
20
+ // @ts-expect-error
21
+ SelectDisplayProps: { 'data-testid': 'trackTypeSelect' },
22
+ },
21
23
  } }, trackTypes.map(({ name, displayName }) => (React.createElement(MenuItem, { key: name, value: name }, displayName)))));
22
24
  });
23
25
  export default TrackTypeSelector;
@@ -111,11 +111,15 @@ const AssemblyAddForm = observer(function ({ rootModel, setFormOpen, }) {
111
111
  }
112
112
  return (React.createElement("div", null,
113
113
  React.createElement(Paper, null,
114
- React.createElement(TextField, { id: "assembly-name", inputProps: { 'data-testid': 'assembly-name' }, label: "Assembly name", helperText: "The assembly name e.g. hg38", variant: "outlined", value: assemblyName, onChange: event => {
114
+ React.createElement(TextField, { id: "assembly-name", label: "Assembly name", helperText: "The assembly name e.g. hg38", variant: "outlined", value: assemblyName, onChange: event => {
115
115
  setAssemblyName(event.target.value);
116
+ }, slotProps: {
117
+ htmlInput: { 'data-testid': 'assembly-name' },
116
118
  } }),
117
- React.createElement(TextField, { id: "assembly-name", inputProps: { 'data-testid': 'assembly-display-name' }, label: "Assembly display name", helperText: 'A human readable display name for the assembly e.g. "Homo sapiens (hg38)"', variant: "outlined", value: assemblyDisplayName, onChange: event => {
119
+ React.createElement(TextField, { id: "assembly-name", label: "Assembly display name", helperText: 'A human readable display name for the assembly e.g. "Homo sapiens (hg38)"', variant: "outlined", value: assemblyDisplayName, onChange: event => {
118
120
  setAssemblyDisplayName(event.target.value);
121
+ }, slotProps: {
122
+ htmlInput: { 'data-testid': 'assembly-display-name' },
119
123
  } }),
120
124
  React.createElement(AdapterSelector, { adapterSelection: adapterSelection, adapterTypes: adapterTypes, setAdapterSelection: setAdapterSelection }),
121
125
  React.createElement(AdapterInput, { adapterSelection: adapterSelection, fastaLocation: fastaLocation, faiLocation: faiLocation, gziLocation: gziLocation, twoBitLocation: twoBitLocation, chromSizesLocation: chromSizesLocation, setFaiLocation: setFaiLocation, setGziLocation: setGziLocation, setTwoBitLocation: setTwoBitLocation, setFastaLocation: setFastaLocation, setChromSizesLocation: setChromSizesLocation })),
@@ -15,12 +15,14 @@ export default function FacetedHeader({ model, }) {
15
15
  React.createElement(Grid, { item: true },
16
16
  React.createElement(TextField, { label: "Search...", value: faceted.filterText, onChange: event => {
17
17
  faceted.setFilterText(event.target.value);
18
- }, InputProps: {
19
- endAdornment: (React.createElement(InputAdornment, { position: "end" },
20
- React.createElement(IconButton, { onClick: () => {
21
- faceted.setFilterText('');
22
- } },
23
- React.createElement(ClearIcon, null)))),
18
+ }, slotProps: {
19
+ input: {
20
+ endAdornment: (React.createElement(InputAdornment, { position: "end" },
21
+ React.createElement(IconButton, { onClick: () => {
22
+ faceted.setFilterText('');
23
+ } },
24
+ React.createElement(ClearIcon, null)))),
25
+ },
24
26
  } })),
25
27
  React.createElement(Grid, { item: true },
26
28
  React.createElement(IconButton, { onClick: event => {
@@ -18,12 +18,14 @@ const SearchTracksTextField = observer(function ({ model, }) {
18
18
  const { classes } = useStyles();
19
19
  return (React.createElement(TextField, { className: classes.searchBox, label: "Filter tracks", value: filterText, onChange: event => {
20
20
  model.setFilterText(event.target.value);
21
- }, fullWidth: true, InputProps: {
22
- endAdornment: (React.createElement(InputAdornment, { position: "end" },
23
- React.createElement(IconButton, { onClick: () => {
24
- model.clearFilterText();
25
- } },
26
- React.createElement(ClearIcon, null)))),
21
+ }, fullWidth: true, slotProps: {
22
+ input: {
23
+ endAdornment: (React.createElement(InputAdornment, { position: "end" },
24
+ React.createElement(IconButton, { onClick: () => {
25
+ model.clearFilterText();
26
+ } },
27
+ React.createElement(ClearIcon, null)))),
28
+ },
27
29
  } }));
28
30
  });
29
31
  const HierarchicalTrackSelectorHeader = observer(function ({ model, setHeaderHeight, }) {
@@ -54,12 +54,14 @@ const PluginStoreWidget = observer(function ({ model, }) {
54
54
  }, model: model }))) : null)),
55
55
  React.createElement(TextField, { label: "Filter plugins", value: model.filterText, onChange: event => {
56
56
  model.setFilterText(event.target.value);
57
- }, fullWidth: true, InputProps: {
58
- endAdornment: (React.createElement(InputAdornment, { position: "end" },
59
- React.createElement(IconButton, { onClick: () => {
60
- model.clearFilterText();
61
- } },
62
- React.createElement(ClearIcon, null)))),
57
+ }, fullWidth: true, slotProps: {
58
+ input: {
59
+ endAdornment: (React.createElement(InputAdornment, { position: "end" },
60
+ React.createElement(IconButton, { onClick: () => {
61
+ model.clearFilterText();
62
+ } },
63
+ React.createElement(ClearIcon, null)))),
64
+ },
63
65
  } }),
64
66
  React.createElement(Accordion, { defaultExpanded: true },
65
67
  React.createElement(AccordionSummary, { expandIcon: React.createElement(ExpandMoreIcon, { className: classes.expandIcon }) },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-data-management",
3
- "version": "2.16.1",
3
+ "version": "2.17.0",
4
4
  "description": "JBrowse 2 linear genome view",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -60,5 +60,5 @@
60
60
  "distModule": "esm/index.js",
61
61
  "srcModule": "src/index.ts",
62
62
  "module": "esm/index.js",
63
- "gitHead": "c6a658d2344989895543f0456b1cf7dd3b937769"
63
+ "gitHead": "eed30b5e671f8f7823652d7cecc51aa89226de46"
64
64
  }