Skip to content

Commit 7221f87

Browse files
authored
Add comments field to MCC request (#109)
* Add comments field to MCC request
1 parent 440832f commit 7221f87

12 files changed

Lines changed: 160 additions & 16 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE mcc.animalrequests add comments varchar(4000);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE mcc.animalrequests add comments varchar(4000);

mcc/resources/schemas/mcc.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,10 @@
373373
<columnTitle>IACUC Protocol #</columnTitle>
374374
<nullable>true</nullable>
375375
</column>
376+
<column columnName="comments">
377+
<columnTitle>Other Comments</columnTitle>
378+
<nullable>true</nullable>
379+
</column>
376380
<column columnName="status">
377381
<defaultValue>Draft</defaultValue>
378382
</column>

mcc/resources/views/mccRequests.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
return;
88

99
Ext4.get(webpart.wrapperDivId).update(
10-
'The MCC is now accepting animal requests! Investigators interested in requesting marmosets for their research can submit applications via the animal request portal. Please note, while you are encouraged to submit your requests now, the review process will not begin until June 2022, and the first animals will not be available until at least September 2022. Investigators can anticipate the estimated cost for getting marmosets to be about $5K USD per animal plus $8-10K USD for shipping. Please note that this is an estimate and the actual cost is determined by the breeding centers and shipping can vary based on distance.' +
10+
'The MCC is now accepting animal requests! Investigators interested in requesting marmosets for their research can submit applications via the animal request portal.<br><br>' +
11+
'<span style="font-weight: bold">Investigators can anticipate the estimated cost for getting marmosets to be about $5,500 USD per animal plus approximately $10,000 USD for shipping. Please note that this is an estimate and the actual cost is determined by the breeding centers and shipping can vary based on distance.</span>' +
1112
'<p></p>' +
1213
'<a class="labkey-text-link" href="<%=contextPath%>/mcc' + ctx['MCCRequestContainer'] + '/animalRequest.view">Submit New Animal Request</a><br>' +
1314
'<a class="labkey-text-link" href="/become-a-user.html#request-animals">Click Here to View Documentation on the Request Process and Scoring Criteria</a>' +

mcc/src/client/AnimalRequest/animal-request.tsx

Lines changed: 77 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { FormEvent, useState } from 'react';
1+
import React, { FormEvent, useRef, useState } from 'react';
22
import { ActionURL, getServerContext, Query } from '@labkey/api';
33
import {
44
AnimalCohort,
@@ -21,32 +21,46 @@ import AnimalCohorts from './components/animal-cohort';
2121
import Button from './components/button';
2222
import SavingOverlay from './saving-overlay';
2323
import ErrorMessageHandler from './components/error-message-handler';
24+
import {
25+
Box,
26+
Dialog,
27+
DialogActions,
28+
DialogContent,
29+
DialogContentText,
30+
DialogTitle, TextareaAutosize,
31+
TextField
32+
} from '@material-ui/core';
2433

2534
import {
2635
animalWellfarePlaceholder,
36+
censusToolTip,
2737
certificationLabel,
28-
terminalProceduresLabel,
2938
collaborationsPlaceholder,
39+
commentsPlaceholder,
3040
earlyInvestigatorTooltip,
3141
existingMarmosetColonyOptions,
3242
existingNHPFacilityOptions,
3343
experimentalRationalePlaceholder,
3444
institutionTypeOptions,
3545
methodsProposedPlaceholder,
36-
signingOfficialTooltip, censusToolTip
46+
signingOfficialTooltip,
47+
terminalProceduresLabel
3748
} from './components/values';
3849
import AnimalCensus from './components/census';
3950

4051
export function AnimalRequest() {
4152
const requestId = (new URLSearchParams(window.location.search)).get("requestId")
4253

54+
const [showWithdrawDialog, setShowWithdrawDialog] = useState(false)
55+
const [withdrawReasonText, setWithdrawReasonText] = useState<string>(null)
4356
const [isSubmitting, setIsSubmitting] = useState(false)
4457
const [displayOverlay, setDisplayOverlay] = useState(false)
4558
const [requestData, setRequestData] = useState<AnimalRequestModel>(null)
4659
const [stateRollbackOnFailure, setStateRollbackOnFailure] = useState(requestData?.request?.status)
4760

4861
const [ deletedCohortRecords, setDeletedCohortRecords ] = useState(new Set<number>())
4962
const [ deletedCoIRecords, setDeletedCoIRecords ] = useState(new Set<number>())
63+
const formRef = useRef(null)
5064

5165
function onAddCohort() {
5266
requestData.cohorts.push(new AnimalCohort())
@@ -114,7 +128,7 @@ export function AnimalRequest() {
114128
}
115129

116130
function doEnforceRequiredFields() {
117-
return isSubmitting || requestData.request.status !== "Draft"
131+
return "Withdrawn" === requestData.request.status ? false : isSubmitting || requestData.request.status !== "Draft"
118132
}
119133

120134
// The general idea is that users with MCCRequestAdminPermission can edit all states.
@@ -250,8 +264,8 @@ export function AnimalRequest() {
250264
setRequestData({...requestData})
251265
}
252266
}
253-
254-
const el = e.currentTarget as HTMLFormElement
267+
268+
const el = formRef.current as HTMLFormElement
255269
const data = new FormData(el)
256270
el.querySelectorAll<HTMLSelectElement>('select[multiple]').forEach(function(x){
257271
data.set(x.id, Array.from(x.selectedOptions, option => option.value).join(','))
@@ -313,6 +327,7 @@ export function AnimalRequest() {
313327
"iacucprotocol": data.get("iacuc-protocol"),
314328
"grantnumber" : data.get("funding-grant-number"),
315329
"applicationduedate": data.get("funding-application-due-date"),
330+
"comments": data.get("comments"),
316331
"status": requestData.request.status,
317332
}]
318333
},
@@ -333,8 +348,8 @@ export function AnimalRequest() {
333348
requestData.request.rowid = rowId
334349
}
335350

336-
if (response.result[0].rows[0].rowid.status) {
337-
requestData.request.status = response.result[0].rows[0].rowid.status
351+
if (response.result[0].rows[0].status) {
352+
requestData.request.status = response.result[0].rows[0].status
338353
}
339354
else {
340355
console.error('Status was null for the animalrequest row after save. This is not expected.')
@@ -444,7 +459,7 @@ export function AnimalRequest() {
444459

445460
return (
446461
<>
447-
<form className="tw-w-full tw-max-w-4xl" onSubmit={handleSubmit} autoComplete="off">
462+
<form className="tw-w-full tw-max-w-4xl" onSubmit={handleSubmit} autoComplete="off" id={"animalRequestForm"} ref={formRef}>
448463
<h3>Overview</h3>
449464

450465
<Title text="1. Project Title*"/>
@@ -689,6 +704,15 @@ export function AnimalRequest() {
689704
<AnimalCensus id="census" isSubmitting={isSubmitting} required={doEnforceRequiredFields()} request={requestData.request}/>
690705
</div>
691706

707+
<Title text={"8. " + commentsPlaceholder}/>
708+
<div className="tw-w-full tw-px-3 tw-mb-6">
709+
<ErrorMessageHandler isSubmitting={isSubmitting}>
710+
<div className="tw-w-full tw-px-3 tw-mb-6">
711+
<TextArea id="comments" ariaLabel="Comments" isSubmitting={isSubmitting} placeholder={commentsPlaceholder} required={false} defaultValue={requestData.request.comments}/>
712+
</div>
713+
</ErrorMessageHandler>
714+
</div>
715+
692716
<div className="tw-flex tw-flex-wrap tw-mx-2">
693717
<Title text="Request Status: "/>{requestData.request.status}
694718
</div>
@@ -711,13 +735,54 @@ export function AnimalRequest() {
711735
}} text={getSubmitButtonText()} display={hasEditPermission()}/>
712736

713737
<Button onClick={(e) => {
714-
requestData.request.status = "withdrawn"
715-
handleSubmitButton(e, false);
716-
}} text={"Widthdraw"} display={shouldShowWithdraw()}/>
738+
e.preventDefault()
739+
setShowWithdrawDialog(true)
740+
}} text={"Withdraw"} display={shouldShowWithdraw()}/>
717741
</div>
718742
</form>
719743

720744
<SavingOverlay display={displayOverlay} />
745+
746+
<Dialog open={showWithdrawDialog}>
747+
<DialogTitle>Withdraw Request</DialogTitle>
748+
<DialogContent>
749+
<DialogContentText>Please enter a reason for withdrawing this request</DialogContentText>
750+
<TextareaAutosize
751+
minRows={4}
752+
id="withdrawReason"
753+
required={true}
754+
autoFocus={true}
755+
defaultValue={withdrawReasonText}
756+
form={"animalRequestForm"}
757+
onChange={(e) => setWithdrawReasonText(e.target.value)}
758+
/>
759+
</DialogContent>
760+
<DialogActions>
761+
<Box mr="5px">
762+
<Button onClick={(e) => {
763+
if (!withdrawReasonText) {
764+
alert("Must enter the reason")
765+
return
766+
}
767+
768+
// The record was never saved, so just leave the page
769+
if (!requestData.request.rowid) {
770+
e.preventDefault()
771+
window.location.href = ActionURL.buildURL('mcc', 'mccRequests.view')
772+
}
773+
else {
774+
requestData.request.status = "Withdrawn"
775+
formRef.current.querySelectorAll('#comments')[0].value = (requestData.request.comments ? requestData.request.comments + '\n' : '') + withdrawReasonText
776+
777+
setWithdrawReasonText(null)
778+
setShowWithdrawDialog(false)
779+
setIsSubmitting(true)
780+
}
781+
}} form={"animalRequestForm"} disabled={false} text={"Submit"}/>
782+
<Button onClick={(e) => setShowWithdrawDialog(false)} text={"Close"}/>
783+
</Box>
784+
</DialogActions>
785+
</Dialog>
721786
</>
722787
)
723788
}

mcc/src/client/AnimalRequest/components/button.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export default function Button(props) {
1414
} else {
1515
return (
1616
<button className="tw-ml-16 tw-bg-blue-500 hover:tw-bg-blue-400 tw-text-white tw-font-bold tw-py-4 tw-mt-2 tw-px-6 tw-border-none tw-rounded"
17-
onClick={(e) => onClick(e)}>{props.text}</button>
17+
onClick={(e) => onClick(e)} form={props.form}>{props.text}</button>
1818
)
1919
}
2020
}

mcc/src/client/AnimalRequest/components/values.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ export const otherCharacteristicsPlaceholder = "Other characteristics (ie. age,
88
export const methodsProposedPlaceholder = "Methods proposed and investigators' experience in the methods"
99
export const animalBreedingPlaceholder = "Purpose of the animal breeding program"
1010
export const collaborationsPlaceholder = "Any collaborations, pilot studies, and/or publications"
11+
12+
export const commentsPlaceholder = "Other comments"
1113
export const animalWellfarePlaceholder = "Animal welfare (proposed care and use)"
1214
export const censusReasonPlaceholder = "Reason for not participating"
1315

mcc/src/client/RequestReview/components/ReadOnlyRequest.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,12 @@ export default function ReadOnlyRequest(props: {requestData: AnimalRequestModel}
261261
<Grid item xs={10}>
262262
{requestData.request.censusreason || 'N/A'}
263263
</Grid>
264+
<Grid item xs={2} className={styles.fieldLabel}>
265+
Other Comments:
266+
</Grid>
267+
<Grid item xs={10}>
268+
{requestData.request.comments}
269+
</Grid>
264270
<Grid item xs={2} className={styles.fieldLabel}>
265271
Status:
266272
</Grid>

mcc/src/client/components/RequestUtils.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export class AnimalRequestProps {
4646
vetemail: string;
4747
vetfirstname: string;
4848
objectid: string;
49+
comments: string;
4950
}
5051

5152
export class CoInvestigatorModel {
@@ -122,6 +123,7 @@ export async function queryRequestInformation(requestId, handleFailure) {
122123
"iacucprotocol",
123124
"grantnumber",
124125
"applicationduedate",
126+
"comments",
125127
"status"
126128
],
127129
filterArray: [

mcc/src/org/labkey/mcc/MccModule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public String getName()
5959
@Override
6060
public @Nullable Double getSchemaVersion()
6161
{
62-
return 20.014;
62+
return 20.015;
6363
}
6464

6565
@Override

0 commit comments

Comments
 (0)