Frontend: Add modules

Add User's modules in the profile page
Add Canape's modules in the admin page
This commit is contained in:
Lucas BEE 2019-04-13 00:05:19 +02:00
parent 779ef8d211
commit a61c1379ec
9 changed files with 163 additions and 6 deletions

View File

@ -14,6 +14,13 @@ export function getStats() {
) )
} }
export function getAdminModules() {
return request(
"ADMIN_GET_MODULES",
configureAxios().get("/admins/modules")
)
}
export function updateUser(data) { export function updateUser(data) {
return request( return request(
"ADMIN_UPDATE_USER", "ADMIN_UPDATE_USER",

View File

@ -67,3 +67,10 @@ export function deleteUserToken(token) {
] ]
) )
} }
export function getUserModules() {
return request(
"GET_USER_MODULES",
configureAxios().get("/users/modules/status")
)
}

View File

@ -3,6 +3,7 @@ import { connect } from "react-redux"
import { bindActionCreators } from "redux" import { bindActionCreators } from "redux"
import { updateUser } from "../../actions/admins" import { updateUser } from "../../actions/admins"
import Modules from "../modules/modules"
import UserList from "./users" import UserList from "./users"
import Stats from "./stats" import Stats from "./stats"
@ -10,6 +11,7 @@ function mapStateToProps(state) {
return { return {
users : state.adminStore.get("users"), users : state.adminStore.get("users"),
stats : state.adminStore.get("stats"), stats : state.adminStore.get("stats"),
modules : state.adminStore.get("modules"),
}; };
} }
const mapDispatchToProps = (dipatch) => const mapDispatchToProps = (dipatch) =>
@ -25,6 +27,9 @@ function AdminPanel(props) {
users={props.users} users={props.users}
updateUser={props.updateUser} updateUser={props.updateUser}
/> />
<Modules
modules={props.modules}
/>
</div> </div>
); );
} }

View File

@ -0,0 +1,115 @@
import React from "react"
import { OverlayTrigger, Tooltip } from "react-bootstrap"
export default function Modules(props) {
return (
<div>
<h2>Modules</h2>
{props.modules && props.modules.keySeq().map(function(value, key) {
return (
<ModulesByVideoType
key={value}
videoType={value}
data={props.modules.get(value)}
/>
);
})}
</div>
);
}
function capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
function ModulesByVideoType(props) {
return (
<div className="col-md-6 col-xs-12">
<div className="panel panel-default">
<div className="panel-heading">
<h3 className="panel-title">
{capitalize(props.videoType)} {/* Movie or Show */}
</h3>
</div>
<div className="panel-body">
{props.data.keySeq().map(function(value, key) {
return (
<ModuleByType
key={value}
type={value}
data={props.data.get(value)}
/>
);
})}
</div>
</div>
</div>
);
}
function ModuleByType(props) {
return (
<div className="col-md-3 col-xs-6">
<h4>{props.type} {/* Detailer / Explorer / ... */}</h4>
<table className="table">
<tbody>
{props.data.map(function(value, key) {
return (
<Module
key={key}
type={key}
data={value}
/>
);
})}
</tbody>
</table>
</div>
);
}
function Module(props) {
var iconClass, prettyStatus, labelClass
switch(props.data.get("status")) {
case "ok":
iconClass = "fa fa-check-circle"
labelClass = "label label-success"
prettyStatus = "OK"
break;
case "fail":
iconClass = "fa fa-times-circle"
labelClass = "label label-danger"
prettyStatus = "Fail"
break;
case "not_implemented":
iconClass = "fa fa-question-circle"
labelClass = "label label-default"
prettyStatus = "Not implemented"
break;
default:
iconClass = "fa fa-question-circle"
labelClass = "label label-warning"
prettyStatus = "Unknown"
}
const tooltip = (
<Tooltip id={`tooltip-status-${props.name}`}>
<p><span className={labelClass}>Status: {prettyStatus}</span></p>
<p>Error: {props.data.get("error")}</p>
</Tooltip>
);
return (
<tr>
<th>{props.data.get("name")}</th>
<td>
<OverlayTrigger placement="right" overlay={tooltip}>
<span className={labelClass}>
<i className={iconClass}></i> {prettyStatus}
</span>
</OverlayTrigger>
</td>
</tr>
);
}

View File

@ -161,7 +161,7 @@ function UserDropdown(props) {
} }
{props.isActivated && {props.isActivated &&
<LinkContainer to="/users/edit"> <LinkContainer to="/users/edit">
<MenuItem>Edit</MenuItem> <MenuItem>Profil</MenuItem>
</LinkContainer> </LinkContainer>
} }
{props.isActivated && {props.isActivated &&

View File

@ -3,16 +3,32 @@ import { connect } from "react-redux"
import { bindActionCreators } from "redux" import { bindActionCreators } from "redux"
import { updateUser } from "../../actions/users" import { updateUser } from "../../actions/users"
import Modules from "../modules/modules"
function mapStateToProps(state) { function mapStateToProps(state) {
return { return {
polochonToken: state.userStore.get("polochonToken"), polochonToken: state.userStore.get("polochonToken"),
polochonUrl: state.userStore.get("polochonUrl"), polochonUrl: state.userStore.get("polochonUrl"),
modules : state.userStore.get("modules"),
}; };
} }
const mapDispatchToProps = (dispatch) => const mapDispatchToProps = (dispatch) =>
bindActionCreators({ updateUser }, dispatch) bindActionCreators({ updateUser }, dispatch)
function UserProfile(props) {
return (
<div>
<UserEdit
polochonToken={props.polochonToken}
polochonUrl={props.polochonUrl}
updateUser={props.updateUser}
/>
<Modules modules={props.modules} />
</div>
)
}
class UserEdit extends React.PureComponent { class UserEdit extends React.PureComponent {
constructor(props) { constructor(props) {
super(props); super(props);
@ -100,4 +116,4 @@ class UserEdit extends React.PureComponent {
); );
} }
} }
export default connect(mapStateToProps, mapDispatchToProps)(UserEdit); export default connect(mapStateToProps, mapDispatchToProps)(UserProfile);

View File

@ -3,11 +3,13 @@ import { Map, List, fromJS } from "immutable"
const defaultState = Map({ const defaultState = Map({
"users": List(), "users": List(),
"stats": Map({}), "stats": Map({}),
"modules": Map({}),
}); });
const handlers = { const handlers = {
"ADMIN_LIST_USERS_FULFILLED": (state, action) => state.set("users", fromJS(action.payload.response.data)), "ADMIN_LIST_USERS_FULFILLED": (state, action) => state.set("users", fromJS(action.payload.response.data)),
"ADMIN_GET_STATS_FULFILLED": (state, action) => state.set("stats", fromJS(action.payload.response.data)), "ADMIN_GET_STATS_FULFILLED": (state, action) => state.set("stats", fromJS(action.payload.response.data)),
"ADMIN_GET_MODULES_FULFILLED": (state, action) => state.set("modules", fromJS(action.payload.response.data)),
} }
export default (state = defaultState, action) => export default (state = defaultState, action) =>

View File

@ -32,6 +32,9 @@ const handlers = {
"GET_USER_TOKENS_FULFILLED": (state, action) => state.set( "GET_USER_TOKENS_FULFILLED": (state, action) => state.set(
"tokens", fromJS(action.payload.response.data) "tokens", fromJS(action.payload.response.data)
), ),
"GET_USER_MODULES_FULFILLED": (state, action) => state.set(
"modules", fromJS(action.payload.response.data)
),
} }
function logoutUser() { function logoutUser() {

View File

@ -2,7 +2,7 @@ import MovieList from "./components/movies/list"
import ShowList from "./components/shows/list" import ShowList from "./components/shows/list"
import ShowDetails from "./components/shows/details" import ShowDetails from "./components/shows/details"
import UserLoginForm from "./components/users/login" import UserLoginForm from "./components/users/login"
import UserEdit from "./components/users/edit" import UserProfile from "./components/users/edit"
import UserTokens from "./components/users/tokens" import UserTokens from "./components/users/tokens"
import UserActivation from "./components/users/activation" import UserActivation from "./components/users/activation"
import UserSignUp from "./components/users/signup" import UserSignUp from "./components/users/signup"
@ -11,10 +11,10 @@ import TorrentSearch from "./components/torrents/search"
import AdminPanel from "./components/admins/panel" import AdminPanel from "./components/admins/panel"
import { fetchTorrents, searchTorrents } from "./actions/torrents" import { fetchTorrents, searchTorrents } from "./actions/torrents"
import { userLogout, getUserInfos, getUserTokens } from "./actions/users" import { userLogout, getUserInfos, getUserTokens, getUserModules } from "./actions/users"
import { fetchMovies, getMovieExploreOptions } from "./actions/movies" import { fetchMovies, getMovieExploreOptions } from "./actions/movies"
import { fetchShows, fetchShowDetails, getShowExploreOptions } from "./actions/shows" import { fetchShows, fetchShowDetails, getShowExploreOptions } from "./actions/shows"
import { getUsers, getStats } from "./actions/admins" import { getUsers, getStats, getAdminModules } from "./actions/admins"
import store from "./store" import store from "./store"
@ -112,10 +112,11 @@ export default function getRoutes(App) {
}, },
{ {
path: "/users/edit", path: "/users/edit",
component: UserEdit, component: UserProfile,
onEnter: function(nextState, replace, next) { onEnter: function(nextState, replace, next) {
loginCheck(nextState, replace, next, function() { loginCheck(nextState, replace, next, function() {
store.dispatch(getUserInfos()); store.dispatch(getUserInfos());
store.dispatch(getUserModules());
}); });
}, },
}, },
@ -282,6 +283,7 @@ export default function getRoutes(App) {
adminCheck(nextState, replace, next, function() { adminCheck(nextState, replace, next, function() {
store.dispatch(getUsers()); store.dispatch(getUsers());
store.dispatch(getStats()); store.dispatch(getStats());
store.dispatch(getAdminModules());
}); });
}, },
}, },