-
Notifications
You must be signed in to change notification settings - Fork 1
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
Paginate Operations Form #269
Changes from all commits
32ac6db
287f553
247c0d0
7c50c5d
f390087
db6bd95
40de665
5d78acb
51b1df5
f2035b1
29b398c
4474432
90b7c8d
462d79f
38de8f5
ea5e951
294ccce
e7331d2
c1fec7a
677c806
3fc8cda
44303ab
2de2304
6d2b837
fd3d738
ec29bfe
3d69ab2
bbaa6ec
2f68838
6965bb5
425f485
f0330c3
9659194
6828090
410877e
13824ea
636c158
2a5f7be
2406d79
70d5f4b
d03a2f0
4c1b8a0
a3e766d
0bd8830
a63d00d
123048c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Generated by Django 4.2.6 on 2023-11-22 23:59 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
dependencies = [ | ||
('registration', '0001_initial'), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterField( | ||
model_name='operation', | ||
name='status', | ||
field=models.CharField( | ||
choices=[ | ||
('not_registered', 'Not Registered'), | ||
('pending', 'Pending'), | ||
('approved', 'Approved'), | ||
('rejected', 'Rejected'), | ||
], | ||
db_comment='The status of an operation in the app (e.g. pending review)', | ||
default='not_registered', | ||
max_length=1000, | ||
), | ||
), | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Generated by Django 4.2.6 on 2023-11-23 00:11 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
dependencies = [ | ||
('registration', '0002_alter_operation_status'), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterField( | ||
model_name='operation', | ||
name='status', | ||
field=models.CharField( | ||
choices=[ | ||
('not_registered', 'Not Registered'), | ||
('pending', 'Pending'), | ||
('approved', 'Approved'), | ||
('rejected', 'Rejected'), | ||
], | ||
db_comment='The status of an operation in the app (e.g. pending review)', | ||
default='pending', | ||
max_length=1000, | ||
), | ||
), | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -90,10 +90,11 @@ def test_post_new_operation(self, client): | |
) | ||
post_response = client.post(self.endpoint, content_type=content_type_json, data=mock_operation.json()) | ||
assert post_response.status_code == 200 | ||
assert post_response.json() == {"name": "Springfield Nuclear Power Plant"} | ||
assert post_response.json().get('name') == "Springfield Nuclear Power Plant" | ||
assert post_response.json().get('id') is not None | ||
# check that the default status of pending was applied | ||
marcellmueller marked this conversation as resolved.
Show resolved
Hide resolved
|
||
get_response = client.get(self.endpoint).json()[0] | ||
assert 'status' in get_response and get_response['status'] == 'pending' | ||
assert 'status' in get_response and get_response['status'] == 'not_registered' | ||
|
||
def test_post_new_malformed_operation(self, client): | ||
response = client.post( | ||
|
@@ -105,7 +106,7 @@ def test_post_new_malformed_operation(self, client): | |
|
||
def test_put_operation_update_status_approved(self, client): | ||
operation = baker.make(Operation) | ||
assert operation.status == Operation.Statuses.PENDING | ||
assert operation.status == Operation.Statuses.NOT_REGISTERED | ||
|
||
url = self.build_update_status_url(operation_id=operation.id) | ||
|
||
|
@@ -128,7 +129,7 @@ def test_put_operation_update_status_approved(self, client): | |
|
||
def test_put_operation_update_status_rejected(self, client): | ||
operation = baker.make(Operation) | ||
assert operation.status == Operation.Statuses.PENDING | ||
assert operation.status == Operation.Statuses.NOT_REGISTERED | ||
|
||
url = self.build_update_status_url(operation_id=operation.id) | ||
|
||
|
@@ -151,7 +152,7 @@ def test_put_operation_update_status_rejected(self, client): | |
|
||
def test_put_operation_not_verified_when_not_registered(self, client): | ||
operation = baker.make(Operation) | ||
assert operation.status == Operation.Statuses.PENDING | ||
assert operation.status == Operation.Statuses.NOT_REGISTERED | ||
|
||
url = self.build_update_status_url(operation_id=operation.id) | ||
|
||
|
@@ -173,7 +174,7 @@ def test_put_operation_not_verified_when_not_registered(self, client): | |
def test_put_operation_update_status_invalid_data(self, client): | ||
def send_put_invalid_data(): | ||
operation = baker.make(Operation) | ||
assert operation.status == Operation.Statuses.PENDING | ||
assert operation.status == Operation.Statuses.NOT_REGISTERED | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need to check the default status so often? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure, I updated the original tests which were checking the default status and kept it in. |
||
|
||
url = self.build_update_status_url(operation_id=operation.id) | ||
|
||
|
@@ -198,7 +199,7 @@ def test_get_method_for_200_status(self, client): | |
response = client.get(self.endpoint + str(operation.id)) | ||
assert response.status_code == 200 | ||
|
||
def test_put_operation(self, client): | ||
def test_put_operation_without_submit(self, client): | ||
naics_code = baker.make(NaicsCode) | ||
naics_category = baker.make(NaicsCategory) | ||
document = baker.make(Document) | ||
|
@@ -229,15 +230,53 @@ def test_put_operation(self, client): | |
) | ||
|
||
response = client.put( | ||
self.endpoint + str(operation.id), content_type=content_type_json, data=mock_operation.json() | ||
self.endpoint + str(operation.id) + "?submit=false", | ||
content_type=content_type_json, | ||
data=mock_operation.json(), | ||
) | ||
assert response.status_code == 200 | ||
assert response.json() == {"name": "New name"} | ||
|
||
get_response = client.get(self.endpoint + str(operation.id)).json() | ||
assert get_response["status"] == Operation.Statuses.NOT_REGISTERED | ||
|
||
def test_put_operation_with_submit(self, client): | ||
naics_code = baker.make(NaicsCode) | ||
naics_category = baker.make(NaicsCategory) | ||
document = baker.make(Document) | ||
contact = baker.make(Contact, postal_code="V1V 1V2") | ||
operator = baker.make(Operator) | ||
activity = baker.make(ReportingActivity) | ||
operation = baker.make(Operation) | ||
operation.reporting_activities.set([activity.id]) | ||
|
||
mock_operation = OperationIn( | ||
name="New name", | ||
type="Single Facility Operation", | ||
naics_code_id=naics_code.id, | ||
reporting_activities=[1], | ||
regulated_products=[1], | ||
naics_category_id=naics_category.id, | ||
documents=[document.id], | ||
contacts=[contact.id], | ||
operator_id=operator.id, | ||
) | ||
|
||
response = client.put( | ||
self.endpoint + str(operation.id) + "?submit=true", | ||
content_type=content_type_json, | ||
data=mock_operation.json(), | ||
) | ||
assert response.status_code == 200 | ||
assert response.json() == {"name": "New name"} | ||
|
||
get_response = client.get(self.endpoint + str(operation.id)).json() | ||
assert get_response["status"] == Operation.Statuses.PENDING | ||
|
||
def test_put_malformed_operation(self, client): | ||
operation = baker.make(Operation) | ||
response = client.put( | ||
self.endpoint + str(operation.id), | ||
self.endpoint + str(operation.id) + "?submit=false", | ||
content_type=content_type_json, | ||
data={"garbage": "i am bad data"}, | ||
) | ||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ export default function Page() { | |
return ( | ||
<> | ||
<h1>Operations List</h1> | ||
<Link href="/dashboard/operations/create"> | ||
<Link href="/dashboard/operations/0/1"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the It would be nice if we could create the operation and ID when someone clicks the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've discussed the breadcrumbs bugs a bit with Shon and this will be fixed. Though it's out of scope for this ticket. |
||
<Button variant="contained">Add Operation</Button> | ||
</Link> | ||
<Suspense fallback={<Loading />}> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
"use client"; | ||
|
||
import { Button } from "@mui/material"; | ||
import { useFormStatus } from "react-dom"; | ||
import Link from "next/link"; | ||
|
||
interface SubmitButtonProps { | ||
baseUrl: string; | ||
cancelUrl: string; | ||
classNames?: string; | ||
step: number; | ||
steps: string[]; | ||
submitEveryStep?: boolean; | ||
} | ||
|
||
const SubmitButton: React.FunctionComponent<SubmitButtonProps> = ({ | ||
baseUrl, | ||
step, | ||
steps, | ||
cancelUrl, | ||
classNames, | ||
submitEveryStep, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm having trouble with the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it's about validation, I'd suggest changing the variable name to something about validation or adding the explanation above in a comment. (Sidenote, why would we ever not want to validate?) |
||
}) => { | ||
const { pending } = useFormStatus(); | ||
const isFinalStep = step === steps.length - 1; | ||
return ( | ||
<div className={`flex w-full mt-8 justify-between ${classNames}`}> | ||
{cancelUrl && ( | ||
<Link href={cancelUrl}> | ||
<Button variant="outlined">Cancel</Button> | ||
</Link> | ||
)} | ||
<div> | ||
{step !== 0 ? ( | ||
<Link href={`${baseUrl}/${step}`}> | ||
<Button | ||
variant="contained" | ||
type="button" | ||
disabled={step === 0} | ||
className="mr-4" | ||
> | ||
Back | ||
</Button> | ||
</Link> | ||
) : ( | ||
<Button variant="contained" type="button" disabled className="mr-4"> | ||
Back | ||
</Button> | ||
)} | ||
{!isFinalStep && !submitEveryStep && ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since I don't understand what |
||
<Link href={`${baseUrl}/${step + 2}`}> | ||
<Button variant="contained" type="button" disabled={isFinalStep}> | ||
Next | ||
</Button> | ||
</Link> | ||
)} | ||
{isFinalStep && !submitEveryStep && ( | ||
<Button type="submit" aria-disabled={pending} variant="contained"> | ||
Submit | ||
</Button> | ||
)} | ||
{submitEveryStep && ( | ||
<Button type="submit" aria-disabled={pending} variant="contained"> | ||
{!isFinalStep ? "Next" : "Submit"} | ||
</Button> | ||
)} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default SubmitButton; |
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.
What does submit true/false mean? Like if it's the entire form submission vs one of the steps?
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.
On the final step we set
?submit=true
so that we can set the status topending
. We want the status to stay asnot_registered
unless we are submitting.