Add multiple polochon handling in the frontend
This commit is contained in:
parent
d9d71c8ebd
commit
615a0b6d7c
35
frontend/js/actions/polochon.js
Normal file
35
frontend/js/actions/polochon.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { configureAxios, request } from "../requests"
|
||||||
|
|
||||||
|
export const getPolochons = () => request(
|
||||||
|
"PUBLIC_POLOCHON_LIST_FETCH",
|
||||||
|
configureAxios().get("/polochons"),
|
||||||
|
)
|
||||||
|
|
||||||
|
export const getManagedPolochons = () => request(
|
||||||
|
"MANAGED_POLOCHON_LIST_FETCH",
|
||||||
|
configureAxios().get("/users/polochons"),
|
||||||
|
)
|
||||||
|
|
||||||
|
export const addPolochon = (params) => request(
|
||||||
|
"ADD_POLOCHON",
|
||||||
|
configureAxios().post("/polochons", params),
|
||||||
|
[
|
||||||
|
() => getManagedPolochons(),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
export const updatePolochon = ({ id, ...params }) => request(
|
||||||
|
"UPDATE_POLOCHON",
|
||||||
|
configureAxios().post(`/polochons/${id}`, params),
|
||||||
|
[
|
||||||
|
() => getManagedPolochons(),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
export const deletePolochon = (id) => request(
|
||||||
|
"UPDATE_POLOCHON",
|
||||||
|
configureAxios().delete(`/polochons/${id}`),
|
||||||
|
[
|
||||||
|
() => getManagedPolochons(),
|
||||||
|
],
|
||||||
|
)
|
22
frontend/js/components/forms/input.js
Normal file
22
frontend/js/components/forms/input.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import React from "react"
|
||||||
|
import PropTypes from "prop-types"
|
||||||
|
|
||||||
|
export const FormInput = ({ label, value, updateValue }) => {
|
||||||
|
return (
|
||||||
|
<div className="form-group">
|
||||||
|
<label className="control-label">
|
||||||
|
{label}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
className="form-control"
|
||||||
|
value={value}
|
||||||
|
onChange={(e) => updateValue(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
FormInput.propTypes = {
|
||||||
|
label: PropTypes.string,
|
||||||
|
value: PropTypes.string,
|
||||||
|
updateValue: PropTypes.func,
|
||||||
|
};
|
49
frontend/js/components/forms/modal.js
Normal file
49
frontend/js/components/forms/modal.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import React from "react"
|
||||||
|
import PropTypes from "prop-types"
|
||||||
|
|
||||||
|
import { Modal } from "react-bootstrap"
|
||||||
|
|
||||||
|
export const FormModal = ({
|
||||||
|
show,
|
||||||
|
setShow,
|
||||||
|
title,
|
||||||
|
icon,
|
||||||
|
handleSubmit,
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
const submit = function(e) {
|
||||||
|
if (e) { e.preventDefault(); }
|
||||||
|
handleSubmit();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal show={show} onHide={() => setShow(false)}>
|
||||||
|
<Modal.Header closeButton>
|
||||||
|
<Modal.Title>
|
||||||
|
<i className={`fa fa-${icon} mr-1`} />
|
||||||
|
{title}
|
||||||
|
</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body bsPrefix="modal-body">
|
||||||
|
<form className="form-horizontal" onSubmit={(ev) => submit(ev)}>
|
||||||
|
{children}
|
||||||
|
</form>
|
||||||
|
</Modal.Body>
|
||||||
|
<Modal.Footer>
|
||||||
|
<div className="btn btn-success" onClick={submit}>Apply</div>
|
||||||
|
<div className="btn btn-error" onClick={() => setShow(false)}>Close</div>
|
||||||
|
</Modal.Footer>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
FormModal.propTypes = {
|
||||||
|
show: PropTypes.bool,
|
||||||
|
setShow: PropTypes.func,
|
||||||
|
icon: PropTypes.string,
|
||||||
|
title: PropTypes.string,
|
||||||
|
handleSubmit: PropTypes.func,
|
||||||
|
children: PropTypes.oneOf(
|
||||||
|
PropTypes.object,
|
||||||
|
PropTypes.array,
|
||||||
|
),
|
||||||
|
};
|
31
frontend/js/components/polochons/add.js
Normal file
31
frontend/js/components/polochons/add.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import React, { useState } from "react"
|
||||||
|
import PropTypes from "prop-types"
|
||||||
|
import { connect } from "react-redux"
|
||||||
|
|
||||||
|
import { addPolochon } from "../../actions/polochon"
|
||||||
|
|
||||||
|
import { PolochonEdit } from "./edit"
|
||||||
|
|
||||||
|
export const PolochonAddConnected = ({ addPolochon }) => {
|
||||||
|
const [modal, setModal] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<div className="btn btn-primary btn-lg" onClick={() => setModal(true)}>
|
||||||
|
<i className="fa fa-plus mr-2" />
|
||||||
|
Add new polochon
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<PolochonEdit
|
||||||
|
show={modal}
|
||||||
|
setShow={setModal}
|
||||||
|
update={addPolochon}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
PolochonAddConnected.propTypes = {
|
||||||
|
addPolochon: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PolochonAdd = connect(null, {addPolochon})(PolochonAddConnected);
|
59
frontend/js/components/polochons/edit.js
Normal file
59
frontend/js/components/polochons/edit.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import React, { useState, useEffect } from "react"
|
||||||
|
import PropTypes from "prop-types"
|
||||||
|
|
||||||
|
import { FormModal } from "../forms/modal"
|
||||||
|
import { FormInput } from "../forms/input"
|
||||||
|
|
||||||
|
export const PolochonEdit = ({
|
||||||
|
show,
|
||||||
|
setShow,
|
||||||
|
id,
|
||||||
|
initialName,
|
||||||
|
initialUrl,
|
||||||
|
initialToken,
|
||||||
|
update,
|
||||||
|
}) => {
|
||||||
|
const [name, setName] = useState(initialName);
|
||||||
|
const [url, setUrl] = useState(initialUrl);
|
||||||
|
const [token, setToken] = useState(initialToken);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setName(initialName);
|
||||||
|
setUrl(initialUrl);
|
||||||
|
setToken(initialToken);
|
||||||
|
}, [id, initialName, initialUrl, initialToken])
|
||||||
|
|
||||||
|
const handleSubmit = () => {
|
||||||
|
update({ id, name, url, token });
|
||||||
|
setShow(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormModal
|
||||||
|
show={show}
|
||||||
|
setShow={setShow}
|
||||||
|
title="Add a new polochon"
|
||||||
|
icon="plus"
|
||||||
|
handleSubmit={handleSubmit}
|
||||||
|
>
|
||||||
|
<FormInput label="Name" value={name} updateValue={setName} />
|
||||||
|
<FormInput label="URL" value={url} updateValue={setUrl} />
|
||||||
|
<FormInput label="Token" value={token} updateValue={setToken} />
|
||||||
|
</FormModal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
PolochonEdit.propTypes = {
|
||||||
|
show: PropTypes.bool,
|
||||||
|
setShow: PropTypes.func,
|
||||||
|
update: PropTypes.func,
|
||||||
|
id: PropTypes.string,
|
||||||
|
initialName: PropTypes.string,
|
||||||
|
initialUrl: PropTypes.string,
|
||||||
|
initialToken: PropTypes.string,
|
||||||
|
};
|
||||||
|
PolochonEdit.defaultProps = {
|
||||||
|
id: "",
|
||||||
|
initialName: "",
|
||||||
|
initialUrl: "",
|
||||||
|
initialToken: "",
|
||||||
|
};
|
56
frontend/js/components/polochons/list.js
Normal file
56
frontend/js/components/polochons/list.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import React, { useEffect } from "react"
|
||||||
|
import PropTypes from "prop-types"
|
||||||
|
import { connect } from "react-redux"
|
||||||
|
import { List } from "immutable"
|
||||||
|
|
||||||
|
import { getManagedPolochons } from "../../actions/polochon"
|
||||||
|
|
||||||
|
import { Polochon } from "./polochon"
|
||||||
|
import { PolochonAdd } from "./add"
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => ({
|
||||||
|
managedList: state.polochon.get("managed"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const mapDispatchToProps = {
|
||||||
|
getManagedPolochons,
|
||||||
|
}
|
||||||
|
|
||||||
|
const PolochonListConnected = ({
|
||||||
|
getManagedPolochons,
|
||||||
|
managedList,
|
||||||
|
}) => {
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getManagedPolochons();
|
||||||
|
}, [getManagedPolochons])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="row mb-3">
|
||||||
|
<div className="col-12 col-md-6 offset-md-3">
|
||||||
|
<h2>My polochons</h2>
|
||||||
|
<hr />
|
||||||
|
<span>
|
||||||
|
{managedList.map((el, index) => (
|
||||||
|
<Polochon
|
||||||
|
key={index}
|
||||||
|
id={el.get("id")}
|
||||||
|
name={el.get("name")}
|
||||||
|
token={el.get("token")}
|
||||||
|
url={el.get("url")}
|
||||||
|
authToken={el.get("auth_token")}
|
||||||
|
users={el.get("users")}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</span>
|
||||||
|
<PolochonAdd />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
PolochonListConnected.propTypes = {
|
||||||
|
getManagedPolochons: PropTypes.func,
|
||||||
|
managedList: PropTypes.instanceOf(List),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PolochonList = connect(mapStateToProps, mapDispatchToProps)(PolochonListConnected);
|
83
frontend/js/components/polochons/polochon.js
Normal file
83
frontend/js/components/polochons/polochon.js
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import React, { useState } from "react"
|
||||||
|
import PropTypes from "prop-types"
|
||||||
|
import { List } from "immutable"
|
||||||
|
import { connect } from "react-redux"
|
||||||
|
|
||||||
|
import { PolochonUser } from "./user"
|
||||||
|
import { PolochonEdit } from "./edit"
|
||||||
|
|
||||||
|
import { updatePolochon, deletePolochon } from "../../actions/polochon"
|
||||||
|
|
||||||
|
export const PolochonConnected = ({
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
token,
|
||||||
|
url,
|
||||||
|
authToken,
|
||||||
|
users,
|
||||||
|
updatePolochon,
|
||||||
|
deletePolochon,
|
||||||
|
}) => {
|
||||||
|
const [edit, setEdit] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<div className="card mb-2">
|
||||||
|
<div className="card-header">
|
||||||
|
{name !== "" ? name : "-"}
|
||||||
|
<small className="ml-1">
|
||||||
|
({url !== "" ? url : "-"})
|
||||||
|
</small>
|
||||||
|
<span className="pull-right">
|
||||||
|
<i
|
||||||
|
className="fa fa-edit mr-3 clickable"
|
||||||
|
onClick={() => setEdit(true)}
|
||||||
|
/>
|
||||||
|
<i
|
||||||
|
className="fa fa-trash clickable"
|
||||||
|
onClick={() => deletePolochon(id)}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="card-body">
|
||||||
|
<p className="card-text">ID: {id}</p>
|
||||||
|
<p className="card-text">Egress token: {token}</p>
|
||||||
|
<p className="card-text">Ingress token: {authToken}</p>
|
||||||
|
<p className="card-text">
|
||||||
|
Users:
|
||||||
|
{users.map((user, index) => (
|
||||||
|
<PolochonUser
|
||||||
|
key={index}
|
||||||
|
id={user.get("id")}
|
||||||
|
name={user.get("name")}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<PolochonEdit
|
||||||
|
show={edit}
|
||||||
|
setShow={setEdit}
|
||||||
|
update={updatePolochon}
|
||||||
|
id={id}
|
||||||
|
initialName={name}
|
||||||
|
initialUrl={url}
|
||||||
|
initialToken={token}
|
||||||
|
initialAuthToken={authToken}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
PolochonConnected.propTypes = {
|
||||||
|
id: PropTypes.string,
|
||||||
|
name: PropTypes.string,
|
||||||
|
token: PropTypes.string,
|
||||||
|
url: PropTypes.string,
|
||||||
|
authToken: PropTypes.string,
|
||||||
|
users: PropTypes.instanceOf(List),
|
||||||
|
updatePolochon: PropTypes.func,
|
||||||
|
deletePolochon: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Polochon = connect(null, { updatePolochon, deletePolochon })(PolochonConnected);
|
14
frontend/js/components/polochons/user.js
Normal file
14
frontend/js/components/polochons/user.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import React from "react"
|
||||||
|
import PropTypes from "prop-types"
|
||||||
|
|
||||||
|
export const PolochonUser = ({ id, name }) => {
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{name} ({id})
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
PolochonUser.propTypes = {
|
||||||
|
id: PropTypes.string,
|
||||||
|
name: PropTypes.string,
|
||||||
|
};
|
@ -4,6 +4,8 @@ import { connect } from "react-redux"
|
|||||||
import Loader from "../loader/loader"
|
import Loader from "../loader/loader"
|
||||||
import { Map } from "immutable"
|
import { Map } from "immutable"
|
||||||
|
|
||||||
|
import { PolochonList } from "../polochons/list"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
updateUser, getUserInfos,
|
updateUser, getUserInfos,
|
||||||
getUserTokens, getUserModules
|
getUserTokens, getUserModules
|
||||||
@ -37,6 +39,7 @@ const UserProfile = (props) => {
|
|||||||
url={props.url}
|
url={props.url}
|
||||||
updateUser={props.updateUser}
|
updateUser={props.updateUser}
|
||||||
/>
|
/>
|
||||||
|
<PolochonList />
|
||||||
<Modules
|
<Modules
|
||||||
modules={props.modules}
|
modules={props.modules}
|
||||||
isLoading={props.modulesLoading}
|
isLoading={props.modulesLoading}
|
||||||
|
@ -7,6 +7,7 @@ import userStore from "./users"
|
|||||||
import alerts from "./alerts"
|
import alerts from "./alerts"
|
||||||
import torrentStore from "./torrents"
|
import torrentStore from "./torrents"
|
||||||
import adminStore from "./admins"
|
import adminStore from "./admins"
|
||||||
|
import polochon from "./polochon"
|
||||||
|
|
||||||
export default combineReducers({
|
export default combineReducers({
|
||||||
movieStore,
|
movieStore,
|
||||||
@ -16,4 +17,5 @@ export default combineReducers({
|
|||||||
alerts,
|
alerts,
|
||||||
torrentStore,
|
torrentStore,
|
||||||
adminStore,
|
adminStore,
|
||||||
|
polochon,
|
||||||
});
|
});
|
||||||
|
28
frontend/js/reducers/polochon.js
Normal file
28
frontend/js/reducers/polochon.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { List, Map, fromJS } from "immutable"
|
||||||
|
|
||||||
|
const defaultState = Map({
|
||||||
|
loadingPublic: false,
|
||||||
|
loadingManaged: false,
|
||||||
|
public: List(),
|
||||||
|
managed: List(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const handlers = {
|
||||||
|
"PUBLIC_POLOCHON_LIST_FETCH_PENDING": state => state.set("loadingPublic", true),
|
||||||
|
"PUBLIC_POLOCHON_LIST_FETCH_FULFILLED": (state, action) => {
|
||||||
|
return state.merge({
|
||||||
|
loadingPublic: false,
|
||||||
|
public: List(fromJS(action.payload.response.data)),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"MANAGED_POLOCHON_LIST_FETCH_PENDING": state => state.set("loadingManaged", true),
|
||||||
|
"MANAGED_POLOCHON_LIST_FETCH_FULFILLED": (state, action) => {
|
||||||
|
return state.merge({
|
||||||
|
loadingManaged: false,
|
||||||
|
managed: List(fromJS(action.payload.response.data)),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default (state = defaultState, action) =>
|
||||||
|
handlers[action.type] ? handlers[action.type](state, action) : state;
|
@ -13,6 +13,8 @@ const defaultState = Map({
|
|||||||
isLogged: false,
|
isLogged: false,
|
||||||
polochonToken: "",
|
polochonToken: "",
|
||||||
polochonUrl: "",
|
polochonUrl: "",
|
||||||
|
polochonName: "",
|
||||||
|
polochonActivated: false,
|
||||||
tokens: List(),
|
tokens: List(),
|
||||||
modules: Map(),
|
modules: Map(),
|
||||||
modulesLoading: false,
|
modulesLoading: false,
|
||||||
@ -45,6 +47,8 @@ const handlers = {
|
|||||||
"GET_USER_FULFILLED": (state, action) => state.merge(Map({
|
"GET_USER_FULFILLED": (state, action) => state.merge(Map({
|
||||||
polochonToken: action.payload.response.data.token,
|
polochonToken: action.payload.response.data.token,
|
||||||
polochonUrl: action.payload.response.data.url,
|
polochonUrl: action.payload.response.data.url,
|
||||||
|
polochonName: action.payload.response.data.name,
|
||||||
|
polochonActivated: action.payload.response.data.activated,
|
||||||
loading: false,
|
loading: false,
|
||||||
})),
|
})),
|
||||||
"GET_USER_TOKENS_PENDING": state => state.set("loading", true),
|
"GET_USER_TOKENS_PENDING": state => state.set("loading", true),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user