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

feat: Dedicated styles for locked editor graph and modal #4312

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

Conversation

ianjon3s
Copy link
Contributor

@ianjon3s ianjon3s commented Feb 13, 2025

What does this PR do?

  • Sets styles for non-editable graph + components (to be shared with templates)
  • Configures editor modal to have disabled inputs when non-editable (only "Section" component done so far)

Preview:
https://4312.planx.pizza/barnet/apply-for-prior-approval

Copy link

github-actions bot commented Feb 13, 2025

Pizza

Deployed 604a35b to https://4312.planx.pizza.

Useful links:

@ianjon3s ianjon3s force-pushed the ian/locked-editor-graph-and-modal branch from 04e16d0 to 436b27c Compare February 13, 2025 14:25
@@ -14,6 +15,8 @@ import { parseSection, Section } from "./model";

type Props = EditorProps<TYPES.Section, Section>;

const teamSlug = window.location.pathname.split("/")[1];
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd expect to get the team slug from the store rather than the pathname on the page (i.e. maintaining that the store is our source of truth which feeds into everything else, including the pathname).

There are examples in other files of getting both the team and the canUserEditTeam function from the store at once, e.g.

const [teamSlug, canUserEditTeam] = useStore((state) => [
    state.teamSlug,
    state.canUserEditTeam,
    ])
    
     canUserEditTeam(teamSlug)
    ...
    

Copy link
Contributor

@DafyddLlyr DafyddLlyr left a comment

Choose a reason for hiding this comment

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

Addressing your question from Slack here -

The question I have from a technical perspective, to achieve the "can't edit" state I'm using

const teamSlug = window.location.pathname.split("/")[1];

Then conditionally showing an input as disabled:

disabled={!useStore.getState().canUserEditTeam(teamSlug)}

This instinctively feels like repetitive or non-systemised way of doing things, what are people's thoughts on this?

You've perfectly identified the challenge here! We have a large number of inputs (and possibly other components) that will need to change their appearances and behaviours based on the modal being in a read-only / disabled view or not.

This approach of handling everything and repeating the check at the most granular level is indeed error prone for the following reasons -

  • Easy to miss an input, or to misconfigure them
  • Difficult to update them all if our definition of "read-only / disabled" changes

Here's how I think we can solve this. If we set a property once at the highest level of the modal, with a single permission check, we can then cascade this value down into all children in a consistent manner. We'll still have the slightly tedious exercise of passing this prop to the right place once but there's no real getting around that one.

This might look something like this -

  • Set permission level once in FormModal.tsx
  • Use this value instead of the multiple instances of !useStore.getState().canUserEditTeam(teamSlug) already here
    • We should probably make a new store function with a better name - maybe canUserEditNode() - right now it just needs to check the team/role permissions but this function could also encapsulate the logic for checking flow customisations in future
    • This is very much another task in future we can pick up as part of the template work - just trying to illustrate how we would end up with one place where we could decided what "permission to edit" really means. The definition will change over time and it's nice to have a single place to do this.
  • Pass disabled as a prop into <Component>
  • Update EditorProps<Type, Data> interface to have a disabled prop

I'm very happy for you to pick up this task and run with it - hopefully there's enough information here to work from. If not, we can pair/share/troubleshoot. Also very happy to pick up this code structure task if you'd prefer - whatever's best for you 👍

@ianjon3s
Copy link
Contributor Author

ianjon3s commented Feb 14, 2025

@DafyddLlyr @jamdelion , thanks both for your comments and guidance.

I've refactored this so that the disabled state is now controlled from FormModal.tsx based on user permission.

This is working for the Section and Find property components:
https://4312.planx.pizza/barnet/apply-for-prior-approval/nodes/_root/nodes/f9HnFqX403/edit
https://4312.planx.pizza/barnet/apply-for-prior-approval/nodes/_root/nodes/T1zEiqX403/edit

If this approach is the correct one I'll continue to work through the other components to correctly apply the disabled state.

I was able to apply the disabled state to the tag selector but this caused tests to fail, I'll need some assistance with this eventually as I'm not familiar with the logic required for multiple test scenarios.

Copy link
Contributor

@DafyddLlyr DafyddLlyr left a comment

Choose a reason for hiding this comment

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

Looking great - this is exactly what I had in mind 🙌

@@ -6,6 +6,7 @@ export interface EditorProps<Type, Data> {
id?: string;
handleSubmit?: (data: { type: Type; data: Data }) => void;
node?: any;
disabled?: boolean;
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
disabled?: boolean;
disabled: boolean;

We'll eventually want to make this mandatory. Having it optional for now allows you to fix a component at a time however. Something to make required just before opening for review I think 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

Just seen this comment applies a few times throughout this PR!

@@ -143,8 +143,11 @@ const FormModal: React.FC<{
]);
const handleClose = () => navigate(rootFlowPath(true));

// useStore.getState().getTeam().slug undefined here, use window instead
const teamSlug = window.location.pathname.split("/")[1];
const teamSlug = useStore.getState().getTeam().slug;
Copy link
Contributor

Choose a reason for hiding this comment

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

Have you had any issues with this method? The comment this replaces suggests there might be an issue with using the store. Not sure of the original source of this, just flagging!

Copy link
Contributor Author

@ianjon3s ianjon3s Feb 18, 2025

Choose a reason for hiding this comment

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

I've not had any issues getting this from the store, I'll keep on eye on this though.

@@ -40,7 +40,7 @@ import {
linkSelectionError,
} from "./validationHelpers";

const RichTextInput: FC<Props> = (props) => {
const RichTextInput: FC<Props & { disabled?: boolean }> = (props) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd modify Props directly here as opposed to extending this just in-line.

@ianjon3s ianjon3s force-pushed the ian/locked-editor-graph-and-modal branch 2 times, most recently from fb6d935 to fb1bb13 Compare February 20, 2025 15:54
@ianjon3s ianjon3s force-pushed the ian/locked-editor-graph-and-modal branch from 3df17d4 to 52801e1 Compare February 21, 2025 10:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants