Skip to content

Commit

Permalink
Merge pull request #356 from labzero/develop
Browse files Browse the repository at this point in the history
Merge to master
  • Loading branch information
JeffreyATW authored Mar 18, 2024
2 parents 482b6bd + 0085968 commit bd6098f
Show file tree
Hide file tree
Showing 48 changed files with 590 additions and 821 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ DB_NAME=your_test_db_name
SUPERUSER_NAME=test
SUPERUSER_PASSWORD=test
[email protected]
USE_HTTPS=false
```

Then run:
Expand Down
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"@sendgrid/helpers": "^7.7.0",
"@sendgrid/mail": "^7.7.0",
"@ubilabs/react-geosuggest": "^2.16.1",
"bcrypt": "^5.1.0",
"bcrypt": "^5.1.1",
"body-parser": "^1.18.3",
"bootstrap": "^5.2.3",
"classnames": "^2.2.6",
Expand Down Expand Up @@ -45,6 +45,7 @@
"method-override": "^3.0.0",
"mocha-junit-reporter": "^2.2.0",
"morgan": "^1.10.0",
"node-fetch": "^2.7.0",
"normalizr": "^3.2.2",
"passport": "^0.6.0",
"passport-google-oauth20": "^2.0.0",
Expand Down Expand Up @@ -72,10 +73,10 @@
"rotating-file-stream": "^3.1.0",
"sequelize": "^6.29.0",
"sequelize-cli": "^6.6.0",
"sequelize-typescript": "^2.1.5",
"sequelize-typescript": "^2.1.6",
"serialize-javascript": "^6.0.1",
"source-map-support": "^0.5.21",
"universal-router": "^8.1.0"
"universal-router": "^9.2.0"
},
"devDependencies": {
"@istanbuljs/nyc-config-typescript": "^1.0.2",
Expand All @@ -90,6 +91,7 @@
"@types/compression": "^1.7.2",
"@types/connect-flash": "^0.0.37",
"@types/cookie-parser": "^1.4.3",
"@types/cors": "^2.8.17",
"@types/express-serve-static-core": "^4.17.35",
"@types/express-session": "^1.17.6",
"@types/express-sslify": "^1.2.2",
Expand All @@ -102,6 +104,7 @@
"@types/mocha": "^10.0.1",
"@types/morgan": "^1.9.4",
"@types/node": "^20.2.5",
"@types/node-fetch": "^2.6.11",
"@types/passport": "^1.0.11",
"@types/passport-google-oauth20": "^2.0.11",
"@types/passport-local": "^1.0.35",
Expand All @@ -118,7 +121,6 @@
"@typescript-eslint/eslint-plugin": "^5.59.1",
"@typescript-eslint/parser": "^5.59.1",
"autoprefixer": "^9.1.5",
"browser-sync": "2.29.1",
"chai": "4.3.7",
"chai-jsdom": "^0.2.3",
"chokidar": "^3.5.3",
Expand Down
13 changes: 13 additions & 0 deletions src/api/main/teams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ export default () => {
next(err);
}
})
.get("/all", loggedIn, async (req, res, next) => {
if (!req.user?.superuser) {
res.status(404).send();
} else {
try {
const teams = await Team.findAllWithAdminData();

res.status(200).json({ error: false, data: teams });
} catch (err) {
next(err);
}
}
})
.post("/", loggedIn, async (req, res, next) => {
const { address, lat, lng, name, slug } = req.body;
const message409 = "Could not create new team. It might already exist.";
Expand Down
24 changes: 17 additions & 7 deletions src/client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,11 @@ import configureStore from "./store/configureStore";
import history from "./history";
import { updateMeta } from "./DOMUtils";
import routerCreator from "./router";
import { AppContext, App as AppType } from "./interfaces";
import { AppContext, WindowWithApp } from "./interfaces";
import createFetch from "./createFetch";

let subdomain: string | undefined;

interface WindowWithApp extends Window {
App: AppType;
}

declare const window: WindowWithApp;

// Undo Browsersync mangling of host
Expand Down Expand Up @@ -55,6 +52,10 @@ if (!subdomain) {
const store = configureStore(window.App.state, { history });
/* eslint-enable no-underscore-dangle */

const fetchWithCache = createFetch(fetch, {
baseUrl: window.App.apiUrl,
});

// Global (context) variables that can be easily accessed from any React component
// https://facebook.github.io/react/docs/context.html
const context: AppContext = {
Expand All @@ -73,6 +74,7 @@ const context: AppContext = {
store,
pathname: "",
query: undefined,
fetch: fetchWithCache,
};

const container = document.getElementById("app");
Expand All @@ -89,7 +91,7 @@ if (subdomain) {
routes = require("./routes/main").default; // eslint-disable-line global-require, @typescript-eslint/no-var-requires
}

const router = routerCreator(routes);
const router = routerCreator(routes, fetchWithCache);

// Re-render the app when window.location changes
const onLocationChange = async ({
Expand Down Expand Up @@ -123,6 +125,14 @@ const onLocationChange = async ({
subdomain,
});

if (route == null) {
throw new Error("No route returned");
}

if (route.payload != null) {
context.payload = route.payload;
}

// Prevent multiple page renders during the routing process
if (currentLocation.key !== location.key) {
return;
Expand Down Expand Up @@ -217,7 +227,7 @@ const onLocationChange = async ({
// Handle client-side navigation by using HTML5 History API
// For more information visit https://github.com/mjackson/history#readme
history!.listen(onLocationChange);
onLocationChange({ action: Action.Replace, location: currentLocation });
onLocationChange({ location: currentLocation });

// Enable Hot Module Replacement (HMR)
/* if (module.hot) {
Expand Down
1 change: 1 addition & 0 deletions src/components/RestaurantMarker/RestaurantMarker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ const RestaurantMarker = ({ restaurant, ...props }: RestaurantMarkerProps) => {
store: props.store,
pathname: props.pathname,
query: props.query,
fetch: props.fetch,
};

return (
Expand Down
15 changes: 10 additions & 5 deletions src/components/TeamMap/TeamMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,18 @@ class TeamMap extends Component<TeamMapProps> {

setMap = ({ map }: { map: google.maps.Map }) => {
this.map = map;
this.map.addListener("bounds_changed", () => {
this.map.addListener("idle", () => {
const center = map.getCenter();

if (center) {
this.props.setCenter({
lat: center.lat(),
lng: center.lng(),
});
const lat = center.lat();
const lng = center.lng();
if (this.props.center?.lat !== lat || this.props.center?.lng !== lng) {
this.props.setCenter({
lat,
lng,
});
}
}
});
};
Expand Down
4 changes: 3 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ export const api = {
// API URL to be used in the server-side code
serverUrl:
process.env.API_SERVER_URL ||
`http://localhost:${process.env.PORT || 3000}`,
`http${process.env.USE_HTTPS === "true" ? "s" : ""}://localhost:${
process.env.PORT || 3000
}`,
};
export const host =
process.env.WEBSITE_HOSTNAME ||
Expand Down
74 changes: 74 additions & 0 deletions src/createFetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* React Starter Kit (https://www.reactstarterkit.com/)
*
* Copyright © 2014-present Kriasoft, LLC. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE.txt file in the root directory of this source tree.
*/

import type { Agent } from "https";
import { Fetch, FetchWithCache, WindowWithApp } from "./interfaces";

declare const window: WindowWithApp;

type Options = {
baseUrl: string;
cookie?: string;
agent?: Agent;
};

/**
* Creates a wrapper function around the HTML5 Fetch API that provides
* default arguments to fetch(...) and is intended to reduce the amount
* of boilerplate code in the application.
* https://developer.mozilla.org/docs/Web/API/Fetch_API/Using_Fetch
*/
function createFetch(
fetch: Fetch,
{ agent, baseUrl, cookie }: Options
): FetchWithCache {
// NOTE: Tweak the default options to suite your application needs
const defaults = {
agent,
mode: baseUrl ? "cors" : "same-origin",
credentials: baseUrl ? "include" : "same-origin",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
...(cookie ? { Cookie: cookie } : null),
},
};

return async (url, cacheConfig, options) => {
// Instead of making an actual HTTP request to the API, use
// hydrated data available during the initial page load.
if (typeof window !== "undefined" && window.App.cache !== undefined) {
// eslint-disable-next-line no-param-reassign
cacheConfig[url] = window.App.cache[url];
delete window.App.cache[url];
}

if (cacheConfig[url]) {
return Promise.resolve(cacheConfig[url]);
}

const response = await (url.startsWith("/api")
? fetch(`${baseUrl}${url}`, {
...defaults,
...options,
headers: {
...defaults.headers,
...(options && options.headers),
},
})
: fetch(url, options));

const json = await response.json();
// eslint-disable-next-line no-param-reassign
cacheConfig[url] = json;
return json;
};
}

export default createFetch;
26 changes: 25 additions & 1 deletion src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ export interface Tag extends TagModel {

export type Team = TeamModel;

export interface TeamWithAdminData
extends Pick<Team, "id" | "name" | "slug" | "createdAt"> {
roleCount: number;
recentVoteCreatedAt: string;
}

export interface Flash {
id: string;
message: string;
Expand Down Expand Up @@ -600,18 +606,34 @@ export type Reducer<T extends keyof State> = (

export type Dispatch = ThunkDispatch<State, unknown, Action>;

export type Cache = Record<string, Record<string, any>>;

export type Fetch = (url: string, options?: any) => Promise<any>;

export type FetchWithCache = (
url: string,
cache: Cache,
options?: any
) => Promise<any>;

export interface App {
apiUrl: string;
state: NonNormalizedState;
googleApiKey: string;
cache?: Cache;
}

export interface WindowWithApp extends Window {
App: App;
}

export interface AppContext extends ResolveContext {
insertCss: InsertCSS;
googleApiKey: string;
pathname: string;
query?: URLSearchParams;
store: EnhancedStore<State, Action>;
fetch: FetchWithCache;
payload?: Cache;
}

export interface AppRoute {
Expand All @@ -622,6 +644,8 @@ export interface AppRoute {
fullTitle?: string;
ogTitle?: string;
redirect?: string;
queries?: string[];
payload?: Cache;
status?: number;
title?: string;
}
7 changes: 7 additions & 0 deletions src/models/Restaurant.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import {
BelongsTo,
BelongsToMany,
Column,
ForeignKey,
HasMany,
Index,
Model,
Table,
} from "sequelize-typescript";
Expand Down Expand Up @@ -87,9 +90,13 @@ class Restaurant extends Model {
@Column
placeId: string;

@ForeignKey(() => Team)
@Column
teamId: string;

@BelongsTo(() => Team)
team: Team;

@HasMany(() => Vote)
votes: Vote[];

Expand Down
Loading

0 comments on commit bd6098f

Please sign in to comment.