diff --git a/code/frontend/src/PageSwitcher.js b/code/frontend/src/PageSwitcher.js index 2f2afa7..309da02 100644 --- a/code/frontend/src/PageSwitcher.js +++ b/code/frontend/src/PageSwitcher.js @@ -7,6 +7,7 @@ import PageSettings from "./routes/PageSettings" import PageSandbox from "./routes/PageSandbox" import PageDashboard from "./routes/PageDashboard" import PageRoot from "./routes/PageRoot" +import PageEdit from "./routes/PageEdit" export default function PageSwitcher({ ...props }) { @@ -15,6 +16,9 @@ export default function PageSwitcher({ ...props }) { + + + diff --git a/code/frontend/src/components/interactive/BoxRepositoriesActive.js b/code/frontend/src/components/interactive/BoxRepositoriesActive.js index 5835dcf..509835a 100644 --- a/code/frontend/src/components/interactive/BoxRepositoriesActive.js +++ b/code/frontend/src/components/interactive/BoxRepositoriesActive.js @@ -18,18 +18,15 @@ import useDataImmediately from "../../hooks/useDataImmediately" */ export default function BoxRepositoriesActive({ ...props }) { const {user, fetchDataAuth} = useContext(ContextUser) - const {data, started, loading, error} = useDataImmediately(fetchDataAuth, "GET", "/api/v1/repositories/", { + const {data, error} = useDataImmediately(fetchDataAuth, "GET", "/api/v1/repositories/", { "onlyActive": true, }) let contents; - if(!started || loading) { - contents = - } - else if(error) { + if(error) { contents = {error.toString()} } - else { + else if(data) { let repositories = [...data["owner"], ...data["spectator"]] if(repositories.length > 0) { contents = repositories.map(repo => ( @@ -46,6 +43,9 @@ export default function BoxRepositoriesActive({ ...props }) { contents = There's nothing here. } } + else { + contents = + } return ( diff --git a/code/frontend/src/components/interactive/BoxRepositoriesArchived.js b/code/frontend/src/components/interactive/BoxRepositoriesArchived.js index f717f8c..4668cb2 100644 --- a/code/frontend/src/components/interactive/BoxRepositoriesArchived.js +++ b/code/frontend/src/components/interactive/BoxRepositoriesArchived.js @@ -17,18 +17,15 @@ import useDataImmediately from "../../hooks/useDataImmediately" */ export default function BoxRepositoriesArchived({ ...props }) { const {user, fetchDataAuth} = useContext(ContextUser) - const {data, started, loading, error} = useDataImmediately(fetchDataAuth, "GET", "/api/v1/repositories/", { + const {data, error} = useDataImmediately(fetchDataAuth, "GET", "/api/v1/repositories/", { "onlyDead": true, }) let contents; - if(!started || loading) { - contents = - } - else if(error) { + if(error) { contents = {error.toString()} } - else { + else if(data) { let repositories = [...data["owner"], ...data["spectator"]] if(repositories.length > 0) { contents = repositories.map(repo => ( @@ -45,6 +42,9 @@ export default function BoxRepositoriesArchived({ ...props }) { contents = There's nothing here. } } + else { + contents = + } return ( diff --git a/code/frontend/src/components/interactive/BoxRepositoryCreate.js b/code/frontend/src/components/interactive/BoxRepositoryCreate.js index f32c753..088784d 100644 --- a/code/frontend/src/components/interactive/BoxRepositoryCreate.js +++ b/code/frontend/src/components/interactive/BoxRepositoryCreate.js @@ -3,15 +3,23 @@ import BoxFull from "../base/BoxFull" import FormLabelled from "../base/FormLabelled" import FormLabel from "../base/formparts/FormLabel" import InputWithIcon from "../base/InputWithIcon" -import { faFolder, faPlus } from "@fortawesome/free-solid-svg-icons" +import { faFolder, faPencilAlt, faPlus } from "@fortawesome/free-solid-svg-icons" import Radio from "../base/Radio" import Button from "../base/Button" import useRepositoryEditor from "../../hooks/useRepositoryEditor" import FormAlert from "../base/formparts/FormAlert" +/** + * A {@link BoxFull} allowing the user to save the changes made in the current {@link RepositoryEditor}. + * + * @param props + * @returns {JSX.Element} + * @constructor + */ export default function BoxRepositoryCreate({ ...props }) { const { + id, evaluationMode, setEvaluationMode, name, @@ -35,7 +43,7 @@ export default function BoxRepositoryCreate({ ...props }) { ) diff --git a/code/frontend/src/components/interactive/RepositorySummaryBase.js b/code/frontend/src/components/interactive/RepositorySummaryBase.js index 96333cd..737b95f 100644 --- a/code/frontend/src/components/interactive/RepositorySummaryBase.js +++ b/code/frontend/src/components/interactive/RepositorySummaryBase.js @@ -1,18 +1,21 @@ -import React from "react" +import React, { useContext } from "react" import Style from "./RepositorySummaryBase.module.css" import classNames from "classnames" import {FontAwesomeIcon} from "@fortawesome/react-fontawesome" import Button from "../base/Button" import { faArchive, faPencilAlt, faTrash } from "@fortawesome/free-solid-svg-icons" +import { useHistory } from "react-router" +import useData from "../../hooks/useData" +import ContextUser from "../../contexts/ContextUser" /** * A long line representing a repository in a list. * + * @param id - The id of the repository. + * @param owner - The owner of the repository. * @param icon - The FontAwesome IconDefinition that represents the repository. * @param name - The title of the repository. - * @todo What goes in the details field? - * @param details - Whatever should be rendered in the details field. * @param start - The start date of the repository. * @param end - The end date of the repository. * @param isActive - Whether the repository is active or not. @@ -25,8 +28,14 @@ import { faArchive, faPencilAlt, faTrash } from "@fortawesome/free-solid-svg-ico * @constructor */ export default function RepositorySummaryBase( - { icon, name, details, start, end, isActive, canDelete, canEdit, canArchive, className, ...props } + { id, owner, icon, name, start, end, isActive, canDelete, canEdit, canArchive, className, ...props } ) { + const {fetchDataAuth} = useContext(ContextUser) + const {history} = useHistory() + const {fetchNow: archiveThis} = useData(fetchDataAuth, "PATCH", `/api/v1/repositories/${id}`, {"close": true}) + const {fetchNow: unarchiveThis} = useData(fetchDataAuth, "PATCH", `/api/v1/repositories/${id}`, {"open": true}) + const {fetchNow: deletThis} = useData(fetchDataAuth, "DELETE", `/api/v1/repositories/${id}`) + return (
@@ -36,22 +45,45 @@ export default function RepositorySummaryBase(
{name}
-
- {start} +
+ {owner["username"]}
- {details} +
+ Start: {start} +
+
+ End: {end} +
{canDelete ? - + : null} {canEdit ? - + : null} {canArchive ? - + : null}
diff --git a/code/frontend/src/components/interactive/RepositorySummaryBase.module.css b/code/frontend/src/components/interactive/RepositorySummaryBase.module.css index 7f5a9c0..2f21b39 100644 --- a/code/frontend/src/components/interactive/RepositorySummaryBase.module.css +++ b/code/frontend/src/components/interactive/RepositorySummaryBase.module.css @@ -50,7 +50,7 @@ align-self: flex-end; } -.StartDate { +.Author { grid-area: d; font-size: small; @@ -59,10 +59,23 @@ .Middle { flex-grow: 1; - height: 60px; background-color: var(--bg-light); + + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: stretch; + +} + +.StartDate { + +} + +.EndDate { + } .Right { diff --git a/code/frontend/src/hooks/useData.js b/code/frontend/src/hooks/useData.js index 1ca1b46..304c6fa 100644 --- a/code/frontend/src/hooks/useData.js +++ b/code/frontend/src/hooks/useData.js @@ -20,16 +20,19 @@ export default function useData(fetchData, method, path, body, init) { */ const load = useCallback( async () => { - console.debug(`Trying to ${method} ${path}...`) - + console.debug(`Loading ${method} ${path}...`) setLoading(true) + console.debug(`Fetching ${method} ${path}...`) try { const _data = await fetchData(method, path, body, init) + console.debug(`Displaying data of ${method} ${path}: `, _data) setData(_data) } catch(e) { + console.debug(`Displaying error of ${method} ${path}: `, e) setError(e) } finally { + console.debug(`Stopping loading of ${method} ${path}...`) setLoading(false) } }, diff --git a/code/frontend/src/routes/PageEdit.js b/code/frontend/src/routes/PageEdit.js new file mode 100644 index 0000000..25d4659 --- /dev/null +++ b/code/frontend/src/routes/PageEdit.js @@ -0,0 +1,38 @@ +import React, { useContext } from "react" +import Style from "./PageDashboard.module.css" +import classNames from "classnames" +import BoxHeader from "../components/base/BoxHeader" +import RepositoryEditor from "../components/providers/RepositoryEditor" +import useDataImmediately from "../hooks/useDataImmediately" +import ContextUser from "../contexts/ContextUser" +import BoxAlert from "../components/base/BoxAlert" +import RepositorySummaryBase from "../components/interactive/RepositorySummaryBase" +import { faSearch } from "@fortawesome/free-solid-svg-icons" +import Loading from "../components/base/Loading" +import BoxFull from "../components/base/BoxFull" + + +export default function PageEdit({ id, className, ...props }) { + const {fetchDataAuth} = useContext(ContextUser) + const {data, error} = useDataImmediately(fetchDataAuth, "GET", `/api/v1/repositories/${id}`) + + let contents; + if(error) { + contents = {error.toString()} + } + else if(data) { + contents = + } + else { + contents = + } + + return ( +
+ + Edit repository + + {contents} +
+ ) +} diff --git a/code/frontend/src/utils/goToOnSuccess.js b/code/frontend/src/utils/goToOnSuccess.js new file mode 100644 index 0000000..d11eac7 --- /dev/null +++ b/code/frontend/src/utils/goToOnSuccess.js @@ -0,0 +1,23 @@ +/** + * Decorator which adds a redirect on success to an event handler. + * + * @param func - The function to decorate. + * @param history - The history to push the destination to. + * @param destination - The path of the destination. + * @returns {(function(): void)|*} + */ +export default function goToOnSuccess(func, history, destination) { + return ([...args]) => { + let success = false + try { + func(...args) + success = true + } + catch(e) { + success = false + } + if(success) { + history.push(destination) + } + } +}