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

Doc(adr): move formFields from CMS into app #1339

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

chohner
Copy link
Member

@chohner chohner commented Oct 22, 2024

Copy link
Contributor

@rbrtrfl rbrtrfl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting concept. I'm not sure I'd be in favour of implementing it without the “synchronize form fields” feature 🤷

doc/adr/0013-pageConfig-inside-application.md Outdated Show resolved Hide resolved
doc/adr/0013-pageConfig-inside-application.md Outdated Show resolved Hide resolved
doc/adr/0013-pageConfig-inside-application.md Outdated Show resolved Hide resolved
doc/adr/0013-pageConfig-inside-application.md Outdated Show resolved Hide resolved
doc/adr/0013-pageConfig-inside-application.md Outdated Show resolved Hide resolved
doc/adr/0013-pageConfig-inside-application.md Outdated Show resolved Hide resolved
doc/adr/0013-pageConfig-inside-application.md Outdated Show resolved Hide resolved
doc/adr/0013-pageConfig-inside-application.md Outdated Show resolved Hide resolved
doc/adr/0013-pageConfig-inside-application.md Outdated Show resolved Hide resolved
doc/adr/0013-pageConfig-inside-application.md Outdated Show resolved Hide resolved
Copy link
Member

@frederike-ramin frederike-ramin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably too tired for doing a PR review, but here you go. ;)

doc/adr/0013-pageConfig-inside-application.md Outdated Show resolved Hide resolved

Loader->>CMS: GET(slug)
CMS-->>Loader: content, fieldnames, formLabels
Loader->>Frontend: content, fieldnames, formLabels
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better word than "Frontend"? It's very generic. Is this the ValidatedForm maybe?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought staying generic might be less confusing than specifying the exact consumer of each (between the nested page/form/field components)...

Comment on lines 17 to 23
- `stepSchema`: All schemas required for a single page, e.g.:
```typescript
{
hasAnwalt: z.enum(["yes", "no"]) },
hasContacted: z.enum(["yes", "no"]) },
}
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that concept currently exists? The schemaStore merely returns a list of validations?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The word does not exist but we do build a validation for exactly the formData object (not a list)

CMS-->>Loader: content, fieldnames, formLabels
Loader->>Frontend: content, fieldnames, formLabels
Frontend->>SchemaStore: fieldnames
SchemaStore->>Frontend: stepSchema
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe to make it more clear a self-loop with "validation" would help? To be clear what the schemas are even used for in the frontend?

doc/adr/0013-pageConfig-inside-application.md Outdated Show resolved Hide resolved
doc/adr/0013-pageConfig-inside-application.md Outdated Show resolved Hide resolved

- Its hard to understand where which fields are filled out on what page (requires manually checking the CMS)
- The app **cannot** know why fields where seen when traversing a flow (pruner needs to request the CMS)
- The app **cannot** work without the CMS
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really the only point that keeps us from showing pages without content? If we do the change, this problem doesn't exist anymore?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I.. think so? can't think of anything else 🤔

doc/adr/0013-pageConfig-inside-application.md Outdated Show resolved Hide resolved
### Pros:

- Full decoupling of domains (flow configuration vs content)
- Follows mental model of domain driven architecture
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that so? How?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rephrased, does it make more sense?


- `fieldname`: the name of a field in the form, e.g. `hasAnwalt`
- `fieldSchema`: Combination of fieldname and its schema, e.g. `hasAnwalt: z.enum(["yes", "no"]) }`
- `stepSchema`: All schemas required for a single page, e.g.:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still wondering if we could go one step further and not only represent pages this way but pages within whole subflows. Such as:

anwaltlicheVertretung: {
  anwaltEntscheidung: {
    hasAnwalt: z.enum(["yes", "no"]) },
    hasContacted: z.enum(["yes", "no"]) },
  }
}

That would mean that we could validate whole sub-areas of the flow by checking only for anwaltlicheVertretung and gathering all fields in there.
I don't know, probably a thought for the future as this is not that well thought-out, still wanted to leave it here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow - but I have to admit, nested schemas (and arrays) are still not prototyped using this approach.

Right now I think we could either encode them the way you showed (which matches our current userInputSchemas) or do it like in the CMS (eg anwaltEntscheidung.hasAnwalt: z.enum(["yes", "no"]) }).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's essentially the same thing? With the first option just giving us more variety (because you can define things on the object-level)?
But yes, this is probably just one step further and not part of this ADR necessarily

Copy link
Contributor

@aaschlote aaschlote left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm bit confusing about the two parts:

  1. How the associate the fieldNames from the app with the CMS
  2. How these changes will improve the developer experience. The changes sounds huge and it's not clear if it worth to do it. I would need some examples before to approve it.

Another thing we need to think, it's about how to move all the contexts to stepSchema (please think about a better name), because it exists a lot of fields in the current flows, specially for beratungshilfe and flugggastrechte. How we will need to do all the change without break the application.

- `field`: A user-facing input that appears on a page inside a flow
- `fieldName`: the name of a field in the form, e.g. `hasAnwalt`
- `fieldSchema`: Combination of field name and its schema, e.g. `hasAnwalt: z.enum(["yes", "no"]) }`
- `fieldLabel`: The user-facing string associated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- `fieldLabel`: The user-facing string associated
- `fieldLabel`: Description value render on the UI. Value can be optional for a few components.


Loader->>PageConfig: pathname
PageConfig->>Loader: fieldNames
Loader->>CMS: GET(pathname, fieldNames)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me still not clear how the fieldNames will be connected with CMS. Can you better explain this integration? And where the validation should be set? In the CMS or source code?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this is confusing because we probably wouldn't send the fieldnames right now (as they already exist on each flow page). The schemas continue to live in the app just like they do now

doc/adr/0013-pageConfig-inside-application.md Show resolved Hide resolved
const pages = {
anwalt: {
stepId: "/anwalt",
stepSchema: { hasAnwalt: z.enum(["yes", "no"]) },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are going to associate the values and translation from Strapi? Or it's going to be as it's?

Copy link
Member Author

@chohner chohner Oct 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally I think our data model in strapi also needs to be refactored, but I didn't want to include this in this ADR (and also not create another ADR, we already have a lot...).

So for now I propose to leave as is because each flow page in Strapi already contains the correct labels etc.

But I could be convinced to park this ADR in favor of restructuring our CMS first (I think @rbrtrfl prefers that too)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so should we first restructuring our CMS first before to make the change proposal in this ADR?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont have a strong opinion on the order, however I have the feeling restructuring the CMS is probably going to be a bigger task and I think the benefits of this are useful already.

But I would be fine with either order


## Consequences

### Pros:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How this changes would improve the development process?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having an understanding of which page fills out which field is going to be useful when reasoning about flow logic. And creating new flows should be much faster.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean about the flow logic, only if I use the .ts instead of .json for the configuration of the xstate?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this would apply to any flow. I think this will become more of a problem as we add more flows because its will get harder and harder to remember with field comes from which page

const pages = {
anwalt: {
stepId: "/anwalt",
stepSchema: { hasAnwalt: z.enum(["yes", "no"]) },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is called stepSchema? Those are not fieldSchema? Not sure why we have decided for the name step. It bring a bit of confusion when I need to explain it for other people, specially for non engineers.

Copy link
Member Author

@chohner chohner Oct 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its the collection of all fieldSchemas for specific step. For Example:

const airportStepSchema = {
	startAirport: z.string(),
	endAirport: z.string(),
}

startAirport and endAirport would each be a fieldSchema and airportsSchema would be a stepSchema. Maybe pageSchema is a better name?

Note: This construct already exists as the return value of validatorFromFieldnames but is generated on the fly and therefore quite hidden

doc/adr/0013-pageConfig-inside-application.md Show resolved Hide resolved
doc/adr/0013-pageConfig-inside-application.md Show resolved Hide resolved

- Domain driven architecture: Full decoupling of flow configuration from content
- Reduced mental load when reasoning about form fields and their position inside the flow
- App works without CMS (pruner, prototyping, ...)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am unsure if "App works without CMS" is a good thing. If the app can function without the CMS, does that mean it might not alert us to issues with missing content? Since content is essential to delivering value to users, wouldn’t it be better for the app to indicate when the CMS isn’t working or content is missing? This way, we’d catch potential issues during testing or production instead of relying on users to report them. or maybe I understood it differently?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course altering of missing content should still happen. but we shouldn't need to crash the whole application, especially when prototyping. Also the pruner shouldn't need to rely on the CMS

@chohner chohner marked this pull request as draft November 7, 2024 10:40
@chohner chohner changed the title Doc(adr): pageConfig inside application Doc(adr): move formFields from CMS into app Nov 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants