From 335ffdca1279a101d0783a8abd704ea83110317d Mon Sep 17 00:00:00 2001 From: chris <kokosias@yahoo.gr> Date: Sun, 9 Aug 2020 01:57:46 +0300 Subject: [PATCH] allow table operations --- .../src/components/Button.js | 1 + .../src/components/HeadingsDropDown.js | 21 ++--- .../src/components/ImageUpload.js | 5 +- .../src/components/TableDropDown.js | 40 +++++----- .../src/components/comments/Comment.js | 3 +- .../src/components/comments/CommentBox.js | 3 +- .../comments/CommentBubbleComponent.js | 10 +-- .../src/components/link/LinkComponent.js | 77 ++++++++++--------- .../src/components/notes/NoteNumber.js | 5 +- .../src/components/rightArea/BoxList.js | 1 + .../src/components/rightArea/RightArea.js | 9 +-- .../components/trackChanges/TrackChangeBox.js | 38 +++++---- .../trackChanges/TrackChangeEnable.js | 1 + .../EditTableService/TableDropDownOptions.js | 24 +++--- .../TablesService/InsertTableService/Table.js | 10 +-- .../track-changes/trackedTransaction.js | 10 +++ wax-prosemirror-themes/package.json | 2 +- wax-prosemirror-utilities/package.json | 2 +- 18 files changed, 142 insertions(+), 120 deletions(-) diff --git a/wax-prosemirror-components/src/components/Button.js b/wax-prosemirror-components/src/components/Button.js index cb1049cca..85cf9df09 100644 --- a/wax-prosemirror-components/src/components/Button.js +++ b/wax-prosemirror-components/src/components/Button.js @@ -1,3 +1,4 @@ +/* eslint react/prop-types: 0 */ import React, { useContext } from 'react'; import styled from 'styled-components'; import { ButtonStyles } from 'wax-prosemirror-themes'; diff --git a/wax-prosemirror-components/src/components/HeadingsDropDown.js b/wax-prosemirror-components/src/components/HeadingsDropDown.js index d4fdcaea7..18d1a5712 100644 --- a/wax-prosemirror-components/src/components/HeadingsDropDown.js +++ b/wax-prosemirror-components/src/components/HeadingsDropDown.js @@ -1,20 +1,21 @@ -import React from "react"; -import styled from "styled-components"; -import { Commands } from "wax-prosemirror-utilities"; -import Dropdown from "react-dropdown"; -import "react-dropdown/style.css"; +/* eslint react/prop-types: 0 */ +import React from 'react'; +import styled from 'styled-components'; +import { Commands } from 'wax-prosemirror-utilities'; +import Dropdown from 'react-dropdown'; +import 'react-dropdown/style.css'; const DropdownStyled = styled(Dropdown)` - display: ${props => (props.select ? "inline-flex" : "none")}; + display: ${props => (props.select ? 'inline-flex' : 'none')}; .Dropdown-control { border: none; } `; const dropDownOptions = [ - { label: "Heading 1", value: "1" }, - { label: "Heading 2", value: "2" }, - { label: "Heading 3", value: "3" } + { label: 'Heading 1', value: '1' }, + { label: 'Heading 2', value: '2' }, + { label: 'Heading 3', value: '3' }, ]; const HeadingsDropDown = ({ dispatch, state, item }) => ( @@ -22,7 +23,7 @@ const HeadingsDropDown = ({ dispatch, state, item }) => ( options={dropDownOptions} onChange={option => { Commands.setBlockType(state.config.schema.nodes.heading, { - level: option.value + level: option.value, })(state, dispatch); }} placeholder="Choose heading" diff --git a/wax-prosemirror-components/src/components/ImageUpload.js b/wax-prosemirror-components/src/components/ImageUpload.js index a82798f32..5858b097b 100644 --- a/wax-prosemirror-components/src/components/ImageUpload.js +++ b/wax-prosemirror-components/src/components/ImageUpload.js @@ -1,5 +1,6 @@ -import React from "react"; -import styled from "styled-components"; +/* eslint react/prop-types: 0 */ +import React from 'react'; +import styled from 'styled-components'; const UploadImage = styled.div` color: #777; diff --git a/wax-prosemirror-components/src/components/TableDropDown.js b/wax-prosemirror-components/src/components/TableDropDown.js index 950c1a53e..72c1f5d69 100644 --- a/wax-prosemirror-components/src/components/TableDropDown.js +++ b/wax-prosemirror-components/src/components/TableDropDown.js @@ -1,14 +1,15 @@ -import React from "react"; -import styled from "styled-components"; -import * as tablesFn from "prosemirror-tables"; -import Dropdown from "react-dropdown"; -import "react-dropdown/style.css"; +/* eslint react/prop-types: 0 */ +import React from 'react'; +import styled from 'styled-components'; +import * as tablesFn from 'prosemirror-tables'; +import Dropdown from 'react-dropdown'; +import 'react-dropdown/style.css'; const DropdownStyled = styled(Dropdown)` display: inline-flex; cursor: not-allowed; opacity: ${props => (props.select ? 1 : 0.4)}; - pointer-events: ${props => (props.select ? "default" : "none")}; + pointer-events: ${props => (props.select ? 'default' : 'none')}; .Dropdown-control { border: none; } @@ -28,28 +29,29 @@ const DropdownStyled = styled(Dropdown)` `; const dropDownOptions = [ - { label: "add column before", value: "addColumnBefore" }, - { label: "add column after", value: "addColumnAfter" }, - { label: "Delete column", value: "deleteColumn" }, - { label: "Insert row before", value: "addRowBefore" }, - { label: "Insert row after", value: "addRowAfter" }, - { label: "Delete row", value: "deleteRow" }, - { label: "Delete table", value: "deleteTable" }, - { label: "Merge cells", value: "mergeCells" }, - { label: "Split cell", value: "splitCell" }, - { label: "Toggle header column", value: "toggleHeaderColumn" }, - { label: "Toggle header row", value: "toggleHeaderRow" }, - { label: "Toggle header cells", value: "toggleHeaderCell" } + { label: 'add column before', value: 'addColumnBefore' }, + { label: 'add column after', value: 'addColumnAfter' }, + { label: 'Delete column', value: 'deleteColumn' }, + { label: 'Insert row before', value: 'addRowBefore' }, + { label: 'Insert row after', value: 'addRowAfter' }, + { label: 'Delete row', value: 'deleteRow' }, + { label: 'Delete table', value: 'deleteTable' }, + { label: 'Merge cells', value: 'mergeCells' }, + { label: 'Split cell', value: 'splitCell' }, + { label: 'Toggle header column', value: 'toggleHeaderColumn' }, + { label: 'Toggle header row', value: 'toggleHeaderRow' }, + { label: 'Toggle header cells', value: 'toggleHeaderCell' }, ]; const TableDropDown = ({ view: { dispatch, state }, item }) => ( <DropdownStyled options={dropDownOptions} onChange={option => { - tablesFn[option.value](state, dispatch); + item.run(state, dispatch, tablesFn[option.value]); }} placeholder="Table Options" select={item.select && item.select(state)} /> ); + export default TableDropDown; diff --git a/wax-prosemirror-components/src/components/comments/Comment.js b/wax-prosemirror-components/src/components/comments/Comment.js index 6845cc58a..c215af8c8 100644 --- a/wax-prosemirror-components/src/components/comments/Comment.js +++ b/wax-prosemirror-components/src/components/comments/Comment.js @@ -1,3 +1,4 @@ +/* eslint react/prop-types: 0 */ import React, { useState, useRef, useEffect } from 'react'; import { v4 as uuidv4 } from 'uuid'; import { last } from 'lodash'; @@ -43,7 +44,7 @@ export default ({ comment, activeView, user, active }) => { const { current: { value }, } = commentInput; - const { tr, doc } = state; + const { tr } = state; const obj = { content: value, diff --git a/wax-prosemirror-components/src/components/comments/CommentBox.js b/wax-prosemirror-components/src/components/comments/CommentBox.js index d77ee8032..05b730cb2 100644 --- a/wax-prosemirror-components/src/components/comments/CommentBox.js +++ b/wax-prosemirror-components/src/components/comments/CommentBox.js @@ -1,3 +1,4 @@ +/* eslint react/prop-types: 0 */ import React, { useState, useEffect, useContext, memo } from 'react'; import { TextSelection } from 'prosemirror-state'; import { last, maxBy } from 'lodash'; @@ -27,12 +28,12 @@ const CommentBoxStyled = styled.div` return 0.6; case 'entered': return 1; + default: } }}; `; export default ({ comment, top, dataBox }) => { - console.log('rerender'); const [animate, setAnimate] = useState(false); const { attrs: { id }, diff --git a/wax-prosemirror-components/src/components/comments/CommentBubbleComponent.js b/wax-prosemirror-components/src/components/comments/CommentBubbleComponent.js index 1c8b2fcd0..79b2a117e 100644 --- a/wax-prosemirror-components/src/components/comments/CommentBubbleComponent.js +++ b/wax-prosemirror-components/src/components/comments/CommentBubbleComponent.js @@ -1,5 +1,5 @@ -import React, { useLayoutEffect, useState, useContext } from 'react'; -import styled from 'styled-components'; +/* eslint react/prop-types: 0 */ +import React, { useLayoutEffect, useContext } from 'react'; import { Commands, DocumentHelpers } from 'wax-prosemirror-utilities'; import { WaxContext } from 'wax-prosemirror-core'; @@ -32,12 +32,8 @@ const CommentBubbleComponent = ({ const isSelectionComment = () => { const commentMark = activeView.state.schema.marks.comment; const mark = DocumentHelpers.findMark(state, commentMark, true); - const { - selection: { $from, $to }, - doc, - } = state; - //TODO Overlapping comments . for now don't allow + // TODO Overlapping comments . for now don't allow if (mark.length >= 1) return true; return false; }; diff --git a/wax-prosemirror-components/src/components/link/LinkComponent.js b/wax-prosemirror-components/src/components/link/LinkComponent.js index 7fc43a202..8c4b32a8d 100644 --- a/wax-prosemirror-components/src/components/link/LinkComponent.js +++ b/wax-prosemirror-components/src/components/link/LinkComponent.js @@ -1,7 +1,8 @@ -import React, { useRef, useEffect, useState, useContext } from "react"; -import styled from "styled-components"; -import { WaxContext } from "wax-prosemirror-core"; -import { DocumentHelpers } from "wax-prosemirror-utilities"; +/* eslint react/prop-types: 0 */ +import React, { useRef, useEffect, useState, useContext } from 'react'; +import styled from 'styled-components'; +import { WaxContext } from 'wax-prosemirror-core'; +import { DocumentHelpers } from 'wax-prosemirror-utilities'; const LinkWrapper = styled.div` padding: 20px; @@ -19,25 +20,23 @@ const Button = styled.button` `; const LinkComponent = ({ mark, setPosition, position }) => { - const href = mark ? mark.attrs.href : null, - linkMark = mark ? mark : null, - { view: { main }, activeView } = useContext(WaxContext), - { state, dispatch } = activeView, - ref = useRef(null), - linkInput = useRef(null), - [addButtonText, setButtonText] = useState("Create"), - [lastLinkMark, setLLastLinkMark] = useState(linkMark), - [linkHref, setLinkHref] = useState(href); + const href = mark ? mark.attrs.href : null; + const linkMark = mark ? mark : null; + const { + view: { main }, + activeView, + } = useContext(WaxContext); + const { state, dispatch } = activeView; + const ref = useRef(null); + const linkInput = useRef(null); + const [addButtonText, setButtonText] = useState('Create'); + const [lastLinkMark, setLLastLinkMark] = useState(linkMark); + const [linkHref, setLinkHref] = useState(href); - useEffect( - () => { - const width = ref.current ? ref.current.offsetWidth : 0; - const left = Math.abs(position.left - width / 2); - setLinkText(); - removeMarkIfEmptyHref(); - }, - [ref.current, href] - ); + useEffect(() => { + setLinkText(); + removeMarkIfEmptyHref(); + }, [ref.current, href]); const addLinkHref = () => { const href = linkHref; @@ -50,9 +49,9 @@ const LinkComponent = ({ mark, setPosition, position }) => { mark.to, linkMark.create({ ...((mark && mark.attrs) || {}), - href - }) - ) + href, + }), + ), ); activeView.focus(); }; @@ -63,45 +62,49 @@ const LinkComponent = ({ mark, setPosition, position }) => { }; const handleKeyDown = event => { - if (event.key === "Enter" || event.which === 13) { + if (event.key === 'Enter' || event.which === 13) { addLinkHref(); } }; const updateLinkHref = () => { - const { current: { value } } = linkInput; + const { + current: { value }, + } = linkInput; setLinkHref(value); }; const setLinkText = () => { - if (mark && mark.attrs.href !== "") { - setButtonText("Update"); + if (mark && mark.attrs.href !== '') { + setButtonText('Update'); setLinkHref(mark.attrs.href); } else { - setButtonText("Create"); - setLinkHref(""); + setButtonText('Create'); + setLinkHref(''); if (linkInput.current) linkInput.current.focus(); } }; const removeMarkIfEmptyHref = () => { - const { selection: { $from, $to } } = state; - const PMLinkMark = state.schema.marks["link"]; + const { + selection: { $from, $to }, + } = state; + const PMLinkMark = state.schema.marks['link']; const actualMark = DocumentHelpers.getSelectionMark(state, PMLinkMark); setLLastLinkMark(actualMark); if ( - lastLinkMark.attrs.href === "" && + lastLinkMark.attrs.href === '' && ($from.pos < lastLinkMark.from || $to.pos > lastLinkMark.to) ) { dispatch( state.tr - .setMeta("addToHistory", false) + .setMeta('addToHistory', false) .removeMark( lastLinkMark.from, lastLinkMark.to, - state.schema.marks.link - ) + state.schema.marks.link, + ), ); } }; diff --git a/wax-prosemirror-components/src/components/notes/NoteNumber.js b/wax-prosemirror-components/src/components/notes/NoteNumber.js index aa79ea8c7..3341978ed 100644 --- a/wax-prosemirror-components/src/components/notes/NoteNumber.js +++ b/wax-prosemirror-components/src/components/notes/NoteNumber.js @@ -1,5 +1,6 @@ -import React from "react"; -import styled from "styled-components"; +/* eslint react/prop-types: 0 */ +import React from 'react'; +import styled from 'styled-components'; const NoteNumberStyled = styled.div` display: flex; diff --git a/wax-prosemirror-components/src/components/rightArea/BoxList.js b/wax-prosemirror-components/src/components/rightArea/BoxList.js index 10d1d454d..23e2ab47a 100644 --- a/wax-prosemirror-components/src/components/rightArea/BoxList.js +++ b/wax-prosemirror-components/src/components/rightArea/BoxList.js @@ -1,3 +1,4 @@ +/* eslint react/prop-types: 0 */ import { Mark } from 'prosemirror-model'; import React from 'react'; import CommentBox from '../comments/CommentBox'; diff --git a/wax-prosemirror-components/src/components/rightArea/RightArea.js b/wax-prosemirror-components/src/components/rightArea/RightArea.js index a11ecbbb7..b66fa208e 100644 --- a/wax-prosemirror-components/src/components/rightArea/RightArea.js +++ b/wax-prosemirror-components/src/components/rightArea/RightArea.js @@ -1,11 +1,6 @@ +/* eslint react/prop-types: 0 */ import { Mark } from 'prosemirror-model'; -import React, { - useContext, - useState, - useEffect, - useMemo, - useCallback, -} from 'react'; +import React, { useContext, useState, useMemo, useCallback } from 'react'; import useDeepCompareEffect from 'use-deep-compare-effect'; import { each, uniqBy, sortBy } from 'lodash'; import { WaxContext } from 'wax-prosemirror-core'; diff --git a/wax-prosemirror-components/src/components/trackChanges/TrackChangeBox.js b/wax-prosemirror-components/src/components/trackChanges/TrackChangeBox.js index d2ec7235f..b81aa5ec4 100644 --- a/wax-prosemirror-components/src/components/trackChanges/TrackChangeBox.js +++ b/wax-prosemirror-components/src/components/trackChanges/TrackChangeBox.js @@ -1,8 +1,9 @@ -import { Mark } from "prosemirror-model"; -import React, { Fragment, useState, useEffect, useContext } from "react"; -import { Transition } from "react-transition-group"; -import styled from "styled-components"; -import { WaxContext } from "wax-prosemirror-core"; +/* eslint react/prop-types: 0 */ +import { Mark } from 'prosemirror-model'; +import React, { useState, useEffect, useContext } from 'react'; +import { Transition } from 'react-transition-group'; +import styled from 'styled-components'; +import { WaxContext } from 'wax-prosemirror-core'; const TrackChangeBoxStyled = styled.div` display: flex; @@ -10,30 +11,37 @@ const TrackChangeBoxStyled = styled.div` margin-top: 10px; border: 1px solid blue; position: absolute; - transition: ${({ state }) => "top 1s, opacity 1.5s, left 1s"}; + transition: ${({ state }) => 'top 1s, opacity 1.5s, left 1s'}; top: ${props => (props.top ? `${props.top}px` : 0)}; left: ${props => (props.active ? `${63}%` : `${65}%`)}; opacity: ${({ state }) => { switch (state) { - case "exited": + case 'exited': return 0.2; - case "exiting": + case 'exiting': return 0.4; - case "entering": + case 'entering': return 0.6; - case "entered": + case 'entered': return 1; + default: } }}; `; export default ({ trackChange, view, top, dataBox }) => { const [animate, setAnimate] = useState(false); - const { view: { main }, app, activeView } = useContext(WaxContext); + const { + view: { main }, + app, + activeView, + } = useContext(WaxContext); let action; if (trackChange instanceof Mark) { - if ((trackChange.type.name = "format_change")) { - const { attrs: { username, before, after } } = trackChange; + if ((trackChange.type.name = 'format_change')) { + const { + attrs: { username, before, after }, + } = trackChange; action = `User ${username} added ${after[0]}`; } } else { @@ -46,7 +54,7 @@ export default ({ trackChange, view, top, dataBox }) => { }, []); return ( - <Fragment> + <> <Transition in={animate} timeout={1000}> {state => ( <TrackChangeBoxStyled @@ -63,6 +71,6 @@ export default ({ trackChange, view, top, dataBox }) => { </TrackChangeBoxStyled> )} </Transition> - </Fragment> + </> ); }; diff --git a/wax-prosemirror-components/src/components/trackChanges/TrackChangeEnable.js b/wax-prosemirror-components/src/components/trackChanges/TrackChangeEnable.js index 4966c9841..742f9a9b0 100644 --- a/wax-prosemirror-components/src/components/trackChanges/TrackChangeEnable.js +++ b/wax-prosemirror-components/src/components/trackChanges/TrackChangeEnable.js @@ -1,3 +1,4 @@ +/* eslint react/prop-types: 0 */ import React, { useContext, useState } from 'react'; import styled from 'styled-components'; import { ButtonStyles } from 'wax-prosemirror-themes'; diff --git a/wax-prosemirror-services/src/TablesService/EditTableService/TableDropDownOptions.js b/wax-prosemirror-services/src/TablesService/EditTableService/TableDropDownOptions.js index c08f229bb..d48701582 100644 --- a/wax-prosemirror-services/src/TablesService/EditTableService/TableDropDownOptions.js +++ b/wax-prosemirror-services/src/TablesService/EditTableService/TableDropDownOptions.js @@ -1,20 +1,20 @@ -import React from "react"; -import { v4 as uuidv4 } from "uuid"; -import { injectable } from "inversify"; -import { isEmpty } from "lodash"; -import { TableDropDown } from "wax-prosemirror-components"; -import { addColumnBefore } from "prosemirror-tables"; -import { Commands } from "wax-prosemirror-utilities"; -import Tools from "../../lib/Tools"; +import React from 'react'; +import { v4 as uuidv4 } from 'uuid'; +import { injectable } from 'inversify'; +import { isEmpty } from 'lodash'; +import { TableDropDown } from 'wax-prosemirror-components'; +import { addColumnBefore } from 'prosemirror-tables'; +import { Commands } from 'wax-prosemirror-utilities'; +import Tools from '../../lib/Tools'; @injectable() export default class TableDropDownOptions extends Tools { - title = "Select Options"; - content = "table"; + title = 'Select Options'; + content = 'table'; get run() { - return () => { - return true; + return (state, dispatch, tableFn) => { + tableFn(state, dispatch); }; } diff --git a/wax-prosemirror-services/src/TablesService/InsertTableService/Table.js b/wax-prosemirror-services/src/TablesService/InsertTableService/Table.js index cae1293ff..d475193db 100644 --- a/wax-prosemirror-services/src/TablesService/InsertTableService/Table.js +++ b/wax-prosemirror-services/src/TablesService/InsertTableService/Table.js @@ -1,11 +1,11 @@ -import Tools from "../../lib/Tools"; -import { Commands } from "wax-prosemirror-utilities"; -import { injectable } from "inversify"; -import { icons } from "wax-prosemirror-components"; +import Tools from '../../lib/Tools'; +import { Commands } from 'wax-prosemirror-utilities'; +import { injectable } from 'inversify'; +import { icons } from 'wax-prosemirror-components'; @injectable() export default class Table extends Tools { - title = "Insert table"; + title = 'Insert table'; content = icons.table; get run() { diff --git a/wax-prosemirror-services/src/TrackChangeService/track-changes/trackedTransaction.js b/wax-prosemirror-services/src/TrackChangeService/track-changes/trackedTransaction.js index 43fc3a0fb..e452aaad1 100644 --- a/wax-prosemirror-services/src/TrackChangeService/track-changes/trackedTransaction.js +++ b/wax-prosemirror-services/src/TrackChangeService/track-changes/trackedTransaction.js @@ -14,6 +14,16 @@ import addMarkStep from './helpers/addMarkStep'; import removeMarkStep from './helpers/removeMarkStep'; const trackedTransaction = (tr, state, user) => { + if (!tr.selectionSet) { + const $pos = state.selection.$anchor; + for (let { depth } = $pos; depth > 0; depth--) { + const node = $pos.node(depth); + if (node.type.spec.tableRole === 'table') { + return tr; + } + } + } + if ( !tr.steps.length || (tr.meta && diff --git a/wax-prosemirror-themes/package.json b/wax-prosemirror-themes/package.json index cb35a2db4..d63550ca5 100644 --- a/wax-prosemirror-themes/package.json +++ b/wax-prosemirror-themes/package.json @@ -1,6 +1,6 @@ { "name": "wax-prosemirror-themes", - "author": "Collaborative Knowledge Foundation", + "author": "Christos Kokosias", "version": "0.0.13", "description": "Wax prosemirror themes", "license": "MIT", diff --git a/wax-prosemirror-utilities/package.json b/wax-prosemirror-utilities/package.json index 5161ee3a4..28ea30ba3 100644 --- a/wax-prosemirror-utilities/package.json +++ b/wax-prosemirror-utilities/package.json @@ -1,6 +1,6 @@ { "name": "wax-prosemirror-utilities", - "author": "Collaborative Knowledge Foundation", + "author": "Christos Kokosias", "version": "0.0.13", "description": "Wax prosemirror utilities", "license": "MIT", -- GitLab