From 38aa9d1443e4176765b03a01fbee87f1b62ffdf1 Mon Sep 17 00:00:00 2001 From: xaralis <filip.varecha@fragaria.cz> Date: Fri, 18 Dec 2020 10:41:40 +0100 Subject: [PATCH] feat: global actions on program --- src/actions/program.js | 60 +++++++++++++++- src/containers/AnnoucementsContainer.jsx | 4 +- src/containers/PostsContainer.jsx | 18 ++--- src/hooks.js | 19 ++++- src/pages/Home.jsx | 91 ++++++++++++++++++------ 5 files changed, 154 insertions(+), 38 deletions(-) diff --git a/src/actions/program.js b/src/actions/program.js index f1d0fa3..23000ee 100644 --- a/src/actions/program.js +++ b/src/actions/program.js @@ -33,9 +33,9 @@ export const loadProgram = createAsyncAction( "description", "proposer", ]), - expectedStartAt: new Date(entry.expectedStartAt), - expectedFinishAt: entry.expectedFinishAt - ? new Date(entry.expectedFinishAt) + expectedStartAt: new Date(entry.expected_start_at), + expectedFinishAt: entry.expected_finish_at + ? new Date(entry.expected_finish_at) : undefined, }; } @@ -60,3 +60,57 @@ export const loadProgram = createAsyncAction( }, } ); + +/** + * Open discussion. + */ +export const endProgramPoint = createAsyncAction( + async () => { + return successResult(); + }, + { + postActionHook: ({ result }) => { + if (!result.error) { + ProgramStore.update((state) => { + state.current = null; + }); + } + }, + } +); + +/** + * Open discussion. + */ +export const openDiscussion = createAsyncAction( + async () => { + return successResult(); + }, + { + postActionHook: ({ result }) => { + if (!result.error) { + ProgramStore.update((state) => { + state.current.discussionOpened = true; + }); + } + }, + } +); + +/** + * Close discussion. + */ +export const closeDiscussion = createAsyncAction( + async () => { + return successResult(); + }, + { + postActionHook: ({ result }) => { + if (!result.error) { + ProgramStore.update((state) => { + state.current.discussionOpened = false; + }); + } + }, + } +); diff --git a/src/containers/AnnoucementsContainer.jsx b/src/containers/AnnoucementsContainer.jsx index daeafc6..6ac1c56 100644 --- a/src/containers/AnnoucementsContainer.jsx +++ b/src/containers/AnnoucementsContainer.jsx @@ -7,7 +7,7 @@ import { import AnnouncementEditModal from "components/annoucements/AnnouncementEditModal"; import AnnouncementList from "components/annoucements/AnnouncementList"; import ModalConfirm from "components/modals/ModalConfirm"; -import { useModalConfirmControl } from "hooks"; +import { useItemActionConfirm } from "hooks"; import { AnnouncementStore } from "stores"; const AnnoucementsContainer = () => { @@ -18,7 +18,7 @@ const AnnoucementsContainer = () => { setItemToDelete, onDeleteConfirm, onDeleteCancel, - ] = useModalConfirmControl(deleteAnnouncement); + ] = useItemActionConfirm(deleteAnnouncement); const items = AnnouncementStore.useState((state) => state.items); diff --git a/src/containers/PostsContainer.jsx b/src/containers/PostsContainer.jsx index 0b512ec..7608cbe 100644 --- a/src/containers/PostsContainer.jsx +++ b/src/containers/PostsContainer.jsx @@ -14,7 +14,7 @@ import { import { ban } from "actions/users"; import ModalConfirm from "components/modals/ModalConfirm"; import PostList from "components/posts/PostList"; -import { useModalConfirmControl } from "hooks"; +import { useItemActionConfirm } from "hooks"; import { PostStore } from "stores"; const PostsContainer = ({ className }) => { @@ -23,31 +23,31 @@ const PostsContainer = ({ className }) => { setUserToBan, onBanUserConfirm, onBanUserCancel, - ] = useModalConfirmControl(ban); + ] = useItemActionConfirm(ban); const [ postToHide, setPostToHide, onPostHideConfirm, onPostHideCancel, - ] = useModalConfirmControl(hide); + ] = useItemActionConfirm(hide); const [ postToAnnounce, setPostToAnnounce, onAnnounceConfirm, onAnnounceCancel, - ] = useModalConfirmControl(announceProposal); + ] = useItemActionConfirm(announceProposal); const [ postToAccept, setPostToAccept, onAcceptConfirm, onAcceptCancel, - ] = useModalConfirmControl(acceptProposal); + ] = useItemActionConfirm(acceptProposal); const [ postToReject, setPostToReject, onRejectConfirm, onRejectCancel, - ] = useModalConfirmControl(rejectProposal); + ] = useItemActionConfirm(rejectProposal); const { window, items } = PostStore.useState((state) => pick(state, ["window", "items"]) @@ -82,9 +82,6 @@ const PostsContainer = ({ className }) => { } }; - const sliceStart = (window.page - 1) * window.perPage; - const sliceEnd = window.page * window.perPage; - /** * Ban a post's author. * @param {CF2021.Post} post @@ -93,6 +90,9 @@ const PostsContainer = ({ className }) => { setUserToBan(post.author); }; + const sliceStart = (window.page - 1) * window.perPage; + const sliceEnd = window.page * window.perPage; + return ( <> <PostList diff --git a/src/hooks.js b/src/hooks.js index 6942ed6..f138fe4 100644 --- a/src/hooks.js +++ b/src/hooks.js @@ -1,6 +1,6 @@ import { useCallback, useState } from "react"; -export const useModalConfirmControl = (actionFn) => { +export const useItemActionConfirm = (actionFn) => { const [item, setItem] = useState(null); const onActionConfirm = useCallback(() => { @@ -16,3 +16,20 @@ export const useModalConfirmControl = (actionFn) => { return [item, setItem, onActionConfirm, onActionCancel]; }; + +export const useActionConfirm = (actionFn) => { + const [showConfirm, setShowConfirm] = useState(false); + + const onActionConfirm = useCallback(() => { + if (showConfirm) { + actionFn.run(); + setShowConfirm(false); + } + }, [showConfirm, setShowConfirm, actionFn]); + + const onActionCancel = useCallback(() => { + setShowConfirm(false); + }, [setShowConfirm]); + + return [showConfirm, setShowConfirm, onActionConfirm, onActionCancel]; +}; diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx index 4221673..4b0c764 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.jsx @@ -1,5 +1,10 @@ -import React, { useState } from "react"; +import React from "react"; +import { + closeDiscussion, + endProgramPoint, + openDiscussion, +} from "actions/program"; import Button from "components/Button"; import { DropdownMenu, DropdownMenuItem } from "components/dropdown-menu"; import ModalConfirm from "components/modals/ModalConfirm"; @@ -8,6 +13,7 @@ import AddPostForm from "containers/AddPostForm"; import AnnouncementsContainer from "containers/AnnoucementsContainer"; import PostFilters from "containers/PostFilters"; import PostsContainer from "containers/PostsContainer"; +import { useActionConfirm } from "hooks"; import { ProgramStore } from "stores"; const noCurrentDiscussion = ( @@ -29,22 +35,30 @@ const noCurrentDiscussion = ( ); const Home = () => { - const [showEndDiscussionConfirm, setShowEndDiscussionConfirm] = useState( - false - ); + const [ + showCloseDiscussion, + setShowCloseDiscussion, + onCloseDiscussionConfirm, + onCloseDiscussionCancel, + ] = useActionConfirm(closeDiscussion); + const [ + showOpenDiscussion, + setShowOpenDiscussion, + onOpenDiscussionConfirm, + onOpenDiscussionCancel, + ] = useActionConfirm(openDiscussion); + const [ + showEndProgramPoint, + setShowEndProgramPoint, + onEndProgramPointConfirm, + onEndProgramPointCancel, + ] = useActionConfirm(endProgramPoint); const { current } = ProgramStore.useState(); const onRenameProgramPoint = () => { console.log("renameProgramPoint"); }; - const onEndDiscussion = () => { - console.log("endDiscussion"); - setShowEndDiscussionConfirm(true); - }; - const onEndProgramPoint = () => { - console.log("endProgramPoint"); - }; if (!current) { return noCurrentDiscussion; @@ -66,15 +80,26 @@ const Home = () => { titleSize="base" iconSize="base" /> + {current.discussionOpened && ( + <DropdownMenuItem + onClick={() => setShowCloseDiscussion(true)} + icon="ico--bubbles" + title="Ukončit rozpravu" + titleSize="base" + iconSize="base" + /> + )} + {!current.discussionOpened && ( + <DropdownMenuItem + onClick={() => setShowOpenDiscussion(true)} + icon="ico--bubbles" + title="Otevřít rozpravu" + titleSize="base" + iconSize="base" + /> + )} <DropdownMenuItem - onClick={onEndDiscussion} - icon="ico--bubbles" - title="Ukončit rozpravu" - titleSize="base" - iconSize="base" - /> - <DropdownMenuItem - onClick={onEndProgramPoint} + onClick={() => setShowEndProgramPoint(true)} icon="ico--switch" title="Ukončit bod programu" titleSize="base" @@ -115,18 +140,38 @@ const Home = () => { </div> <PostsContainer className="container-padding--zero lg:container-padding--auto" /> - <AddPostForm className="my-8 space-y-4" /> + {current.discussionOpened && ( + <AddPostForm className="my-8 space-y-4" /> + )} </section> </article> <ModalConfirm - isOpen={showEndDiscussionConfirm} - onConfirm={() => setShowEndDiscussionConfirm(false)} - onCancel={() => setShowEndDiscussionConfirm(false)} + isOpen={showCloseDiscussion} + onConfirm={onCloseDiscussionConfirm} + onCancel={onCloseDiscussionCancel} title="Ukončit rozpravu?" yesActionLabel="Ukončit" > Opravdu chcete ukončit rozpravu? </ModalConfirm> + <ModalConfirm + isOpen={showOpenDiscussion} + onConfirm={onOpenDiscussionConfirm} + onCancel={onOpenDiscussionCancel} + title="Otevřít rozpravu?" + yesActionLabel="Otevřít" + > + Opravdu chcete otevřít rozpravu k tomuto bodu programu? + </ModalConfirm> + <ModalConfirm + isOpen={showEndProgramPoint} + onConfirm={onEndProgramPointConfirm} + onCancel={onEndProgramPointCancel} + title="Ukončit bod programu?" + yesActionLabel="Ukončit bod programu" + > + Bod programu <strong>bude ukončen</strong>. Opravdu to chcete? + </ModalConfirm> </> ); }; -- GitLab