diff --git a/.env.example b/.env.example index 6b78d3253..0f46c1b49 100644 --- a/.env.example +++ b/.env.example @@ -19,6 +19,7 @@ SPONSOR_USERS_SCOPES="show-medata/read show-medata/write access-requests/read ac EMAIL_SCOPES="clients/read templates/read templates/write emails/read" FILE_UPLOAD_SCOPES="files/upload" FILE_UPLOAD_ALLOWED_EXTENSIONS="pdf,jpg,jpeg,png,ppt,key,pptx" +FILE_UPLOAD_USE_V4= SPONSOR_PAGES_API_URL=https://sponsor-pages-api.dev.fnopen.com SPONSOR_REPORTS_API_URL=https://sponsor-reports-api.dev.fnopen.com SPONSOR_PAGES_SCOPES="page-template/read page-template/write show-page/read show-page/write media-upload/read" diff --git a/package.json b/package.json index 53f73d565..ba894aed3 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,8 @@ "@uiw/codemirror-theme-sublime": "^4.21.23", "@uiw/react-codemirror": "^4.21.7", "@uiw/react-color-sketch": "^2.1.0", + "@uppy/aws-s3": "^5.1.0", + "@uppy/core": "^5.2.0", "ably": "^2.30.0", "address-rfc2822": "^2.2.2", "awesome-bootstrap-checkbox": "^1.0.1", @@ -95,7 +97,7 @@ "moment-duration-format": "^2.3.2", "moment-timezone": "^0.5.33", "mui-color-input": "^9.0.0", - "openstack-uicore-foundation": "5.0.73-beta.1", + "openstack-uicore-foundation": "5.0.75", "p-limit": "^6.1.0", "path-browserify": "^1.0.1", "postcss-loader": "^6.2.1", diff --git a/src/app.js b/src/app.js index 7a8fa36b1..55da85ca2 100644 --- a/src/app.js +++ b/src/app.js @@ -86,6 +86,7 @@ window.SPONSOR_USERS_API_URL = process.env.SPONSOR_USERS_API_URL; window.SPONSOR_PAGES_API_URL = process.env.SPONSOR_PAGES_API_URL; window.SPONSOR_REPORTS_API_URL = process.env.SPONSOR_REPORTS_API_URL; window.FILE_UPLOAD_API_BASE_URL = process.env.FILE_UPLOAD_API_BASE_URL; +window.FILE_UPLOAD_USE_V4 = process.env.FILE_UPLOAD_USE_V4; window.SIGNAGE_BASE_URL = process.env.SIGNAGE_BASE_URL; window.INVENTORY_API_BASE_URL = process.env.INVENTORY_API_BASE_URL; window.OAUTH2_CLIENT_ID = process.env.OAUTH2_CLIENT_ID; diff --git a/src/components/forms/__tests__/company-form.test.js b/src/components/forms/__tests__/company-form.test.js index ed1dcc90d..55a9e75b2 100644 --- a/src/components/forms/__tests__/company-form.test.js +++ b/src/components/forms/__tests__/company-form.test.js @@ -15,28 +15,50 @@ jest.mock("openstack-uicore-foundation/lib/utils/query-actions", () => ({ }) })); +function mockUploadInput({ + id, + onUploadComplete, + onUploadStart, + onRemove, + value +}) { + return ( +
+ + +
+ ); +} + jest.mock( "openstack-uicore-foundation/lib/components/inputs/upload-input-v3", - () => ({ - __esModule: true, - default: ({ id, onUploadComplete, onUploadStart, value }) => ( -
- -
- ) - }) + () => ({ __esModule: true, default: mockUploadInput }) +); + +jest.mock( + "openstack-uicore-foundation/lib/components/inputs/upload-input-v4", + () => ({ __esModule: true, default: mockUploadInput }) ); jest.mock( @@ -160,6 +182,7 @@ const Harness = ({ onDeleteSponsorship={onDeleteSponsorship} />
{JSON.stringify(formik.values)}
+
{String(isSaving)}
); }; @@ -252,6 +275,25 @@ describe("CompanyForm", () => { expect(onAttach).not.toHaveBeenCalled(); }); + it("clears the saving state when a new company cancels an in-flight V4 upload", async () => { + const user = userEvent.setup(); + const onRemove = jest.fn(() => Promise.resolve()); + window.FILE_UPLOAD_USE_V4 = "true"; + + try { + render(); + + await act(async () => { + await user.click(screen.getByTestId("cancel-upload-logo")); + }); + + expect(screen.getByTestId("debug-saving")).toHaveTextContent("false"); + expect(onRemove).not.toHaveBeenCalled(); + } finally { + delete window.FILE_UPLOAD_USE_V4; + } + }); + it("reverts the logo preview when onAttach fails for an existing company", async () => { const user = userEvent.setup(); let rejectAttach; diff --git a/src/components/forms/badge-feature-type-form.js b/src/components/forms/badge-feature-type-form.js index 40aef9d7f..3a47aa83a 100644 --- a/src/components/forms/badge-feature-type-form.js +++ b/src/components/forms/badge-feature-type-form.js @@ -18,7 +18,7 @@ import { useFormikContext } from "formik"; import { Box, Grid2, InputLabel } from "@mui/material"; import MuiFormikTextField from "openstack-uicore-foundation/lib/components/mui/formik-inputs/textfield"; import FormikTextEditor from "openstack-uicore-foundation/lib/components/mui/formik-inputs/texteditor"; -import UploadInputV3 from "openstack-uicore-foundation/lib/components/inputs/upload-input-v3"; +import FileUploadInput from "../inputs/file-upload-input"; import useScrollToError from "../../hooks/useScrollToError"; import { KB, MAX_BADGE_FEATURE_IMAGE_UPLOAD_SIZE } from "../../utils/constants"; @@ -101,7 +101,7 @@ const BadgeFeatureTypeForm = ({ entity, onRemoveImage, onUploadingChange }) => { {T.translate("edit_badge_feature.image")} - { onUploadStart={() => onUploadingChange(true)} onError={() => onUploadingChange(false)} onRemove={handleRemoveImage} - postUrl={`${window.FILE_UPLOAD_API_BASE_URL}/api/v1/files/upload`} - djsConfig={{ withCredentials: true }} maxFiles={1} canAdd={!formik.values.image} mediaType={{ diff --git a/src/components/forms/company-form.js b/src/components/forms/company-form.js index 5b216b71d..66332a9ef 100644 --- a/src/components/forms/company-form.js +++ b/src/components/forms/company-form.js @@ -23,11 +23,11 @@ import { MenuItem, Select } from "@mui/material"; -import UploadInputV3 from "openstack-uicore-foundation/lib/components/inputs/upload-input-v3"; import { getCountryList } from "openstack-uicore-foundation/lib/utils/query-actions"; import Table from "openstack-uicore-foundation/lib/components/mui/table"; import MuiFormikTextField from "openstack-uicore-foundation/lib/components/mui/formik-inputs/textfield"; import MuiFormikSelect from "openstack-uicore-foundation/lib/components/mui/formik-inputs/select"; +import FileUploadInput from "../inputs/file-upload-input"; import useScrollToError from "../../hooks/useScrollToError"; import FormikTextEditor from "../inputs/formik-text-editor"; import MuiFormikAsyncAutocomplete from "../mui/formik-inputs/mui-formik-async-select"; @@ -99,6 +99,9 @@ const CompanyForm = ({ onRemove(initialEntity, field) .catch(() => formik.setFieldValue(field, prevValue)) .finally(() => setIsSaving(false)); + } else { + // also reached when cancelling an in-flight upload + setIsSaving(false); } }; @@ -370,7 +373,7 @@ const CompanyForm = ({ {T.translate("edit_company.logo")} - {T.translate("edit_company.big_logo")} -