Skip to content
Snippets Groups Projects
Commit 26fbc88c authored by xaralis's avatar xaralis
Browse files

feat: edit announcement (wip)

parent c2fe36f7
No related branches found
No related tags found
No related merge requests found
......@@ -10949,19 +10949,12 @@
}
},
"pullstate": {
"version": "1.20.4",
"resolved": "https://registry.npmjs.org/pullstate/-/pullstate-1.20.4.tgz",
"integrity": "sha512-SksJ70iYNrC+YsGjMx54pXT2/iYYUu3zg9hezjHNjPPwyViglo4lh+N0I4DwB6xw92s+9NagD3AXMGMfiIt76g==",
"version": "1.20.5",
"resolved": "https://registry.npmjs.org/pullstate/-/pullstate-1.20.5.tgz",
"integrity": "sha512-9+QAXjf5WugIPEFHgMTwKM42uDx8ezB1BDobh7gpg9OCta5rp1XdFxa6tLljB/4NUxnI5YqoiE2s15ZOh+sl4A==",
"requires": {
"fast-deep-equal": "^3.1.3",
"immer": "^7.0.1"
},
"dependencies": {
"immer": {
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/immer/-/immer-7.0.15.tgz",
"integrity": "sha512-yM7jo9+hvYgvdCQdqvhCNRRio0SCXc8xDPzA25SvKWa7b1WVPjLwQs1VYU5JPXjcJPTqAa5NP5dqpORGYBQ2AA=="
}
}
},
"pump": {
......
......@@ -10,7 +10,7 @@
"immer": "^7.0.15",
"keycloak-js": "^10.0.2",
"lodash": "^4.17.20",
"pullstate": "^1.20.4",
"pullstate": "^1.20.5",
"react": "^16.13.1",
"react-device-detect": "^1.13.1",
"react-dom": "^16.13.1",
......
import findIndex from "lodash/findIndex";
import remove from "lodash/remove";
import { createAsyncAction, successResult } from "pullstate";
import { AnnouncementStore } from "stores";
......@@ -20,9 +22,59 @@ export const addAnnouncement = createAsyncAction(
},
{
postActionHook: ({ result }) => {
if (!result.error) {
AnnouncementStore.update((state) => {
state.items.push(result.payload);
});
}
},
}
);
/**
* Delete existing announcement.
*/
export const deleteAnnouncement = createAsyncAction(
/**
*
* @param {CF2021.Announcement} item
*/
async (item) => {
return successResult(item);
},
{
postActionHook: ({ result }) => {
if (!result.error) {
AnnouncementStore.update((state) => {
remove(state.items, { id: result.payload.id });
});
}
},
}
);
/**
* Update content of an announcement.
*/
export const updateAnnouncementContent = createAsyncAction(
/**
*
* @param {CF2021.Announcement} item
* @param {string} newContent
*/
async (item, newContent) => {
return successResult({ item, newContent });
},
{
postActionHook: ({ result }) => {
if (!result.error) {
AnnouncementStore.update((state) => {
const itemIdx = findIndex(state.items, {
id: result.payload.item.id,
});
state.items[itemIdx].content = result.payload.newContent;
});
}
},
}
);
import { fetch } from "api";
import pick from "lodash/pick";
import { createAsyncAction, errorResult, successResult } from "pullstate";
import fetch from "unfetch";
import { ProgramStore } from "stores";
export const loadProgram = createAsyncAction(
async () => {
try {
const resp = await fetch(`${process.env.REACT_APP_API_BASE_URL}/program`);
const resp = await fetch("/program");
const mappings = await resp.json();
return successResult(mappings);
} catch (err) {
......
import baseFetch from "unfetch";
import { AuthStore } from "./stores";
export const fetch = (url, opts) => {
const { isAuthenticated, user } = AuthStore.getRawState();
opts = opts || {};
opts.headers = opts.headers || {};
if (isAuthenticated) {
// opts.headers.Authorization = "Bearer " + user.accessToken;
}
return baseFetch(process.env.REACT_APP_API_BASE_URL + url, opts);
};
import React, { useState } from "react";
import Button from "components/Button";
import { Card, CardActions, CardBody, CardHeadline } from "components/cards";
import Modal from "components/modals/Modal";
const AnnouncementEditModal = ({
announcement,
onCancel,
onConfirm,
...props
}) => {
const [text, setText] = useState(announcement.content);
const onTextInput = (evt) => {
setText(evt.target.value);
};
const confirm = (evt) => {
if (!!text) {
onConfirm(text);
}
};
return (
<Modal containerClassName="max-w-md" onRequestClose={onCancel} {...props}>
<Card>
<CardBody>
<div className="flex items-center justify-between mb-4">
<CardHeadline>Upravit oznámení</CardHeadline>
<button onClick={onCancel}>
<i className="ico--close"></i>
</button>
</div>
<div className="form-field">
<div className="form-field__wrapper form-field__wrapper--shadowed">
<textarea
className="text-input form-field__control "
value={text}
rows="8"
placeholder="Vyplňte text oznámení"
onChange={onTextInput}
></textarea>
</div>
</div>
</CardBody>
<CardActions right className="space-x-1">
<Button
hoverActive
color="blue-300"
className="text-sm"
onClick={confirm}
>
Uložit
</Button>
<Button
hoverActive
color="red-600"
className="text-sm"
onClick={onCancel}
>
Zrušit
</Button>
</CardActions>
</Card>
</Modal>
);
};
export default AnnouncementEditModal;
import React from "react";
import classNames from "classnames";
const Card = ({ children, elevation = 21, className }) => {
const cls = classNames("card", `elevation-${elevation}`, className);
return <div className={cls}>{children}</div>;
};
export default Card;
import React from "react";
import classNames from "classnames";
const CardActions = ({ children, right, className }) => {
const cls = classNames(
"card-actions",
{ "card-actions--right": !!right },
className
);
return <div className={cls}>{children}</div>;
};
export default CardActions;
import React from "react";
import classNames from "classnames";
const CardBody = ({ children, className }) => {
const cls = classNames("card__body", className);
return <div className={cls}>{children}</div>;
};
export default CardBody;
import React from "react";
const CardBodyText = ({ children }) => {
return <div className="card-body-text">{children}</div>;
};
export default CardBodyText;
import React from "react";
const CardHeadline = ({ children }) => {
return <h1 className="card-headline">{children}</h1>;
};
export default CardHeadline;
export { default as Card } from "./Card";
export { default as CardActions } from "./CardActions";
export { default as CardBody } from "./CardBody";
export { default as CardBodyText } from "./CardBodyText";
export { default as CardHeadline } from "./CardHeadline";
import React from "react";
import Button from "components/Button";
import {
Card,
CardActions,
CardBody,
CardBodyText,
CardHeadline,
} from "components/cards";
import Modal from "./Modal";
......@@ -15,19 +22,19 @@ const ModalConfirm = ({
}) => {
return (
<Modal containerClassName="max-w-md" onRequestClose={onCancel} {...props}>
<div className="card elevation-21">
<div className="card__body">
<Card>
<CardBody>
<div className="flex items-center justify-between mb-4">
<h1 className="card-headline">{title}</h1>
<CardHeadline>{title}</CardHeadline>
<button onClick={onCancel}>
<i className="ico--close"></i>
</button>
</div>
<p className="card-body-text">{children}</p>
</div>
<div className="card-actions card-actions--right space-x-1">
<CardBodyText>{children}</CardBodyText>
</CardBody>
<CardActions right className="space-x-1">
<Button
hoveractive
hoverActive
color="blue-300"
className="text-sm"
onClick={onConfirm}
......@@ -35,15 +42,15 @@ const ModalConfirm = ({
{yesActionLabel}
</Button>
<Button
hoveractive
hoverActive
color="red-600"
className="text-sm"
onClick={onConfirm}
onClick={onCancel}
>
{cancelActionLabel}
</Button>
</div>
</div>
</CardActions>
</Card>
</Modal>
);
};
......
import React from "react";
import React, { useCallback, useState } from "react";
import {
deleteAnnouncement,
updateAnnouncementContent,
} from "actions/announcements";
import AnnouncementEditModal from "components/annoucements/AnnouncementEditModal";
import AnnouncementList from "components/annoucements/AnnouncementList";
import ModalConfirm from "components/modals/ModalConfirm";
import { AnnouncementStore } from "stores";
const AnnoucementsContainer = () => {
const [itemToDelete, setItemToDelete] = useState(null);
const [itemToEdit, setItemToEdit] = useState(null);
const items = AnnouncementStore.useState((state) => state.items);
const onEdit = (announcement) => {
console.log("edit", announcement);
};
const onDelete = (announcement) => {
console.log("delete", announcement);
};
const confirmEdit = useCallback(
async (newContent) => {
if (itemToEdit && newContent) {
await updateAnnouncementContent.run(itemToEdit, newContent);
setItemToEdit(null);
}
},
[itemToEdit, setItemToEdit]
);
const cancelEdit = useCallback(() => {
setItemToEdit(null);
}, [setItemToEdit]);
const confirmDelete = useCallback(async () => {
await deleteAnnouncement.run(itemToDelete);
setItemToDelete(null);
}, [setItemToDelete, itemToDelete]);
const cancelDelete = useCallback(() => {
setItemToDelete(null);
}, [setItemToDelete]);
return (
<>
<AnnouncementList
items={items}
displayActions={true}
onDelete={onDelete}
onEdit={onEdit}
onDelete={setItemToDelete}
onEdit={setItemToEdit}
/>
<ModalConfirm
isOpen={!!itemToDelete}
onConfirm={confirmDelete}
onCancel={cancelDelete}
title="Opravdu chcete toto oznámení smazat?"
yesActionLabel="Smazat"
>
Opravdu chcete ukončit rozpravu?
</ModalConfirm>
{itemToEdit && (
<AnnouncementEditModal
isOpen={true}
announcement={itemToEdit}
onConfirm={confirmEdit}
onCancel={cancelEdit}
/>
)}
</>
);
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment