Continue adding context, small refactor on api methods, and moved cluster rows to separate component getting user from context

develop
Thomas Lynch 2 years ago
parent 6257420ef0
commit 463c7a21aa
  1. 45
      api.js
  2. 31
      components/ClusterRow.js
  3. 15
      pages/account.js
  4. 73
      pages/clusters.js
  5. 12
      pages/domains.js
  6. 6
      pages/login.js
  7. 12
      pages/map/[name].js
  8. 4
      pages/register.js

@ -1,5 +1,31 @@
import NProgress from 'nprogress';
export async function getAccount(dispatch, errorCallback, router) {
return ApiCall('/account.json', 'GET', null, dispatch, errorCallback, router, null);
}
export async function getClusters(dispatch, errorCallback, router) {
return ApiCall('/clusters.json', 'GET', null, dispatch, errorCallback, router, null);
}
export async function changeCluster(body, dispatch, errorCallback, router) {
return ApiCall('/forms/cluster', 'POST', body, dispatch, errorCallback, router, 0.5);
}
export async function globalToggle(body, dispatch, errorCallback, router) {
return ApiCall('/forms/global/toggle', 'POST', body, dispatch, errorCallback, router, 0.5);
}
export async function addCluster(body, dispatch, errorCallback, router) {
return ApiCall('/forms/cluster/add', 'POST', body, dispatch, errorCallback, router, 0.5);
}
export async function deleteCluster(body, dispatch, errorCallback, router) {
return ApiCall('/forms/cluster/delete', 'POST', body, dispatch, errorCallback, router, 0.5);
}
function buildOptions(route, method, body) {
// Convert method uppercase
@ -12,15 +38,16 @@ function buildOptions(route, method, body) {
}
};
if (body != null) {
options.body = body;
options.body = JSON.stringify(body);
}
//TODO: for GETs, use "body" with URLSearchParams and append as url query
return options;
}
export default async function ApiCall(route, method='get', body, dispatch, finishProgress, router) {
export async function ApiCall(route, method='get', body, dispatch, errorCallback, router, finishProgress=1) {
// Start progress bar
NProgress.start();
NProgress.start();
// Build request options for fetch
const requestOptions = buildOptions(route, method, body);
@ -40,7 +67,7 @@ export default async function ApiCall(route, method='get', body, dispatch, finis
}
if (!response) {
dispatch && dispatch({ type: 'error', payload: 'An error occurred' });
errorCallback('An error occurred');
return;
}
@ -51,16 +78,12 @@ export default async function ApiCall(route, method='get', body, dispatch, finis
if (response.redirect) {
return router.push(response.redirect, null, { scroll: false });
} else if (response.error) {
dispatch && dispatch({ type: 'error', payload: response.error });
errorCallback(response.error);
return;
}
dispatch && dispatch({ type: 'state', payload: response });
dispatch({ type: 'state', payload: response });
} else {
dispatch && dispatch({ type: 'error', payload: 'An error occurred' });
errorCallback('An error occurred');
}
}
export async function getAccount(dispatch, finishProgress, router) {
return ApiCall('/account.json', 'GET', null, dispatch, finishProgress, router)
}

@ -0,0 +1,31 @@
import { useContext } from 'react';
import { GlobalContext } from '../providers/GlobalProvider.js';
export default function ClusterRow({ i, cluster, setCluster, deleteCluster }) {
const [state] = useContext(GlobalContext);
const { user, csrf } = state;
return (
<tr className="align-middle">
<td className="col-1 text-center">
<form onSubmit={deleteCluster} action="/forms/cluster/delete" method="post">
<input type="hidden" name="_csrf" value={csrf} />
<input type="hidden" name="cluster" value={cluster} />
<input className="btn btn-danger" type="submit" value="×" />
</form>
</td>
<td className="col-1 text-center">
<form onSubmit={setCluster} action="/forms/cluster" method="post">
<input type="hidden" name="_csrf" value={csrf} />
<input type="hidden" name="cluster" value={i} />
<input className="btn btn-primary" type="submit" value="Select" disabled={(i === user.activeCluster ? 'disabled' : null)} />
</form>
</td>
<td>
{cluster}
</td>
</tr>
);
};

@ -4,7 +4,7 @@ import Link from 'next/link';
import MapLink from '../components/MapLink.js';
import LoadingPlaceholder from '../components/LoadingPlaceholder.js';
import ErrorAlert from '../components/ErrorAlert.js';
import { getAccount } from '../api.js';
import * as API from '../api.js';
import { useRouter } from 'next/router';
import { GlobalContext } from '../providers/GlobalProvider.js';
@ -12,13 +12,14 @@ const Account = (props) => {
const router = useRouter();
const [state, dispatch] = useContext(GlobalContext);
const [error, setError] = useState();
// Set into context from props (From getServerSideProps), else make API call
useEffect(() => {
if (props.user != null) {
dispatch({ type: 'state', payload: props });
} else {
getAccount(dispatch, null, router);
API.getAccount(dispatch, setError, router);
}
}, [dispatch, props, router]);
@ -47,14 +48,14 @@ const Account = (props) => {
async function switchCluster(e) {
e.preventDefault();
await ApiCall('/forms/cluster', 'POST', JSON.stringify({ _csrf: csrf, cluster: nextCluster }), null, 0.5, router);
await ApiCall('/account.json', 'GET', null, dispatch, null, router);
await API.changeCluster({ _csrf: csrf, cluster: nextCluster }, dispatch, setError, router);
await API.getAccount(dispatch, setError, router);
}
async function toggleGlobal(e) {
e.preventDefault();
await ApiCall('/forms/global/toggle', 'POST', JSON.stringify({ _csrf: csrf }), null, 0.5, router);
await ApiCall('/account.json', 'GET', null, dispatch, null, router);
await API.globalToggle({ _csrf: csrf },dispatch, setError, router);
await API.getAccount(dispatch, setError, router);
}
innerData = (
@ -157,7 +158,7 @@ const Account = (props) => {
<title>Account</title>
</Head>
{state.error && <ErrorAlert error={state.error} />}
{error && <ErrorAlert error={error} />}
<h5 className="fw-bold">
Controls:

@ -1,25 +1,29 @@
import React, { useState } from 'react';
import React, { useState, useContext, useEffect } from 'react';
import Head from 'next/head';
import Link from 'next/link';
import BackButton from '../components/BackButton.js'
import ErrorAlert from '../components/ErrorAlert.js';
import ApiCall from '../api.js'
import ClusterRow from '../components/ClusterRow.js';
import * as API from '../api.js'
import { useRouter } from 'next/router';
import { GlobalContext } from '../providers/GlobalProvider.js';
export default function Clusters(props) {
const router = useRouter();
const [accountData, setAccountData] = useState(props);
const [state, dispatch] = useContext(GlobalContext);
const [error, setError] = useState();
React.useEffect(() => {
if (!accountData.user) {
ApiCall('/clusters.json', 'GET', null, setAccountData, setError, null, router);
}
}, [accountData.user, router]);
// Set into context from props (From getServerSideProps), else make API call
useEffect(() => {
if (props.user != null) {
dispatch({ type: 'state', payload: props });
} else {
API.getClusters(dispatch, setError, router);
}
}, [dispatch, props, router]);
if (!accountData.user) {
if (!state.user) {
return (
<>
Loading...
@ -28,50 +32,33 @@ export default function Clusters(props) {
);
}
const { user, csrf } = accountData;
const { user, csrf } = state;
async function addCluster(e) {
e.preventDefault();
await ApiCall('/forms/cluster/add', 'POST', JSON.stringify({ _csrf: csrf, cluster: e.target.cluster.value }), null, setError, 0.5, router);
await ApiCall('/clusters.json', 'GET', null, setAccountData, setError, null, router);
await API.addCluster({ _csrf: csrf, cluster: e.target.cluster.value }, dispatch, setError, router);
await API.getClusters(dispatch, setError, router);
}
async function deleteCluster(e) {
e.preventDefault();
await ApiCall('/forms/cluster/delete', 'POST', JSON.stringify({ _csrf: csrf, cluster: e.target.cluster.value }), null, setError, 0.5, router);
await ApiCall('/clusters.json', 'GET', null, setAccountData, setError, null, router);
await API.deleteCluster({ _csrf: csrf, cluster: e.target.cluster.value }, dispatch, setError, router);
await API.getClusters(dispatch, setError, router);
}
async function setCluster(e) {
e.preventDefault();
await ApiCall('/forms/cluster', 'POST', JSON.stringify({ _csrf: csrf, cluster: e.target.cluster.value }), null, setError, 0.5, router);
await ApiCall('/clusters.json', 'GET', null, setAccountData, setError, null, router);
await API.changeCluster({ _csrf: csrf, cluster: e.target.cluster.value }, dispatch, setError, router);
await API.getClusters(dispatch, setError, router);
}
const domainList = user.clusters.map((c, i) => {
//TODO: refactor, to component
return (
<tr key={c} className="align-middle">
<td className="col-1 text-center">
<form onSubmit={deleteCluster} action="/forms/cluster/delete" method="post">
<input type="hidden" name="_csrf" value={csrf} />
<input type="hidden" name="cluster" value={c} />
<input className="btn btn-danger" type="submit" value="×" />
</form>
</td>
<td className="col-1 text-center">
<form onSubmit={setCluster} action="/forms/cluster" method="post">
<input type="hidden" name="_csrf" value={csrf} />
<input type="hidden" name="cluster" value={i} />
<input className="btn btn-primary" type="submit" value="Select" disabled={(i === user.activeCluster ? 'disabled' : null)} />
</form>
</td>
<td>
{c}
</td>
</tr>
);
})
const clusterList = user.clusters.map((cluster, i) => (<ClusterRow
i={i}
key={cluster}
cluster={cluster}
setCluster={setCluster}
deleteCluster={deleteCluster}
/>));
return (
<>
@ -90,9 +77,9 @@ export default function Clusters(props) {
<table className="table table-bordered text-nowrap">
<tbody>
{domainList}
{clusterList}
{/* Add new domain form */}
{/* Add new cluster form */}
<tr className="align-middle">
<td className="col-1 text-center" colSpan="3">
<form className="d-flex" onSubmit={addCluster} action="/forms/cluster/add" method="post">

@ -4,7 +4,7 @@ import Link from 'next/link';
import BackButton from '../components/BackButton.js';
import LoadingPlaceholder from '../components/LoadingPlaceholder.js';
import ErrorAlert from '../components/ErrorAlert.js';
import ApiCall from '../api.js';
import * as API from '../api.js'
import { useRouter } from 'next/router';
export default function Domains(props) {
@ -16,7 +16,7 @@ export default function Domains(props) {
React.useEffect(() => {
if (!accountData.user) {
ApiCall('/domains.json', 'GET', null, setAccountData, setError, null, router);
API.ApiCall('/domains.json', 'GET', null, setAccountData, setError, null, router);
}
}, [accountData.user, router]);
@ -33,14 +33,14 @@ export default function Domains(props) {
async function addDomain(e) {
e.preventDefault();
await ApiCall('/forms/domain/add', 'POST', JSON.stringify({ _csrf: csrf, domain: e.target.domain.value }), null, setError, 0.5, router);
await ApiCall('/domains.json', 'GET', null, setAccountData, setError, null, router);
await API.ApiCall('/forms/domain/add', 'POST', JSON.stringify({ _csrf: csrf, domain: e.target.domain.value }), null, setError, 0.5, router);
await API.ApiCall('/domains.json', 'GET', null, setAccountData, setError, null, router);
}
async function deleteDomain(e) {
e.preventDefault();
await ApiCall('/forms/domain/delete', 'POST', JSON.stringify({ _csrf: csrf, domain: e.target.domain.value }), null, setError, 0.5, router);
await ApiCall('/domains.json', 'GET', null, setAccountData, setError, null, router);
await API.ApiCall('/forms/domain/delete', 'POST', JSON.stringify({ _csrf: csrf, domain: e.target.domain.value }), null, setError, 0.5, router);
await API.ApiCall('/domains.json', 'GET', null, setAccountData, setError, null, router);
}
const domainList = user.domains.map((d, i) => {

@ -1,6 +1,6 @@
import Head from 'next/head';
import { useRouter } from 'next/router';
import ApiCall from '../api.js';
import * as API from '../api.js'
import ErrorAlert from '../components/ErrorAlert.js';
import { useState } from 'react';
@ -12,10 +12,10 @@ const Login = () => {
async function login(e) {
e.preventDefault();
await ApiCall('/forms/login', 'POST', JSON.stringify({
await API.ApiCall('/forms/login', 'POST', JSON.stringify({
username: e.target.username.value,
password: e.target.password.value,
}), null, setError, null, router);
}), null, setError, router, null);
}
return (

@ -5,7 +5,7 @@ import Link from 'next/link';
import MapRow from '../../components/MapRow.js';
import BackButton from '../../components/BackButton.js';
import ErrorAlert from '../../components/ErrorAlert.js';
import ApiCall from '../../api.js';
import * as API from '../../api.js'
const MapPage = (props) => {
@ -18,7 +18,7 @@ const MapPage = (props) => {
React.useEffect(() => {
if (!mapData.user) {
ApiCall(`/map/${mapName}.json`, 'GET', null, setMapData, setError, null, router);
API.ApiCall(`/map/${mapName}.json`, 'GET', null, setMapData, setError, null, router);
}
}, [mapData.user, mapName, router]);
@ -35,15 +35,15 @@ const MapPage = (props) => {
async function addToMap(e) {
e.preventDefault();
await ApiCall(`/forms/map/${mapId.name}/add`, 'POST', JSON.stringify({ _csrf: csrf, key: e.target.key.value, value: e.target.value?.value }), null, setError, 0.5, router);
await ApiCall(`/map/${mapId.name}.json`, 'GET', null, setMapData, setError, null, router);
await API.ApiCall(`/forms/map/${mapId.name}/add`, 'POST', JSON.stringify({ _csrf: csrf, key: e.target.key.value, value: e.target.value?.value }), null, setError, 0.5, router);
await API.ApiCall(`/map/${mapId.name}.json`, 'GET', null, setMapData, setError, null, router);
e.target.reset();
}
async function deleteFromMap(e) {
e.preventDefault();
await ApiCall(`/forms/map/${mapId.name}/delete`, 'POST', JSON.stringify({ _csrf: csrf, key: e.target.key.value }), null, setError, 0.5, router);
await ApiCall(`/map/${mapId.name}.json`, 'GET', null, setMapData, setError, null, router);
await API.ApiCall(`/forms/map/${mapId.name}/delete`, 'POST', JSON.stringify({ _csrf: csrf, key: e.target.key.value }), null, setError, 0.5, router);
await API.ApiCall(`/map/${mapId.name}.json`, 'GET', null, setMapData, setError, null, router);
}
const mapRows = map.map((row, i) => {

@ -1,6 +1,6 @@
import Head from 'next/head';
import { useRouter } from 'next/router';
import ApiCall from '../api.js';
import * as API from '../api.js'
import ErrorAlert from '../components/ErrorAlert.js';
import { useState } from 'react';
@ -12,7 +12,7 @@ const Register = () => {
async function register(e) {
e.preventDefault();
await ApiCall('/forms/regiser', 'POST', JSON.stringify({
await API.ApiCall('/forms/regiser', 'POST', JSON.stringify({
username: e.target.username.value,
password: e.target.password.value,
rpasword: e.target.repeat_password.value,

Loading…
Cancel
Save