diff --git a/demo/src/defaultClauseValue.js b/demo/src/defaultClauseValue.js new file mode 100644 index 00000000..f9707ca1 --- /dev/null +++ b/demo/src/defaultClauseValue.js @@ -0,0 +1,36 @@ +export default { + object: 'value', + document: { + object: 'document', + data: {}, + nodes: [ + { + object: 'block', + type: 'clause', + data: { + tag: 'clause', + attributes: { + src: 'https://templates.accordproject.org/archives/latedeliveryandpenalty@0.13.1.cta' + }, + attributeString: 'src = "https://templates.accordproject.org/archives/latedeliveryandpenalty@0.13.1.cta"', + content: '\n Late Delivery and Penalty. In case of delayed delivery except for Force Majeure cases, "Dan" (the Seller) shall pay to "Steve" (the Buyer) for every 2 days of delay penalty amounting to 10.5% of the total value of the Equipment whose delivery has been delayed. Any fractional part of a days is to be considered a full days. The total amount of penalty shall not however, exceed 55% of the total value of the Equipment involved in late delivery. If the delay is more than 15 days, the Buyer is entitled to terminate this Contract.\n ', + closed: false + }, + nodes: [ + { + object: 'block', + type: 'paragraph', + data: {}, + nodes: [ + { + object: 'text', + text: '\n Late Delivery and Penalty. In case of delayed delivery except for Force Majeure cases, "Dan" (the Seller) shall pay to "Steve" (the Buyer) for every 2 days of delay penalty amounting to 10.5% of the total value of the Equipment whose delivery has been delayed. Any fractional part of a days is to be considered a full days. The total amount of penalty shall not however, exceed 55% of the total value of the Equipment involved in late delivery. If the delay is more than 15 days, the Buyer is entitled to terminate this Contract.\n ', + marks: [] + } + ] + } + ] + }, + ] + } +}; diff --git a/demo/src/defaultContractValue.js b/demo/src/defaultContractValue.js new file mode 100644 index 00000000..b52ee89d --- /dev/null +++ b/demo/src/defaultContractValue.js @@ -0,0 +1,123 @@ +export default { + object: 'value', + document: { + object: 'document', + data: {}, + nodes: [ + { + object: 'block', + type: 'heading_one', + data: {}, + nodes: [ + { + object: 'text', + text: 'Supply Agreement', + marks: [] + } + ] + }, + { + object: 'block', + type: 'paragraph', + data: {}, + nodes: [ + { + object: 'text', + text: 'This is a supply agreement between Party A and Party B.', + marks: [] + } + ] + }, + { + object: 'block', + type: 'heading_one', + data: {}, + nodes: [ + { + object: 'text', + text: 'Payment', + marks: [] + } + ] + }, + { + object: 'block', + type: 'clause', + data: { + tag: 'clause', + attributes: { + src: 'https://templates.accordproject.org/archives/full-payment-upon-signature@0.7.1.cta' + }, + attributeString: 'src = "https://templates.accordproject.org/archives/full-payment-upon-signature@0.7.1.cta"', + content: '\n Upon the signing of this Agreement, "Dan" shall pay the total purchase price to "Steve" in the amount of 0.01 USD.\n ', + closed: false + }, + nodes: [ + { + object: 'block', + type: 'paragraph', + data: {}, + nodes: [ + { + object: 'text', + text: '\n Upon the signing of this Agreement, "Dan" shall pay the total purchase price to "Steve" in the amount of 0.01 USD.\n ', + marks: [] + } + ] + } + ] + }, + { + object: 'block', + type: 'heading_two', + data: {}, + nodes: [ + { + object: 'text', + text: 'Late Delivery And Penalty', + marks: [] + } + ] + }, + { + object: 'block', + type: 'clause', + data: { + tag: 'clause', + attributes: { + src: 'https://templates.accordproject.org/archives/latedeliveryandpenalty@0.13.1.cta' + }, + attributeString: 'src = "https://templates.accordproject.org/archives/latedeliveryandpenalty@0.13.1.cta"', + content: '\n Late Delivery and Penalty. In case of delayed delivery except for Force Majeure cases, "Dan" (the Seller) shall pay to "Steve" (the Buyer) for every 2 days of delay penalty amounting to 10.5% of the total value of the Equipment whose delivery has been delayed. Any fractional part of a days is to be considered a full days. The total amount of penalty shall not however, exceed 55% of the total value of the Equipment involved in late delivery. If the delay is more than 15 days, the Buyer is entitled to terminate this Contract.\n ', + closed: false + }, + nodes: [ + { + object: 'block', + type: 'paragraph', + data: {}, + nodes: [ + { + object: 'text', + text: '\n Late Delivery and Penalty. In case of delayed delivery except for Force Majeure cases, "Dan" (the Seller) shall pay to "Steve" (the Buyer) for every 2 days of delay penalty amounting to 10.5% of the total value of the Equipment whose delivery has been delayed. Any fractional part of a days is to be considered a full days. The total amount of penalty shall not however, exceed 55% of the total value of the Equipment involved in late delivery. If the delay is more than 15 days, the Buyer is entitled to terminate this Contract.\n ', + marks: [] + } + ] + } + ] + }, + { + object: 'block', + type: 'paragraph', + data: {}, + nodes: [ + { + object: 'text', + text: 'End.', + marks: [] + } + ] + } + ] + } +}; diff --git a/demo/src/index.js b/demo/src/index.js index f54b92f3..98394465 100644 --- a/demo/src/index.js +++ b/demo/src/index.js @@ -8,28 +8,8 @@ import { Template, Clause } from '@accordproject/cicero-core'; import 'semantic-ui-css/semantic.min.css'; import ClauseEditor from '../../src/ClauseEditor'; import ContractEditor from '../../src/ContractEditor'; - -const clauseEditorInitialMarkdown = ` -Late Delivery and Penalty. In case of delayed delivery except for Force Majeure cases, "Dan" (the Seller) shall pay to "Steve" (the Buyer) for every 2 days of delay penalty amounting to 10.5% of the total value of the Equipment whose delivery has been delayed. Any fractional part of a days is to be considered a full days. The total amount of penalty shall not however, exceed 55% of the total value of the Equipment involved in late delivery. If the delay is more than 15 days, the Buyer is entitled to terminate this Contract. -`; - -const contractEditorInitialMarkdown = `# Supply Agreement - This is a supply agreement between Party A and Party B. - - # Payment - - - Upon the signing of this Agreement, "Dan" shall pay the total purchase price to "Steve" in the amount of 0.01 USD. - - - ## Late Delivery And Penalty - - - Late Delivery and Penalty. In case of delayed delivery except for Force Majeure cases, "Dan" (the Seller) shall pay to "Steve" (the Buyer) for every 2 days of delay penalty amounting to 10.5% of the total value of the Equipment whose delivery has been delayed. Any fractional part of a days is to be considered a full days. The total amount of penalty shall not however, exceed 55% of the total value of the Equipment involved in late delivery. If the delay is more than 15 days, the Buyer is entitled to terminate this Contract. - - - End. - `; +import defaultContractValue from './defaultContractValue'; +import defaultClauseValue from './defaultClauseValue'; /** * A demo component that uses ContractEditor and @@ -66,13 +46,13 @@ function Demo() { const demo = activeItem === 'clauseEditor' ? : ; diff --git a/package-lock.json b/package-lock.json index 2a9f3e56..d7b35332 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,9 +51,9 @@ } }, "@accordproject/markdown-editor": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@accordproject/markdown-editor/-/markdown-editor-0.4.9.tgz", - "integrity": "sha512-HvUKZ8mkp9ZhIRFNAf1dYJMWpukps84ocv13Pa16jE9KYyCInrrZHSq4Ai6JFapbTSj6UBhMq65j0KEHIeSJSQ==", + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/@accordproject/markdown-editor/-/markdown-editor-0.4.13.tgz", + "integrity": "sha512-ElUYFbSsOFqv2kyZRFOlfcN+hymSCykC635JGu3voihA/hj+3qLNX8IELuuy2lrggEqi78AyhRWWW3gL5y2AEw==", "requires": { "commonmark": "^0.29.0", "css-loader": "^2.1.1", @@ -71,7 +71,32 @@ "slate-plain-serializer": "^0.7.5", "slate-react": "^0.22.3", "style-loader": "^0.23.1", - "styled-components": "^4.2.0" + "styled-components": "^4.2.1" + }, + "dependencies": { + "memoize-one": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.0.4.tgz", + "integrity": "sha512-P0z5IeAH6qHHGkJIXWw0xC2HNEgkx/9uWWBQw64FJj3/ol14VYdfVGWWr0fXfjhhv3TKVIqUq65os6O4GUNksA==" + }, + "styled-components": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-4.2.1.tgz", + "integrity": "sha512-zBSMOJW1zfQ1rASGHJ5dHXIkn3VoOGLtQAYhkd4Ib7e+eI//uwMJWsI65JRe3aGrN2Xx8IT9jxxnVSXt9LaLCw==", + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@emotion/is-prop-valid": "^0.7.3", + "@emotion/unitless": "^0.7.0", + "babel-plugin-styled-components": ">= 1", + "css-to-react-native": "^2.2.2", + "memoize-one": "^5.0.0", + "prop-types": "^15.5.4", + "react-is": "^16.6.0", + "stylis": "^3.5.0", + "stylis-rule-sheet": "^0.0.10", + "supports-color": "^5.5.0" + } + } } }, "@babel/cli": { diff --git a/package.json b/package.json index 837e6126..51a81431 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ }, "dependencies": { "@accordproject/cicero-core": "^0.12.3", - "@accordproject/markdown-editor": "^0.4.9", + "@accordproject/markdown-editor": "^0.4.13", "lodash": "^4.17.11", "mini-css-extract-plugin": "^0.7.0", "node-sass": "^4.12.0", diff --git a/src/ClauseEditor/__snapshots__/index.test.js.snap b/src/ClauseEditor/__snapshots__/index.test.js.snap index 552d85b0..7e5bbd8c 100644 --- a/src/ClauseEditor/__snapshots__/index.test.js.snap +++ b/src/ClauseEditor/__snapshots__/index.test.js.snap @@ -2,13 +2,11 @@ exports[` on initialization renders page correctly 1`] = `
- 1, onChange: () => 1, lockText: true, diff --git a/src/ContractEditor/__snapshots__/index.test.js.snap b/src/ContractEditor/__snapshots__/index.test.js.snap index 466f51c8..abed553b 100644 --- a/src/ContractEditor/__snapshots__/index.test.js.snap +++ b/src/ContractEditor/__snapshots__/index.test.js.snap @@ -1,115 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` on initialization renders page correctly 1`] = ` - - Upon the signing of this Agreement, \\"Dan\\" shall pay the total purchase price to \\"Steve\\" in the amount of 0.01 USD. - - - ## Late Delivery And Penalty - - - Late Delivery and Penalty. In case of delayed delivery except for Force Majeure cases, \\"Dan\\" (the Seller) shall pay to \\"Steve\\" (the Buyer) for every 2 days of delay penalty amounting to 10.5% of the total value of the Equipment whose delivery has been delayed. Any fractional part of a days is to be considered a full days. The total amount of penalty shall not however, exceed 55% of the total value of the Equipment involved in late delivery. If the delay is more than 15 days, the Buyer is entitled to terminate this Contract. - - - End. - " - onChange={[Function]} - plugins={ - Array [ - Object { - "fromHTML": [Function], - "fromMarkdown": [Function], - "markdownTags": Array [ - "list", - "item", - ], - "onKeyDown": [Function], - "plugin": "list", - "renderBlock": [Function], - "schema": Object { - "blocks": Object { - "list": Object { - "nodes": Array [ - Object { - "match": Object { - "type": "list_item", - }, - }, - ], - }, - "list_item": Object { - "marks": Array [ - Object { - "type": "bold", - }, - Object { - "type": "italic", - }, - ], - "nodes": Array [ - Object { - "match": Array [ - Object { - "object": "text", - }, - Object { - "type": "link", - }, - ], - }, - ], - "parent": Object { - "type": "list", - }, - }, - }, - }, - "tags": Array [ - "ul", - "ol", - "li", - ], - "toMarkdown": [Function], - }, - Object { - "fromHTML": [Function], - "fromMarkdown": [Function], - "markdownTags": Array [ - "clause", - ], - "onChange": [Function], - "onKeyDown": [Function], - "plugin": "Clause", - "renderBlock": [Function], - "renderToolbar": [Function], - "schema": Object { - "blocks": Object { - "Clause": Object { - "nodes": Array [ - Object { - "match": Array [ - Object { - "type": "paragraph", - }, - ], - }, - ], - }, - }, - }, - "tags": Array [ - "clause", - ], - "toMarkdown": [Function], - }, - ] - } - showEditButton={true} -/> -`; +exports[` on initialization renders page correctly 1`] = `""`; diff --git a/src/ContractEditor/index.js b/src/ContractEditor/index.js index 4fe37693..0200b8e9 100644 --- a/src/ContractEditor/index.js +++ b/src/ContractEditor/index.js @@ -12,30 +12,11 @@ * limitations under the License. */ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; -import { MarkdownEditor } from '@accordproject/markdown-editor'; +import { SlateAsInputEditor } from '@accordproject/markdown-editor'; import List from '@accordproject/markdown-editor/dist/plugins/list'; import ClausePlugin from '../plugins/ClausePlugin'; -import ClauseComponent from '../components/ClauseComponent'; - -const defaultMarkdown = `# Supply Agreement - This is a supply agreement between Party A and Party B. - - # Payment - - - Upon the signing of this Agreement, "Dan" shall pay the total purchase price to "Steve" in the amount of 0.01 USD. - - - ## Late Delivery And Penalty - - - Late Delivery and Penalty. In case of delayed delivery except for Force Majeure cases, "Dan" (the Seller) shall pay to "Steve" (the Buyer) for every 2 days of delay penalty amounting to 10.5% of the total value of the Equipment whose delivery has been delayed. Any fractional part of a days is to be considered a full days. The total amount of penalty shall not however, exceed 55% of the total value of the Equipment involved in late delivery. If the delay is more than 15 days, the Buyer is entitled to terminate this Contract. - - - End. - `; /** * Adds the current markdown to local storage @@ -48,7 +29,23 @@ function storeLocal(value, markdown) { * Default contract props */ const contractProps = { - markdown: defaultMarkdown, + value: { + object: 'value', + document: { + object: 'document', + data: {}, + nodes: [{ + object: 'block', + type: 'paragraph', + data: {}, + nodes: [{ + object: 'text', + text: 'Welcome! Edit this text to get started.', + marks: [] + }], + }] + } + }, onChange: storeLocal, plugins: [] }; @@ -59,17 +56,26 @@ const contractProps = { * * @param {*} props the properties for the component */ -const ContractEditor = props => ( - { + const [plugins, setplugins] = useState([]); + useEffect(() => { + setplugins( props.plugins - ? props.plugins.concat([List(), ClausePlugin(ClauseComponent, props.loadTemplateObject, props.parseClause)]) - : [List(), ClausePlugin(ClauseComponent, props.loadTemplateObject, props.parseClause)] - } - /> -); + ? props.plugins.concat( + [List(), ClausePlugin(props.loadTemplateObject, props.parseClause)] + ) + : [List(), ClausePlugin(props.loadTemplateObject, props.parseClause)] + ); + }, [props.loadTemplateObject, props.parseClause, props.plugins]); + return ( + plugins.length ? : null + ); +}; /** * The property types for this component */ @@ -78,7 +84,7 @@ ContractEditor.propTypes = { /** * Initial contents of the editor */ - markdown: PropTypes.string, + value: PropTypes.object, /** * Callback called when the contents of the editor changes diff --git a/src/ContractEditor/index.test.js b/src/ContractEditor/index.test.js index 1ff6b542..fbc8eb0d 100644 --- a/src/ContractEditor/index.test.js +++ b/src/ContractEditor/index.test.js @@ -5,8 +5,7 @@ import toJson from 'enzyme-to-json'; import ContractEditor from './index'; const props = { - markdown: '', - onParse: () => 1, + value: null, onChange: () => 1, lockText: true, template: {}, diff --git a/src/ContractEditor/plugins/clausePlugin.js b/src/ContractEditor/plugins/clausePlugin.js deleted file mode 100644 index 15827228..00000000 --- a/src/ContractEditor/plugins/clausePlugin.js +++ /dev/null @@ -1,209 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Icon } from 'semantic-ui-react'; -import styled from 'styled-components'; -import ClauseComponent from '../components/ClauseComponent'; - -const StyledIcon = styled(Icon)` - color: #ffffff !important; -`; - -/** - * A plugin for a clause embedded in a contract - */ -function ClausePlugin(loadTemplateObject, parseClause) { - const plugin = 'Clause'; - const tags = ['clause']; - const markdownTags = ['clause']; - const schema = { - blocks: { - Clause: { - nodes: [ - { - match: [{ type: 'paragraph' }], - }, - ], - }, - }, - }; - - /** - * @param {Event} event - * @param {Editor} editor - * @param {Function} next - */ - function onEnter(event, editor, next) { - return next(); - } - - /** - * Handles change to document. - */ - function onChange(editor, next) { - console.log('onChange'); - let clauseNode = null; - let textNode = null; - const textNodes = editor.value.texts; - if (textNodes.size === 1) { - textNode = textNodes.get(0); - const para = editor.value.document.getParent(textNode.key); - clauseNode = editor.value.document.getParent(para.key); - } - - if (!clauseNode || clauseNode.type !== 'clause') { - return next(); - } - - const nodeAttributes = clauseNode.data.get('attributes'); - const { src, clauseid } = nodeAttributes; - - parseClause(src, textNode.text.trim(), clauseid) - .then(parseResult => console.log(parseResult)) // add/remove annotation - .catch(error => console.log(error)); // add/remove annotation - return next(); - } - - /** - * @param {Event} event - * @param {Editor} editor - * @param {Function} next - */ - function onKeyDown(event, editor, next) { - switch (event.key) { - case 'Enter': - return onEnter(event, editor, next); - default: - return next(); - } - } - - /** - * @param {Object} props - * @param {Editor} editor - * @param {Function} next - */ - function renderBlock(props, editor, next) { - renderBlock.propTypes = { - node: PropTypes.any, - attributes: PropTypes.any, - children: PropTypes.any, - }; - - const { node, children } = props; - - const nodeAttributes = node.data.get('attributes'); - const { src } = nodeAttributes; - - if (src) { - console.log(`handing over responsibility of loading: ${src}`); - loadTemplateObject(src.toString()); - } - - return ({children}); - } - - /** - * @param {ToMarkdown} parent - * @param {Node} value - */ - function toMarkdown(parent, value) { - let markdown = `\n\n`; - - value.nodes.forEach((li) => { - const text = parent.recursive(li.nodes); - markdown += text; - }); - - markdown += ''; - return markdown; - } - - /** - * Handles data from markdown. - */ - function fromMarkdown(stack, event, tag) { - const block = { - object: 'block', - type: 'clause', - data: Object.assign(tag), - nodes: [], - }; - - stack.push(block); - - const para = { - object: 'block', - type: 'paragraph', - data: {}, - nodes: [], - }; - - stack.push(para); - stack.addTextLeaf({ - object: 'leaf', - text: tag.content ? tag.content : '', - marks: [], - }); - stack.pop(); - stack.pop(); - return true; - } - - /** - * Handles data from the HTML format. - */ - function fromHTML(editor, el, next) { - return { - object: 'block', - type: 'clause', - data: {}, - nodes: next(el.childNodes), - }; - } - - /** - * When then button is clicked - * - * @param {Editor} editor - * @param {Event} event - */ - - /** - * Handles a button click. - */ - function onClickButton(editor, event) { - event.preventDefault(); - alert('Clause plugin button clicked!'); - } - - /** - * Render a clause toolbar button. - * - * @param {Editor} editor - * @return {Element} - */ - function renderToolbar(editor) { - return ( onClickButton(editor, event)} - />); - } - - return { - plugin, - tags, - markdownTags, - schema, - onKeyDown, - renderBlock, - toMarkdown, - fromMarkdown, - fromHTML, - onChange, - renderToolbar, - }; -} - -export default ClausePlugin; diff --git a/src/plugins/ClausePlugin.js b/src/plugins/ClausePlugin.js index d0cae1f6..8719296a 100644 --- a/src/plugins/ClausePlugin.js +++ b/src/plugins/ClausePlugin.js @@ -7,6 +7,8 @@ import { Template, Clause } from '@accordproject/cicero-core'; import '../styles.css'; // eslint-disable-next-line camelcase import murmurhash3_32_gc from './murmurhash3_gc'; +import ClauseComponent from '../components/ClauseComponent'; + const StyledIcon = styled(Icon)` color: #ffffff !important; @@ -18,7 +20,7 @@ const StyledIcon = styled(Icon)` * @param {*} customLoadTemplate - a custom function used to load templates * @param {*} customParseClause - a custom function used to parse clause text */ -function ClausePlugin(ClauseComponent, customLoadTemplate, customParseClause) { +function ClausePlugin(customLoadTemplate, customParseClause) { const plugin = 'Clause'; const tags = ['clause']; const markdownTags = ['clause'];