Skip to content

Commit

Permalink
Merge pull request #259 from jadmsaadaot/SUBMIT-task#306
Browse files Browse the repository at this point in the history
Implement remove object
  • Loading branch information
djnunez-aot authored Jan 27, 2025
2 parents 6350596 + 0ee569b commit 16df086
Show file tree
Hide file tree
Showing 16 changed files with 348 additions and 121 deletions.
18 changes: 16 additions & 2 deletions submit-api/src/submit_api/resources/proponent/submission.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ def patch(submission_id):
return SubmissionSchema().dump(edited_submission), HTTPStatus.OK


@cors_preflight("OPTIONS, POST")
@API.route("/<int:submission_id>/document", methods=["POST", "OPTIONS"])
@cors_preflight("OPTIONS, POST, DELETE")
@API.route("/<int:submission_id>/document", methods=["POST", "OPTIONS", "DELETE"])
class DocumentSubmission(Resource):
"""Resource for managing a document submission."""

Expand All @@ -97,3 +97,17 @@ def post(submission_id):
new_submission_data = CreateSubmissionRequestSchema().load(API.payload)
created_submission = SubmissionService.replace_submission(submission_id, new_submission_data)
return SubmissionSchema().dump(created_submission), HTTPStatus.CREATED

@staticmethod
@ApiHelper.swagger_decorators(API, endpoint_description="Delete a document submission")
@API.expect(create_submission_model)
@API.response(
code=HTTPStatus.OK, model=submission_model, description="Submission"
)
@API.response(HTTPStatus.BAD_REQUEST, "Bad Request")
@cors.crossdomain(origin="*")
@auth.require
def delete(submission_id):
"""Delete a submission document."""
deleted_submission = SubmissionService.delete_submission(submission_id)
return SubmissionSchema().dump(deleted_submission), HTTPStatus.OK
38 changes: 36 additions & 2 deletions submit-api/src/submit_api/resources/staff/internal_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
)


@cors_preflight("OPTIONS, POST")
@API.route("/submission-items/<int:submission_item_id>", methods=["POST", "OPTIONS"])
@cors_preflight("OPTIONS, POST, DELETE")
@API.route("/submission-items/<int:submission_item_id>", methods=["POST", "OPTIONS", "DELETE"])
class InternalStaffDocuments(Resource):
"""Resource for managing projects."""

Expand All @@ -57,3 +57,37 @@ def post(submission_item_id):
created_document = (InternalStaffDocumentService
.create_internal_staff_document(submission_item_id, create_document_data))
return InternalStaffDocument().dump(created_document), HTTPStatus.CREATED

@staticmethod
@ApiHelper.swagger_decorators(API, endpoint_description="Delete an internal staff document")
@API.response(
code=HTTPStatus.OK, model=internal_document, description="Deleted Internal Staff Document"
)
@API.response(HTTPStatus.NOT_FOUND, "Not found")
@auth.has_one_of_roles([EpicSubmitRole.EAO_CREATE.value])
@cors.crossdomain(origin="*")
def delete(internal_staff_document_id):
"""Delete an internal staff document."""
deleted_document = (InternalStaffDocumentService
.delete_internal_staff_document(internal_staff_document_id))
return InternalStaffDocument().dump(deleted_document), HTTPStatus.OK


@cors_preflight("OPTIONS, DELETE")
@API.route("/<int:internal_staff_document_id>", methods=["OPTIONS", "DELETE"])
class InternalStaffDocument(Resource):
"""Resource for managing projects."""

@staticmethod
@ApiHelper.swagger_decorators(API, endpoint_description="Delete an internal staff document")
@API.response(
code=HTTPStatus.OK, model=internal_document, description="Deleted Internal Staff Document"
)
@API.response(HTTPStatus.NOT_FOUND, "Not found")
@auth.has_one_of_roles([EpicSubmitRole.EAO_CREATE.value])
@cors.crossdomain(origin="*")
def delete(internal_staff_document_id):
"""Delete an internal staff document."""
deleted_document = (InternalStaffDocumentService
.delete_internal_staff_document(internal_staff_document_id))
return InternalStaffDocument().dump(deleted_document), HTTPStatus.OK
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,12 @@ def create_internal_staff_document(cls, submission_item_id, data):
)
internal_staff_document.save()
return internal_staff_document

@classmethod
def delete_internal_staff_document(cls, internal_staff_document_id):
"""Delete internal staff document."""
internal_staff_document = InternalStaffDocumentModel.find_by_id(internal_staff_document_id)
if not internal_staff_document:
raise ResourceNotFoundError("Internal staff document not found")
internal_staff_document.delete()
return internal_staff_document
9 changes: 9 additions & 0 deletions submit-api/src/submit_api/services/submission/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,12 @@ def update_submission_item_status(cls, item_id, status, session):
if not status:
return
ItemService.update_submission_item_status(item_id, status, session)

@classmethod
def delete_submission(cls, submission_id):
"""Delete a submission."""
submission = SubmissionModel.find_by_id(submission_id)
if not submission:
raise ValueError("Submission not found.")
submission.delete()
return submission
22 changes: 18 additions & 4 deletions submit-web/src/components/DocumentUpload/DocumentTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,30 @@ import DocumentTableRow, {
import { UploadObject } from "@/store/documentUploadStore";
import PendingDocumentRow from "./PendingDocumentRow";

type DocumentTableProps = {
type DocumentTableProps = Readonly<{
header: string;
documents?: Array<Submission>;
pendingDocuments: Array<UploadObject>;
folder?: string;
};
setDocumentSubmissions: React.Dispatch<React.SetStateAction<Submission[]>>;
}>;

export default function DocumentTable({
header,
documents = [],
pendingDocuments,
pendingDocuments = [],
folder: s3Folder,
setDocumentSubmissions,
}: DocumentTableProps) {
if (documents.length === 0 && pendingDocuments.length === 0) {
return null;
}

const documentIds = documents.map((document) => document.id);
const filteredPendingDocuments = pendingDocuments.filter(
(document) => !documentIds.includes(document.id),
);

return (
<TableContainer component={Box} sx={{ height: "100%" }}>
<Table sx={{ tableLayout: "fixed" }}>
Expand Down Expand Up @@ -75,13 +87,15 @@ export default function DocumentTable({
<DocumentTableRow
key={`custom-row-${document.id}`}
documentItem={document}
setDocumentSubmissions={setDocumentSubmissions}
/>
))}
{pendingDocuments?.map((document) => (
{filteredPendingDocuments?.map((document) => (
<PendingDocumentRow
key={`pending-row-${document.file.name}`}
documentItem={document}
folder={s3Folder}
setDocumentSubmissions={setDocumentSubmissions}
/>
))}
</TableBody>
Expand Down
49 changes: 37 additions & 12 deletions submit-web/src/components/DocumentUpload/DocumentTableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import {
Typography,
} from "@mui/material";
import { BCDesignTokens } from "epic.theme";
import { downloadObject } from "@/hooks/api/useObjectStorage";
import { deleteDocument, downloadObject } from "@/hooks/api/useObjectStorage";
import { notify } from "../Shared/Snackbar/snackbarStore";
import { Submission } from "@/models/Submission";
import { LoadingButton } from "../Shared/LoadingButton";
import { useDeleteSubmission } from "@/hooks/api/useSubmissions";

export const StyledHeadTableCell = styled(TableCell)<{ error?: boolean }>(
({ error }) => ({
Expand Down Expand Up @@ -83,18 +85,23 @@ export const PackageTableRow = ({
return <StyledTableRow {...otherProps}>{childrenWithProps}</StyledTableRow>;
};

type DocumentTableRowProps = {
type DocumentTableRowProps = Readonly<{
documentItem: Submission;
error?: boolean;
};
setDocumentSubmissions: React.Dispatch<React.SetStateAction<Submission[]>>;
}>;
export default function DocumentTableRow({
documentItem,
setDocumentSubmissions,
error = false,
}: DocumentTableRowProps) {
const { submitted_by, version, submitted_document } = documentItem;

const onActionClick = () => {};
const [pendingGetObject, setPendingGetObject] = useState(false);
const [isRemovingDocument, setIsRemovingDocument] = useState(false);

const { mutateAsync: deleteSubmission } = useDeleteSubmission({
submissionItemId: documentItem.item_id,
});

const getObjectFromS3 = async () => {
try {
Expand All @@ -111,12 +118,27 @@ export default function DocumentTableRow({
document.body.appendChild(link);
link.click();
} catch (e) {
notify.error("Failed to download documentItem");
notify.error("Failed to download submission");
} finally {
setPendingGetObject(false);
}
};

const onRemoveClick = async () => {
try {
setIsRemovingDocument(true);
await deleteDocument({ filepath: submitted_document.url });
await deleteSubmission(documentItem.id);
setDocumentSubmissions((prev) =>
prev.filter((sub) => sub.id !== documentItem.id),
);
} catch (e) {
notify.error("Failed to remove document");
} finally {
setIsRemovingDocument(false);
}
};

return (
<PackageTableRow
key={`row-${documentItem.submitted_document.name}`}
Expand All @@ -142,19 +164,22 @@ export default function DocumentTableRow({
<DocumentTableCell align="right">{submitted_by}</DocumentTableCell>
<DocumentTableCell align="right">{version}</DocumentTableCell>
<DocumentTableCell align="center">
<Typography
variant="body2"
<LoadingButton
onClick={onRemoveClick}
loading={isRemovingDocument}
variant="text"
sx={{
color: BCDesignTokens.typographyColorLink,
"&:hover": {
cursor: "pointer",
textDecoration: "underline",
backgroundColor: "transparent",
},
"&:focus": {
outline: "none",
},
}}
onClick={onActionClick}
>
Remove
</Typography>
</LoadingButton>
</DocumentTableCell>
</PackageTableRow>
);
Expand Down
33 changes: 8 additions & 25 deletions submit-web/src/components/DocumentUpload/PendingDocumentRow.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { CircularProgress, Link as MuiLink, Typography } from "@mui/material";
import { BCDesignTokens } from "epic.theme";
import { PackageTableRow, DocumentTableCell } from "./DocumentTableRow";
import { createSubmission } from "@/hooks/api/useSubmissions";
import { SUBMISSION_TYPE } from "@/models/Submission";
import { Submission, SUBMISSION_TYPE } from "@/models/Submission";
import { QUERY_KEY } from "@/hooks/api/constants";
import { notify } from "../Shared/Snackbar/snackbarStore";
import { useEffect } from "react";
Expand All @@ -16,23 +15,22 @@ type DocumentTableRowProps = {
documentItem: UploadObject;
error?: boolean;
folder?: string;
setDocumentSubmissions: React.Dispatch<React.SetStateAction<Submission[]>>;
};
export default function PendingDocumentRow({
documentItem,
error = false,
folder: s3Folder,
setDocumentSubmissions,
}: DocumentTableRowProps) {
const { submissionId: subItemId } = useParams({
from: "/proponent/_proponentLayout/projects/$projectId/_projectLayout/submission-packages/$submissionPackageId/_submissionLayout/submissions/$submissionId",
});

const queryClient = useQueryClient();

const {
triggerPending,
completeObject: completeDocument,
removeObject: removeDocument,
} = useObjectUploadStore();
const { triggerPending, removeObject: removeDocument } =
useObjectUploadStore();

useEffect(() => {
triggerPending(documentItem.id);
Expand All @@ -59,7 +57,8 @@ export default function PendingDocumentRow({
data: documentData,
});

completeDocument(documentItem.id, documentSubmission.id);
removeDocument(documentItem.id);
setDocumentSubmissions((prev) => [...prev, documentSubmission]);
queryClient.invalidateQueries({
queryKey: [QUERY_KEY.SUBMISSION_ITEM, documentSubmission.item_id],
});
Expand All @@ -76,8 +75,6 @@ export default function PendingDocumentRow({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [documentItem.pending]);

const onActionClick = () => {};

return (
<PackageTableRow key={`row-${documentItem.file.name}`} error={error}>
<DocumentTableCell colSpan={2}>
Expand All @@ -100,21 +97,7 @@ export default function PendingDocumentRow({
<DocumentTableCell align="center" colSpan={2}>
<CircularProgress size={"16px"} />
</DocumentTableCell>
<DocumentTableCell align="center">
<Typography
variant="body2"
sx={{
color: BCDesignTokens.typographyColorLink,
"&:hover": {
cursor: "pointer",
textDecoration: "underline",
},
}}
onClick={onActionClick}
>
Remove
</Typography>
</DocumentTableCell>
<DocumentTableCell align="center"></DocumentTableCell>
</PackageTableRow>
);
}
1 change: 1 addition & 0 deletions submit-web/src/components/Submission/ItemsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export default function ItemsTable({ submissionPackage }: ItemsTableProps) {
<InternalDocumentsRows
internalStaffDocuments={internalStaffDocuments}
numColumns={5}
hideAction
/>
</When>
</TableBody>
Expand Down
Loading

0 comments on commit 16df086

Please sign in to comment.