import * as React from "react"; import { Box, Button, Flash, Form } from "rimble-ui"; import { colors } from "../../../../themes"; import { WorkingSchema, newSchemaAttribute, defaultSchemaProperties } from "../types"; import { SchemaAttribute } from "./SchemaAttribute"; export interface AttributesStepProps { schema: WorkingSchema; updateSchema(updates: Partial): void; onComplete(): void; } export const AttributesStep: React.FunctionComponent = (props) => { const { schema, updateSchema } = props; const [doValidation, setDoValidation] = React.useState(false); const [error, setError] = React.useState(""); function addAttribute(e: Event) { if (schema.properties?.credentialSubject?.properties?.[""]) { // We have a property with no name - have them update that before creating a no one. We don't have to do anything, since the un-preventDefaulted event will trigger browser UI on empty required title field return; } e.preventDefault(); updateSchema({ ...schema, properties: { ...schema.properties, credentialSubject: { ...schema.properties?.credentialSubject, properties: { ...schema.properties?.credentialSubject?.properties, "": { ...newSchemaAttribute }, }, }, }, }); } function goNext(e: Event) { e.preventDefault(); setError(""); const propertyIds = new Set(); let missingField = false; let duplicateId = false; let invalidId = false; // @TODO/tobek These checks should be recursive. Empty `title`'s are already handled by native browser form checks, but `$linkedData.term` collisions (which would have to be unique only among sibling properties) are not handled. Object.entries(schema.properties?.credentialSubject?.properties || {}).forEach(([key, prop]) => { if (key === "") { missingField = true; } if (prop.$linkedData?.term) { if (prop.$linkedData?.term === "type") { setError( `An attribute name result in ID "${prop.$linkedData.term}" - this is a reserved keyword in the JSON-LD specification that VCs use. Please use a different name.`, ); invalidId = true; } else if (propertyIds.has(prop.$linkedData.term)) { setError( `Two attribute names result in ID "${prop.$linkedData.term}" - all attributes must have unique IDs.`, ); duplicateId = true; } else { propertyIds.add(prop.$linkedData.term); } } }); if (missingField || duplicateId || invalidId) { setDoValidation(true); } else { setDoValidation(false); props.onComplete(); } } return (
{defaultSchemaProperties.map((prop, i) => ( ))} {schema.properties?.credentialSubject && ( { updateSchema({ ...schema, properties: { ...schema.properties, credentialSubject: attr, }, }); }} /> )} Add Another Attribute {error && ( Error: {error} )} ); };