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

332 conditional fields #336

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
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
323 changes: 268 additions & 55 deletions utils/api/configurations.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,85 +248,298 @@ const configureLineItems = (lineItems) => (lineItems.map(lineItem => ({
unitPrice: lineItem.unit_price,
})))

export const configureDynamicFormSchema = (defaultSchema) => {
/**
*
* @param {Object} adjustedSchema - the schema that has been adjusted to remove properties that shouldn't be shown based on `removedProperties`
* @returns {Object}
*
* This function takes the adjusted schema and returns a new schema that is formatted for react-jsonschema-form
*/
export const configureDynamicFormSchema = (adjustedSchema) => {
// TODO(alishaevn): will need to account for multiple forms in phase 2
// TODO(alishaevn): if I remove all of the configuration below, as well as from configureDynamicFormUiSchema the select and input boxes
// work fine. the checkboxes and conditionals don't. try focusing on just that to simplify the code.

const removedProperties = [
'concierge_support', 'suppliers_identified', 'price_comparison', 'number_suppliers',
'supplier_criteria', 'supplier_confirmation'
]
let propertyFields = {}
let requiredFields = []
let dependencyFields = {}
let propertyFields = {}

Object.entries(defaultSchema.properties).forEach(prop => {
Object.entries(adjustedSchema.properties).forEach(prop => {
const [key, value] = prop
let adjustedProperty
let definitionFields = {
[key]: { 'properties': {} },
}
let propertyValues = {
'title': '',
'$ref': `#/definitions/${key}`
}

if (!removedProperties.includes(key)) {
if (value.required) {
requiredFields.push(key)
let { required, ...remainingProperties } = value
adjustedProperty = { ...remainingProperties }
}
if (value.required) requiredFields.push(key)

if (value.dependencies) {
dependencyFields[key] = [value['dependencies']]
// fallback to the initial value in case "required" wasn't on this property
let { dependencies, ...remainingProperties } = adjustedProperty || value
adjustedProperty = { ...remainingProperties }
if (value.type === 'array') {
propertyValues['title'] = value.title
value.enum?.forEach(item => {
definitionFields[key]['properties'][item] = {
type: 'boolean',
title: item,
}
})
} else {
definitionFields[key]['properties'] = {
[key]: {
'type': value.type,
'title': value.title,
'enum': value.enum,
}
}
}

if (value.type === 'array') {
let { title, type } = adjustedProperty
if (value.dependencies) {
// dependencyFields[key] = [value['dependencies']]
// // fallback to the initial value in case "required" wasn't on this property
// let { dependencies, ...remainingProperties } = propertyValues || value
// propertyValues = { ...remainingProperties }

propertyFields[key] = {
type,
title,
items: {
type: 'string',
enum: adjustedProperty.enum,
},
uniqueItems: true,
}
} else {
propertyFields[key] = adjustedProperty
}
}

// schema types are "string" or "array"
// if (value.type === 'array') {
// // if (key === 'n_terminus_modifications') {
// // console.log('before', { propertyValues })
// // delete propertyValues.enum
// // const { enum, ...remainingProperties } = propertyValues
// // console.log('after', { propertyValues })

// propertyFields[key] = {
// ...propertyValues,
// // type: 'object',
// // items: {
// // type: 'string',
// // enum: propertyValues.enum,
// // },
// // uniqueItems: true,
// }
// } else {
propertyFields[key] = propertyValues
// }
// }
})

// ARRAY WITH ENUM
// console.log('c_terminus_modifications::', propertyFields.c_terminus_modifications)
// {
// "type": "array",
// "title": "Please select any modifications you want added to the C-terminus",
// "dependencies": "suppliers_identified",
// "enum": [
// "Amidated",
// "Free Acid",
// "Biotinylated",
// "Peptide Nucleic Acids (PNAs)",
// "Other"
// ]
// }

// STRING WITH ENUM
// console.log('purity::', propertyFields.purity)
// {
// "type": "string",
// "title": "What is the requested purity?",
// "enum": [
// "Crude",
// "> 75%",
// "> 85%",
// "> 90%",
// "> 95%",
// "> 98%",
// "Other"
// ],
// "dependencies": "n_terminus_modifications"
// }

return {
'type': defaultSchema.type,
'type': adjustedSchema.type,
'required': requiredFields,
'properties': propertyFields,
'dependencies': dependencyFields,
// 'properties': adjustedSchema.properties,
// 'properties': propertyFields,
'properties': {
// CHECKBOXES
"c_terminus_modifications": {
"title": "Please select any modifications you want added to the C-terminus",
"$ref": "#/definitions/c_terminus_modifications"
},
// RADIO/SELECT
"purity": {
"title": "",
"$ref": "#/definitions/purity",
},
'suppliers_identified': {
"title": "",
"$ref": "#/definitions/suppliers_identified",
},
'timeline': {
"title": "",
"$ref": "#/definitions/timeline",
},
},
'definitions': {
'c_terminus_modifications': {
"properties": {
"Amidated": {
"type": "boolean",
"title": "Amidated"
},
"Other": {
"type": "boolean",
"title": "Other"
}
},
"dependencies": {
"Other": {
"oneOf": [
{
"properties": {
"Other": {
"enum": [true]
},
"description": {
"type": "string",
"title": "Other (e.g. Phosphorylation, Head-to-tail cyclic, stable isotope, BSA, etc.)"
}
},
"required": [
"description"
]
}
]
}
}
},
'purity': {
"properties": {
"purity": {
"type": "string",
"title": "What is the requested purity?",
"enum": ["One", "Two", "Three", "Other"]
},
},
"dependencies": {
"purity": {
"oneOf": [
{
"properties": {
"purity": {
"enum": ["Other"]
},
"description": {
"type": "string",
"title": "Other"
}
},
"required": ["description"]
}
]
}
}
},
'suppliers_identified': {
"properties": {
"suppliers_identified": {
"type": "string",
"title": "Have you identified any suppliers?",
"enum": ["Yes", "No"]
},
},
},
'timeline': {
"properties": {
"timeline": {
"type": "string",
"title": "What is the timeline for this project?",
},
},
},
}
}
}

export const configureDynamicFormUiSchema = (schema, defaultOptions) => {
const removedProperties = [
//'concierge_support', 'suppliers_identified', 'price_comparison', 'quote_or_information',
'number_suppliers', 'supplier_criteria', 'supplier_confirmation'
]

export const configureDynamicFormUiSchema = (defaultSchemaProperties, defaultOptionsFields) => {
let UiSchema = {}
const { fields } = defaultOptions

if (fields) {
for (let key in schema.properties) {
if (fields.hasOwnProperty(key)) {
let fieldOptions = { 'ui:classNames': 'mb-4' }

if(fields[key].helper) fieldOptions['ui:help'] = fields[key].helper
if(fields[key].placeholder) fieldOptions['ui:placeholder'] = fields[key].placeholder
if(fields[key].type) fieldOptions['ui:inputType'] = fields[key].type
if(fields[key].type === 'checkbox') fieldOptions['ui:widget'] = 'checkboxes'
if(fields[key].rows) {
fieldOptions['ui:options']= {
widget: 'textarea',
rows: fields[key].rows,
let adjustedSchemaProperties = defaultSchemaProperties

for (let key in defaultOptionsFields) {
let fieldOptions = { 'ui:classNames': 'mb-4' }

if (removedProperties.includes(key)) {
delete adjustedSchemaProperties[key]
next
}

if (defaultOptionsFields[key].dependencies) {
const [dependency] = Object.entries(defaultOptionsFields[key].dependencies)

if (removedProperties.includes(dependency[0])) {
delete adjustedSchemaProperties[key]
next
} else if (!Object.keys(adjustedSchemaProperties).includes(dependency[0])) {
delete adjustedSchemaProperties[key]
next
} else {
fieldOptions[dependency[0]] = {
...UiSchema[dependency[0]],
[dependency[1]]: {
description: {
'ui:widget': 'text'
}
}
}
}
}

UiSchema[key] = fieldOptions
if (defaultOptionsFields[key].helper) fieldOptions['ui:help'] = defaultOptionsFields[key].helper
if (defaultOptionsFields[key].placeholder) fieldOptions['ui:placeholder'] = defaultOptionsFields[key].placeholder
if (defaultOptionsFields[key].type) fieldOptions['ui:inputType'] = defaultOptionsFields[key].type
if (defaultOptionsFields[key].type === 'checkbox') fieldOptions['ui:widget'] = 'checkboxes'
if (defaultOptionsFields[key].rows) {
fieldOptions['ui:options']= {
widget: 'textarea',
rows: defaultOptionsFields[key].rows,
}
}

UiSchema[key] = fieldOptions
}
// console.log('purity_other ui schema::', UiSchema.purity_other)

return { defaultSchemaProperties, defaultOptionsFields }
// return { adjustedSchemaProperties, UiSchema }

return UiSchema
return {
"purity": {
"ui:classNames": "mb-4",
"ui:inputType": "radio",
// "Other": {
// "Other": {
// "ui:widget": "text"
// }
// },
},
'purity_other': {
"ui:classNames": "mb-4",
// "purity_other": {
// "ui:classNames": "mb-4",
// "ui:inputType": "radio",
// "Other": {
// "description": {
"ui:widget": "text",
"ui:placeholder": "Other"
// }
// }
// },
}
}
}
6 changes: 3 additions & 3 deletions utils/api/requests.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ export const useFiles = (id, accessToken) => {
}
}


export const useInitializeRequest = (id, accessToken) => {
const { data, error } = useSWR(accessToken ? [`/wares/${id}/quote_groups/new.json`, accessToken] : null)
let dynamicForm = { name: data?.name }
Expand All @@ -127,12 +126,13 @@ export const useInitializeRequest = (id, accessToken) => {
if (dynamicFormInfo) {
const defaultSchema = dynamicFormInfo.schema
const defaultOptions = dynamicFormInfo.options
const schema = configureDynamicFormSchema(defaultSchema)
const { adjustedSchemaProperties, uiSchema } = configureDynamicFormUiSchema(defaultSchema.properties, defaultOptions.fields)
const schema = configureDynamicFormSchema({...defaultSchema, ...adjustedSchemaProperties})

dynamicForm = {
...dynamicForm,
schema,
uiSchema: configureDynamicFormUiSchema(schema, defaultOptions),
uiSchema,
}
}

Expand Down
8 changes: 7 additions & 1 deletion utils/theme/globals.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ footer {
margin-top: auto;
}

.form-group.field-array .checkbox input {
.form-group {
legend {
font-size: 16px;
}

.checkbox input {
margin-right: 10px;
}
}
Loading