From 4878dae539c280145de92d1c5f666eaafa6c07f2 Mon Sep 17 00:00:00 2001 From: Alexander Platov Date: Fri, 18 Nov 2022 09:45:30 +0300 Subject: [PATCH] Tables support for Markup editor (#2385) Signed-off-by: Alexander Platov --- .../src/components/message/Nodes.svelte | 10 + .../src/components/CollaboratorEditor.svelte | 68 +---- .../src/components/StyledTextBox.svelte | 4 + .../src/components/StyledTextEditor.svelte | 240 +++++++++++++++++- .../src/components/TextEditor.svelte | 40 ++- .../text-editor/src/components/extensions.ts | 63 +++++ packages/theme/styles/_layouts.scss | 1 + packages/theme/styles/prose.scss | 1 + .../ui/src/components/CircleButton.svelte | 2 - .../src/components/AttachmentStyledBox.svelte | 7 +- .../components/issues/edit/EditIssue.svelte | 49 +--- 11 files changed, 366 insertions(+), 119 deletions(-) diff --git a/packages/presentation/src/components/message/Nodes.svelte b/packages/presentation/src/components/message/Nodes.svelte index acd8456c18..3733c2f7a1 100644 --- a/packages/presentation/src/components/message/Nodes.svelte +++ b/packages/presentation/src/components/message/Nodes.svelte @@ -97,6 +97,16 @@ } }} /> + {:else if node.nodeName === 'TABLE'} +
+ {:else if node.nodeName === 'TBODY'} + + {:else if node.nodeName === 'TR'} + + {:else if node.nodeName === 'TH'} + + {:else if node.nodeName === 'TD'} + {:else} Unknown {node.nodeName} {/if} diff --git a/packages/text-editor/src/components/CollaboratorEditor.svelte b/packages/text-editor/src/components/CollaboratorEditor.svelte index 48cb02e443..b73c326714 100644 --- a/packages/text-editor/src/components/CollaboratorEditor.svelte +++ b/packages/text-editor/src/components/CollaboratorEditor.svelte @@ -43,7 +43,7 @@ import CodeBlock from './icons/CodeBlock.svelte' import { calculateDecorations } from './diff/decorations' - import { defaultExtensions, headingLevels } from './extensions' + import { defaultExtensions, headingLevels, mInsertTable } from './extensions' import Header from './icons/Header.svelte' import IconTable from './icons/IconTable.svelte' import Italic from './icons/Italic.svelte' @@ -316,74 +316,12 @@ } function insertTable (event: MouseEvent) { - const tables = [ - { - label: '2x2', - rows: 2, - cols: 2, - header: false - }, - { - label: '3x3', - rows: 3, - cols: 3, - header: false - }, - { - label: '2x1', - rows: 2, - cols: 1, - header: false - }, - { - label: '5x5', - rows: 5, - cols: 5, - header: false - }, - { - label: '1x2', - rows: 1, - cols: 2, - header: false - }, - { - label: 'Headed 2x2', - rows: 2, - cols: 2, - header: true - }, - { - label: 'Headed 3x3', - rows: 3, - cols: 3, - header: true - }, - { - label: 'Headed 2x1', - rows: 2, - cols: 1, - header: true - }, - { - label: 'Headed 5x5', - rows: 5, - cols: 5, - header: true - }, - { - label: 'Headed 1x2', - rows: 1, - cols: 2, - header: true - } - ] showPopup( SelectPopup, { value: [ { id: '#delete', label: presentation.string.Remove }, - ...tables.map((it) => ({ id: it.label, text: it.label })) + ...mInsertTable.map((it) => ({ id: it.label, text: it.label })) ] }, getEventPositionElement(event), @@ -395,7 +333,7 @@ updateFormattingState() return } - const tab = tables.find((it) => it.label === val) + const tab = mInsertTable.find((it) => it.label === val) if (tab) { editor.commands.insertTable({ cols: tab.cols, diff --git a/packages/text-editor/src/components/StyledTextBox.svelte b/packages/text-editor/src/components/StyledTextBox.svelte index 45afc38d49..66b48aa11b 100644 --- a/packages/text-editor/src/components/StyledTextBox.svelte +++ b/packages/text-editor/src/components/StyledTextBox.svelte @@ -22,6 +22,7 @@ export let emphasized: boolean = false export let alwaysEdit: boolean = false export let showButtons: boolean = true + export let showAttach: boolean = false export let buttonSize: IconSize = 'small' export let hideExtraButtons: boolean = false export let maxHeight: 'max' | 'card' | 'limited' | string = 'max' @@ -78,6 +79,7 @@ } +
{ focused = true }} diff --git a/packages/text-editor/src/components/StyledTextEditor.svelte b/packages/text-editor/src/components/StyledTextEditor.svelte index bd2ca7338c..42906fd70b 100644 --- a/packages/text-editor/src/components/StyledTextEditor.svelte +++ b/packages/text-editor/src/components/StyledTextEditor.svelte @@ -13,19 +13,29 @@ // limitations under the License. -->
{#if isFormatting}
+ + + {#if activeModes.has('table')} + + {/if}
{/if}
@@ -259,8 +479,8 @@
{#if showButtons} -
- {#each defActions as a} +
+ {#each defActions.filter((it) => it.hidden === undefined || it.hidden === true) as a} handleAction(a, evt)} /> {/each}
@@ -315,9 +535,5 @@ } } } - .buttons { - display: flex; - align-items: center; - } } diff --git a/packages/text-editor/src/components/TextEditor.svelte b/packages/text-editor/src/components/TextEditor.svelte index 39a8f884c7..42289a5343 100644 --- a/packages/text-editor/src/components/TextEditor.svelte +++ b/packages/text-editor/src/components/TextEditor.svelte @@ -23,6 +23,7 @@ import textEditorPlugin from '../plugin' import { FormatMode } from '../types' import { defaultExtensions } from './extensions' + import { Level } from '@tiptap/extension-heading' export let content: string = '' export let placeholder: IntlString = textEditorPlugin.string.EditorPlaceholder @@ -55,8 +56,8 @@ export function insertText (text: string): void { editor.commands.insertContent(text as HTMLContent) } - export function checkIsActive (formatMode: FormatMode) { - return editor.isActive(formatMode) + export function checkIsActive (formatMode: FormatMode, attributes?: {} | undefined) { + return editor.isActive(formatMode, attributes) } export function toggleBold () { editor.commands.toggleBold() @@ -94,9 +95,41 @@ export function toggleCodeBlock () { editor.commands.toggleCodeBlock() } - let needFocus = false + export function toggleHeading (attributes: { level: Level }) { + editor.commands.toggleHeading(attributes) + } + export function addColumnBefore () { + editor.commands.addColumnBefore() + } + export function addColumnAfter () { + editor.commands.addColumnAfter() + } + export function deleteColumn () { + editor.commands.deleteColumn() + } + export function addRowBefore () { + editor.commands.addRowBefore() + } + export function addRowAfter () { + editor.commands.addRowAfter() + } + export function deleteRow () { + editor.commands.deleteRow() + } + export function deleteTable () { + editor.commands.deleteTable() + } + export function insertTable (options?: { rows?: number; cols?: number; withHeaderRow?: boolean }) { + editor.commands.insertTable({ + cols: options?.cols ?? 2, + rows: options?.rows ?? 1, + withHeaderRow: options?.withHeaderRow + }) + } + let needFocus = false let focused = false + export function focus (): void { needFocus = true } @@ -164,6 +197,7 @@ content = editor.getHTML() isEmpty = editor.isEmpty dispatch('value', content) + dispatch('update', content) }, onSelectionUpdate: () => dispatch('selection-update') }) diff --git a/packages/text-editor/src/components/extensions.ts b/packages/text-editor/src/components/extensions.ts index 2e3172da47..8f83a2ae13 100644 --- a/packages/text-editor/src/components/extensions.ts +++ b/packages/text-editor/src/components/extensions.ts @@ -60,3 +60,66 @@ export const defaultExtensions = [ ...tableExtensions, ...taskListExtensions ] + +export const mInsertTable = [ + { + label: '2x2', + rows: 2, + cols: 2, + header: false + }, + { + label: '3x3', + rows: 3, + cols: 3, + header: false + }, + { + label: '2x1', + rows: 2, + cols: 1, + header: false + }, + { + label: '5x5', + rows: 5, + cols: 5, + header: false + }, + { + label: '1x2', + rows: 1, + cols: 2, + header: false + }, + { + label: 'Headed 2x2', + rows: 2, + cols: 2, + header: true + }, + { + label: 'Headed 3x3', + rows: 3, + cols: 3, + header: true + }, + { + label: 'Headed 2x1', + rows: 2, + cols: 1, + header: true + }, + { + label: 'Headed 5x5', + rows: 5, + cols: 5, + header: true + }, + { + label: 'Headed 1x2', + rows: 1, + cols: 2, + header: true + } +] diff --git a/packages/theme/styles/_layouts.scss b/packages/theme/styles/_layouts.scss index 89ae064916..768813118f 100644 --- a/packages/theme/styles/_layouts.scss +++ b/packages/theme/styles/_layouts.scss @@ -404,6 +404,7 @@ input.search { .mx-3 { margin: 0 .75rem; } .mx-10 { margin: 0 2.5rem; } .mx-auto { margin: 0 auto; } +.my-2 { margin: .5rem 0; } .my-4 { margin: 1rem 0; } .pl-1 { padding-left: .25rem; } diff --git a/packages/theme/styles/prose.scss b/packages/theme/styles/prose.scss index 8a29758812..c68c5b6648 100644 --- a/packages/theme/styles/prose.scss +++ b/packages/theme/styles/prose.scss @@ -24,6 +24,7 @@ table.proseTable { td, th { min-width: 1rem; + height: 2rem; border: 1px solid var(--button-border-hover); padding: .25rem .5rem; vertical-align: top; diff --git a/packages/ui/src/components/CircleButton.svelte b/packages/ui/src/components/CircleButton.svelte index 86f7647cfd..78c2879bac 100644 --- a/packages/ui/src/components/CircleButton.svelte +++ b/packages/ui/src/components/CircleButton.svelte @@ -25,8 +25,6 @@ export let id: string | undefined = undefined -/** eslint-disable a11y-click-events-have-key-events */ -
attach()} /> {#if attachments.size} -
+
{#each Array.from(attachments.values()) as attachment}
.list { padding: 0.5rem; + min-width: 0; color: var(--theme-caption-color); overflow-x: auto; overflow-y: hidden; diff --git a/plugins/tracker-resources/src/components/issues/edit/EditIssue.svelte b/plugins/tracker-resources/src/components/issues/edit/EditIssue.svelte index e645b0256c..dac3348474 100644 --- a/plugins/tracker-resources/src/components/issues/edit/EditIssue.svelte +++ b/plugins/tracker-resources/src/components/issues/edit/EditIssue.svelte @@ -25,7 +25,6 @@ Button, EditBox, getCurrentLocation, - IconAttachment, IconEdit, IconMoreH, Label, @@ -296,30 +295,19 @@
{/if} -
- {#key description} -
- -
- {/key} -
{ - descriptionBox.attach() - }} - > - -
+
+
@@ -422,15 +410,4 @@ height: 1px; background-color: var(--divider-color); } - - .tool { - align-self: start; - width: 20px; - height: 20px; - opacity: 0.3; - cursor: pointer; - &:hover { - opacity: 1; - } - }