-
Notifications
You must be signed in to change notification settings - Fork 5
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
[JN-1020] Admin form editing #894
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work on all the code rearranging! Overall, code looks good. Some minor suggestions. Only commenting for now because, as you said, I want to take a lot of time to test this code out
.surveyId(survey.getId()) | ||
.complete(responseDto.isComplete()) | ||
.resumeData(responseDto.getResumeData()) | ||
.build(); | ||
Optional.ofNullable(operator.getParticipantUser()).ifPresent(pUser -> newResponse.setCreatingParticipantUserId(pUser.getId())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a standard if/else
is more appropriate here -- we're not doing any chaining so the functional wrapper makes if harder to pinpoint the if logic--but maybe that's just me. Connor, what's your take? Better yet, add a "setResponsibleUser" method to SurveyResponse that takes a responsibleEntity and sets the ids appropriately. That method might then be reused via interface with Answer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm... I like the setResponsibleUser
on the survey response approach. That mirrors (iirc) the flow on the data audit info. I don't feel super strongly on if/else
, but I agree it might make the logic clearer.
Store.addNotification(successNotification('Response saved')) | ||
}} | ||
onFailure={() => Store.addNotification(failureNotification('Response could not be saved'))} | ||
updateProfile={() => {}} //eslint-disable-line @typescript-eslint/no-empty-function |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can avoid the typescript warning by having it return null or true, or some other simple value
updateProfile={() => {}} //eslint-disable-line @typescript-eslint/no-empty-function | |
updateProfile={() => null} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you an also have a commment on the inside
() => {
// todo
}
|
||
/** allows editing of a survey response */ | ||
export default function SurveyEditView({ response, survey }: {response: SurveyResponse, survey: Survey}) { | ||
console.log(`not implemented ${response.surveyId} ${survey.stableId}`) | ||
export default function SurveyEditView({ studyEnvContext, response, survey, enrollee, adminUserId, onUpdate }: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's rename this to SurveyResponseEditor to avoid confusion with the form editor
|
||
/** Show responses for a survey based on url param */ | ||
export default function EnrolleeSurveyView({ enrollee, responseMap, studyEnvContext }: | ||
{enrollee: Enrollee, responseMap: ResponseMapT, studyEnvContext: StudyEnvContextT}) { | ||
export default function EnrolleeSurveyView({ enrollee, responseMap, studyEnvContext, onUpdate }: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SurveyResponseView might be a better name for this component
Initial testing seems solid -- I had tabs open to admin and participant view of the same survey and was taking turns editing both, and it always saved the answers, which were then available to the other side upon refresh. (which is desired behavior -- CMI confirmed earlier they do not want a google-docs-like shared editing experience. They'd rather risk accidental overwrites than have a patient jarred by seeing their data change in front of them |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
worked great! a really impressive lift, excited to see the final product. also commenting for now, ran into some bugs. i'll be gone all next week, though, so if devon gives it a thumb then consider it worthy 😄
|
||
export * from './test-utils/asMockedFn' | ||
export * from './test-utils/router-testing-utils' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that we already had some testing stuff in core's index file, but I wonder if we should break this out into something like @ui-core/testing
: it seems weird (to me) to have testing utils interspersed with the core app functionality. That is probably out of the scope of this PR, though.
import { Enrollee } from 'src/types/user' | ||
import { Profile } from 'src/types/address' | ||
|
||
const AUTO_SAVE_INTERVAL = 3 * 1000 // auto-save every 3 seconds if there are changes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still wary of relying on autosave for editing participant data, since it seems like a "thing we should not do often", but CMI folks seemed to not mind, so 🤷 . It definitely makes sense in regards to admin-only forms, though.
envName: EnvironmentName, | ||
profile?: Profile, | ||
proxyProfile?: Profile, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sad that we have to move these to the parameters :( these are so easy to forget, as evidenced by the preenroll breaking. it would be so cool if there was some way to allow useUser
/useActiveUser
to still function in core.
It feels like more and more things are moving to core as we start to allow the admins to do more of the participant experience in the admin side. As such, I suspect we might start running into more cases like this where we have to awkwardly pass down user information to things in core. it would be cool if these hooks worked in the admin app but returned nothing except for the cases that you are looking at an enrollee's page, then it would return the appropriate user.
potentially, we could rename them to useParticipantUser
and useActiveParticipantUser
so that it's more clear in the admin side that they are only available when you're viewing a specific participant? dunno just spitballing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
100% agree that the parameter list on this is way too burdensome. hooks are an interesting idea here, let me see what I can do to clean it up (but i may defer that work to a followup PR though since this branch is super vulnerable to merge conflicts)
ui-core/src/types/address.ts
Outdated
@@ -17,3 +17,17 @@ export type AddressValidationResult = { | |||
hasInferredComponents?: boolean, | |||
vacant?: boolean | |||
} | |||
|
|||
export type Profile = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be in user.ts
?
creatingAdminUserId: string | ||
} | ||
|
||
export type Enrollee = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's goooooooooo
import { SurveyResponse } from 'src/types/forms' | ||
import { StudyEnvParams } from 'src/types/study' | ||
import { HubResponse } from 'src/types/user' | ||
import { AddressValidationResult, MailingAddress } from 'src/types/address' | ||
|
||
export type ImageUrlFunc = (cleanFileName: string, version: number) => string | ||
export type SubmitMailingListContactFunc = (name: string, email: string) => Promise<object> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried the e2e tests (and then tried it myself) and found that, oddly, I couldn't add myself to the mailing list. It wouldn't error in the participant side, but it didn't show up on the admin side. I tried on dev and it worked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm unable to reproduce this locally or with the e2e tests.
Devon, do you see this as well?
onChange={e => updateWorkingForm({ | ||
...workingForm, allowAdminEdit: e.target.checked | ||
})} | ||
/> Allow admin completion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The word completion
feels weird to me, especially when half of the time we really mean admins can edit this participant's responses, but should only edit one small thing
not complete it on behalf of them
- Imo, this would make more sense to me as a radio group
opt 1 - Participant-only form (e.g., consent form)
opt 2 - Admin-editable participant survey (e.g., demographics)
opt 3 - Admin-only survey (e.g., medical records)
This also eliminates the weird possibility of a form being editable by no one haha
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed- this will definitely be touched up in a followup UX PR
} | ||
}> | ||
{isEditing ? | ||
<div><FontAwesomeIcon icon={faX}/> Cancel</div> : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me this feels more like Complete
or Finish
button since the changes are already saved - but that's probably more of a UX concern.
undefined, | ||
undefined, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we actually do need to pass these in, if they exist - they are used to prefill proxy/governed user name in the case of adding a new proxy or signing yourself up as a governed user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice, let's get this merged so we have time to poke at it!
Quality Gate passedIssues Measures |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Admin survey editing good to merge.
DESCRIPTION (include screenshots, and mobile screenshots for participant UX)
Adds support for admin form editing. As a result, this brings a lot of survey-related infrastructure and types into ui-core.
OUT OF SCOPE: a refined admin UX. This PR is massive and challenging to review as-is, the focus here is just getting the survey infrastructure into core along with all of the related dependencies. Refined UX will come in follow-on PRs.
This needs some extra attention when testing the participant side to ensure that there weren't any regressions. This branch has also undergone several notable rebases during it's life, and accounting for newer changes during a rebase while also moving them ui-core is particularly vulnerable to dropping new functionality. Some areas worth calling out:
TO TEST: (simple manual steps for confirming core behavior -- used for pre-release checks)
More specific steps coming soon, but definitely focus on the above areas.