Final fixups for deployment #31
|
@ -4,6 +4,8 @@ from werkzeug.security import generate_password_hash, check_password_hash
|
|||
import json
|
||||
import sqlite3
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
DB_PATH = os.path.join(os.path.dirname(__file__), 'links.db')
|
||||
|
||||
app = Flask(__name__)
|
||||
|
@ -72,11 +74,16 @@ def update_links():
|
|||
cur.executemany('INSERT INTO links VALUES (?,?,?,?,?)', links)
|
||||
con.commit()
|
||||
con.close()
|
||||
data = regen_JSON()
|
||||
# TODO: Trigger a rebuild of the frontend
|
||||
outfile = open('data.json', 'w')
|
||||
print(data, file=outfile)
|
||||
outfile.close()
|
||||
|
||||
frontend_path = os.environ.get('FRONTEND_PATH', None)
|
||||
if frontend_path is None:
|
||||
raise Exception('FRONTEND_PATH is not defined')
|
||||
|
||||
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:
|
||||
cur.execute("rollback")
|
||||
|
|
2
dev.sh
2
dev.sh
|
@ -18,7 +18,7 @@ function dev_backend() {
|
|||
cd ./backend
|
||||
source venv/bin/activate
|
||||
|
||||
python main.py
|
||||
FRONTEND_UPDATE_SCRIPT=$(realpath ./frontend/update.sh) python main.py
|
||||
}
|
||||
|
||||
run_frontend_backend "dev_frontend" "dev_backend"
|
||||
|
|
|
@ -16,6 +16,7 @@ const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
|
|||
const { displayDragDrop } = useDragDrop();
|
||||
const { headers } = useAuth();
|
||||
const [editableLinks, setEditableLinks] = useState<EditableLink[]>(links);
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setEditableLinks(links);
|
||||
|
@ -44,7 +45,9 @@ const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
|
|||
]);
|
||||
|
||||
const onSubmit = async () => {
|
||||
const res = await fetch("/api/editor/links", {
|
||||
setIsSaving(true);
|
||||
|
||||
const res = await fetch("api/editor/links", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
@ -52,8 +55,11 @@ const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
|
|||
},
|
||||
body: JSON.stringify({ links: editableLinks }),
|
||||
});
|
||||
|
||||
const updatedLinks = await res.json();
|
||||
|
||||
setLinks(updatedLinks);
|
||||
setIsSaving(false);
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
|
@ -110,15 +116,15 @@ const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
|
|||
<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"
|
||||
onClick={onSubmit}
|
||||
disabled={equal(editableLinks, links)}
|
||||
disabled={isSaving || equal(editableLinks, links)}
|
||||
>
|
||||
Submit
|
||||
{isSaving ? "Saving ..." : "Submit"}
|
||||
</button>
|
||||
<div className="mr-4" />
|
||||
<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"
|
||||
onClick={onCancel}
|
||||
disabled={equal(editableLinks, links)}
|
||||
disabled={isSaving || equal(editableLinks, links)}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
|
|
|
@ -12,7 +12,7 @@ interface Props {
|
|||
export const Links: React.FC<Props> = ({ links, logClicks = false }) => {
|
||||
const handleClick = (name: string, url: string) => {
|
||||
if (logClicks) {
|
||||
fetch("/api/clicks", {
|
||||
fetch("api/clicks", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
|
|
@ -31,7 +31,7 @@ export const AuthProvider: React.FC = ({ children }) => {
|
|||
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) {
|
||||
setHeaders(newHeaders);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import React, { useState } from "react";
|
||||
import { useAuth } from "components/Login/AuthContext";
|
||||
import Image from "next/image";
|
||||
import Head from "next/head";
|
||||
|
||||
const LoginBox: React.FC = () => {
|
||||
|
@ -37,8 +36,8 @@ const LoginBox: React.FC = () => {
|
|||
</Head>
|
||||
<div className="flex flex-col justify-center items-center space-y-10">
|
||||
<div className="flex flex-row justify-center items-center space-x-5">
|
||||
<Image
|
||||
src="/images/csc-logo-fb-trans.png"
|
||||
<img
|
||||
src="csc-logo-trans.png"
|
||||
height={80}
|
||||
width={80}
|
||||
alt="CSC Logo"
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
// @ts-check
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const { PHASE_DEVELOPMENT_SERVER } = require("next/constants");
|
||||
|
||||
const devConfig = {
|
||||
module.exports = {
|
||||
async rewrites() {
|
||||
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;
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"build": "next build && next export",
|
||||
"type-check": "tsc",
|
||||
"format": "prettier --write './**/*'",
|
||||
"format:check": "prettier --check './**/*'",
|
||||
|
|
|
@ -13,7 +13,7 @@ const EditorPage: React.FC = () => {
|
|||
async function fetchLinks() {
|
||||
if (!loggedIn) return;
|
||||
|
||||
const res = await fetch("/api/editor/links", { headers });
|
||||
const res = await fetch("api/editor/links", { headers });
|
||||
const links = await res.json();
|
||||
setLinks(links);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { GetStaticProps } from "next";
|
|||
import { Link, Links } from "components/Links";
|
||||
|
||||
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();
|
||||
|
||||
return {
|
||||
|
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
npm run build
|
|
@ -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
|
Loading…
Reference in New Issue