From acc72d5a05eb824bdee0660a48bf64e377c2132a Mon Sep 17 00:00:00 2001 From: jeromesimeon Date: Tue, 27 Jul 2021 10:47:14 -0400 Subject: [PATCH] feature(metaodel) New ConcertoModelBuilder component + storybook improvements Signed-off-by: jeromesimeon --- .../src/stories/3-ConcertoForm.stories.js | 57 ++---- .../storybook/src/stories/concerto.models.js | 193 ------------------ .../src/components/concertoModelBuilder.js | 44 ++++ packages/ui-concerto/src/index.js | 5 +- 4 files changed, 66 insertions(+), 233 deletions(-) create mode 100644 packages/ui-concerto/src/components/concertoModelBuilder.js diff --git a/packages/storybook/src/stories/3-ConcertoForm.stories.js b/packages/storybook/src/stories/3-ConcertoForm.stories.js index 1ff1e19..f6a3ca1 100644 --- a/packages/storybook/src/stories/3-ConcertoForm.stories.js +++ b/packages/storybook/src/stories/3-ConcertoForm.stories.js @@ -1,8 +1,8 @@ import React, { useState } from 'react'; import { action } from '@storybook/addon-actions'; import { text, boolean, object } from '@storybook/addon-knobs'; -import { ConcertoForm, ModelBuilderVisitor } from '@accordproject/ui-concerto'; -import { ConcertoMetamodel, TestModel } from './concerto.models'; +import { ConcertoForm, ConcertoModelBuilder } from '@accordproject/ui-concerto'; +import { TestModel } from './concerto.models'; import { MetaModel } from '@accordproject/concerto-core'; export default { @@ -16,35 +16,6 @@ export default { } }; -const initialJson = null; - -// const initialJson = { -// "$class": "concerto.metamodel.ModelFile", -// "namespace": "org.litle.test", -// "imports": [], -// "declarations": [ -// { -// "$class": "concerto.metamodel.ConceptDeclaration", -// "isAbstract": false, -// "name": "Person", -// "fields": [ -// { -// "$class": "concerto.metamodel.StringFieldDeclaration", -// "name": "name", -// "isArray": false, -// "isOptional": false -// }, -// { -// "$class": "concerto.metamodel.IntegerFieldDeclaration", -// "name": "age", -// "isArray": false, -// "isOptional": false -// } -// ] -// } -// ] -// }; - export const SimpleExample = () => { const readOnly = boolean('Read-only', false); const type = text('Type', 'test.Person'); @@ -124,7 +95,6 @@ export const ModelBuilder = () => { const options = object('Options', { includeOptionalFields: false, updateExternalModels: false, - visitor: new ModelBuilderVisitor(), customSelectors: { types: [ { text: 'Contract', value: 'Contract' }, @@ -132,21 +102,32 @@ export const ModelBuilder = () => { ] } }); - const model = text('Model', ConcertoMetamodel); + const cto = text('Initial CTO', TestModel); + const json = MetaModel.ctoToMetaModel(cto); const handleValueChange = async (json) => { - await action("new cto")(MetaModel.ctoFromMetaModel(json, false)); - await action("value changed")(json); + let newCto; + try { + newCto = MetaModel.ctoFromMetaModel(json, true); + await action("metamodel change")(json); + } catch (error) { + await action("Invalid metamodel")(json); + } + try { + const roundtripForSafety = MetaModel.ctoToMetaModel(newCto); + await action("New CTO")(newCto); + } catch (error) { + await action("Invalid CTO")(`${newCto}\n[${error.message}]`); + } }; return (
-
diff --git a/packages/storybook/src/stories/concerto.models.js b/packages/storybook/src/stories/concerto.models.js index 3bc2d03..43fecf0 100644 --- a/packages/storybook/src/stories/concerto.models.js +++ b/packages/storybook/src/stories/concerto.models.js @@ -21,196 +21,3 @@ concept Address { o Country country } `; - -export const ConcertoMetamodel = `/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -namespace concerto.metamodel - -/** - * The metadmodel for Concerto files - */ -abstract concept DecoratorLiteral { -} - -concept DecoratorString extends DecoratorLiteral { - o String value -} - -concept DecoratorNumber extends DecoratorLiteral { - o Double value -} - -concept DecoratorBoolean extends DecoratorLiteral { - o Boolean value -} - -concept TypeIdentifier { - @FormEditor("selectOptions", "types") - o String name default="Concept" - @FormEditor( "hide", true) - o String fullyQualifiedName optional -} - -concept DecoratorIdentifier extends DecoratorLiteral { - o TypeIdentifier identifier - o Boolean isArray default=false -} - -concept Decorator { - o String name - o DecoratorLiteral[] arguments optional -} - -concept Identified { -} - -concept IdentifiedBy extends Identified { - o String name -} - -@FormEditor("defaultSubclass","concerto.metamodel.ConceptDeclaration") -abstract concept ClassDeclaration { - @FormEditor("hide", true) - o Decorator[] decorators optional - o Boolean isAbstract default=false - // TODO use regex /^(?!null|true|false)(\\p{Lu}|\\p{Ll}|\\p{Lt}|\\p{Lm}|\\p{Lo}|\\p{Nl}|\\$|_|\\\\u[0-9A-Fa-f]{4})(?:\\p{Lu}|\\p{Ll}|\\p{Lt}|\\p{Lm}|\\p{Lo}|\\p{Nl}|\\$|_|\\\\u[0-9A-Fa-f]{4}|\\p{Mn}|\\p{Mc}|\\p{Nd}|\\p{Pc}|\\u200C|\\u200D)*/u - @FormEditor("title", "Name") - o String name default="ClassName" // regex=/^(?!null|true|false)(\\w|\\d|\\$|_|\\\\u[0-9A-Fa-f]{4})(?:\\w|\\d|\\$|_|\\\\u[0-9A-Fa-f]{4}|\\S|\\u200C|\\u200D)*$/ - o Identified identified optional - @FormEditor("title", "Super Type") - o TypeIdentifier superType optional - o FieldDeclaration[] fields -} - -concept AssetDeclaration extends ClassDeclaration { -} - -concept ParticipantDeclaration extends ClassDeclaration { -} - -concept TransactionDeclaration extends ClassDeclaration { -} - -concept EventDeclaration extends ClassDeclaration { -} - -concept ConceptDeclaration extends ClassDeclaration { -} - -concept EnumDeclaration extends ClassDeclaration { -} - -@FormEditor("defaultSubclass","concerto.metamodel.StringFieldDeclaration") -abstract concept FieldDeclaration { - // TODO Allow regex modifiers e.g. //ui - // regex /^(?!null|true|false)(\\p{Lu}|\\p{Ll}|\\p{Lt}|\\pLm}|\\p{Lo}|\\p{Nl}|\\$|_|\\\\u[0-9A-Fa-f]{4})(?:\\p{Lu}|\\p{Ll}|\\p{Lt}|\\p{Lm}|\\p{Lo}|\\p{Nl}|\\$|_|\\\\u[0-9A-Fa-f]{4}|\\p{Mn}|\\p{Mc}|\\p{Nd}|\\p{Pc}|\\u200C|\\u200D)*/u - // This regex is an approximation of what the parser accepts without using unicode character classes - o String name default="fieldName" // regex=/^(?!null|true|false)(\\w|\\d|\\$|_|\\\\u[0-9A-Fa-f]{4})(?:\\w|\\d|\\$|_|\\\\u[0-9A-Fa-f]{4}|\\S|\\u200C|\\u200D)*$/ - @FormEditor("title", "Is Array?") - o Boolean isArray default=false - @FormEditor("title", "Is Optional?") - o Boolean isOptional default=false - @FormEditor("hide", true) - o Decorator[] decorators optional -} - -concept EnumFieldDeclaration extends FieldDeclaration { -} - -concept RelationshipDeclaration extends FieldDeclaration { - @FormEditor("title", "Type Name", "selectOptions", "types") - o TypeIdentifier type -} - -concept ObjectFieldDeclaration extends FieldDeclaration { - @FormEditor("hide", true) - o String defaultValue optional - @FormEditor("title", "Type Name", "selectOptions", "types") - o TypeIdentifier type -} - -concept BooleanFieldDeclaration extends FieldDeclaration { - @FormEditor("hide", true) - o Boolean defaultValue optional -} - -concept DateTimeFieldDeclaration extends FieldDeclaration { -} - -concept StringFieldDeclaration extends FieldDeclaration { - @FormEditor("hide", true) - o String defaultValue optional - @FormEditor("hide", true) - o StringRegexValidator validator optional -} - -concept StringRegexValidator { - o String regex -} - -concept DoubleFieldDeclaration extends FieldDeclaration { - o Double defaultValue optional - o DoubleDomainValidator validator optional -} - -concept DoubleDomainValidator { - o Double lower optional - o Double upper optional -} - -concept IntegerFieldDeclaration extends FieldDeclaration { - @FormEditor("hide", true) - o Integer defaultValue optional - @FormEditor("hide", true) - o IntegerDomainValidator validator optional -} - -concept IntegerDomainValidator { - o Integer lower optional - o Integer upper optional -} - -concept LongFieldDeclaration extends FieldDeclaration { - @FormEditor("hide", true) - o Long defaultValue optional - @FormEditor("hide", true) - o LongDomainValidator validator optional -} - -concept LongDomainValidator { - o Long lower optional - o Long upper optional -} - -abstract concept Import { - o String namespace - o String uri optional -} - -concept ImportAll extends Import { -} - -concept ImportType extends Import { - o String name -} - -concept ModelFile { - o String namespace default="my.namespace" - @FormEditor("hide", true) - o Import[] imports optional - @FormEditor("title", "Classes") - o ClassDeclaration[] declarations optional -} -`; \ No newline at end of file diff --git a/packages/ui-concerto/src/components/concertoModelBuilder.js b/packages/ui-concerto/src/components/concertoModelBuilder.js new file mode 100644 index 0000000..aa24e12 --- /dev/null +++ b/packages/ui-concerto/src/components/concertoModelBuilder.js @@ -0,0 +1,44 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import PropTypes from 'prop-types'; +import ErrorBoundary from './errorBoundary'; +import ConcertoForm from './concertoForm'; +import ModelBuilderVisitor from '../modelBuilderVisitor'; +import { MetaModel } from '@accordproject/concerto-core'; + +/** + * This React component generates a React object for a bound model. + */ +const ConcertoModelBuilder = props => { + const options = props.options ? props.options : {}; + options.visitor = new ModelBuilderVisitor(); + console.log(`PROPS ${Object.keys(props.options)}`); + return ( + + + + ); +}; + +ConcertoModelBuilder.propTypes = { + type: PropTypes.string, + json: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), + onValueChange: PropTypes.func.isRequired, + options: PropTypes.shape(), + readOnly: PropTypes.bool, +}; + +export default ConcertoModelBuilder; diff --git a/packages/ui-concerto/src/index.js b/packages/ui-concerto/src/index.js index f2082e3..d31c9e7 100644 --- a/packages/ui-concerto/src/index.js +++ b/packages/ui-concerto/src/index.js @@ -11,9 +11,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import ConcertoFormWrapper from './components/concertoFormWrapper'; import ReactFormVisitor from './reactformvisitor'; import ModelBuilderVisitor from './modelBuilderVisitor'; +import ConcertoFormWrapper from './components/concertoFormWrapper'; +import ConcertoModelBuilder from './components/concertoModelBuilder'; import * as Utilities from './utilities'; -export { ConcertoFormWrapper as ConcertoForm, ReactFormVisitor, ModelBuilderVisitor, Utilities }; +export { ConcertoFormWrapper as ConcertoForm, ReactFormVisitor, ModelBuilderVisitor, Utilities, ConcertoModelBuilder };