diff --git a/src/actions/summitdoc-actions.js b/src/actions/summitdoc-actions.js
index 478811d18..455f01492 100644
--- a/src/actions/summitdoc-actions.js
+++ b/src/actions/summitdoc-actions.js
@@ -17,8 +17,7 @@ import {
createAction,
stopLoading,
startLoading,
- showMessage,
- showSuccessMessage,
+ snackbarSuccessHandler,
authErrorHandler,
postRequest,
putRequest,
@@ -179,15 +178,14 @@ export const saveSummitDoc = (entity, file) => async (dispatch, getState) => {
authErrorHandler,
entity
)(params)(dispatch).then(() => {
- dispatch(showSuccessMessage(T.translate("summitdoc.saved")));
+ dispatch(
+ snackbarSuccessHandler({
+ title: T.translate("general.done"),
+ html: T.translate("summitdoc.saved")
+ })
+ );
});
} else {
- const successMessage = {
- title: T.translate("general.done"),
- html: T.translate("summitdoc.created"),
- type: "success"
- };
-
postFile(
createAction(UPDATE_SUMMITDOC),
createAction(SUMMITDOC_ADDED),
@@ -198,12 +196,14 @@ export const saveSummitDoc = (entity, file) => async (dispatch, getState) => {
entity
)(params)(dispatch).then((payload) => {
dispatch(
- showMessage(successMessage, () => {
- history.push(
- `/app/summits/${currentSummit.id}/summitdocs/${payload.response.id}`
- );
+ snackbarSuccessHandler({
+ title: T.translate("general.done"),
+ html: T.translate("summitdoc.created")
})
);
+ history.push(
+ `/app/summits/${currentSummit.id}/summitdocs/${payload.response.id}`
+ );
});
}
};
diff --git a/src/components/forms/__tests__/summitdoc-form.test.js b/src/components/forms/__tests__/summitdoc-form.test.js
new file mode 100644
index 000000000..f47e6a481
--- /dev/null
+++ b/src/components/forms/__tests__/summitdoc-form.test.js
@@ -0,0 +1,142 @@
+import React from "react";
+import { render, screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import "@testing-library/jest-dom";
+import SummitDocForm from "../summitdoc-form";
+
+jest.mock("i18n-react/dist/i18n-react", () => ({
+ __esModule: true,
+ default: { translate: (key) => key }
+}));
+
+jest.mock(
+ "openstack-uicore-foundation/lib/components/inputs/upload-input",
+ () => ({
+ __esModule: true,
+ default: ({ value, handleUpload, handleRemove, disabled }) => (
+
+
+ {value && (
+
+ )}
+
+ )
+ })
+);
+
+const currentSummit = {
+ event_types: [
+ { id: 1, name: "Keynote" },
+ { id: 2, name: "Panel" }
+ ],
+ selection_plans: [{ id: 10, name: "Plan A" }]
+};
+
+const baseEntity = {
+ id: 0,
+ name: "",
+ label: "",
+ description: "",
+ event_types: [],
+ file_preview: "",
+ file: null,
+ selection_plan_id: null,
+ show_always: false,
+ web_link: ""
+};
+
+const renderForm = (entityOverrides = {}, props = {}) =>
+ render(
+
+ );
+
+describe("SummitDocForm", () => {
+ it("clears and disables event types when show_always is checked", async () => {
+ renderForm({ event_types: [1] });
+
+ const eventTypesSelect = screen.getByTestId("event-types-select");
+ expect(eventTypesSelect).toHaveTextContent("Keynote");
+
+ await userEvent.click(
+ screen.getByRole("checkbox", { name: "summitdoc.show_always" })
+ );
+
+ expect(eventTypesSelect).not.toHaveTextContent("Keynote");
+ expect(eventTypesSelect.querySelector("[role='combobox']")).toHaveClass(
+ "Mui-disabled"
+ );
+ });
+
+ it("disables the file upload when a web link is entered", async () => {
+ renderForm();
+
+ await userEvent.type(
+ screen.getByLabelText("summitdoc.web_link *"),
+ "http://example.com"
+ );
+
+ expect(screen.getByRole("button", { name: "upload-file" })).toBeDisabled();
+ });
+
+ it("disables the web link field once a file is present", () => {
+ renderForm({ file_preview: "blob:existing-file" });
+
+ expect(screen.getByLabelText("summitdoc.web_link *")).toBeDisabled();
+ });
+
+ it("holds the file in local state for a new doc and submits it together with the entity on save", async () => {
+ const onSubmit = jest.fn();
+ const addFileToDoc = jest.fn();
+ renderForm({}, { onSubmit, addFileToDoc });
+
+ await userEvent.click(screen.getByRole("button", { name: "upload-file" }));
+
+ expect(addFileToDoc).not.toHaveBeenCalled();
+ expect(
+ screen.getByRole("button", { name: "remove-file" })
+ ).toBeInTheDocument();
+
+ await userEvent.click(screen.getByRole("button", { name: "general.save" }));
+
+ expect(onSubmit).toHaveBeenCalledWith(
+ expect.objectContaining({ file_preview: "blob:new-file" }),
+ { preview: "blob:new-file" }
+ );
+ });
+
+ it("uploads/removes the file directly against the API for an existing doc", async () => {
+ const addFileToDoc = jest.fn();
+ const removeFileFromDoc = jest.fn();
+ renderForm(
+ { id: 5, file_preview: "blob:existing-file" },
+ { addFileToDoc, removeFileFromDoc }
+ );
+
+ await userEvent.click(screen.getByRole("button", { name: "upload-file" }));
+ expect(addFileToDoc).toHaveBeenCalledWith(
+ expect.objectContaining({ id: 5 }),
+ { preview: "blob:new-file" }
+ );
+
+ await userEvent.click(screen.getByRole("button", { name: "remove-file" }));
+ expect(removeFileFromDoc).toHaveBeenCalledWith(
+ expect.objectContaining({ id: 5 })
+ );
+ });
+});
diff --git a/src/components/forms/summitdoc-form.js b/src/components/forms/summitdoc-form.js
index 3af66746b..f39da9052 100644
--- a/src/components/forms/summitdoc-form.js
+++ b/src/components/forms/summitdoc-form.js
@@ -9,249 +9,292 @@
* 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 React from "react";
+import React, { useEffect, useState } from "react";
import T from "i18n-react/dist/i18n-react";
-import "awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css";
-import Dropdown from "openstack-uicore-foundation/lib/components/inputs/dropdown"
-import Input from "openstack-uicore-foundation/lib/components/inputs/text-input"
-import TextArea from "openstack-uicore-foundation/lib/components/inputs/textarea-input"
+import Box from "@mui/material/Box";
+import { Grid2 } from "@mui/material";
+import TextField from "@mui/material/TextField";
+import Select from "@mui/material/Select";
+import MenuItem from "@mui/material/MenuItem";
+import Checkbox from "@mui/material/Checkbox";
+import FormControlLabel from "@mui/material/FormControlLabel";
+import Button from "@mui/material/Button";
+import Tooltip from "@mui/material/Tooltip";
+import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
import UploadInput from "openstack-uicore-foundation/lib/components/inputs/upload-input";
-import { isEmpty, scrollToError, shallowEqual } from "../../utils/methods";
+import { scrollToError, shallowEqual } from "../../utils/methods";
-class SummitDocForm extends React.Component {
- constructor(props) {
- super(props);
+const SummitDocForm = ({
+ currentSummit,
+ entity: entityProp,
+ errors: errorsProp,
+ onSubmit,
+ addFileToDoc,
+ removeFileFromDoc
+}) => {
+ const [entity, setEntity] = useState({ ...entityProp });
+ const [errors, setErrors] = useState(errorsProp);
+ const [file, setFile] = useState(null);
- this.state = {
- entity: { ...props.entity },
- errors: props.errors
- };
+ useEffect(() => {
+ scrollToError(errorsProp);
+ }, [errorsProp]);
- this.handleChange = this.handleChange.bind(this);
- this.handleSubmit = this.handleSubmit.bind(this);
- this.handleUploadFile = this.handleUploadFile.bind(this);
- this.handleRemoveFile = this.handleRemoveFile.bind(this);
- }
-
- componentDidUpdate(prevProps, prevState, snapshot) {
- const state = {};
- scrollToError(this.props.errors);
-
- if (!shallowEqual(prevProps.entity, this.props.entity)) {
- state.entity = { ...this.props.entity };
- state.errors = {};
+ useEffect(() => {
+ if (!shallowEqual(entity, entityProp)) {
+ setEntity({ ...entityProp });
+ setErrors({});
}
+ }, [entityProp]);
- if (!shallowEqual(prevProps.errors, this.props.errors)) {
- state.errors = { ...this.props.errors };
+ useEffect(() => {
+ if (!shallowEqual(errors, errorsProp)) {
+ setErrors({ ...errorsProp });
}
+ }, [errorsProp]);
- if (!isEmpty(state)) {
- this.setState({ ...this.state, ...state });
- }
- }
-
- handleChange(ev) {
- let entity = { ...this.state.entity };
- let errors = { ...this.state.errors };
- let { value, id } = ev.target;
+ const handleChange = (ev) => {
+ const newEntity = { ...entity };
+ const newErrors = { ...errors };
+ const { id } = ev.target;
+ let { value } = ev.target;
if (ev.target.type === "checkbox") {
value = ev.target.checked;
}
if (ev.target.type === "number") {
- value = parseInt(ev.target.value);
+ value = parseInt(value, 10);
}
- errors[id] = "";
- entity[id] = value;
+ newErrors[id] = "";
+ newEntity[id] = value;
if (id === "show_always" && value) {
- entity.event_types = [];
+ newEntity.event_types = [];
}
- this.setState({ entity: entity, errors: errors });
- }
+ setEntity(newEntity);
+ setErrors(newErrors);
+ };
- handleSubmit(ev) {
- const { entity, file } = this.state;
+ const handleSubmit = (ev) => {
ev.preventDefault();
+ onSubmit(entity, file);
+ };
- this.props.onSubmit(entity, file);
- }
-
- hasErrors(field) {
- let { errors } = this.state;
+ const hasErrors = (field) => {
if (field in errors) {
return errors[field];
}
return "";
- }
+ };
- handleUploadFile(file) {
- let entity = { ...this.state.entity };
+ const handleUploadFile = (uploadedFile) => {
+ const newEntity = { ...entity };
- if (entity.id) {
- this.props.addFileToDoc(entity, file);
+ if (newEntity.id) {
+ addFileToDoc(newEntity, uploadedFile);
} else {
- entity.file_preview = file.preview;
- this.setState({ file: file, entity: entity });
+ newEntity.file_preview = uploadedFile.preview;
+ setFile(uploadedFile);
+ setEntity(newEntity);
}
- }
+ };
- handleRemoveFile(ev) {
- let entity = { ...this.state.entity };
+ const handleRemoveFile = () => {
+ const newEntity = { ...entity };
- if (entity.id) {
- this.props.removeFileFromDoc(entity);
+ if (newEntity.id) {
+ removeFileFromDoc(newEntity);
} else {
- entity.file_preview = "";
- this.setState({ file: null, entity: entity });
+ newEntity.file_preview = "";
+ setFile(null);
+ setEntity(newEntity);
}
- }
+ };
- render() {
- const { entity } = this.state;
- const { currentSummit } = this.props;
+ const eventTypesDDL = currentSummit.event_types.map((et) => ({
+ value: et.id,
+ label: et.name
+ }));
- let event_types_ddl = currentSummit.event_types.map((et) => ({
- value: et.id,
- label: et.name
- }));
+ const selectionPlansDDL = currentSummit.selection_plans.map((sp) => ({
+ value: sp.id,
+ label: sp.name
+ }));
- let selection_plans_ddl = currentSummit.selection_plans.map((et) => ({
- value: et.id,
- label: et.name
- }));
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- return (
-
- );
- }
-}
+
+
+
+
+ );
+};
export default SummitDocForm;
diff --git a/src/pages/summitdocs/__tests__/summitdoc-list-page.test.js b/src/pages/summitdocs/__tests__/summitdoc-list-page.test.js
new file mode 100644
index 000000000..35653d789
--- /dev/null
+++ b/src/pages/summitdocs/__tests__/summitdoc-list-page.test.js
@@ -0,0 +1,221 @@
+import React from "react";
+import { act, render, screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import "@testing-library/jest-dom";
+import { renderWithRedux, createMockSummit } from "../../../utils/test-utils";
+import SummitDocListPage from "../summitdoc-list-page";
+import {
+ getSummitDocs,
+ deleteSummitDoc
+} from "../../../actions/summitdoc-actions";
+import { DEFAULT_CURRENT_PAGE } from "../../../utils/constants";
+
+jest.mock("../../../actions/summitdoc-actions", () => ({
+ getSummitDocs: jest.fn(),
+ deleteSummitDoc: jest.fn()
+}));
+
+let capturedColumns;
+
+jest.mock("openstack-uicore-foundation/lib/components/mui/table", () => ({
+ __esModule: true,
+ default: ({
+ onEdit,
+ onDelete,
+ onSort,
+ onPageChange,
+ onPerPageChange,
+ columns
+ }) => {
+ capturedColumns = columns;
+ return (
+
+
+
+
+
+
+
+ );
+ }
+}));
+
+jest.mock(
+ "openstack-uicore-foundation/lib/components/mui/search-input",
+ () => ({
+ __esModule: true,
+ default: ({ onSearch }) => (
+
+ )
+ })
+);
+
+jest.mock("i18n-react/dist/i18n-react", () => ({
+ __esModule: true,
+ default: { translate: (key) => key }
+}));
+
+const mockHistory = { push: jest.fn() };
+
+const initialState = {
+ currentSummitState: { currentSummit: createMockSummit() },
+ summitDocListState: {
+ summitDocs: [
+ {
+ id: 1,
+ name: "test-doc",
+ label: "test-label",
+ description: "test-description",
+ event_types_string: "Keynote, Panel"
+ }
+ ],
+ totalSummitDocs: 1,
+ perPage: 10,
+ currentPage: 1,
+ term: "",
+ order: "id",
+ orderDir: 1,
+ lastPage: 1
+ }
+};
+
+describe("SummitDocListPage", () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ getSummitDocs.mockReturnValue(() => Promise.resolve());
+ deleteSummitDoc.mockReturnValue(() => Promise.resolve());
+ });
+
+ it("bounds the description and event types column widths and wraps long content", () => {
+ renderWithRedux(, {
+ initialState
+ });
+
+ const descriptionColumn = capturedColumns.find(
+ (c) => c.columnKey === "description"
+ );
+ const eventTypesColumn = capturedColumns.find(
+ (c) => c.columnKey === "event_types_string"
+ );
+ expect(descriptionColumn.width).toBe(400);
+ expect(eventTypesColumn.width).toBe(300);
+
+ const longValue = "lorem ipsum ".repeat(50).trim();
+ const { container } = render(
+ descriptionColumn.render({ description: longValue })
+ );
+
+ expect(container.firstChild).toHaveStyle({
+ wordBreak: "break-word",
+ overflowWrap: "anywhere"
+ });
+ expect(container).toHaveTextContent(longValue);
+ });
+
+ it("deletes the summit doc by id (confirm is handled inside MuiTable)", async () => {
+ renderWithRedux(, {
+ initialState
+ });
+
+ await act(async () => {
+ await userEvent.click(screen.getByRole("button", { name: "delete-row" }));
+ });
+
+ expect(deleteSummitDoc).toHaveBeenCalledWith(1);
+ });
+
+ it("resets to the first page on search", async () => {
+ renderWithRedux(, {
+ initialState
+ });
+
+ await act(async () => {
+ await userEvent.click(
+ screen.getByRole("button", { name: "search-trigger" })
+ );
+ });
+
+ expect(getSummitDocs).toHaveBeenLastCalledWith(
+ "newterm",
+ DEFAULT_CURRENT_PAGE,
+ 10,
+ "id",
+ 1
+ );
+ });
+
+ it("resets to the first page on per-page change", async () => {
+ renderWithRedux(, {
+ initialState
+ });
+
+ await act(async () => {
+ await userEvent.click(screen.getByRole("button", { name: "perpage-50" }));
+ });
+
+ expect(getSummitDocs).toHaveBeenLastCalledWith(
+ "",
+ DEFAULT_CURRENT_PAGE,
+ 50,
+ "id",
+ 1
+ );
+ });
+
+ it("keeps the current page on sort", async () => {
+ renderWithRedux(, {
+ initialState
+ });
+
+ await act(async () => {
+ await userEvent.click(screen.getByRole("button", { name: "sort-col" }));
+ });
+
+ expect(getSummitDocs).toHaveBeenLastCalledWith("", 1, 10, "label", -1);
+ });
+
+ it("navigates to the edit page", async () => {
+ renderWithRedux(, {
+ initialState
+ });
+
+ await act(async () => {
+ await userEvent.click(screen.getByRole("button", { name: "edit-row" }));
+ });
+
+ expect(mockHistory.push).toHaveBeenCalledWith(
+ "/app/summits/456/summitdocs/1"
+ );
+ });
+
+ it("navigates to the add page", async () => {
+ renderWithRedux(, {
+ initialState
+ });
+
+ await act(async () => {
+ await userEvent.click(
+ screen.getByRole("button", { name: "summitdoc.add" })
+ );
+ });
+
+ expect(mockHistory.push).toHaveBeenCalledWith(
+ "/app/summits/456/summitdocs/new"
+ );
+ });
+});
diff --git a/src/pages/summitdocs/summitdoc-list-page.js b/src/pages/summitdocs/summitdoc-list-page.js
index cfad0996b..89babc234 100644
--- a/src/pages/summitdocs/summitdoc-list-page.js
+++ b/src/pages/summitdocs/summitdoc-list-page.js
@@ -9,175 +9,144 @@
* 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 React from "react";
+import React, { useEffect } 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 from "openstack-uicore-foundation/lib/components/free-text-search"
-import Table from "openstack-uicore-foundation/lib/components/table";
+import Button from "@mui/material/Button";
+import AddIcon from "@mui/icons-material/Add";
+import MuiTable from "openstack-uicore-foundation/lib/components/mui/table";
+import GridToolbar from "../../components/mui/grid-toolbar";
import { getSummitById } from "../../actions/summit-actions";
import {
getSummitDocs,
deleteSummitDoc
} from "../../actions/summitdoc-actions";
+import { DEFAULT_CURRENT_PAGE } from "../../utils/constants";
+
+const wrapLongText = (value) => (
+
+ {value}
+
+);
+
+const SummitDocListPage = ({
+ currentSummit,
+ summitDocs,
+ currentPage,
+ perPage,
+ term,
+ order,
+ orderDir,
+ totalSummitDocs,
+ history,
+ getSummitDocs,
+ deleteSummitDoc
+}) => {
+ useEffect(() => {
+ if (currentSummit) {
+ getSummitDocs(term, currentPage, perPage, order, orderDir);
+ }
+ }, [currentSummit]);
-class SummitDocListPage extends React.Component {
- constructor(props) {
- super(props);
+ const handleEdit = (row) => {
+ history.push(`/app/summits/${currentSummit.id}/summitdocs/${row.id}`);
+ };
- 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.handleNew = this.handleNew.bind(this);
- this.handleDelete = this.handleDelete.bind(this);
- }
+ const handlePageChange = (page) => {
+ getSummitDocs(term, page, perPage, order, orderDir);
+ };
- componentDidMount() {
- const { currentSummit } = this.props;
- if (currentSummit) {
- this.props.getSummitDocs();
- }
- }
-
- handleEdit(summitdoc_id) {
- const { currentSummit, history } = this.props;
- history.push(`/app/summits/${currentSummit.id}/summitdocs/${summitdoc_id}`);
- }
-
- handlePageChange(page) {
- const { term, order, orderDir, perPage } = this.props;
- this.props.getSummitDocs(term, page, perPage, order, orderDir);
- }
-
- handleSort(index, key, dir, func) {
- const { term, page, perPage } = this.props;
- this.props.getSummitDocs(term, page, perPage, key, dir);
- }
-
- handleSearch(term) {
- const { order, orderDir, page, perPage } = this.props;
- this.props.getSummitDocs(term, page, perPage, order, orderDir);
- }
-
- handleNew(ev) {
- const { currentSummit, history } = this.props;
+ const handlePerPageChange = (newPerPage) => {
+ getSummitDocs(term, DEFAULT_CURRENT_PAGE, newPerPage, order, orderDir);
+ };
+
+ const handleSort = (key, dir) => {
+ getSummitDocs(term, currentPage, perPage, key, dir);
+ };
+
+ const handleSearch = (newTerm) => {
+ getSummitDocs(newTerm, DEFAULT_CURRENT_PAGE, perPage, order, orderDir);
+ };
+
+ const handleNew = (ev) => {
+ ev.preventDefault();
history.push(`/app/summits/${currentSummit.id}/summitdocs/new`);
- }
-
- handleDelete(summitDocId) {
- const { deleteSummitDoc, summitDocs } = this.props;
- let summitDoc = summitDocs.find((s) => s.id === summitDocId);
-
- Swal.fire({
- title: T.translate("general.are_you_sure"),
- text: T.translate("summitdoc.delete_warning") + " " + summitDoc.label,
- type: "warning",
- showCancelButton: true,
- confirmButtonColor: "#DD6B55",
- confirmButtonText: T.translate("general.yes_delete")
- }).then(function (result) {
- if (result.value) {
- deleteSummitDoc(summitDocId);
- }
- });
- }
-
- render() {
- const {
- currentSummit,
- summitDocs,
- lastPage,
- currentPage,
- term,
- order,
- orderDir,
- totalSummitDocs
- } = this.props;
-
- const columns = [
- { columnKey: "id", value: T.translate("general.id"), sortable: true },
- {
- columnKey: "label",
- value: T.translate("summitdoc.label"),
- sortable: true
- },
- { columnKey: "description", value: T.translate("summitdoc.description") },
- {
- columnKey: "event_types_string",
- value: T.translate("summitdoc.event_types")
- }
- ];
-
- const table_options = {
- sortCol: order,
- sortDir: orderDir,
- actions: {
- edit: { onClick: this.handleEdit },
- delete: { onClick: this.handleDelete }
- }
- };
-
- if (!currentSummit.id) return ;
-
- return (
-
-
- {" "}
- {T.translate("summitdoc.list")} ({totalSummitDocs})
-
-
-
-
-
-
-
-
+ };
+
+ const columns = [
+ { columnKey: "id", header: T.translate("general.id"), sortable: true },
+ {
+ columnKey: "label",
+ header: T.translate("summitdoc.label"),
+ sortable: true
+ },
+ {
+ columnKey: "description",
+ header: T.translate("summitdoc.description"),
+ width: 400,
+ render: (row) => wrapLongText(row.description)
+ },
+ {
+ columnKey: "event_types_string",
+ header: T.translate("summitdoc.event_types"),
+ width: 300,
+ render: (row) => wrapLongText(row.event_types_string)
+ }
+ ];
+
+ const tableOptions = { sortCol: order, sortDir: orderDir };
+
+ if (!currentSummit.id) return
;
+
+ return (
+
+
+ {" "}
+ {T.translate("summitdoc.list")} ({totalSummitDocs})
+
+
+ }>
+ {T.translate("summitdoc.add")}
+
+
+
+ {summitDocs.length === 0 && (
+
{T.translate("summitdoc.no_items")}
+ )}
+
+ {summitDocs.length > 0 && (
+
+ row.label}
+ deleteDialogBody={(name) =>
+ `${T.translate("summitdoc.delete_warning")} ${name}`
+ }
+ confirmButtonColor="error"
+ />
-
- {summitDocs.length === 0 && (
-
{T.translate("summitdoc.no_items")}
- )}
-
- {summitDocs.length > 0 && (
-
- )}
-
- );
- }
-}
+ )}
+
+ );
+};
const mapStateToProps = ({ currentSummitState, summitDocListState }) => ({
currentSummit: currentSummitState.currentSummit,