@opencloning/ui 1.5.3 → 1.5.5

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/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @opencloning/ui
2
2
 
3
+ ## 1.5.5
4
+
5
+ ### Patch Changes
6
+
7
+ - [#659](https://github.com/manulera/OpenCloning_frontend/pull/659) [`f69d0d6`](https://github.com/manulera/OpenCloning_frontend/commit/f69d0d6b5c4558b502bf13f20fac9fa183cfc8f2) Thanks [@manulera](https://github.com/manulera)! - Non-virtualized syntax table for Ctrl+F to work even
8
+
9
+ - Updated dependencies []:
10
+ - @opencloning/store@1.5.5
11
+ - @opencloning/utils@1.5.5
12
+
13
+ ## 1.5.4
14
+
15
+ ### Patch Changes
16
+
17
+ - [#657](https://github.com/manulera/OpenCloning_frontend/pull/657) [`36f5e08`](https://github.com/manulera/OpenCloning_frontend/commit/36f5e08a0dc346842ec922706735362929b5ac84) Thanks [@manulera](https://github.com/manulera)! - Plasmid syntax tables showing which part is contained in each plasmid can now be sorted
18
+
19
+ - Updated dependencies []:
20
+ - @opencloning/store@1.5.4
21
+ - @opencloning/utils@1.5.4
22
+
3
23
  ## 1.5.3
4
24
 
5
25
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencloning/ui",
3
- "version": "1.5.3",
3
+ "version": "1.5.5",
4
4
  "type": "module",
5
5
  "main": "./src/index.js",
6
6
  "scripts": {
@@ -26,8 +26,8 @@
26
26
  "@mui/icons-material": "^5.15.17",
27
27
  "@mui/material": "^5.15.17",
28
28
  "@mui/x-data-grid": "^8.25.0",
29
- "@opencloning/store": "1.5.3",
30
- "@opencloning/utils": "1.5.3",
29
+ "@opencloning/store": "1.5.5",
30
+ "@opencloning/utils": "1.5.5",
31
31
  "@teselagen/bio-parsers": "^0.4.34",
32
32
  "@teselagen/ove": "^0.8.34",
33
33
  "@teselagen/range-utils": "^0.3.20",
@@ -1,6 +1,6 @@
1
-
2
- import React from 'react'
3
- import { Table, TableHead, TableRow, TableCell, TableBody, Typography, Chip, Box } from '@mui/material'
1
+ import React, { useMemo } from 'react'
2
+ import { Typography, Chip, Box } from '@mui/material'
3
+ import { DataGrid } from '@mui/x-data-grid'
4
4
 
5
5
  function PartChip({ name, overhang}) {
6
6
  const label = name ? `${overhang} (${name})` : overhang;
@@ -10,73 +10,138 @@ function PartChip({ name, overhang}) {
10
10
  )
11
11
  }
12
12
 
13
- function PlasmidRow({ plasmid }) {
14
- const { name, appData } = plasmid;
15
- const { fileName, correspondingParts, correspondingPartsNames, partInfo, longestFeature } = appData;
16
- let sx = undefined;
17
- let infoStr = '-';
18
- let longestFeatureStr = '-';
19
- let noParts = partInfo.length === 0;
20
- if (partInfo.length === 1) {
21
- sx = {
22
- backgroundColor: partInfo[0]?.color,
13
+ function PlasmidSyntaxTable({ plasmids, maxHeight = 500 }) {
14
+ const rows = useMemo(() => plasmids.map((plasmid, index) => {
15
+ const { name, appData } = plasmid;
16
+ const { fileName, correspondingParts, correspondingPartsNames, partInfo, longestFeature } = appData;
17
+
18
+ let infoStr = '-';
19
+ let longestFeatureStr = '-';
20
+ const noParts = partInfo.length === 0;
21
+ const multipleParts = partInfo.length > 1;
22
+
23
+ if (partInfo.length === 1) {
24
+ infoStr = partInfo[0] ? partInfo[0].name : 'Spans multiple parts';
25
+ longestFeatureStr = longestFeature[0] ? longestFeature[0].name : '-';
23
26
  }
24
- infoStr = partInfo[0] ? partInfo[0].name : 'Spans multiple parts';
25
- longestFeatureStr = longestFeature[0] ? longestFeature[0].name : '-';
26
- }
27
- const multipleParts = partInfo.length > 1;
28
- if (multipleParts) {
29
- infoStr = 'Contains multiple parts';
30
- }
31
-
32
- return (
33
- <TableRow sx={sx}>
34
- <TableCell sx={{ maxWidth: 200 }}>
35
- <Typography variant="body2" noWrap title={name}>
36
- {name}
27
+ if (multipleParts) {
28
+ infoStr = 'Contains multiple parts';
29
+ }
30
+
31
+ return {
32
+ id: index,
33
+ name,
34
+ fileName,
35
+ correspondingParts,
36
+ correspondingPartsNames,
37
+ noParts,
38
+ multipleParts,
39
+ infoStr,
40
+ longestFeatureStr,
41
+ rowColor: partInfo.length === 1 ? partInfo[0]?.color : null,
42
+ };
43
+ }), [plasmids]);
44
+
45
+ const rowColorStyles = useMemo(() => {
46
+ const entries = rows
47
+ .filter((r) => r.rowColor)
48
+ .map((r) => [`& .MuiDataGrid-row[data-id="${r.id}"]`, { backgroundColor: `${r.rowColor} !important` }]);
49
+ return Object.fromEntries(entries);
50
+ }, [rows]);
51
+
52
+ const columns = useMemo(() => [
53
+ {
54
+ field: 'name',
55
+ headerName: 'Name',
56
+ width: 200,
57
+ sortable: true,
58
+ renderCell: (params) => (
59
+ <Typography variant="body2" noWrap title={params.value}>
60
+ {params.value}
37
61
  </Typography>
38
- </TableCell>
39
- <TableCell sx={{ maxWidth: 200 }}>
40
- <Typography variant="body2" noWrap title={fileName}>
41
- {fileName}
62
+ ),
63
+ },
64
+ {
65
+ field: 'fileName',
66
+ headerName: 'File Name',
67
+ width: 200,
68
+ sortable: true,
69
+ renderCell: (params) => (
70
+ <Typography variant="body2" noWrap title={params.value}>
71
+ {params.value}
42
72
  </Typography>
43
- </TableCell>
44
- <TableCell sx={multipleParts ? {backgroundColor: 'red'} : null}>
45
- <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
46
- {noParts ? '-' : correspondingParts.map((part, idx) => (
47
- <PartChip key={idx} name={correspondingPartsNames[idx]} overhang={part}
48
- />
49
- ))}
50
- </Box>
51
- </TableCell>
52
- <TableCell>
53
- <Typography variant="body2">{infoStr}</Typography>
54
- </TableCell>
55
- <TableCell>
56
- <Typography variant="body2">{longestFeatureStr}</Typography>
57
- </TableCell>
58
- </TableRow>
59
- )
60
- }
73
+ ),
74
+ },
75
+ {
76
+ field: 'correspondingParts',
77
+ headerName: 'Overhangs',
78
+ width: 250,
79
+ sortable: false,
80
+ renderCell: (params) => {
81
+ const { correspondingPartsNames, noParts } = params.row;
82
+ const parts = params.value ?? [];
83
+ return (
84
+ <Box sx={{
85
+ display: 'flex',
86
+ flexWrap: 'wrap',
87
+ gap: 0.5,
88
+ width: '100%',
89
+ ...(params.row.multipleParts ? { backgroundColor: 'red' } : {}),
90
+ }}
91
+ >
92
+ {noParts ? '-' : parts.map((part, idx) => (
93
+ <PartChip key={idx} name={correspondingPartsNames?.[idx]} overhang={part} />
94
+ ))}
95
+ </Box>
96
+ );
97
+ },
98
+ },
99
+ {
100
+ field: 'infoStr',
101
+ headerName: 'Part Info',
102
+ width: 180,
103
+ sortable: true,
104
+ renderCell: (params) => (
105
+ <Typography variant="body2">{params.value}</Typography>
106
+ ),
107
+ },
108
+ {
109
+ field: 'longestFeatureStr',
110
+ headerName: 'Longest Feature',
111
+ width: 180,
112
+ renderCell: (params) => (
113
+ <Typography variant="body2">{params.value}</Typography>
114
+ ),
115
+ },
116
+ ], []);
61
117
 
62
- function PlasmidSyntaxTable( { plasmids } ) {
63
118
  return (
64
- <Table stickyHeader size="small">
65
- <TableHead sx={{ '& th': { fontWeight: 'bold' } }}>
66
- <TableRow>
67
- <TableCell>Name</TableCell>
68
- <TableCell>File Name</TableCell>
69
- <TableCell>Overhangs</TableCell>
70
- <TableCell>Part Info</TableCell>
71
- <TableCell>Longest Feature</TableCell>
72
- </TableRow>
73
- </TableHead>
74
- <TableBody>
75
- {plasmids.map((plasmid, index) => (
76
- <PlasmidRow key={index} plasmid={plasmid} />
77
- ))}
78
- </TableBody>
79
- </Table>
119
+ <Box sx={{ height: Math.min(rows.length * 36 + 56, maxHeight), minHeight: 120, width: '100%' }}>
120
+ <DataGrid
121
+ rows={rows}
122
+ columns={columns}
123
+ density="compact"
124
+ disableRowSelectionOnClick
125
+ disableColumnFilter
126
+ disableVirtualization
127
+ disableColumnMenu
128
+ hideFooter
129
+ initialState={{
130
+ sorting: {
131
+ sortModel: [{ field: 'name', sort: 'asc' }],
132
+ },
133
+ }}
134
+ sx={{
135
+ '& .MuiDataGrid-cell': {
136
+ fontSize: '0.875rem',
137
+ display: 'flex',
138
+ alignItems: 'center',
139
+ },
140
+ '& .MuiDataGrid-columnHeader': { fontWeight: 'bold' },
141
+ ...rowColorStyles,
142
+ }}
143
+ />
144
+ </Box>
80
145
  )
81
146
  }
82
147
 
@@ -50,7 +50,7 @@ const testConfig = {
50
50
  enablePlannotate: false,
51
51
  };
52
52
 
53
- describe.only('<UploadPlasmidsButton />', () => {
53
+ describe('<UploadPlasmidsButton />', () => {
54
54
  beforeEach(() => {
55
55
  cy.window().then((win) => {
56
56
  win.localStorage.clear();
@@ -58,6 +58,7 @@ describe.only('<UploadPlasmidsButton />', () => {
58
58
  });
59
59
 
60
60
  it('calls addPlasmids with correctly formatted valid plasmid', () => {
61
+ cy.viewport(1200, 800);
61
62
  const addPlasmidsSpy = cy.spy().as('addPlasmidsSpy');
62
63
 
63
64
  cy.mount(
@@ -92,24 +93,24 @@ describe.only('<UploadPlasmidsButton />', () => {
92
93
  cy.get('[data-testid="invalid-plasmids-box"]').contains('Contains multiple parts')
93
94
  cy.get('[data-testid="invalid-plasmids-box"]').contains('locus.gb')
94
95
 
95
- cy.get('[data-testid="valid-plasmids-box"] tr').eq(1).find('td').eq(0).should('contain', 'pYTK002')
96
- cy.get('[data-testid="valid-plasmids-box"] tr').eq(1).find('td').eq(1).should('contain', 'pYTK002.gb')
97
- cy.get('[data-testid="valid-plasmids-box"] tr').eq(1).find('td').eq(2).should('contain', 'CCCT-AACG (CCCT_overhang-AACG_overhang)')
98
- cy.get('[data-testid="valid-plasmids-box"] tr').eq(1).find('td').eq(3).should('contain', '1')
99
- cy.get('[data-testid="valid-plasmids-box"] tr').eq(1).find('td').eq(4).should('contain', 'ConS')
100
- cy.get('[data-testid="valid-plasmids-box"] tr').eq(1).then(($el) => {
96
+ cy.get('[data-testid="valid-plasmids-box"] [role="row"]').eq(1).find('[role="gridcell"]').eq(0).should('contain', 'pYTK002')
97
+ cy.get('[data-testid="valid-plasmids-box"] [role="row"]').eq(1).find('[role="gridcell"]').eq(1).should('contain', 'pYTK002.gb')
98
+ cy.get('[data-testid="valid-plasmids-box"] [role="row"]').eq(1).find('[role="gridcell"]').eq(2).should('contain', 'CCCT-AACG (CCCT_overhang-AACG_overhang)')
99
+ cy.get('[data-testid="valid-plasmids-box"] [role="row"]').eq(1).find('[role="gridcell"]').eq(3).should('contain', '1')
100
+ cy.get('[data-testid="valid-plasmids-box"] [role="row"]').eq(1).find('[role="gridcell"]').eq(4).should('contain', 'ConS')
101
+ cy.get('[data-testid="valid-plasmids-box"] [role="row"]').eq(1).then(($el) => {
101
102
  const bgColor = window.getComputedStyle($el[0]).backgroundColor;
102
103
  cy.wrap(bgColor).should('equal', 'rgb(132, 197, 222)');
103
104
  });
104
105
 
105
- cy.get('[data-testid="valid-plasmids-box"] tr').eq(2).find('td').eq(0).should('contain', 'pYTK095')
106
- cy.get('[data-testid="valid-plasmids-box"] tr').eq(2).find('td').eq(1).should('contain', 'pYTK095.gb')
107
- cy.get('[data-testid="valid-plasmids-box"] tr').eq(2).find('td').eq(2).should('contain', 'TACA-CCCT (TACA-CCCT_overhang)')
108
- cy.get('[data-testid="valid-plasmids-box"] tr').eq(2).find('td').eq(3).should('contain', 'Spans multiple parts')
109
- cy.get('[data-testid="valid-plasmids-box"] tr').eq(2).find('td').eq(4).should('contain', 'AmpR')
106
+ cy.get('[data-testid="valid-plasmids-box"] [role="row"]').eq(3).find('[role="gridcell"]').eq(0).should('contain', 'pYTK095')
107
+ cy.get('[data-testid="valid-plasmids-box"] [role="row"]').eq(3).find('[role="gridcell"]').eq(1).should('contain', 'pYTK095.gb')
108
+ cy.get('[data-testid="valid-plasmids-box"] [role="row"]').eq(3).find('[role="gridcell"]').eq(2).should('contain', 'TACA-CCCT (TACA-CCCT_overhang)')
109
+ cy.get('[data-testid="valid-plasmids-box"] [role="row"]').eq(3).find('[role="gridcell"]').eq(3).should('contain', 'Spans multiple parts')
110
+ cy.get('[data-testid="valid-plasmids-box"] [role="row"]').eq(3).find('[role="gridcell"]').eq(4).should('contain', 'AmpR')
110
111
 
111
112
  // No features
112
- cy.get('[data-testid="valid-plasmids-box"] tr').eq(3).find('td').eq(4).should('contain', '-');
113
+ cy.get('[data-testid="valid-plasmids-box"] [role="row"]').eq(2).find('[role="gridcell"]').eq(4).should('contain', '-');
113
114
 
114
115
  // Click the import button
115
116
  cy.contains('button', 'Import valid plasmids').click();
package/src/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Version placeholder - replaced at publish time via prepack script
2
- export const version = "1.5.3";
2
+ export const version = "1.5.5";