Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: favorite pages / databases #623

Merged
merged 14 commits into from
Apr 24, 2022
Merged
7 changes: 7 additions & 0 deletions server/lib/favorite/all.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import DB from "../storage/db";

export default function all(owner: number) {
return DB("favorites").select("*").where({
owner,
});
}
9 changes: 9 additions & 0 deletions server/lib/favorite/create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import DB from "../storage/db";

export default function create(id: string, owner: number, type: string) {
return DB("favorites").insert({
object_id: id,
type,
owner,
});
}
8 changes: 8 additions & 0 deletions server/lib/favorite/remove.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import DB from '../storage/db';

export default function remove(id: string, owner: number) {
return DB('favorites').delete().where({
object_id: id,
owner,
});
}
10 changes: 10 additions & 0 deletions server/migrations/20220423114610_user-favourites.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports.up = function(knex) {
return knex.schema.createTable('favorites', function(table) {
table.integer("owner").references("id").inTable("users").notNullable();
table.text("object_id").notNullable();
})
};

module.exports.down = function(knex) {
return knex.schema.dropTable('favorites');
};
13 changes: 13 additions & 0 deletions server/migrations/20220424145342_user-favourites-add-type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports.up = (knex) => {
return knex.schema.table("favorites", (table) => {
table.string("type").notNullable();
});
};


module.exports.down = (knex) => {
return knex.schema.table("favorites", (table) => {
table.dropColumn("type");
});
};

4 changes: 2 additions & 2 deletions server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"notion2anki"
],
"author": "Alexander Alemayhu",
"version": "0.13.0",
"version": "0.14.0",
"engines": {
"node": ">=12.0.0"
},
Expand Down
16 changes: 16 additions & 0 deletions server/routes/favorite/addFavorite.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Request, Response } from 'express';

import create from '../../lib/favorite/create';
import ensureResponse from '../notion/helpers/ensureResponse';

export default async function addFavorite(req: Request, res: Response) {
ensureResponse(async () => {
const { id, type } = req.body;
if (!id || !type) {
return res.status(400).send();
}
const { owner } = res.locals;
await create(id, owner, type);
return res.status(200).send();
}, res);
}
16 changes: 16 additions & 0 deletions server/routes/favorite/deleteFavorite.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Request, Response } from 'express';

import remove from '../../lib/favorite/remove';
import ensureResponse from '../notion/helpers/ensureResponse';

export default async function deleteFavorite(req: Request, res: Response) {
ensureResponse(async () => {
const { id } = req.body;
if (!id) {
return res.status(400).send();
}
const { owner } = res.locals;
await remove(id, owner);
res.status(200).send();
}, res);
}
Empty file.
8 changes: 8 additions & 0 deletions server/routes/favorite/getFavorites.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Request, Response } from "express";
import all from "../../lib/favorite/all";

export default async function getFavorites(_req: Request, res: Response) {
const {owner} = res.locals;
const favorites = await all(owner);
res.json(favorites);
}
14 changes: 14 additions & 0 deletions server/routes/favorite/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import express from "express";

import RequireAuthentication from "../../middleware/RequireAuthentication";
import addFavorite from "./addFavorite";
import getFavorites from "./getFavorites";
import deleteFavorite from "./deleteFavorite";

const router = express.Router();

router.post("/create", RequireAuthentication, addFavorite);
router.post("/remove", RequireAuthentication, deleteFavorite);
router.get("/", RequireAuthentication, getFavorites);

export default router;
2 changes: 2 additions & 0 deletions server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import users from "./routes/users";
import notion from "./routes/notion";
import rules from "./routes/rules";
import download from "./routes/download/u";
import favorite from "./routes/favorite";

import DB from "./lib/storage/db";
import KnexConfig from "./KnexConfig";
Expand Down Expand Up @@ -80,6 +81,7 @@ function serve() {
app.use("/rules", rules);
app.use("/settings", _settings);
app.use("/download", download);
app.use("/favorite", favorite);

// Note: this has to be the last handler
app.get("*", (_req, res) => {
Expand Down
1 change: 0 additions & 1 deletion web/public/icons/settings.svg

This file was deleted.

12 changes: 10 additions & 2 deletions web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import CardOptionsStore from './store/CardOptionsStore';
import StoreContext from './store/StoreContext';
import GlobalStyle from './GlobalStyle';
import { NavigationBar } from './components/NavigationBar/NavigationBar';
import SettingsPage from './pages/Settings';
import ImportPage from './pages/Import/ImportPage';

const TemplatePage = lazy(() => import('./pages/Templates'));
const PreSignupPage = lazy(() => import('./pages/Register'));
Expand All @@ -19,7 +21,7 @@ const LoginPage = lazy(() => import('./pages/Login'));
const NewPasswordPage = lazy(() => import('./pages/NewPassword'));
const LearnPage = lazy(() => import('./pages/Learn'));
const VerifyPage = lazy(() => import('./pages/Verify'));
const ListUploadsPage = lazy(() => import('./pages/Uploads'));
const MyUploadsPage = lazy(() => import('./pages/MyUploads'));

const Layout = styled.div`
display: flex;
Expand Down Expand Up @@ -59,7 +61,7 @@ function App() {
)}
<Switch>
<Route path="/uploads">
<ListUploadsPage setError={setErrorMessage} />
<MyUploadsPage setError={setErrorMessage} />
</Route>
<Route path="/verify">
<VerifyPage />
Expand All @@ -85,6 +87,12 @@ function App() {
<Route path="/users/r/:id">
<NewPasswordPage setErrorMessage={setErrorMessage} />
</Route>
<Route path="/settings">
<SettingsPage />
</Route>
<Route path="/import">
<ImportPage />
</Route>
<Route path="/">
<HomePage />
</Route>
Expand Down
92 changes: 12 additions & 80 deletions web/src/components/NavigationBar/NavigationBar.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,27 @@
/* eslint-disable jsx-a11y/anchor-is-valid */
import { useState } from 'react';

import NotionWorkspace from '../../lib/interfaces/NotionWorkspace';
import getNavbarStartNewUser from './helpers/getNavbarStartNewUser';
import NavButtonCTA from '../buttons/NavButtonCTA';
import getCookie from './helpers/getCookie';
import Backend from '../../lib/Backend';
import NavbarItem from './NavbarItem';
import { Navbar } from './styled';

interface NavigationBarProps {
workspaces?: NotionWorkspace[];
activeWorkspace?: string;
connectLink?: string;
}
import getNavbarStartRegularUser from './helpers/getNavbarStartRegularUser';
import getNavbarEnd from './helpers/getNavbarEnd';

const backend = new Backend();
// eslint-disable-next-line import/prefer-default-export
export function NavigationBar({
activeWorkspace,
workspaces,
connectLink,
}: NavigationBarProps) {
export function NavigationBar() {
const isSignedIn = getCookie('token');
const [active, setHamburgerMenu] = useState(false);
const path = window.location.pathname;
const { hash } = window.location;

const navbarStart = isSignedIn
? getNavbarStartRegularUser(hash)
: getNavbarStartNewUser(hash, path);

return (
<Navbar className="navbar" role="navigation" aria-label="main navigation">
<div className="navbar-brand">
Expand All @@ -51,53 +47,11 @@ export function NavigationBar({
</div>

<div id="navbar" className={`navbar-menu ${active ? 'is-active' : ''}`}>
<div className="navbar-start">
<div className="navbar-item has-dropdown is-hoverable">
{activeWorkspace && (
<a href="/search" key={activeWorkspace} className="navbar-link">
{activeWorkspace}
</a>
)}
<div className="navbar-dropdown">
{workspaces && (
<>
{workspaces.map((w) => (
<a
key={w.name}
href="/notion/switch-workspace"
className="navbar-item"
>
{w.name}
</a>
))}
<hr className="navbar-divider" />
</>
)}
{connectLink && (
<a href={connectLink} className="dropdown-item">
Connect workspace
</a>
)}
</div>
</div>
</div>

<div className="navbar-start">{navbarStart}</div>
{!isSignedIn && (
<div className="navbar-end">
<NavbarItem href="/" path={hash || path}>
Home
</NavbarItem>
<NavbarItem href="/#about" path={hash}>
About
</NavbarItem>
<NavbarItem href="/#testimony" path={hash}>
Testimony
</NavbarItem>
<NavbarItem href="/#benefits" path={hash}>
Benefits
</NavbarItem>
<NavbarItem href="/#news" path={hash}>
News
<NavbarItem path="login" href="/login#login">
Login
</NavbarItem>
<div className="navbar-item">
<div className="buttons">
Expand All @@ -108,29 +62,7 @@ export function NavigationBar({
</div>
</div>
)}
{isSignedIn && (
<div className="navbar-end">
<NavbarItem href="/upload" path={path}>
📦 Upload
</NavbarItem>
<NavbarItem href="/search" path={path}>
🔍 Search
</NavbarItem>
<NavbarItem href="/uploads/mine" path={path}>
🗄 Uploads
</NavbarItem>
<NavbarItem
path={path}
href="/users/logout"
onClick={(event) => {
event.preventDefault();
backend.logout();
}}
>
🔒 log out
</NavbarItem>
</div>
)}
{isSignedIn && getNavbarEnd(path, backend)}
</div>
</Navbar>
);
Expand Down
22 changes: 22 additions & 0 deletions web/src/components/NavigationBar/helpers/getNavbarEnd.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Backend from '../../../lib/Backend';
import NavbarItem from '../NavbarItem';

export default function getNavbarEnd(path: string, backend: Backend) {
return (
<div className="navbar-end">
<NavbarItem href="/search" path={path}>
🔍 Search
</NavbarItem>
<NavbarItem
path={path}
href="/users/logout"
onClick={(event) => {
event.preventDefault();
backend.logout();
}}
>
🔒 log out
</NavbarItem>
</div>
);
}
23 changes: 23 additions & 0 deletions web/src/components/NavigationBar/helpers/getNavbarStartNewUser.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import NavbarItem from '../NavbarItem';

export default function getNavbarStartNewUser(hash: string, path: string) {
return (
<>
<NavbarItem href="/" path={hash || path}>
Home
</NavbarItem>
<NavbarItem href="/#about" path={hash}>
About
</NavbarItem>
<NavbarItem href="/#testimony" path={hash}>
Testimony
</NavbarItem>
<NavbarItem href="/#benefits" path={hash}>
Benefits
</NavbarItem>
<NavbarItem href="/#news" path={hash}>
News
</NavbarItem>
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import NavbarItem from '../NavbarItem';

export default function getNavbarStartRegularUser(path: string) {
/**
* Coming soon
* /learn
* /import
*/
return (
<>
<NavbarItem href="/upload" path={path}>
📦 Upload
</NavbarItem>
<NavbarItem href="/uploads/mine" path={path}>
🗂 My Uploads
</NavbarItem>
<NavbarItem href="/tm" path={path}>👩🏼‍🎨 Templates</NavbarItem>
</>
);
}
Loading