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

1703 4 hard delete attachments #1835

Closed
wants to merge 77 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
423015f
chore: create and use attachmentDeleteRouter
BCerki Jun 28, 2023
bb785d0
test: jest test attachmentDeleteRouter
BCerki Jun 28, 2023
dec1096
chore: create delete page route
BCerki Jun 28, 2023
f8070c3
feat: hard delete attachments from GCS
BCerki Jun 28, 2023
e1e4dd3
test: add file upload to cypress test
BCerki Jun 28, 2023
27f8a44
feat: hard delete attachments from GCS
BCerki Jul 6, 2023
be0fb2a
chore: create and use attachmentDeleteRouter
BCerki Jul 6, 2023
5dff0e4
test: add file upload to cypress test
BCerki Jul 6, 2023
a63612f
spec work
BCerki Jul 6, 2023
68f4258
chore: add delete permissions to attachment table
BCerki Jul 13, 2023
1b5db6c
feat: hard delete attachments from GCS
BCerki Jul 13, 2023
22295d3
test: test AttachmentTableRow
BCerki Jul 13, 2023
68b1798
chore: spec work
BCerki Jul 13, 2023
1ab5699
test: jest tests
BCerki Jul 13, 2023
b4a866a
feat: hard delete attachments from GCS
BCerki Jul 13, 2023
05686ce
test: jest
BCerki Jul 13, 2023
177cf38
test: update pgtap tests
BCerki Jul 14, 2023
dc218e8
test: debug CI cypress tests
BCerki Jul 14, 2023
ff55ff6
chore: spec work
BCerki Jul 18, 2023
8684a93
test: debug CI cypress tests
BCerki Jul 18, 2023
e87f6c5
test: debug CI cypress tests
BCerki Jul 19, 2023
024ab2b
test: debug CI cypress tests
BCerki Jul 20, 2023
aa87933
test: go back to original emissions migration test
BCerki Jul 20, 2023
ea8088d
test: debug CI cypress tests
BCerki Jul 20, 2023
e22887f
test: debug CI cypress tests
BCerki Jul 20, 2023
2124969
chore: add GCS auth to github e2e action
BCerki Jul 20, 2023
8a31ac0
test: debug CI cypress tests
BCerki Jul 20, 2023
3d8196b
chore: remove loop from discard mutation
BCerki Jul 20, 2023
3f773f2
chore: spec work
BCerki Jul 20, 2023
51395b3
chore: refresh after delete
BCerki Jul 21, 2023
ed8f5ba
test: debug CI cypress tests
BCerki Jul 21, 2023
f8d9309
chore: spec work
BCerki Jul 21, 2023
7e009e2
chore: remove loop from discard mutation
BCerki Jul 21, 2023
4b6ce7c
chore: spec work
BCerki Jul 21, 2023
683b97c
chore: debug cypress CI
BCerki Jul 21, 2023
8fda6ae
chore: debug cypress CI
BCerki Jul 24, 2023
9b1a7f7
chore: debug cypress CI
BCerki Jul 24, 2023
f5fc5e5
chore: debug cypress CI
BCerki Jul 24, 2023
aa109e7
chore: debug cypress CI
BCerki Jul 24, 2023
9689b56
chore: debug cypress CI-bucket error
BCerki Jul 24, 2023
a7d7a39
chore: debug cypress CI-missing file
BCerki Jul 24, 2023
eb31889
chore: debug cypress CI-tmate
BCerki Jul 24, 2023
3141e11
chore: add to gitignore
BCerki Jul 24, 2023
e6102b9
chore: debug cypress CI-reorder CI steps
BCerki Jul 24, 2023
c27cb1b
chore: debug cypress CI--try to set default credentials
BCerki Jul 24, 2023
ec02b03
chore: fix stuck CI
BCerki Jul 24, 2023
e3456e3
chore: debug cypress CI--try to set default credentials
BCerki Jul 24, 2023
ba5422a
chore: debug cypress CI--try to set default credentials
BCerki Jul 24, 2023
b250a32
chore: remove some whitespace to trigger CI
BCerki Jul 25, 2023
d9ae1b0
chore: debug cypress CI
BCerki Jul 25, 2023
f40c808
test: add detached true to tmate session
dleard Jul 25, 2023
d6c4922
test: workflow uses federated identity
dleard Jul 25, 2023
c8460cf
test: add token permissions to e2e job
dleard Jul 25, 2023
71efa3e
test: export env vars in workflow
dleard Jul 25, 2023
39dc671
test: set env var in gh env
dleard Jul 25, 2023
c8275f2
chore: add test env
dleard Jul 26, 2023
6aeb5c1
test: remove run block, it was breaking CI
dleard Jul 26, 2023
f7d6592
test: debugging ci
dleard Jul 26, 2023
ecea111
test: debugging ci
dleard Jul 26, 2023
19361ef
test: debugging ci
dleard Jul 26, 2023
c1e14a7
test: debugging ci
dleard Jul 26, 2023
5d4dfec
test: debugging ci
dleard Jul 26, 2023
389fed2
chore: rename cyress env variables
BCerki Jul 28, 2023
d3b0747
chore: debug cypress
BCerki Jul 31, 2023
6a036c1
chore: debug cypress
BCerki Jul 31, 2023
08239d2
chore: debug cypress
BCerki Jul 31, 2023
5c9b5df
chore: debug CI
BCerki Aug 1, 2023
9c31619
chore: debug CI
BCerki Aug 1, 2023
8861bbc
chore: debug CI
BCerki Aug 1, 2023
0d0fccd
chore: debug CI
BCerki Aug 1, 2023
65f3051
chore: debug CI
BCerki Aug 3, 2023
8bb1432
chore: debug CI
BCerki Aug 3, 2023
a981b27
test: attachments e2e test
BCerki Aug 4, 2023
10ea511
chore: fix revert
BCerki Aug 4, 2023
8e881ab
chore: clean up spec work
BCerki Aug 4, 2023
353c4cd
chore: fix revert
BCerki Aug 4, 2023
46eb659
chore: add wait to see what shows in happo
BCerki Aug 4, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,26 @@ jobs:
e2e:
needs: ["docker-build", "install-dev-tools"]
runs-on: ubuntu-latest
permissions:
contents: "read"
id-token: "write"
steps:
- uses: actions/checkout@v3
- name: dev env setup
uses: ./.github/actions/dev-env-setup
# - name: Setup tmate session
# uses: mxschmitt/action-tmate@v3
# with:
# detached: true
Comment on lines +175 to +178
Copy link
Contributor

Choose a reason for hiding this comment

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

Leftover!

- name: run app locally
uses: ./.github/actions/local-app-run
- id: "auth"
name: "Authenticate to Google Cloud"
uses: "google-github-actions/auth@v1"
with:
export_environment_variables: true
workload_identity_provider: ${{secrets.IDENTITY_PROVIDER}}
service_account: ${{secrets.GCS_SERVICE_ACCOUNT}}
- name: run e2e tests
env:
CYPRESS_TEST_INTERNAL_USERNAME: ${{ secrets.TEST_INTERNAL_USERNAME }}
Expand All @@ -181,7 +195,18 @@ jobs:
CYPRESS_TEST_UNAUTHORIZED_PASSWORD: ${{ secrets.TEST_UNAUTHORIZED_PASSWORD }}
HAPPO_API_KEY: ${{ secrets.HAPPO_API_KEY }}
HAPPO_API_SECRET: ${{ secrets.HAPPO_API_SECRET }}
run: yarn test:e2e
TEST_ENV: "test"
CYPRESS_GOOGLE_APPLICATION_CREDENTIALS: ${{env.GOOGLE_APPLICATION_CREDENTIALS}}
CYPRESS_ATTACHMENTS_BUCKET: ${{secrets.ATTACHMENTS_BUCKET}}
GOOGLE_APPLICATION_CREDENTIALS: ${{env.GOOGLE_APPLICATION_CREDENTIALS}}
ATTACHMENTS_BUCKET: ${{secrets.ATTACHMENTS_BUCKET}}
run: |
echo $CYPRESS_GOOGLE_APPLICATION_CREDENTIALS
echo $TEST_ENV
echo $ATTACHMENTS_BUCKET
echo $CYPRESS_ATTACHMENTS_BUCKET
pwd
yarn test:e2e
working-directory: ./app

zap-owasp:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ cypress.env.json
app/cypress.env.json
dev/db/data
**/.DS_Store

gha-creds-*.json
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to have any files locally related to this rule?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is leftover from experimenting with CI, will remove

50 changes: 29 additions & 21 deletions app/components/Attachment/AttachmentTableRow.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,32 @@
import { Button } from "@button-inc/bcgov-theme";
import useDiscardProjectAttachmentFormChange from "mutations/attachment/discardProjectAttachmentFormChange";
import Link from "next/link";
import { getAttachmentDownloadRoute } from "routes/pageRoutes";
import { graphql, useFragment } from "react-relay";
import useDiscardProjectAttachmentFormChange from "mutations/attachment/discardProjectAttachmentFormChange";
import { getAttachmentDownloadRoute } from "routes/pageRoutes";
import { AttachmentTableRow_attachment$key } from "__generated__/AttachmentTableRow_attachment.graphql";
import hardDeleteAttachment from "./hardDeleteAttachment";
import { useRouter } from "next/router";

interface Props {
attachment: AttachmentTableRow_attachment$key;
connectionId: string;
formChangeRowId: number;
hideDelete?: boolean;
isFirstRevision: boolean;
}

const AttachmentTableRow: React.FC<Props> = ({
attachment,
connectionId,
formChangeRowId,
hideDelete,
isFirstRevision,
}) => {
const [
discardProjectAttachmentFormChange,
isDiscardingProjectAttachmentFormChange,
] = useDiscardProjectAttachmentFormChange();
const {
id,
fileName,
fileType,
fileSize,
createdAt,
cifUserByCreatedBy: { fullName },
} = useFragment(
const attachmentRow = useFragment(
graphql`
fragment AttachmentTableRow_attachment on Attachment {
id
Expand All @@ -45,32 +42,43 @@ const AttachmentTableRow: React.FC<Props> = ({
attachment
);

const handleArchiveAttachment = () => {
discardProjectAttachmentFormChange({
variables: {
input: {
formChangeId: formChangeRowId,
const router = useRouter();
if (!attachmentRow) return null;
const { id, fileName, fileType, fileSize, createdAt, cifUserByCreatedBy } =
attachmentRow;

const handleArchiveAttachment = (attachmentId) => {
if (isFirstRevision) {
console.log("in if handlearchiveattachment");
Copy link
Contributor

Choose a reason for hiding this comment

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

Leftover!

hardDeleteAttachment(attachmentId, formChangeRowId);
router.replace(router.asPath);
} else {
discardProjectAttachmentFormChange({
variables: {
input: {
formChangeId: formChangeRowId,
},
connections: [connectionId],
},
connections: [connectionId],
},
});
});
}
};

console.log("connectionid", connectionId);
Copy link
Contributor

Choose a reason for hiding this comment

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

Leftover!

return (
<>
<tr>
<td>{fileName}</td>
<td>{fileType}</td>
<td>{fileSize}</td>
<td>{fullName}</td>
<td>{cifUserByCreatedBy?.fullName}</td>
<td>{createdAt}</td>
<td className="links">
<Link href={getAttachmentDownloadRoute(id)} passHref>
<Button size="small">Download</Button>
</Link>
{!hideDelete && (
<Button
onClick={handleArchiveAttachment}
onClick={() => handleArchiveAttachment(id)}
disabled={isDiscardingProjectAttachmentFormChange}
size="small"
>
Expand Down
17 changes: 17 additions & 0 deletions app/components/Attachment/hardDeleteAttachment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { getAttachmentDeleteRoute } from "routes/pageRoutes";

const hardDeleteAttachment = (attachmentId, formChangeRowId) => {
fetch(getAttachmentDeleteRoute(attachmentId).pathname, {
method: "DELETE",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
variables: {
input: {
formChangeId: formChangeRowId,
},
},
}),
});
};

export default hardDeleteAttachment;
25 changes: 16 additions & 9 deletions app/components/Form/ProjectAttachmentsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ const ProjectAttachmentsForm: React.FC<Props> = ({
projectRevision,
onSubmit,
}) => {
const { rowId, projectAttachmentFormChanges } = useFragment(
const revision = useFragment(
graphql`
fragment ProjectAttachmentsForm_projectRevision on ProjectRevision {
id
rowId
isFirstRevision
projectAttachmentFormChanges: formChangesFor(
first: 500
formDataTableName: "project_attachment"
Expand All @@ -57,6 +59,7 @@ const ProjectAttachmentsForm: React.FC<Props> = ({
projectRevision
);

const { rowId, projectAttachmentFormChanges, isFirstRevision } = revision;
const attachmentFormChange = projectAttachmentFormChanges.edges[0]?.node;
const [createAttachment, isCreatingAttachment] = useCreateAttachment();
const [createProjectAttachment, isCreatingProjectAttachment] =
Expand Down Expand Up @@ -143,14 +146,18 @@ const ProjectAttachmentsForm: React.FC<Props> = ({
totalRowCount={projectAttachmentFormChanges.totalCount}
filters={tableFilters}
>
{projectAttachmentFormChanges.edges.map(({ node }) => (
<AttachmentTableRow
key={node.id}
attachment={node.asProjectAttachment.attachmentByAttachmentId}
formChangeRowId={node.rowId}
connectionId={projectAttachmentFormChanges.__id}
/>
))}
{projectAttachmentFormChanges.edges.map(({ node }) => {
if (!node) return null;
return (
<AttachmentTableRow
key={node.id}
attachment={node.asProjectAttachment.attachmentByAttachmentId}
formChangeRowId={node.rowId}
connectionId={projectAttachmentFormChanges.__id}
isFirstRevision={isFirstRevision}
/>
);
})}
</Table>
<Button
type="submit"
Expand Down
2 changes: 1 addition & 1 deletion app/components/Form/ProjectAttachmentsFormSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ const ProjectAttachmentsFormSummary: React.FC<Props> = ({

const attachmentsSummary =
revision.summaryProjectAttachmentFormChanges.edges[0]?.node;

const projectAttachmentsFormNotUpdated = useMemo(
() =>
!attachmentsSummary ||
Expand Down Expand Up @@ -100,6 +99,7 @@ const ProjectAttachmentsFormSummary: React.FC<Props> = ({
formChangeRowId={node.rowId}
connectionId={revision.summaryProjectAttachmentFormChanges.__id}
hideDelete={true}
isFirstRevision={revision.isFirstRevision}
/>
)
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,16 @@ describe("when creating a project, the project page", () => {
cy.findByText(/Submit Annual Reports/i).click();

// Add attachments
cy.findByText(/Project Attachments/i).click();
cy.findByText(/Add Project Attachments/i).click();
cy.url().should("include", "/form/8");
cy.findByText(/Submit project attachments/i).click();

cy.fixture("e2e/mock.pdf").as("mockFile");
cy.get("input[type=file]").selectFile("@mockFile");
cy.wait(30000);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm pretty sure you have tested this but just as a sanity check, have you tried using any other assertions rather than using wait? or something like this: https://docs.cypress.io/api/commands/selectfile#Custom-fileName-mimeType-and-lastModified

cy.happoAndAxe("Project attachments", "filled", "main", true);

cy.findByText(/Submit project attachments/i).click();
//review and submit
cy.contains("Review and Submit Project");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const mutation = graphql`
$connections: [ID!]!
) {
discardProjectAttachmentFormChange(input: $input) {
formChanges {
formChange {
projectRevisionByProjectRevisionId {
...TaskList_projectRevision
}
Expand Down
2 changes: 1 addition & 1 deletion app/pages/cif/project-revision/[projectRevision]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { useDeleteProjectRevisionMutation } from "mutations/ProjectRevision/dele
import SavingIndicator from "components/Form/SavingIndicator";
import { faTrash } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";

import {
getProjectsPageRoute,
getProjectRevisionFormPageRoute,
Expand Down Expand Up @@ -72,6 +71,7 @@ const pageQuery = graphql`
}
}
}

formChangesByProjectRevisionId {
edges {
node {
Expand Down
4 changes: 4 additions & 0 deletions app/routes/pageRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ export const getAttachmentDownloadRoute = (attachmentId: string) => ({
pathname: `/download/${attachmentId}`,
});

export const getAttachmentDeleteRoute = (attachmentId: string) => ({
pathname: `/delete/${attachmentId}`,
});

//// External User

export const getExternalUserLandingPageRoute = () => ({
Expand Down
26 changes: 25 additions & 1 deletion app/schema/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -44200,12 +44200,36 @@ input DiscardProjectAttachmentFormChangeInput {

"""The output of our `discardProjectAttachmentFormChange` mutation."""
type DiscardProjectAttachmentFormChangePayload {
"""Reads a single `ChangeStatus` that is related to this `FormChange`."""
changeStatusByChangeStatus: ChangeStatus

"""Reads a single `CifUser` that is related to this `FormChange`."""
cifUserByCreatedBy: CifUser

"""Reads a single `CifUser` that is related to this `FormChange`."""
cifUserByUpdatedBy: CifUser

"""
The exact same `clientMutationId` that was provided in the mutation input,
unchanged and unused. May be used by a client to track mutations.
"""
clientMutationId: String
formChanges: [FormChange]

"""Reads a single `Form` that is related to this `FormChange`."""
formByJsonSchemaName: Form
formChange: FormChange

"""Reads a single `FormChange` that is related to this `FormChange`."""
formChangeByPreviousFormChangeId: FormChange

"""An edge for our `FormChange`. May be used by Relay 1."""
formChangeEdge(
"""The method to use when ordering `FormChange`."""
orderBy: [FormChangesOrderBy!] = [PRIMARY_KEY_ASC]
): FormChangesEdge

"""Reads a single `ProjectRevision` that is related to this `FormChange`."""
projectRevisionByProjectRevisionId: ProjectRevision

"""
Our root query field type. Allows us to run any query from our mutation payload.
Expand Down
Loading