Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature(concerto) Model builder with CTO generation and latest metamodel #354

Merged
merged 10 commits into from
Sep 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60,949 changes: 137 additions & 60,812 deletions package-lock.json

Large diffs are not rendered by default.

701 changes: 555 additions & 146 deletions packages/storybook/package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/storybook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.98.0",
"private": true,
"dependencies": {
"@accordproject/concerto-core": "1.2.2-20210927172800",
"@accordproject/cicero-core": "0.22.0",
"@accordproject/markdown-slate": "0.13.0",
"@accordproject/markdown-transform": "0.13.0",
Expand Down Expand Up @@ -48,7 +49,7 @@
"semantic-ui-css": "^2.4.1",
"slate": "^0.63.0",
"slate-history": "^0.62.0",
"slate-react": "^0.63.0",
"slate-react": "^0.65.0",
"styled-components": "^5.1.0",
"stylelint": "13.3.3",
"stylelint-config-standard": "20.0.0",
Expand Down
43 changes: 30 additions & 13 deletions packages/storybook/src/stories/3-ConcertoForm.stories.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
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 {
title: 'Concerto Form',
Expand Down Expand Up @@ -32,8 +33,8 @@ export const SimpleExample = () => {
});
const model = text('Model', TestModel);

const handleValueChange = (json) => {
return action("value changed")(json);
const handleValueChange = async (json) => {
await action("new cto")(newCto);
};

options.relationshipProvider = {
Expand Down Expand Up @@ -94,28 +95,44 @@ export const ModelBuilder = () => {
const options = object('Options', {
includeOptionalFields: false,
updateExternalModels: false,
visitor: new ModelBuilderVisitor(),
customSelectors: {
types: [
{ text: 'Contract', value: 'org.accordproject.cicero.contract.AccordContract' },
{ text: 'Party', value: 'org.accordproject.cicero.contract.AccordParty' }
{ text: 'Contract', value: 'Contract' },
{ text: 'Party', value: 'Party' }
]
}
});
const model = text('Model', ConcertoMetamodel);

const handleValueChange = (json) => {
return action("value changed")(json);
const cto = text('Initial CTO', TestModel);
let json = null;
try {
json = MetaModel.ctoToMetaModel(cto);
} catch (error) {
console.log(`Invalid CTO: [${error.message}]`);
}
const handleValueChange = async (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")(`[${error.message}]\n${newCto}`);
}
};

return (
<div style={{ padding: '10px' }}>
<ConcertoForm
<ConcertoModelBuilder
readOnly={readOnly}
models={[model]}
options={options}
type={type}
json={null}
json={json}
onValueChange={handleValueChange}
/>
</div>
Expand Down
187 changes: 0 additions & 187 deletions packages/storybook/src/stories/concerto.models.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,190 +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 fullyQualifiedName
}

concept DecoratorIdentifier extends DecoratorLiteral {
o TypeIdentifier identifier
o Boolean isArray default=false
}

concept Decorator {
o String name
o DecoratorLiteral[] arguments optional
}

@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 identifier 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 String identifiedByField optional
@FormEditor("title", "parentType")
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 {
}

// TODO - enums do not support abstract or super types
concept EnumDeclaration extends ClassDeclaration {
}

concept StringDefault {
o String value
}

concept BooleanDefault {
o Boolean value
}

concept IntegerDefault {
o Integer value
}

concept RealDefault {
o Double value
}

@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", "isArray?")
o Boolean isArray optional
@FormEditor("title", "isOptional?")
o Boolean isOptional optional
@FormEditor("hide", true)
o Decorator[] decorators optional
}

concept ObjectFieldDeclaration extends FieldDeclaration {
@FormEditor("hide", true)
o StringDefault defaultValue optional
@FormEditor("title", "typeIdentifier", "selectOptions", "types")
o TypeIdentifier type
}

concept BooleanFieldDeclaration extends FieldDeclaration {
@FormEditor("hide", true)
o BooleanDefault defaultValue optional
}

concept DateTimeFieldDeclaration extends FieldDeclaration {
}

concept StringFieldDeclaration extends FieldDeclaration {
@FormEditor("hide", true)
o StringDefault defaultValue optional
@FormEditor("hide", true)
o StringRegexValidator validator optional
}

concept StringRegexValidator {
o String regex
}

concept RealDomainValidator {
o Double lower optional
o Double upper optional
}

concept IntegerDomainValidator {
o Integer lower optional
o Integer upper optional
}

concept RealFieldDeclaration extends FieldDeclaration {
o RealDefault defaultValue optional
o RealDomainValidator validator optional
}

concept IntegerFieldDeclaration extends FieldDeclaration {
@FormEditor("hide", true)
o IntegerDefault defaultValue optional
@FormEditor("hide", true)
o IntegerDomainValidator validator optional
}

concept RelationshipDeclaration extends FieldDeclaration {
@FormEditor("title", "typeIdentifier", "selectOptions", "types")
o TypeIdentifier type
}

abstract concept Import {
o String uri optional
}

concept NamespaceImport extends Import {
o String namespace
}

concept TypeImport extends Import {
o TypeIdentifier identifier
}

concept ModelFile {
o String namespace
@FormEditor("hide", true)
o Import[] imports optional
@FormEditor("title", "classes")
o ClassDeclaration[] declarations optional
}
`;
2 changes: 1 addition & 1 deletion packages/ui-concerto/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.98.0",
"private": false,
"dependencies": {
"@accordproject/concerto-core": "^1.0.0",
"@accordproject/concerto-core": "1.2.2-20210927172800",
"@babel/runtime": "^7.10.3",
"lodash.get": "^4.4.2",
"lodash.isequal": "^4.5.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/ui-concerto/src/components/concertoForm.css
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
column-gap: 5px;
}

.mbIdentifierDeclaration {
.mbClassNameDeclaration {
display: grid;
grid-template-columns: auto 150px;
column-gap: 5px;
Expand Down
15 changes: 0 additions & 15 deletions packages/ui-concerto/src/components/concertoForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,21 +97,6 @@ const ConcertoForm = (props) => {
useEffect(() => {
setLoading(true);
const modelManager = new ModelManager();
// TODO Refactor this to an option to make this independent of Cicero
modelManager.addModelFile(
`namespace org.accordproject.base
abstract asset Asset { }
abstract participant Participant { }
abstract transaction Transaction identified by transactionId {
o String transactionId
}
abstract event Event identified by eventId {
o String eventId
}`,
'org.accordproject.base.cto',
false,
true
);
models.forEach((model, idx) => {
try {
modelManager.addModelFile(model, `model-${idx}`, true);
Expand Down
44 changes: 44 additions & 0 deletions packages/ui-concerto/src/components/concertoModelBuilder.js
Original file line number Diff line number Diff line change
@@ -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 (
<ErrorBoundary>
<ConcertoForm key={`form-wrapper-${props.type}`} models={[MetaModel.metaModelCto]} {...props} />
</ErrorBoundary>
);
};

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;
5 changes: 3 additions & 2 deletions packages/ui-concerto/src/components/fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ export const ConcertoDropdown = ({
id,
readOnly,
value,
text,
onFieldValueChange,
options,
}) => !readOnly ? (
Expand All @@ -245,7 +246,7 @@ export const ConcertoDropdown = ({
options={options}
/>
) : (
<Input type="text" readOnly value={value} key={`input-${id}`} />
<Input type="text" readOnly value={text} key={`input-${id}`} />
);

const BinaryField = ({ className, children }) => (
Expand All @@ -261,4 +262,4 @@ export const MonetaryAmount = ({ children }) => (

export const Duration = ({ children }) => (
<BinaryField className="duration">{children}</BinaryField>
);
);
Loading