Compare commits

...

3 Commits

Author SHA1 Message Date
Aditya Thakral ae34744c47 Add isSaving to editor 2021-04-06 01:16:13 -04:00
Aditya Thakral 39692a0333 Regenerate website on update 2021-04-06 01:05:10 -04:00
Aditya Thakral 5de03bf8d1 Use relative paths instead of absolute paths 2021-04-06 00:13:02 -04:00
14 changed files with 65 additions and 32 deletions

View File

View File

@ -4,6 +4,8 @@ from werkzeug.security import generate_password_hash, check_password_hash
import json import json
import sqlite3 import sqlite3
import os import os
import subprocess
DB_PATH = os.path.join(os.path.dirname(__file__), 'links.db') DB_PATH = os.path.join(os.path.dirname(__file__), 'links.db')
app = Flask(__name__) app = Flask(__name__)
@ -72,11 +74,16 @@ def update_links():
cur.executemany('INSERT INTO links VALUES (?,?,?,?,?)', links) cur.executemany('INSERT INTO links VALUES (?,?,?,?,?)', links)
con.commit() con.commit()
con.close() con.close()
data = regen_JSON()
# TODO: Trigger a rebuild of the frontend frontend_path = os.environ.get('FRONTEND_PATH', None)
outfile = open('data.json', 'w') if frontend_path is None:
print(data, file=outfile) raise Exception('FRONTEND_PATH is not defined')
outfile.close()
update_command = f"cd '{frontend_path}' && ./update.sh"
status = subprocess.call(update_command, shell=True)
if status != 0:
raise Exception(f"`{update_command}` exited with an error ({status})")
except Exception as e: except Exception as e:
cur.execute("rollback") cur.execute("rollback")

2
dev.sh
View File

@ -18,7 +18,7 @@ function dev_backend() {
cd ./backend cd ./backend
source venv/bin/activate source venv/bin/activate
python main.py FRONTEND_UPDATE_SCRIPT=$(realpath ./frontend/update.sh) python main.py
} }
run_frontend_backend "dev_frontend" "dev_backend" run_frontend_backend "dev_frontend" "dev_backend"

View File

@ -16,6 +16,7 @@ const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
const { displayDragDrop } = useDragDrop(); const { displayDragDrop } = useDragDrop();
const { headers } = useAuth(); const { headers } = useAuth();
const [editableLinks, setEditableLinks] = useState<EditableLink[]>(links); const [editableLinks, setEditableLinks] = useState<EditableLink[]>(links);
const [isSaving, setIsSaving] = useState(false);
useEffect(() => { useEffect(() => {
setEditableLinks(links); setEditableLinks(links);
@ -44,7 +45,9 @@ const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
]); ]);
const onSubmit = async () => { const onSubmit = async () => {
const res = await fetch("/api/editor/links", { setIsSaving(true);
const res = await fetch("api/editor/links", {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
@ -52,8 +55,11 @@ const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
}, },
body: JSON.stringify({ links: editableLinks }), body: JSON.stringify({ links: editableLinks }),
}); });
const updatedLinks = await res.json(); const updatedLinks = await res.json();
setLinks(updatedLinks); setLinks(updatedLinks);
setIsSaving(false);
}; };
const onCancel = () => { const onCancel = () => {
@ -110,15 +116,15 @@ const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
<button <button
className="block flex py-2 items-center justify-center rounded-md bg-purple-600 hover:bg-purple-500 cursor-pointer text-white w-full disabled:opacity-50" className="block flex py-2 items-center justify-center rounded-md bg-purple-600 hover:bg-purple-500 cursor-pointer text-white w-full disabled:opacity-50"
onClick={onSubmit} onClick={onSubmit}
disabled={equal(editableLinks, links)} disabled={isSaving || equal(editableLinks, links)}
> >
Submit {isSaving ? "Saving ..." : "Submit"}
</button> </button>
<div className="mr-4" /> <div className="mr-4" />
<button <button
className="block flex py-2 items-center justify-center rounded-md bg-purple-600 hover:bg-purple-500 cursor-pointer text-white w-full disabled:opacity-50" className="block flex py-2 items-center justify-center rounded-md bg-purple-600 hover:bg-purple-500 cursor-pointer text-white w-full disabled:opacity-50"
onClick={onCancel} onClick={onCancel}
disabled={equal(editableLinks, links)} disabled={isSaving || equal(editableLinks, links)}
> >
Cancel Cancel
</button> </button>

View File

@ -12,7 +12,7 @@ interface Props {
export const Links: React.FC<Props> = ({ links, logClicks = false }) => { export const Links: React.FC<Props> = ({ links, logClicks = false }) => {
const handleClick = (name: string, url: string) => { const handleClick = (name: string, url: string) => {
if (logClicks) { if (logClicks) {
fetch("/api/clicks", { fetch("api/clicks", {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",

View File

@ -31,7 +31,7 @@ export const AuthProvider: React.FC = ({ children }) => {
Authorization: `CustomBasic ${btoa(`${username}:${password}`)}`, Authorization: `CustomBasic ${btoa(`${username}:${password}`)}`,
}; };
const res = await fetch("/api/editor/links", { headers: newHeaders }); const res = await fetch("api/editor/links", { headers: newHeaders });
if (res.status === 200) { if (res.status === 200) {
setHeaders(newHeaders); setHeaders(newHeaders);

View File

@ -1,6 +1,5 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { useAuth } from "components/Login/AuthContext"; import { useAuth } from "components/Login/AuthContext";
import Image from "next/image";
import Head from "next/head"; import Head from "next/head";
const LoginBox: React.FC = () => { const LoginBox: React.FC = () => {
@ -37,8 +36,8 @@ const LoginBox: React.FC = () => {
</Head> </Head>
<div className="flex flex-col justify-center items-center space-y-10"> <div className="flex flex-col justify-center items-center space-y-10">
<div className="flex flex-row justify-center items-center space-x-5"> <div className="flex flex-row justify-center items-center space-x-5">
<Image <img
src="/images/csc-logo-fb-trans.png" src="csc-logo-trans.png"
height={80} height={80}
width={80} width={80}
alt="CSC Logo" alt="CSC Logo"

View File

@ -1,11 +1,7 @@
// @ts-check // @ts-check
/* eslint-disable @typescript-eslint/no-var-requires */
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
const { PHASE_DEVELOPMENT_SERVER } = require("next/constants"); module.exports = {
const devConfig = {
async rewrites() { async rewrites() {
return [ return [
{ {
@ -19,11 +15,3 @@ const devConfig = {
]; ];
}, },
}; };
const prodConfig = {
basePath: "/links",
};
// eslint-disable-next-line no-undef
module.exports = (phase) =>
phase === PHASE_DEVELOPMENT_SERVER ? devConfig : prodConfig;

View File

@ -4,8 +4,7 @@
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
"build": "next build", "build": "next build && next export",
"start": "next start",
"type-check": "tsc", "type-check": "tsc",
"format": "prettier --write './**/*'", "format": "prettier --write './**/*'",
"format:check": "prettier --check './**/*'", "format:check": "prettier --check './**/*'",

View File

@ -13,7 +13,7 @@ const EditorPage: React.FC = () => {
async function fetchLinks() { async function fetchLinks() {
if (!loggedIn) return; if (!loggedIn) return;
const res = await fetch("/api/editor/links", { headers }); const res = await fetch("api/editor/links", { headers });
const links = await res.json(); const links = await res.json();
setLinks(links); setLinks(links);
} }

View File

@ -3,7 +3,7 @@ import { GetStaticProps } from "next";
import { Link, Links } from "components/Links"; import { Link, Links } from "components/Links";
export const getStaticProps: GetStaticProps<Props> = async () => { export const getStaticProps: GetStaticProps<Props> = async () => {
const res = await fetch(`${process.env.DEV_URL}/links`); const res = await fetch(`http://${process.env.SERVER_URL}/links`);
const links = await res.json(); const links = await res.json();
return { return {

View File

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

3
frontend/update.sh Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env bash
npm run build

31
prod.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -e
echo "Starting the python server..."
pushd backend
source venv/bin/activate
FRONTEND_PATH=$(realpath ../frontend) python main.py &
pid_backend=$!
trap_ctrlc() {
kill $pid_backend
}
trap trap_ctrlc INT
popd
sleep 3
echo "Building frontend..."
pushd frontend
npm run build
popd
echo "Done!"
wait