diff --git a/src/blocks/Table/TableBlockView.jsx b/src/blocks/Table/TableBlockView.jsx index e796498a..3dd524bd 100644 --- a/src/blocks/Table/TableBlockView.jsx +++ b/src/blocks/Table/TableBlockView.jsx @@ -3,9 +3,11 @@ * @module volto-slate/blocks/Table/View */ -import React, { useMemo } from 'react'; +import React, { useMemo, useState } from 'react'; +import { map } from 'lodash'; +import cx from 'classnames'; import PropTypes from 'prop-types'; -import { withBlockExtensions } from '@plone/volto/helpers'; +import { Table } from 'semantic-ui-react'; import { serializeNodes, serializeNodesToText, @@ -23,6 +25,10 @@ import '../../editor/plugins/Table/less/public.less'; */ const View = (props) => { const { data } = props; + const [state, setState] = useState({ + column: null, + direction: null, + }); const headers = useMemo(() => { return data.table.rows?.[0]?.cells; @@ -52,11 +58,91 @@ const View = (props) => { return items; }, [data.table.rows]); - const Table = props.variation.view; + const sortedRows = useMemo(() => { + if (state.column === null) return Object.keys(rows); + return Object.keys(rows).sort((a, b) => { + const a_text = rows[a][state.column].valueText; + const b_text = rows[b][state.column].valueText; + if (state.direction === 'ascending' ? a_text < b_text : a_text > b_text) { + return -1; + } + if (state.direction === 'ascending' ? a_text > b_text : a_text < b_text) { + return 1; + } + return 0; + }); + }, [state, rows]); return ( <> - {data && data.table && } + {data && data.table && ( +
+ {!data.table.hideHeaders ? ( + + + {headers.map((cell, index) => ( + { + if (!data.table.sortable) return; + setState({ + column: index, + direction: + state.column !== index + ? 'ascending' + : state.direction === 'ascending' + ? 'descending' + : 'ascending', + }); + }} + > + {cell.value && + Node.string({ children: cell.value }).length > 0 + ? serializeNodes(cell.value) + : '\u00A0'} + + ))} + + + ) : ( + '' + )} + + {map(sortedRows, (row) => ( + + {map(rows[row], (cell, cellIndex) => ( + + {cell.value} + + ))} + + ))} + +
+ )} ); }; @@ -70,4 +156,4 @@ View.propTypes = { data: PropTypes.objectOf(PropTypes.any).isRequired, }; -export default withBlockExtensions(View); +export default View; diff --git a/src/blocks/Table/index.js b/src/blocks/Table/index.js index b0e6ad52..c8c796e5 100644 --- a/src/blocks/Table/index.js +++ b/src/blocks/Table/index.js @@ -3,7 +3,6 @@ import TableBlockEdit from './TableBlockEdit'; import TableBlockView from './TableBlockView'; import { extractTables } from './deconstruct'; import { normalizeTable } from './extensions/normalizeTable'; -import TableVariations from './variations'; /** * @summary Called from Volto to configure new or existing Volto block types. @@ -39,7 +38,6 @@ export default function install(config) { mostUsed: false, blockHasOwnFocusManagement: true, sidebarTab: 1, - variations: TableVariations, security: { addPermission: [], view: [], diff --git a/src/blocks/Table/schema.js b/src/blocks/Table/schema.js index 43153b99..e469fcf3 100644 --- a/src/blocks/Table/schema.js +++ b/src/blocks/Table/schema.js @@ -5,6 +5,10 @@ const messages = defineMessages({ id: 'Hide headers', defaultMessage: 'Hide headers', }, + responsive: { + id: 'Responsive', + defaultMessage: 'Responsive', + }, sortable: { id: 'Make the table sortable', defaultMessage: 'Make the table sortable', @@ -83,6 +87,7 @@ export default (props) => { fields: [ 'hideHeaders', 'sortable', + 'responsive', 'fixed', 'celled', 'striped', @@ -104,6 +109,10 @@ export default (props) => { description: 'Visible only in view mode', type: 'boolean', }, + responsive: { + title: intl.formatMessage(messages.responsive), + type: 'boolean', + }, fixed: { title: intl.formatMessage(messages.fixed), type: 'boolean', diff --git a/src/blocks/Table/variations/DefaultTable.jsx b/src/blocks/Table/variations/DefaultTable.jsx deleted file mode 100644 index 9b19564c..00000000 --- a/src/blocks/Table/variations/DefaultTable.jsx +++ /dev/null @@ -1,90 +0,0 @@ -import React, { useState, useMemo } from 'react'; -import { map } from 'lodash'; -import { Table } from 'semantic-ui-react'; -import { serializeNodes } from 'volto-slate/editor/render'; -import { Node } from 'slate'; - -const DefaultTable = ({ data, headers, rows }) => { - const [state, setState] = useState({ - column: null, - direction: null, - }); - - const sortedRows = useMemo(() => { - if (state.column === null) return Object.keys(rows); - return Object.keys(rows).sort((a, b) => { - const a_text = rows[a][state.column].valueText; - const b_text = rows[b][state.column].valueText; - if (state.direction === 'ascending' ? a_text < b_text : a_text > b_text) { - return -1; - } - if (state.direction === 'ascending' ? a_text > b_text : a_text < b_text) { - return 1; - } - return 0; - }); - }, [state, rows]); - - return ( - - {!data.table.hideHeaders ? ( - - - {headers.map((cell, index) => ( - { - if (!data.table.sortable) return; - setState({ - column: index, - direction: - state.column !== index - ? 'ascending' - : state.direction === 'ascending' - ? 'descending' - : 'ascending', - }); - }} - > - {cell.value && Node.string({ children: cell.value }).length > 0 - ? serializeNodes(cell.value) - : '\u00A0'} - - ))} - - - ) : ( - '' - )} - - {map(sortedRows, (row) => ( - - {map(rows[row], (cell) => ( - - {cell.value} - - ))} - - ))} - -
- ); -}; - -export default DefaultTable; diff --git a/src/blocks/Table/variations/ResponsiveTable.jsx b/src/blocks/Table/variations/ResponsiveTable.jsx deleted file mode 100644 index defbb26b..00000000 --- a/src/blocks/Table/variations/ResponsiveTable.jsx +++ /dev/null @@ -1,94 +0,0 @@ -import React, { useState, useMemo } from 'react'; -import { map } from 'lodash'; -import { Table } from 'semantic-ui-react'; -import { - serializeNodes, - serializeNodesToText, -} from 'volto-slate/editor/render'; -import { Node } from 'slate'; - -const ResponsiveTable = ({ data, headers, rows }) => { - const [state, setState] = useState({ - column: null, - direction: null, - }); - - const sortedRows = useMemo(() => { - if (state.column === null) return Object.keys(rows); - return Object.keys(rows).sort((a, b) => { - const a_text = rows[a][state.column].valueText; - const b_text = rows[b][state.column].valueText; - if (state.direction === 'ascending' ? a_text < b_text : a_text > b_text) { - return -1; - } - if (state.direction === 'ascending' ? a_text > b_text : a_text < b_text) { - return 1; - } - return 0; - }); - }, [state, rows]); - - return ( - - {!data.table.hideHeaders ? ( - - - {headers.map((cell, index) => ( - { - if (!data.table.sortable) return; - setState({ - column: index, - direction: - state.column !== index - ? 'ascending' - : state.direction === 'ascending' - ? 'descending' - : 'ascending', - }); - }} - > - {cell.value && Node.string({ children: cell.value }).length > 0 - ? serializeNodes(cell.value) - : '\u00A0'} - - ))} - - - ) : ( - '' - )} - - {map(sortedRows, (row) => ( - - {map(rows[row], (cell, cellIndex) => ( - - {cell.value} - - ))} - - ))} - -
- ); -}; - -export default ResponsiveTable; diff --git a/src/blocks/Table/variations/index.js b/src/blocks/Table/variations/index.js deleted file mode 100644 index 7f183f3d..00000000 --- a/src/blocks/Table/variations/index.js +++ /dev/null @@ -1,16 +0,0 @@ -import DefaultTable from './DefaultTable'; -import ResponsiveTable from './ResponsiveTable'; - -export default [ - { - id: 'default', - title: 'Table (default)', - view: DefaultTable, - isDefault: true, - }, - { - id: 'testimonial', - title: 'Responsive table', - view: ResponsiveTable, - }, -];