diff --git a/src/actions/media-file-type-actions.js b/src/actions/media-file-type-actions.js
index 7398a21de..d770436b3 100644
--- a/src/actions/media-file-type-actions.js
+++ b/src/actions/media-file-type-actions.js
@@ -21,15 +21,12 @@ import {
createAction,
stopLoading,
startLoading,
- showMessage,
- showSuccessMessage,
- authErrorHandler,
fetchResponseHandler,
fetchErrorHandler,
escapeFilterValue
} from "openstack-uicore-foundation/lib/utils/actions";
import URI from "urijs";
-import history from "../history";
+import { snackbarErrorHandler, snackbarSuccessHandler } from "./base-actions";
import { getAccessTokenSafely } from "../utils/methods";
import {
DEBOUNCE_WAIT,
@@ -87,9 +84,9 @@ export const getMediaFileTypes =
createAction(REQUEST_MEDIA_FILE_TYPES),
createAction(RECEIVE_MEDIA_FILE_TYPES),
`${window.API_BASE_URL}/api/v1/summit-media-file-types`,
- authErrorHandler,
- { order, orderDir, term }
- )(params)(dispatch).then(() => {
+ snackbarErrorHandler,
+ { order, orderDir, term, perPage }
+ )(params)(dispatch).finally(() => {
dispatch(stopLoading());
});
};
@@ -109,9 +106,9 @@ export const getAllMediaFileTypes = () => async (dispatch) => {
createAction(REQUEST_ALL_MEDIA_FILE_TYPES),
createAction(RECEIVE_ALL_MEDIA_FILE_TYPES),
`${window.API_BASE_URL}/api/v1/summit-media-file-types`,
- authErrorHandler,
+ snackbarErrorHandler,
{}
- )(params)(dispatch).then(() => {
+ )(params)(dispatch).finally(() => {
dispatch(stopLoading());
});
};
@@ -129,8 +126,8 @@ export const getMediaFileType = (mediaFileTypeId) => async (dispatch) => {
null,
createAction(RECEIVE_MEDIA_FILE_TYPE),
`${window.API_BASE_URL}/api/v1/summit-media-file-types/${mediaFileTypeId}`,
- authErrorHandler
- )(params)(dispatch).then(() => {
+ snackbarErrorHandler
+ )(params)(dispatch).finally(() => {
dispatch(stopLoading());
});
};
@@ -139,52 +136,52 @@ export const resetMediaFileTypeForm = () => (dispatch) => {
dispatch(createAction(RESET_MEDIA_FILE_TYPE_FORM)({}));
};
-export const saveMediaFileType =
- (entity, noAlert = false) =>
- async (dispatch) => {
- const accessToken = await getAccessTokenSafely();
+export const saveMediaFileType = (entity) => async (dispatch) => {
+ const accessToken = await getAccessTokenSafely();
- dispatch(startLoading());
+ dispatch(startLoading());
- const normalizedEntity = normalizeEntity(entity);
- const params = { access_token: accessToken };
-
- if (entity.id) {
- putRequest(
- createAction(UPDATE_MEDIA_FILE_TYPE),
- createAction(MEDIA_FILE_TYPE_UPDATED),
- `${window.API_BASE_URL}/api/v1/summit-media-file-types/${entity.id}`,
- normalizedEntity,
- authErrorHandler,
- entity
- )(params)(dispatch).then(() => {
- if (!noAlert)
- dispatch(showSuccessMessage(T.translate("media_file_type.saved")));
- else dispatch(stopLoading());
- });
- } else {
- const success_message = {
- title: T.translate("general.done"),
- html: T.translate("media_file_type.created"),
- type: "success"
- };
-
- postRequest(
- createAction(UPDATE_MEDIA_FILE_TYPE),
- createAction(MEDIA_FILE_TYPE_ADDED),
- `${window.API_BASE_URL}/api/v1/summit-media-file-types`,
- normalizedEntity,
- authErrorHandler,
- entity
- )(params)(dispatch).then((payload) => {
+ const normalizedEntity = normalizeEntity(entity);
+ const params = { access_token: accessToken };
+
+ if (entity.id) {
+ return putRequest(
+ createAction(UPDATE_MEDIA_FILE_TYPE),
+ createAction(MEDIA_FILE_TYPE_UPDATED),
+ `${window.API_BASE_URL}/api/v1/summit-media-file-types/${entity.id}`,
+ normalizedEntity,
+ snackbarErrorHandler,
+ entity
+ )(params)(dispatch)
+ .then(() => {
dispatch(
- showMessage(success_message, () => {
- history.push(`/app/media-file-types/${payload.response.id}`);
+ snackbarSuccessHandler({
+ title: T.translate("general.success"),
+ html: T.translate("media_file_type.saved")
})
);
- });
- }
- };
+ })
+ .finally(() => dispatch(stopLoading()));
+ }
+
+ return postRequest(
+ createAction(UPDATE_MEDIA_FILE_TYPE),
+ createAction(MEDIA_FILE_TYPE_ADDED),
+ `${window.API_BASE_URL}/api/v1/summit-media-file-types`,
+ normalizedEntity,
+ snackbarErrorHandler,
+ entity
+ )(params)(dispatch)
+ .then(() => {
+ dispatch(
+ snackbarSuccessHandler({
+ title: T.translate("general.success"),
+ html: T.translate("media_file_type.created")
+ })
+ );
+ })
+ .finally(() => dispatch(stopLoading()));
+};
export const deleteMediaFileType = (mediaFileTypeId) => async (dispatch) => {
const accessToken = await getAccessTokenSafely();
@@ -198,8 +195,8 @@ export const deleteMediaFileType = (mediaFileTypeId) => async (dispatch) => {
createAction(MEDIA_FILE_TYPE_DELETED)({ mediaFileTypeId }),
`${window.API_BASE_URL}/api/v1/summit-media-file-types/${mediaFileTypeId}`,
null,
- authErrorHandler
- )(params)(dispatch).then(() => {
+ snackbarErrorHandler
+ )(params)(dispatch).finally(() => {
dispatch(stopLoading());
});
};
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 3fb5ca6c3..fd248415a 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -3354,7 +3354,7 @@
"description": "Description",
"allowed_extensions_input": "Allowed Extensions (comma separated: PDF,DOC,etc)",
"allowed_extensions": "Allowed Extensions",
- "delete_warning": "Are you sure you want to delete media file type ",
+ "delete_warning": "Are you sure you want to delete media file type {name}?",
"saved": "Media File Type saved successfully.",
"created": "Media File Type created successfully.",
"placeholders": {
diff --git a/src/pages/media_file_types/__tests__/media-file-type-list-page.test.js b/src/pages/media_file_types/__tests__/media-file-type-list-page.test.js
new file mode 100644
index 000000000..ed77e0ed2
--- /dev/null
+++ b/src/pages/media_file_types/__tests__/media-file-type-list-page.test.js
@@ -0,0 +1,222 @@
+import React from "react";
+import { screen, waitFor } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { renderWithRedux } from "../../../utils/test-utils";
+import MediaFileTypeListPage from "../media-file-type-list-page";
+import * as mediaFileTypeActions from "../../../actions/media-file-type-actions";
+import {
+ DEFAULT_CURRENT_PAGE,
+ DEFAULT_PER_PAGE
+} from "../../../utils/constants";
+
+jest.mock("i18n-react/dist/i18n-react", () => ({
+ __esModule: true,
+ default: { translate: (key) => key }
+}));
+
+jest.mock("openstack-uicore-foundation/lib/components/mui/table", () => ({
+ __esModule: true,
+ default: ({ data, onEdit, onDelete }) => (
+
+ {data.map((row) => (
+
+ {row.name}
+
+
+
+ ))}
+
+ )
+}));
+
+jest.mock("openstack-uicore-foundation/lib/components/mui/search-input", () => {
+ const React = require("react");
+ return {
+ __esModule: true,
+ default: ({ onSearch, term }) => {
+ const [value, setValue] = React.useState(term || "");
+ return (
+ setValue(e.target.value)}
+ onKeyDown={(e) => {
+ if (e.key === "Enter") onSearch(value);
+ }}
+ />
+ );
+ }
+ };
+});
+
+jest.mock("../components/media-file-type-dialog", () => ({
+ __esModule: true,
+ default: ({ onClose, onSave }) => (
+
+
+
+
+ )
+}));
+
+jest.mock("../../../actions/media-file-type-actions", () => ({
+ ...jest.requireActual("../../../actions/media-file-type-actions"),
+ getMediaFileTypes: jest.fn(() => () => Promise.resolve()),
+ getMediaFileType: jest.fn(() => () => Promise.resolve()),
+ saveMediaFileType: jest.fn(() => () => Promise.resolve()),
+ deleteMediaFileType: jest.fn(() => () => Promise.resolve()),
+ resetMediaFileTypeForm: jest.fn(() => () => {})
+}));
+
+const buildInitialState = (listOverrides = {}) => ({
+ mediaFileTypeListState: {
+ media_file_types: [],
+ term: "",
+ order: "id",
+ orderDir: 1,
+ currentPage: 1,
+ lastPage: 1,
+ perPage: 10,
+ totalMediaFileTypes: 0,
+ ...listOverrides
+ },
+ mediaFileTypeState: {
+ entity: { id: 0, name: "", description: "", allowed_extensions: "" },
+ errors: {}
+ }
+});
+
+describe("MediaFileTypeListPage", () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ test("should call getMediaFileTypes on mount", async () => {
+ renderWithRedux(, {
+ initialState: buildInitialState()
+ });
+
+ await waitFor(() => {
+ expect(mediaFileTypeActions.getMediaFileTypes).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ test("should show empty state message when list is empty", () => {
+ renderWithRedux(, {
+ initialState: buildInitialState()
+ });
+
+ expect(screen.getByText("media_file_type.no_results")).toBeInTheDocument();
+ expect(screen.queryByTestId("mui-table")).not.toBeInTheDocument();
+ });
+
+ test("should show table and total count when media file types are present", () => {
+ renderWithRedux(, {
+ initialState: buildInitialState({
+ media_file_types: [
+ { id: 1, name: "Image", description: "", allowed_extensions: [] },
+ { id: 2, name: "Document", description: "", allowed_extensions: [] }
+ ],
+ totalMediaFileTypes: 2
+ })
+ });
+
+ expect(screen.getByTestId("mui-table")).toBeInTheDocument();
+ expect(
+ screen.getByText(/2\smedia_file_type\.media_file_types/)
+ ).toBeInTheDocument();
+ expect(
+ screen.queryByText("media_file_type.no_results")
+ ).not.toBeInTheDocument();
+ });
+
+ test("opens dialog and resets form when Add button is clicked", async () => {
+ const user = userEvent.setup();
+ renderWithRedux(, {
+ initialState: buildInitialState()
+ });
+
+ await user.click(screen.getByText("media_file_type.add"));
+
+ expect(mediaFileTypeActions.resetMediaFileTypeForm).toHaveBeenCalled();
+ expect(screen.getByTestId("media-file-type-dialog")).toBeInTheDocument();
+ });
+
+ test("closes dialog when dialog close is triggered", async () => {
+ const user = userEvent.setup();
+ renderWithRedux(, {
+ initialState: buildInitialState()
+ });
+
+ await user.click(screen.getByText("media_file_type.add"));
+ expect(screen.getByTestId("media-file-type-dialog")).toBeInTheDocument();
+
+ await user.click(screen.getByText("dialog-close"));
+ expect(
+ screen.queryByTestId("media-file-type-dialog")
+ ).not.toBeInTheDocument();
+ });
+
+ test("should fetch entity and opens dialog on row edit", async () => {
+ const user = userEvent.setup();
+ renderWithRedux(, {
+ initialState: buildInitialState({
+ media_file_types: [
+ { id: 7, name: "Video", description: "", allowed_extensions: ["MP4"] }
+ ],
+ totalMediaFileTypes: 1
+ })
+ });
+
+ await user.click(screen.getByText("edit-row"));
+
+ await waitFor(() => {
+ expect(mediaFileTypeActions.getMediaFileType).toHaveBeenCalledWith(7);
+ });
+ });
+
+ test("should call deleteMediaFileType and refreshes list on row delete", async () => {
+ const user = userEvent.setup();
+ renderWithRedux(, {
+ initialState: buildInitialState({
+ media_file_types: [
+ { id: 3, name: "Audio", description: "", allowed_extensions: [] }
+ ],
+ totalMediaFileTypes: 1
+ })
+ });
+
+ await user.click(screen.getByText("delete-row"));
+
+ await waitFor(() => {
+ expect(mediaFileTypeActions.deleteMediaFileType).toHaveBeenCalledWith(3);
+ });
+ });
+
+ test("should call getMediaFileTypes with search term on search", async () => {
+ const user = userEvent.setup();
+ renderWithRedux(, {
+ initialState: buildInitialState()
+ });
+
+ await user.type(screen.getByTestId("search-input"), "pdf{Enter}");
+
+ await waitFor(() => {
+ expect(mediaFileTypeActions.getMediaFileTypes).toHaveBeenCalledWith(
+ "pdf",
+ DEFAULT_CURRENT_PAGE,
+ DEFAULT_PER_PAGE,
+ "id",
+ 1
+ );
+ });
+ });
+});
diff --git a/src/pages/media_file_types/components/__tests__/media-file-type-dialog.test.js b/src/pages/media_file_types/components/__tests__/media-file-type-dialog.test.js
new file mode 100644
index 000000000..15e60080f
--- /dev/null
+++ b/src/pages/media_file_types/components/__tests__/media-file-type-dialog.test.js
@@ -0,0 +1,173 @@
+import React from "react";
+import { render, screen, waitFor } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import MediaFileTypeDialog from "../media-file-type-dialog";
+
+jest.mock("i18n-react/dist/i18n-react", () => ({
+ __esModule: true,
+ default: { translate: (key) => key }
+}));
+
+jest.mock(
+ "../../../../components/mui/formik-inputs/mui-formik-textfield",
+ () => {
+ const React = require("react");
+ return {
+ __esModule: true,
+ default: ({ name, id, formik }) => (
+
+ )
+ };
+ }
+);
+
+jest.mock("../../../../hooks/useScrollToError", () => ({
+ __esModule: true,
+ default: jest.fn()
+}));
+
+const NEW_ENTITY = { id: 0, name: "", description: "", allowed_extensions: [] };
+
+describe("MediaFileTypeDialog", () => {
+ let onClose;
+ let onSave;
+
+ beforeEach(() => {
+ onClose = jest.fn();
+ onSave = jest.fn();
+ });
+
+ test("should show Add title for a new entity", () => {
+ render(
+
+ );
+
+ expect(screen.getByText(/general\.add/)).toBeInTheDocument();
+ });
+
+ test("should show Edit title for an existing entity", () => {
+ render(
+
+ );
+
+ expect(screen.getByText(/general\.edit/)).toBeInTheDocument();
+ });
+
+ test("should call onClose when close icon is clicked", async () => {
+ const user = userEvent.setup();
+ render(
+
+ );
+
+ await user.click(screen.getByRole("button", { name: "close" }));
+
+ expect(onClose).toHaveBeenCalledTimes(1);
+ });
+
+ test("should call onSave with form values on valid submit", async () => {
+ const user = userEvent.setup();
+ render(
+
+ );
+
+ await user.type(screen.getByTestId("field-name"), "PDF Type");
+ await user.type(screen.getByTestId("field-description"), "All PDF files");
+ await user.type(screen.getByTestId("field-allowed_extensions"), "PDF");
+ await user.click(screen.getByRole("button", { name: "general.save" }));
+
+ await waitFor(() => {
+ expect(onSave).toHaveBeenCalledWith(
+ expect.objectContaining({
+ name: "PDF Type",
+ description: "All PDF files",
+ allowed_extensions: "PDF"
+ })
+ );
+ });
+ });
+
+ test("should not call onSave when name is empty", async () => {
+ const user = userEvent.setup();
+ render(
+
+ );
+
+ await user.click(screen.getByRole("button", { name: "general.save" }));
+
+ await waitFor(() => {
+ expect(onSave).not.toHaveBeenCalled();
+ });
+ });
+
+ test("should prefill fields with existing entity values", () => {
+ render(
+
+ );
+
+ expect(screen.getByTestId("field-name")).toHaveValue("Video");
+ expect(screen.getByTestId("field-description")).toHaveValue("Video files");
+ expect(screen.getByTestId("field-allowed_extensions")).toHaveValue(
+ "MP4,AVI"
+ );
+ });
+
+ test("should join array allowed_extensions to comma-separated string", () => {
+ render(
+
+ );
+
+ expect(screen.getByTestId("field-allowed_extensions")).toHaveValue(
+ "PDF,DOC,DOCX"
+ );
+ });
+});
diff --git a/src/pages/media_file_types/components/media-file-type-dialog.js b/src/pages/media_file_types/components/media-file-type-dialog.js
new file mode 100644
index 000000000..c795e61e7
--- /dev/null
+++ b/src/pages/media_file_types/components/media-file-type-dialog.js
@@ -0,0 +1,146 @@
+import React from "react";
+import T from "i18n-react/dist/i18n-react";
+import PropTypes from "prop-types";
+import { FormikProvider, useFormik } from "formik";
+import * as yup from "yup";
+import {
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ Button,
+ InputLabel,
+ Box,
+ IconButton,
+ Divider,
+ Grid2
+} from "@mui/material";
+import CloseIcon from "@mui/icons-material/Close";
+import MuiFormikTextField from "../../../components/mui/formik-inputs/mui-formik-textfield";
+import useScrollToError from "../../../hooks/useScrollToError";
+import { requiredStringValidation } from "../../../utils/yup";
+
+const MediaFileTypeDialog = ({ entity: initialEntity, onClose, onSave }) => {
+ const formik = useFormik({
+ initialValues: {
+ id: initialEntity?.id ?? 0,
+ name: initialEntity?.name ?? "",
+ description: initialEntity?.description ?? "",
+ allowed_extensions: Array.isArray(initialEntity?.allowed_extensions)
+ ? initialEntity.allowed_extensions.join(",")
+ : initialEntity?.allowed_extensions ?? ""
+ },
+ enableReinitialize: true,
+ validationSchema: yup.object().shape({
+ name: requiredStringValidation()
+ }),
+ onSubmit: (values) => onSave(values)
+ });
+
+ useScrollToError(formik);
+
+ const handleClose = () => {
+ formik.resetForm();
+ onClose();
+ };
+
+ const title = initialEntity?.id
+ ? `${T.translate("general.edit")} ${T.translate(
+ "media_file_type.media_file_type"
+ )}`
+ : `${T.translate("general.add")} ${T.translate(
+ "media_file_type.media_file_type"
+ )}`;
+
+ return (
+
+ );
+};
+
+MediaFileTypeDialog.propTypes = {
+ entity: PropTypes.object,
+ onClose: PropTypes.func.isRequired,
+ onSave: PropTypes.func.isRequired
+};
+
+export default MediaFileTypeDialog;
diff --git a/src/pages/media_file_types/media-file-type-list-page.js b/src/pages/media_file_types/media-file-type-list-page.js
index 4e4afb5a1..7c410cc14 100644
--- a/src/pages/media_file_types/media-file-type-list-page.js
+++ b/src/pages/media_file_types/media-file-type-list-page.js
@@ -11,177 +11,207 @@
* limitations under the License.
* */
-import React from "react";
+import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import T from "i18n-react/dist/i18n-react";
-import Swal from "sweetalert2";
-import { Pagination } from "react-bootstrap";
-import {
- FreeTextSearch,
- Table
-} from "openstack-uicore-foundation/lib/components";
-import { getSummitById } from "../../actions/summit-actions";
+import { Box, Button, Grid2 } from "@mui/material";
+import AddIcon from "@mui/icons-material/Add";
+import MuiTable from "openstack-uicore-foundation/lib/components/mui/table";
+import SearchInput from "openstack-uicore-foundation/lib/components/mui/search-input";
import {
getMediaFileTypes,
- deleteMediaFileType
+ getMediaFileType,
+ saveMediaFileType,
+ deleteMediaFileType,
+ resetMediaFileTypeForm
} from "../../actions/media-file-type-actions";
-
-class MediaFileTypeListPage extends React.Component {
- constructor(props) {
- super(props);
-
- this.handleEdit = this.handleEdit.bind(this);
- this.handlePageChange = this.handlePageChange.bind(this);
- this.handleSort = this.handleSort.bind(this);
- this.handleSearch = this.handleSearch.bind(this);
- this.handleNewMediaFileType = this.handleNewMediaFileType.bind(this);
- this.handleDelete = this.handleDelete.bind(this);
-
- this.state = {};
- }
-
- componentDidMount() {
- this.props.getMediaFileTypes();
- }
-
- handleEdit(media_file_type_id) {
- const { history } = this.props;
- history.push(`/app/media-file-types/${media_file_type_id}`);
- }
-
- handlePageChange(page) {
- const { term, order, orderDir, perPage } = this.props;
- this.props.getMediaFileTypes(term, page, perPage, order, orderDir);
- }
-
- handleSort(index, key, dir) {
- const { term, page, perPage } = this.props;
- this.props.getMediaFileTypes(term, page, perPage, key, dir);
- }
-
- handleSearch(term) {
- const { order, orderDir, page, perPage } = this.props;
- this.props.getMediaFileTypes(term, page, perPage, order, orderDir);
- }
-
- handleNewMediaFileType(ev) {
- const { history } = this.props;
- ev.preventDefault();
-
- history.push("/app/media-file-types/new");
- }
-
- handleDelete(typeId) {
- const { deleteMediaFileType, media_file_types } = this.props;
- const media_file_type = media_file_types.find((t) => t.id === typeId);
-
- Swal.fire({
- title: T.translate("general.are_you_sure"),
- text: `${T.translate("media_file_type.delete_warning")} ${
- media_file_type.name
- }`,
- type: "warning",
- showCancelButton: true,
- confirmButtonColor: "#DD6B55",
- confirmButtonText: T.translate("general.yes_delete")
- }).then((result) => {
- if (result.value) {
- deleteMediaFileType(accessId);
- }
- });
- }
-
- canEdit = (item) => !item.is_system_defined;
-
- render() {
- const { media_file_types, lastPage, currentPage, term, order, orderDir } =
- this.props;
-
- const columns = [
- { columnKey: "id", value: T.translate("general.id"), sortable: true },
- {
- columnKey: "name",
- value: T.translate("media_file_type.name"),
- sortable: true
- },
- {
- columnKey: "description",
- value: T.translate("media_file_type.description")
- },
- {
- columnKey: "allowed_extensions",
- value: T.translate("media_file_type.allowed_extensions")
- }
- ];
-
- const table_options = {
- sortCol: order,
- sortDir: orderDir,
- actions: {
- edit: { onClick: this.handleEdit },
- delete: { onClick: this.handleDelete, display: this.canEdit }
- }
- };
-
- return (
-
-
{T.translate("media_file_type.media_file_type_list")}
-
-
-
-
-
-
-
-
-
- {media_file_types.length === 0 && (
-
{T.translate("media_file_type.no_results")}
- )}
-
- {media_file_types.length > 0 && (
-
- )}
-
+import { DEFAULT_CURRENT_PAGE } from "../../utils/constants";
+import MediaFileTypeDialog from "./components/media-file-type-dialog";
+
+const MediaFileTypeListPage = ({
+ media_file_types,
+ currentMediaFileType,
+ term,
+ currentPage,
+ perPage,
+ order,
+ orderDir,
+ totalMediaFileTypes,
+ getMediaFileTypes,
+ getMediaFileType,
+ saveMediaFileType,
+ deleteMediaFileType,
+ resetMediaFileTypeForm
+}) => {
+ const [open, setOpen] = useState(false);
+
+ useEffect(() => {
+ getMediaFileTypes();
+ }, []);
+
+ const handlePageChange = (page) => {
+ getMediaFileTypes(term, page, perPage, order, orderDir);
+ };
+
+ const handlePerPageChange = (newPerPage) => {
+ getMediaFileTypes(term, DEFAULT_CURRENT_PAGE, newPerPage, order, orderDir);
+ };
+
+ const handleSort = (key, dir) => {
+ getMediaFileTypes(term, currentPage, perPage, key, dir);
+ };
+
+ const handleSearch = (searchTerm) => {
+ getMediaFileTypes(
+ searchTerm,
+ DEFAULT_CURRENT_PAGE,
+ perPage,
+ order,
+ orderDir
);
- }
-}
-
-const mapStateToProps = ({ mediaFileTypeListState }) => ({
- ...mediaFileTypeListState
+ };
+
+ const handleRowEdit = (row) => {
+ getMediaFileType(row.id).then(() => setOpen(true));
+ };
+
+ const handleNew = () => {
+ resetMediaFileTypeForm();
+ setOpen(true);
+ };
+
+ const handleClose = () => {
+ resetMediaFileTypeForm();
+ setOpen(false);
+ };
+
+ const handleSave = (entity) =>
+ saveMediaFileType(entity)
+ .then(() =>
+ getMediaFileTypes(term, DEFAULT_CURRENT_PAGE, perPage, order, orderDir)
+ )
+ .then(() => setOpen(false));
+
+ const handleDelete = (mediaFileTypeId) => {
+ deleteMediaFileType(mediaFileTypeId).then(() =>
+ getMediaFileTypes(term, DEFAULT_CURRENT_PAGE, perPage, order, orderDir)
+ );
+ };
+
+ const columns = [
+ {
+ columnKey: "id",
+ header: T.translate("media_file_type.id"),
+ sortable: true
+ },
+ {
+ columnKey: "name",
+ header: T.translate("media_file_type.name"),
+ sortable: true
+ },
+ {
+ columnKey: "description",
+ header: T.translate("media_file_type.description")
+ },
+ {
+ columnKey: "allowed_extensions",
+ header: T.translate("media_file_type.allowed_extensions"),
+ render: (row) => row.allowed_extensions.join(", ")
+ }
+ ];
+
+ const tableOptions = { sortCol: order, sortDir: orderDir };
+
+ return (
+
+
{T.translate("media_file_type.media_file_type_list")}
+
+
+
+ {totalMediaFileTypes}{" "}
+ {T.translate("media_file_type.media_file_types")}
+
+
+
+
+
+
+ }
+ sx={{
+ height: "36px",
+ padding: "6px 16px",
+ fontSize: "1.4rem",
+ lineHeight: "2.4rem",
+ letterSpacing: "0.4px"
+ }}
+ >
+ {T.translate("media_file_type.add")}
+
+
+
+
+ {media_file_types.length > 0 && (
+
+ T.translate("media_file_type.delete_warning", { name })
+ }
+ />
+ )}
+
+ {media_file_types.length === 0 && (
+ {T.translate("media_file_type.no_results")}
+ )}
+
+ {open && (
+
+ )}
+
+ );
+};
+
+const mapStateToProps = ({ mediaFileTypeListState, mediaFileTypeState }) => ({
+ ...mediaFileTypeListState,
+ currentMediaFileType: mediaFileTypeState.entity
});
export default connect(mapStateToProps, {
- getSummitById,
getMediaFileTypes,
- deleteMediaFileType
+ getMediaFileType,
+ saveMediaFileType,
+ deleteMediaFileType,
+ resetMediaFileTypeForm
})(MediaFileTypeListPage);
diff --git a/src/reducers/media_file_types/media-file-type-list-reducer.js b/src/reducers/media_file_types/media-file-type-list-reducer.js
index b72693552..01a73c5a8 100644
--- a/src/reducers/media_file_types/media-file-type-list-reducer.js
+++ b/src/reducers/media_file_types/media-file-type-list-reducer.js
@@ -9,7 +9,9 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- **/
+ * */
+
+import { LOGOUT_USER } from "openstack-uicore-foundation/lib/security/actions";
import {
RECEIVE_MEDIA_FILE_TYPES,
@@ -17,16 +19,15 @@ import {
MEDIA_FILE_TYPE_DELETED
} from "../../actions/media-file-type-actions";
-import { LOGOUT_USER } from "openstack-uicore-foundation/lib/security/actions";
-
const DEFAULT_STATE = {
media_file_types: [],
- term: null,
+ term: "",
order: "id",
orderDir: 1,
currentPage: 1,
lastPage: 1,
- perPage: 10
+ perPage: 10,
+ totalMediaFileTypes: 0
};
const mediaFileTypeListReducer = (state = DEFAULT_STATE, action) => {
@@ -36,30 +37,29 @@ const mediaFileTypeListReducer = (state = DEFAULT_STATE, action) => {
return DEFAULT_STATE;
}
case REQUEST_MEDIA_FILE_TYPES: {
- let { order, orderDir, term } = payload;
+ const { order, orderDir, term, perPage } = payload;
- return { ...state, order, orderDir, term };
+ return { ...state, order, orderDir, term, perPage };
}
case RECEIVE_MEDIA_FILE_TYPES: {
- let { total, last_page, current_page } = payload.response;
- let media_file_types = payload.response.data.map((mft) => {
- return {
- id: mft.id,
- name: mft.name,
- description: mft.description,
- allowed_extensions: mft.allowed_extensions
- };
- });
+ const { total, last_page, current_page } = payload.response;
+ const media_file_types = payload.response.data.map((mft) => ({
+ id: mft.id,
+ name: mft.name,
+ description: mft.description,
+ allowed_extensions: mft.allowed_extensions
+ }));
return {
...state,
- media_file_types: media_file_types,
+ media_file_types,
currentPage: current_page,
- lastPage: last_page
+ lastPage: last_page,
+ totalMediaFileTypes: total
};
}
case MEDIA_FILE_TYPE_DELETED: {
- let { mediaFileTypeId } = payload;
+ const { mediaFileTypeId } = payload;
return {
...state,
media_file_types: state.media_file_types.filter(