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 { Map } from "immutable"
|
||||
|
||||
import { PolochonList } from "../polochons/list"
|
||||
|
||||
import {
|
||||
updateUser, getUserInfos,
|
||||
getUserTokens, getUserModules
|
||||
@ -37,6 +39,7 @@ const UserProfile = (props) => {
|
||||
url={props.url}
|
||||
updateUser={props.updateUser}
|
||||
/>
|
||||
<PolochonList />
|
||||
<Modules
|
||||
modules={props.modules}
|
||||
isLoading={props.modulesLoading}
|
||||
|
@ -7,6 +7,7 @@ import userStore from "./users"
|
||||
import alerts from "./alerts"
|
||||
import torrentStore from "./torrents"
|
||||
import adminStore from "./admins"
|
||||
import polochon from "./polochon"
|
||||
|
||||
export default combineReducers({
|
||||
movieStore,
|
||||
@ -16,4 +17,5 @@ export default combineReducers({
|
||||
alerts,
|
||||
torrentStore,
|
||||
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,
|
||||
polochonToken: "",
|
||||
polochonUrl: "",
|
||||
polochonName: "",
|
||||
polochonActivated: false,
|
||||
tokens: List(),
|
||||
modules: Map(),
|
||||
modulesLoading: false,
|
||||
@ -45,6 +47,8 @@ const handlers = {
|
||||
"GET_USER_FULFILLED": (state, action) => state.merge(Map({
|
||||
polochonToken: action.payload.response.data.token,
|
||||
polochonUrl: action.payload.response.data.url,
|
||||
polochonName: action.payload.response.data.name,
|
||||
polochonActivated: action.payload.response.data.activated,
|
||||
loading: false,
|
||||
})),
|
||||
"GET_USER_TOKENS_PENDING": state => state.set("loading", true),
|
||||
|
Loading…
x
Reference in New Issue
Block a user