Make switching between maps set correct context and dont show wrong map content on loading new mape if mapId.name has changed

develop
Thomas Lynch 2 years ago
parent 463c7a21aa
commit e3e63f9af2
  1. 49
      api.js
  2. 6
      components/MapRow.js
  3. 2
      controllers/maps.js
  4. 11
      pages/account.js
  5. 30
      pages/domains.js
  6. 10
      pages/login.js
  7. 42
      pages/map/[name].js
  8. 9
      pages/register.js

@ -1,31 +1,58 @@
import NProgress from 'nprogress';
// Account
export async function getAccount(dispatch, errorCallback, router) {
return ApiCall('/account.json', 'GET', null, dispatch, errorCallback, router, null);
return ApiCall('/account.json', 'GET', null, dispatch, errorCallback, router);
}
export async function login(body, dispatch, errorCallback, router) {
return ApiCall('/forms/login', 'POST', body, dispatch, errorCallback, router);
}
export async function register(body, dispatch, errorCallback, router) {
return ApiCall('/forms/register', 'POST', body, dispatch, errorCallback, router);
}
// Clusters
export async function getClusters(dispatch, errorCallback, router) {
return ApiCall('/clusters.json', 'GET', null, dispatch, errorCallback, router, null);
return ApiCall('/clusters.json', 'GET', null, dispatch, errorCallback, router);
}
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);
}
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);
// Domains
export async function getDomains(dispatch, errorCallback, router) {
return ApiCall('/domains.json', 'GET', null, dispatch, errorCallback, router);
}
export async function addDomain(body, dispatch, errorCallback, router) {
return ApiCall('/forms/domain/add', 'POST', body, dispatch, errorCallback, router, 0.5);
}
export async function deleteDomain(body, dispatch, errorCallback, router) {
return ApiCall('/forms/domain/delete', '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);
// Maps
export async function getMap(mapName, dispatch, errorCallback, router) {
return ApiCall(`/map/${mapName}.json`, 'GET', null, dispatch, errorCallback, router);
}
export async function addToMap(mapName, body, dispatch, errorCallback, router) {
return ApiCall(`/forms/map/${mapName}/add`, 'POST', body, dispatch, errorCallback, router, 0.5);
}
export async function deleteFromMap(mapName, body, dispatch, errorCallback, router) {
return ApiCall(`/forms/map/${mapName}/delete`, 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);
// Global toggle
export async function globalToggle(body, dispatch, errorCallback, router) {
return ApiCall('/forms/global/toggle', 'POST', body, dispatch, errorCallback, router, 0.5);
}
function buildOptions(route, method, body) {
// Convert method uppercase

@ -1,7 +1,11 @@
import Link from 'next/link';
import { useContext } from 'react';
import { GlobalContext } from '../providers/GlobalProvider.js';
export default function MapRow({ name, row, csrf, showValues, mapValueNames, onDeleteSubmit }) {
export default function MapRow({ row, onDeleteSubmit }) {
const [state] = useContext(GlobalContext);
const { user, mapValueNames, mapId, map, csrf, name, showValues } = state;
const [id, key, value] = row.split(' ');
return (

@ -58,7 +58,7 @@ exports.mapData = async (req, res, next) => {
exports.mapPage = async (app, req, res, next) => {
const data = await exports.mapData(req, res, next);
return app.render(req, res, '/map/[mapname]', data);
return app.render(req, res, `/map/${data.name}`, data);
};
exports.mapJson = async (req, res, next) => {

@ -16,7 +16,7 @@ const Account = (props) => {
// Set into context from props (From getServerSideProps), else make API call
useEffect(() => {
if (props.user != null) {
if (props.maps != null) {
dispatch({ type: 'state', payload: props });
} else {
API.getAccount(dispatch, setError, router);
@ -32,8 +32,9 @@ const Account = (props) => {
}, []);
let innerData;
if (state.user != null) {
//TODO: when coming from loaded map after refresh, will already have some data, so we should partially populate page
if (state.maps != null) {
const { user, maps, acls, globalAcl, csrf } = state;
@ -145,8 +146,8 @@ const Account = (props) => {
innerData = (
<>
{Array(9).map((_, i) => <loadingSection key={i}/>)}
</>
{Array(9).fill(loadingSection)}
</>
);
}

@ -1,4 +1,4 @@
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';
@ -6,21 +6,23 @@ import LoadingPlaceholder from '../components/LoadingPlaceholder.js';
import ErrorAlert from '../components/ErrorAlert.js';
import * as API from '../api.js'
import { useRouter } from 'next/router';
import { GlobalContext } from '../providers/GlobalProvider.js';
export default function Domains(props) {
const router = useRouter();
const [accountData, setAccountData] = useState(props);
const [state, dispatch] = useContext(GlobalContext);
const [error, setError] = useState();
React.useEffect(() => {
if (!accountData.user) {
API.ApiCall('/domains.json', 'GET', null, setAccountData, setError, null, router);
}
}, [accountData.user, router]);
useEffect(() => {
if (props.user != null) {
dispatch({ type: 'state', payload: props });
} else {
API.getDomains(dispatch, setError, router);
}
}, [dispatch, props, router]);
if (!accountData.user) {
if (!state.user) {
return (
<>
Loading...
@ -29,18 +31,18 @@ export default function Domains(props) {
);
}
const { user, csrf } = accountData;
const { user, csrf } = state;
async function addDomain(e) {
e.preventDefault();
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);
await API.addDomain({ _csrf: csrf, domain: e.target.domain.value }, dispatch, setError, router);
await API.getDomains(dispatch, setError, router);
}
async function deleteDomain(e) {
e.preventDefault();
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);
await API.deleteDomain({ _csrf: csrf, domain: e.target.domain.value }, dispatch, setError, router);
await API.getDomains(dispatch, setError, router);
}
const domainList = user.domains.map((d, i) => {

@ -2,20 +2,22 @@ import Head from 'next/head';
import { useRouter } from 'next/router';
import * as API from '../api.js'
import ErrorAlert from '../components/ErrorAlert.js';
import { useState } from 'react';
import { useState, useContext } from 'react';
import { GlobalContext } from '../providers/GlobalProvider.js';
const Login = () => {
const router = useRouter();
const router = useRouter();
const [state, dispatch] = useContext(GlobalContext);
const [error, setError] = useState();
async function login(e) {
e.preventDefault();
await API.ApiCall('/forms/login', 'POST', JSON.stringify({
await API.login({
username: e.target.username.value,
password: e.target.password.value,
}), null, setError, router, null);
}, dispatch, setError, router);
}
return (

@ -1,28 +1,31 @@
import { useRouter } from "next/router";
import React, { useState } from 'react';
import React, { useState, useContext, useEffect } from 'react';
import Head from 'next/head';
import Link from 'next/link';
import MapRow from '../../components/MapRow.js';
import BackButton from '../../components/BackButton.js';
import ErrorAlert from '../../components/ErrorAlert.js';
import * as API from '../../api.js'
import * as API from '../../api.js';
import { GlobalContext } from '../../providers/GlobalProvider.js';
const MapPage = (props) => {
const router = useRouter();
const { name: mapName } = router.query;
const [mapData, setMapData] = useState(props);
const [state, dispatch] = useContext(GlobalContext);
const [error, setError] = useState();
const changedMap = state.mapId?.name != mapName;
useEffect(() => {
if (props.map != null) {
dispatch({ type: 'state', payload: props });
} else {
//TODO: eventually, keep all visited maps in the context and refresh on load like e.g. clusters
API.getMap(mapName, dispatch, setError, router);
}
}, [changedMap, mapName, dispatch, props, router]);
React.useEffect(() => {
if (!mapData.user) {
API.ApiCall(`/map/${mapName}.json`, 'GET', null, setMapData, setError, null, router);
}
}, [mapData.user, mapName, router]);
if (!mapData.user) {
if (state.map == null || changedMap) {
return (
<>
Loading...
@ -31,31 +34,26 @@ const MapPage = (props) => {
);
}
const { user, mapValueNames, mapId, map, csrf, name, showValues } = mapData;
const { user, mapValueNames, mapId, map, csrf, name, showValues } = state;
async function addToMap(e) {
e.preventDefault();
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);
await API.addToMap(mapId.name, { _csrf: csrf, key: e.target.key.value, value: e.target.value?.value }, dispatch, setError, router);
await API.getMap(mapName, dispatch, setError, router);
e.target.reset();
}
async function deleteFromMap(e) {
e.preventDefault();
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);
await API.deleteFromMap(mapId.name, { _csrf: csrf, key: e.target.key.value }, dispatch, setError, router);
await API.getMap(mapName, dispatch, setError, router);
}
const mapRows = map.map((row, i) => {
//TODO: address prop drilling
return (
<MapRow
key={i}
row={row}
name={mapId.name}
csrf={csrf}
showValues={showValues}
mapValueNames={mapValueNames}
onDeleteSubmit={deleteFromMap}
/>
)

@ -2,21 +2,22 @@ import Head from 'next/head';
import { useRouter } from 'next/router';
import * as API from '../api.js'
import ErrorAlert from '../components/ErrorAlert.js';
import { useState } from 'react';
import { useState, useContext } from 'react';
import { GlobalContext } from '../providers/GlobalProvider.js';
const Register = () => {
const router = useRouter();
const [state, dispatch] = useContext(GlobalContext);
const [error, setError] = useState();
async function register(e) {
e.preventDefault();
await API.ApiCall('/forms/regiser', 'POST', JSON.stringify({
await API.register({
username: e.target.username.value,
password: e.target.password.value,
rpasword: e.target.repeat_password.value,
}), null, setError, 0.5, router);
}, dispatch, setError, router);
router.push('/login');
}

Loading…
Cancel
Save