mirror of
https://github.com/pds-nest/nest.git
synced 2024-11-22 13:04:19 +00:00
🔧 "Complete" RepositoryEditor
This commit is contained in:
parent
22303cb85a
commit
0ce4ec6993
6 changed files with 68 additions and 32 deletions
|
@ -6,6 +6,7 @@ import RepositorySummaryBase from "./RepositorySummaryBase"
|
||||||
import Loading from "../base/Loading"
|
import Loading from "../base/Loading"
|
||||||
import BoxAlert from "../base/BoxAlert"
|
import BoxAlert from "../base/BoxAlert"
|
||||||
import { faSearch } from "@fortawesome/free-solid-svg-icons"
|
import { faSearch } from "@fortawesome/free-solid-svg-icons"
|
||||||
|
import useDataImmediately from "../../hooks/useDataImmediately"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,7 +18,7 @@ import { faSearch } from "@fortawesome/free-solid-svg-icons"
|
||||||
*/
|
*/
|
||||||
export default function BoxRepositoriesActive({ ...props }) {
|
export default function BoxRepositoriesActive({ ...props }) {
|
||||||
const {user, fetchDataAuth} = useContext(ContextUser)
|
const {user, fetchDataAuth} = useContext(ContextUser)
|
||||||
const {data, started, loading, error} = useData(fetchDataAuth, "GET", "/api/v1/repositories/", {
|
const {data, started, loading, error} = useDataImmediately(fetchDataAuth, "GET", "/api/v1/repositories/", {
|
||||||
"onlyActive": true,
|
"onlyActive": true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import React, { useContext } from "react"
|
import React, { useContext } from "react"
|
||||||
import BoxFull from "../base/BoxFull"
|
import BoxFull from "../base/BoxFull"
|
||||||
import ContextUser from "../../contexts/ContextUser"
|
import ContextUser from "../../contexts/ContextUser"
|
||||||
import useData from "../../hooks/useData"
|
|
||||||
import RepositorySummaryBase from "./RepositorySummaryBase"
|
import RepositorySummaryBase from "./RepositorySummaryBase"
|
||||||
import Loading from "../base/Loading"
|
import Loading from "../base/Loading"
|
||||||
import BoxAlert from "../base/BoxAlert"
|
import BoxAlert from "../base/BoxAlert"
|
||||||
import { faSearch } from "@fortawesome/free-solid-svg-icons"
|
import { faSearch } from "@fortawesome/free-solid-svg-icons"
|
||||||
|
import useDataImmediately from "../../hooks/useDataImmediately"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,7 +17,7 @@ import { faSearch } from "@fortawesome/free-solid-svg-icons"
|
||||||
*/
|
*/
|
||||||
export default function BoxRepositoriesArchived({ ...props }) {
|
export default function BoxRepositoriesArchived({ ...props }) {
|
||||||
const {user, fetchDataAuth} = useContext(ContextUser)
|
const {user, fetchDataAuth} = useContext(ContextUser)
|
||||||
const {data, started, loading, error} = useData(fetchDataAuth, "GET", "/api/v1/repositories/", {
|
const {data, started, loading, error} = useDataImmediately(fetchDataAuth, "GET", "/api/v1/repositories/", {
|
||||||
"onlyDead": true,
|
"onlyDead": true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { faFolder, faPlus } from "@fortawesome/free-solid-svg-icons"
|
||||||
import Radio from "../base/Radio"
|
import Radio from "../base/Radio"
|
||||||
import Button from "../base/Button"
|
import Button from "../base/Button"
|
||||||
import useRepositoryEditor from "../../hooks/useRepositoryEditor"
|
import useRepositoryEditor from "../../hooks/useRepositoryEditor"
|
||||||
|
import FormAlert from "../base/formparts/FormAlert"
|
||||||
|
|
||||||
|
|
||||||
export default function BoxRepositoryCreate({ ...props }) {
|
export default function BoxRepositoryCreate({ ...props }) {
|
||||||
|
@ -16,11 +17,12 @@ export default function BoxRepositoryCreate({ ...props }) {
|
||||||
name,
|
name,
|
||||||
setName,
|
setName,
|
||||||
save,
|
save,
|
||||||
|
error,
|
||||||
} = useRepositoryEditor()
|
} = useRepositoryEditor()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BoxFull header={"Create repository"} {...props}>
|
<BoxFull header={"Create repository"} {...props}>
|
||||||
<FormLabelled>
|
<FormLabelled onSubmit={e => {e.preventDefault(); save()}}>
|
||||||
<FormLabel htmlFor={"repo-name"} text={"Repository name"}>
|
<FormLabel htmlFor={"repo-name"} text={"Repository name"}>
|
||||||
<InputWithIcon
|
<InputWithIcon
|
||||||
id={"repo-name"}
|
id={"repo-name"}
|
||||||
|
@ -48,6 +50,11 @@ export default function BoxRepositoryCreate({ ...props }) {
|
||||||
Every filter
|
Every filter
|
||||||
</label>
|
</label>
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
|
{error ?
|
||||||
|
<FormAlert color={"Red"}>
|
||||||
|
{error.toString()}
|
||||||
|
</FormAlert>
|
||||||
|
: null}
|
||||||
<Button style={{"gridColumn": "1 / 3"}} icon={faPlus} color={"Green"} onClick={e => save()}>
|
<Button style={{"gridColumn": "1 / 3"}} icon={faPlus} color={"Green"} onClick={e => save()}>
|
||||||
Create repository
|
Create repository
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useCallback, useState } from "react"
|
import React, { useCallback, useContext, useState } from "react"
|
||||||
import ContextRepositoryEditor from "../../contexts/ContextRepositoryEditor"
|
import ContextRepositoryEditor from "../../contexts/ContextRepositoryEditor"
|
||||||
import useArrayState from "../../hooks/useArrayState"
|
import useArrayState from "../../hooks/useArrayState"
|
||||||
import Style from "./RepositoryEditor.module.css"
|
import Style from "./RepositoryEditor.module.css"
|
||||||
|
@ -9,10 +9,11 @@ import BoxConditionDatetime from "../interactive/BoxConditionDatetime"
|
||||||
import BoxConditions from "../interactive/BoxConditions"
|
import BoxConditions from "../interactive/BoxConditions"
|
||||||
import BoxRepositoryCreate from "../interactive/BoxRepositoryCreate"
|
import BoxRepositoryCreate from "../interactive/BoxRepositoryCreate"
|
||||||
import classNames from "classnames"
|
import classNames from "classnames"
|
||||||
|
import ContextUser from "../../contexts/ContextUser"
|
||||||
|
import useData from "../../hooks/useData"
|
||||||
|
|
||||||
|
|
||||||
export default function RepositoryEditor({
|
export default function RepositoryEditor({
|
||||||
refresh,
|
|
||||||
id = null,
|
id = null,
|
||||||
name,
|
name,
|
||||||
is_active: isActive,
|
is_active: isActive,
|
||||||
|
@ -44,27 +45,38 @@ export default function RepositoryEditor({
|
||||||
} = useArrayState(conditions)
|
} = useArrayState(conditions)
|
||||||
|
|
||||||
/** The operator the conditions should be evaluated with. */
|
/** The operator the conditions should be evaluated with. */
|
||||||
const [_evaluationMode, setEvaluationMode] = useState(evaluationMode)
|
const [_evaluationMode, setEvaluationMode] = useState(evaluationMode ?? 0)
|
||||||
|
|
||||||
|
const {user, fetchDataAuth} = useContext(ContextUser)
|
||||||
|
|
||||||
|
const method = id ? "PUT" : "POST"
|
||||||
|
const path = id ? `/api/v1/repositories/${id}` : `/api/v1/repositories/`
|
||||||
|
const body = {
|
||||||
|
"conditions": _conditions,
|
||||||
|
"end": _end,
|
||||||
|
"evaluation_mode": _evaluationMode,
|
||||||
|
"id": id,
|
||||||
|
"is_active": true,
|
||||||
|
"name": _name,
|
||||||
|
"owner": user,
|
||||||
|
"start": _start,
|
||||||
|
}
|
||||||
|
const {error, loading, fetchNow} = useData(fetchDataAuth, method, path, body)
|
||||||
|
|
||||||
/**
|
|
||||||
* Invia al backend le modifiche effettuate.
|
|
||||||
*/
|
|
||||||
const save = useCallback(
|
const save = useCallback(
|
||||||
() => {
|
() => {
|
||||||
if(id === null) {
|
if(id) {
|
||||||
// POST
|
console.info("Creating new repository with body: ", body)
|
||||||
throw new Error("Not yet implemented")
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// PUT
|
console.info("Editing repository ", id, " with body: ", body)
|
||||||
throw new Error("Not yet implemented")
|
|
||||||
}
|
}
|
||||||
|
fetchNow()
|
||||||
refresh()
|
|
||||||
},
|
},
|
||||||
[id]
|
[id, body, fetchNow]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancel the changes made so far to the repository.
|
* Cancel the changes made so far to the repository.
|
||||||
*/
|
*/
|
||||||
|
@ -119,6 +131,7 @@ export default function RepositoryEditor({
|
||||||
end: _end, setEnd,
|
end: _end, setEnd,
|
||||||
conditions: _conditions, addCondition, appendRawCondition, removeRawCondition, spliceRawCondition,
|
conditions: _conditions, addCondition, appendRawCondition, removeRawCondition, spliceRawCondition,
|
||||||
evaluationMode: _evaluationMode, setEvaluationMode,
|
evaluationMode: _evaluationMode, setEvaluationMode,
|
||||||
|
error, loading,
|
||||||
revert, save,
|
revert, save,
|
||||||
}}>
|
}}>
|
||||||
<div className={classNames(Style.RepositoryEditor, className)}>
|
<div className={classNames(Style.RepositoryEditor, className)}>
|
||||||
|
|
|
@ -9,13 +9,11 @@ import { useCallback, useEffect, useState } from "react"
|
||||||
* @param path - The HTTP path to fetch the data at.
|
* @param path - The HTTP path to fetch the data at.
|
||||||
* @param body - The body of the HTTP request (it will be JSONified before being sent).
|
* @param body - The body of the HTTP request (it will be JSONified before being sent).
|
||||||
* @param init - Additional `init` parameters to pass to `fetch`.
|
* @param init - Additional `init` parameters to pass to `fetch`.
|
||||||
* @returns {{data: *, refresh: function, error: Error}}
|
|
||||||
*/
|
*/
|
||||||
export default function useData(fetchData, method, path, body, init) {
|
export default function useData(fetchData, method, path, body, init) {
|
||||||
const [error, setError] = useState(null)
|
const [error, setError] = useState(null)
|
||||||
const [data, setData] = useState(null)
|
const [data, setData] = useState(null)
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const started = (loading || data || error)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load data from the API.
|
* Load data from the API.
|
||||||
|
@ -41,7 +39,7 @@ export default function useData(fetchData, method, path, body, init) {
|
||||||
/**
|
/**
|
||||||
* Invalidate the data loaded from the API and try to load it again.
|
* Invalidate the data loaded from the API and try to load it again.
|
||||||
*/
|
*/
|
||||||
const refresh = useCallback(
|
const fetchNow = useCallback(
|
||||||
async () => {
|
async () => {
|
||||||
console.debug("Clearing data...")
|
console.debug("Clearing data...")
|
||||||
setData(null)
|
setData(null)
|
||||||
|
@ -54,15 +52,5 @@ export default function useData(fetchData, method, path, body, init) {
|
||||||
[load]
|
[load]
|
||||||
)
|
)
|
||||||
|
|
||||||
useEffect(
|
return {data, error, loading, fetchNow}
|
||||||
() => {
|
|
||||||
if(!started) {
|
|
||||||
// noinspection JSIgnoredPromiseFromCall
|
|
||||||
load()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[load, started]
|
|
||||||
)
|
|
||||||
|
|
||||||
return {data, error, loading, started, refresh}
|
|
||||||
}
|
}
|
27
code/frontend/src/hooks/useDataImmediately.js
Normal file
27
code/frontend/src/hooks/useDataImmediately.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import useData from "./useData"
|
||||||
|
import { useEffect } from "react"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like {@link useData}, but runs as soon as the component is rendered.
|
||||||
|
*
|
||||||
|
* @param fetchData - The function to use when fetching data.
|
||||||
|
* @param method - The HTTP method to use.
|
||||||
|
* @param path - The HTTP path to fetch the data at.
|
||||||
|
* @param body - The body of the HTTP request (it will be JSONified before being sent).
|
||||||
|
* @param init - Additional `init` parameters to pass to `fetch`.
|
||||||
|
*/
|
||||||
|
export default function useDataImmediately(fetchData, method, path, body, init) {
|
||||||
|
const {data, error, loading, fetchNow} = useData(fetchData, method, path, body, init)
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
() => {
|
||||||
|
if(!(loading || data || error)) {
|
||||||
|
fetchNow()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[data, error, loading, fetchNow]
|
||||||
|
)
|
||||||
|
|
||||||
|
return {data, error, loading, fetchNow}
|
||||||
|
}
|
Loading…
Reference in a new issue