Skip to content

Commit

Permalink
Merge pull request #6540 from nextcloud/table-tweaks
Browse files Browse the repository at this point in the history
feat(table): add row, column buttons outside of table
  • Loading branch information
mejo- authored Nov 13, 2024
2 parents 002dcc0 + 32a41b4 commit 01c6b2f
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 37 deletions.
42 changes: 42 additions & 0 deletions cypress/e2e/nodes/Table.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,48 @@ describe('table plugin', () => {
expect($el.get(0).innerHTML).to.equal(multilinesContent.replace(/\n/g, '<br>'))
})
})

it('Button add row below', () => {
cy.getActionEntry('table').click()

cy.getContent()
.find('table tr')
.should('have.length', 3)

cy.getContent()
.find('.table-wrapper .table-add-row')
.should('be.visible')

cy.getContent()
.find('.table-wrapper .table-add-row')
.click()

// Added a row
cy.getContent()
.find('table tr')
.should('have.length', 4)
})

it('Button add column after', () => {
cy.getActionEntry('table').click()

cy.getContent()
.find('table tr')
.should('have.length', 3)

cy.getContent()
.find('.table-wrapper .table-add-column')
.should('be.visible')

cy.getContent()
.find('.table-wrapper .table-add-column')
.click()

// Added a column
cy.getContent()
.find('table tr th')
.should('have.length', 4)
})
})

describe('Table extension integrated in the editor', () => {
Expand Down
4 changes: 2 additions & 2 deletions src/css/prosemirror.scss
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,10 @@ div.ProseMirror {

table {
border-spacing: 0;
width: calc(100% - 50px);
width: calc(100% - 50px - var(--default-clickable-area));
table-layout: auto;
white-space: normal; // force text to wrapping
margin-bottom: 1em;
margin-bottom: calc(var(--clickable-area-small) + var(--default-clickable-area));
&+ * {
margin-top: 1em;
}
Expand Down
12 changes: 12 additions & 0 deletions src/nodes/Table/TableCell.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { TableCell } from '@tiptap/extension-table-cell'
import { Plugin } from '@tiptap/pm/state'
import { Fragment } from '@tiptap/pm/model'
import { mergeAttributes } from '@tiptap/core'

export default TableCell.extend({
content: 'inline*',
Expand Down Expand Up @@ -58,6 +59,17 @@ export default TableCell.extend({
}
},

renderHTML({ HTMLAttributes }) {
const attributes = mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)
if (attributes.colspan === 1) {
delete attributes.colspan
}
if (attributes.rowspan === 1) {
delete attributes.rowspan
}
return ['td', attributes, 0]
},

addProseMirrorPlugins() {
return [
new Plugin({
Expand Down
12 changes: 12 additions & 0 deletions src/nodes/Table/TableHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

import { TableHeader } from '@tiptap/extension-table-header'
import { mergeAttributes } from '@tiptap/core'

export default TableHeader.extend({
content: 'inline*',
Expand Down Expand Up @@ -39,6 +40,17 @@ export default TableHeader.extend({
]
},

renderHTML({ HTMLAttributes }) {
const attributes = mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)
if (attributes.colspan === 1) {
delete attributes.colspan
}
if (attributes.rowspan === 1) {
delete attributes.rowspan
}
return ['th', attributes, 0]
},

addAttributes() {
return {
...this.parent?.(),
Expand Down
117 changes: 102 additions & 15 deletions src/nodes/Table/TableView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
-->

<template>
<NodeViewWrapper data-text-el="table-view" class="table-wrapper">
<NodeViewWrapper data-text-el="table-view" class="table-wrapper" :class="{ 'focused': isFocused }">
<NcActions v-if="isEditable"
force-menu
data-text-table-actions="settings"
Expand All @@ -22,20 +22,41 @@
</NcActionButton>
</NcActions>
<NodeViewContent class="content" as="table" />
<NcButton v-if="isEditable"
class="table-add-column"
:aria-label="t('text', 'Add column after')"
:title="t('text', 'Add column after')"
@click="addColumnAfter">
<template #icon>
<TableAddColumnAfter />
</template>
</NcButton>
<NcButton v-if="isEditable"
class="table-add-row"
:aria-label="t('text', 'Add row below')"
:title="t('text', 'Add row below')"
@click="addRowAfter">
<template #icon>
<TableAddRowAfter />
</template>
</NcButton>
<div class="clearfix" />
</NodeViewWrapper>
</template>

<script>
import { NodeViewWrapper, NodeViewContent } from '@tiptap/vue-2'
import { NcActions, NcActionButton } from '@nextcloud/vue'
import { TableSettings, Delete } from '../../components/icons.js'
import { NcActions, NcActionButton, NcButton } from '@nextcloud/vue'
import { TableSettings, Delete, TableAddColumnAfter, TableAddRowAfter } from '../../components/icons.js'

export default {
name: 'TableView',
components: {
TableAddColumnAfter,
TableAddRowAfter,
NcActionButton,
NcActions,
NcButton,
NodeViewWrapper,
NodeViewContent,
TableSettings,
Expand All @@ -50,25 +71,103 @@ export default {
type: Function,
required: true,
},
node: {
type: Object,
required: true,
},
},
data() {
return {
isEditable: false,
isFocused: false,
}
},
beforeMount() {
this.isEditable = this.editor.isEditable
this.editor.on('selectionUpdate', ({ editor }) => {
const startOfCurrentNode = this.getPos()
const endOfCurrentNode = startOfCurrentNode + this.node.nodeSize
const { from, to } = editor.state.selection
this.isFocused = from >= startOfCurrentNode && to <= endOfCurrentNode
})
this.editor.on('update', ({ editor }) => {
this.isEditable = editor.isEditable
})
},
methods: {
addColumnAfter() {
const headerRowNode = this.node.firstChild
this.editor.chain()
.focus()
.setTextSelection(this.getPos() + headerRowNode.nodeSize - 1)
.addColumnAfter()
.setTextSelection(this.getPos() + headerRowNode.nodeSize)
.run()
},
addRowAfter() {
const lastRowNode = this.node.lastChild
this.editor.chain()
.focus()
.setTextSelection(this.getPos() + this.node.nodeSize - lastRowNode.nodeSize + 1)
.addRowAfter()
.setTextSelection(this.getPos() + this.node.nodeSize + 1)
.run()
},
},
}
</script>

<style scoped lang="scss">
.table-wrapper {
position: relative;
overflow-x: auto;

&.focused, &:hover {
.table-add-column, .table-add-row {
visibility: visible;
}
}

.table-settings {
padding-left: 3px;
opacity: .5;
position: absolute;
top: 0;
right: var(--default-clickable-area);

&:hover {
opacity: 1;
}
}

.table-add-column {
visibility: hidden;
padding-left: 3px;
opacity: .5;
position: absolute;
top: var(--default-clickable-area);
right: 0;
bottom: 60px;
margin-top: 0 !important;

&:hover {
opacity: 1;
}
}

.table-add-row {
visibility: hidden;
padding-left: 3px;
opacity: .5;
position: absolute;
left: 0;
bottom: 12px;
width: calc(100% - 80px) !important;

&:hover {
opacity: 1;
}
}
}

.clearfix {
Expand All @@ -78,16 +177,4 @@ export default {
table {
float: left;
}

.table-settings {
padding-left: 3px;
opacity: .5;
position: absolute;
top: 0;
right: 3px;

&:hover {
opacity: 1;
}
}
</style>
40 changes: 20 additions & 20 deletions src/tests/fixtures/tables/handbook/handbook.out.html
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
<div class="table-wrapper" style="overflow-x: auto;">
<table>
<tr>
<th colspan="1" rowspan="1"><strong>Heading 0</strong></th>
<th colspan="1" rowspan="1"><strong>Heading 1</strong></th>
<th colspan="1" rowspan="1"><strong>Heading 2</strong></th>
<th colspan="1" rowspan="1"><strong>Heading 3</strong></th>
<th colspan="1" rowspan="1"><strong>Heading 4</strong></th>
<th><strong>Heading 0</strong></th>
<th><strong>Heading 1</strong></th>
<th><strong>Heading 2</strong></th>
<th><strong>Heading 3</strong></th>
<th><strong>Heading 4</strong></th>
</tr>
<tr>
<td colspan="1" rowspan="1"><strong>Letter</strong></td>
<td colspan="1" rowspan="1">a</td>
<td colspan="1" rowspan="1">b</td>
<td colspan="1" rowspan="1">c</td>
<td colspan="1" rowspan="1">d</td>
<td><strong>Letter</strong></td>
<td>a</td>
<td>b</td>
<td>c</td>
<td>d</td>
</tr>
<tr>
<td colspan="1" rowspan="1"><strong>Number</strong></td>
<td colspan="1" rowspan="1">1</td>
<td colspan="1" rowspan="1">2</td>
<td colspan="1" rowspan="1">3</td>
<td colspan="1" rowspan="1">4</td>
<td><strong>Number</strong></td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td colspan="1" rowspan="1"><strong>Square</strong></td>
<td colspan="1" rowspan="1">1</td>
<td colspan="1" rowspan="1">4</td>
<td colspan="1" rowspan="1">9</td>
<td colspan="1" rowspan="1">16</td>
<td><strong>Square</strong></td>
<td>1</td>
<td>4</td>
<td>9</td>
<td>16</td>
</tr>
</table>
</div>
Expand Down

0 comments on commit 01c6b2f

Please sign in to comment.