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: multiple project managers #304

Merged
merged 25 commits into from
Mar 9, 2022

Conversation

dleard
Copy link
Contributor

@dleard dleard commented Feb 28, 2022

Allows adding multiple managers to a project.

addManagerToRevision and deleteManagerFromRevision mutations have a query in the mutation return. The record returned from projectManagerFormChangesByLabel is a composite return value that doesn't represent an actual single database record. This means that we can't use the connection directive to update the data. We may want to look into subscriptions at some point. I think they may end up being necessary to handle concurrent editing.

We could also look into using refetchable fragments to refresh the ProjectManagerForm fragment, though it kind of sounds like this is essentially the same as adding a query to the mutation return.

@dleard dleard marked this pull request as ready for review February 28, 2022 23:02
{projectRevision.managerFormChanges.edges.map(({ node }) => (
<React.Fragment key={node.projectManagerLabel.id}>
<Grid.Row>
<label>{node.projectManagerLabel.label}</label>
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
<label>{node.projectManagerLabel.label}</label>
<label htmlFor={your_select_id}>{node.projectManagerLabel.label} (optional)</label>

In the current behaviour, all managers are optional, so this should be reflected in the label.
We do have a FieldLabel component, which could be reused here. At least the getRequiredLabel function could be reused.

app/components/Form/ProjectManagerForm.tsx Show resolved Hide resolved
size="small"
onClick={() => deleteManager(node.formChange?.id)}
>
Clear
Copy link
Contributor

Choose a reason for hiding this comment

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

should be disabled if there is no manager selected, or if the mutation is already in flight for this manager. You may need to refactor the react fragment into a separate component to track individual mutations

Copy link
Contributor

@pbastia pbastia Mar 3, 2022

Choose a reason for hiding this comment

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

As an alternative, we could also make the clear button a noop if the mutation is in flight or if there is no manager selected, I don't think that would harm the UX, things would be cleared again from the user's perspective

@@ -1,4 +1,5 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
Copy link
Contributor

@matthieu-foucault matthieu-foucault Mar 3, 2022

Choose a reason for hiding this comment

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

you need to update your local yarn packages. This was removed in the latest nextjs update

},
});
});

Copy link
Contributor

Choose a reason for hiding this comment

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

We're missing a test that makes sure the updateFormChangeMutation is called when we update a dropdown field without clearing it

Copy link
Contributor

@pbastia pbastia left a comment

Choose a reason for hiding this comment

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

Nice! 👌 Just missing a small test

@dleard dleard force-pushed the feat/multiple-project-managers branch from 60161af to aef7b35 Compare March 4, 2022 00:12
Comment on lines 23 to 37
projectRevision(id: $projectRevision) {
managerFormChanges: projectManagerFormChangesByLabel {
edges {
node {
projectManagerLabel {
id
rowId
label
}
formChange {
id
newFormData
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

https://bcgov-cas.promyze.app/#/CAS%20GGIRCS/home?practiceId=61e1eb156e4cd70fe286ec9f
You could reuse ProjectManagerForm_query here, or, if that fragment was split in two, ProjectManagerForm_projectRevision

// Delete a manager from the project revision
const [discardFormChange] = useDeleteManagerFromRevisionMutation();
const deleteManager = (id: string) => {
discardFormChange({
Copy link
Contributor

Choose a reason for hiding this comment

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

The action here needs to depend on the form_change operation:

  • If operation === "CREATE", then you can discard it, as the manager was added in the same revision
  • If operation === "UPDATE", then the form_change.operation should be updated to ARCHIVE

@dleard dleard force-pushed the feat/multiple-project-managers branch from fb9f614 to 3ef1b05 Compare March 8, 2022 21:31
Copy link
Contributor

@matthieu-foucault matthieu-foucault left a comment

Choose a reason for hiding this comment

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

Haven't done a pass on the code yet, but there's an issue with the screenshots:
image

"required" validation should not show if this is optional

// If a form_change exists, and the payload does not contain a cifUserId delete it
else if (formChangeId && !formChange.cifUserId && !discardInFlight) {
deleteManager(formChangeId);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel this entire pattern of creating / updating / deleting form changes depending on whether we have a certain field or not will be reused over and over, just a noting a thought for later on how we could reuse that logic

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, this may be refactored into a hook. We can do that after we have two examples of this pattern (there will be a second one in #280 )

Copy link
Contributor

@matthieu-foucault matthieu-foucault left a comment

Choose a reason for hiding this comment

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

-- nvm -- reviewing too many PRs in parallel

revision={query.projectRevision}
projectManagerFormRef={projectManagerFormRef}
setValidatingForm={(validator) =>
(projectManagerFormRef.current = validator)
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 really like to find better wording for this function / callback if you have ideas, I'm quite unhappy with what I chose when I first implemented it.
This is just confusing

@matthieu-foucault matthieu-foucault dismissed their stale review March 9, 2022 00:18

Too many tabs, wrong PR

Copy link
Contributor

@pbastia pbastia left a comment

Choose a reason for hiding this comment

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

looks good! I'll let @matthieu-foucault approve if he has more comments

pbastia
pbastia previously approved these changes Mar 9, 2022
@dleard dleard force-pushed the feat/multiple-project-managers branch from 249c692 to c82b5c0 Compare March 9, 2022 00:46
Comment on lines 30 to 37
allCifUsers {
edges {
node {
rowId
firstName
lastName
}
}
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 this removed? You should have two fragments instead of passing allCifUsers as a prop, no? You can use useFragment multiple times in the same component.

Comment on lines 19 to 34
const { allCifUsers } = useFragment(
graphql`
fragment ProjectManagerFormGroup_query on Query {
allCifUsers {
edges {
node {
rowId
firstName
lastName
}
}
}
}
`,
props.query
);
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 this fragment here and not in the child component?

Comment on lines 90 to 98
:global(button.pg-button) {
margin-left: 0.4em;
margin-right: 0em;
}
:global(.right-aligned-column) {
display: flex;
justify-content: flex-end;
align-items: flex-start;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

See #324 (comment)
I think that we need to use an outer div to scope those styles, otherwise they're no better than if you used <style jsx global> (I could be wrong though, haven't fully tested this)

Comment on lines 225 to 226
<>
<React.Fragment key={change.projectManagerLabel.id}>
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't need those two fragments

@matthieu-foucault matthieu-foucault merged commit e9dd666 into develop Mar 9, 2022
@matthieu-foucault matthieu-foucault deleted the feat/multiple-project-managers branch March 9, 2022 19:42
@bc-cas-shipit bc-cas-shipit bot temporarily deployed to dev March 9, 2022 20:16 Inactive
@bc-cas-shipit bc-cas-shipit bot temporarily deployed to test March 15, 2022 22:23 Inactive
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