better mobile support, error handling
This commit is contained in:
24
.github/workflows/main.yml
vendored
24
.github/workflows/main.yml
vendored
@@ -8,10 +8,23 @@ env:
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
# just kidding, these are like, not ready at all
|
||||||
|
- never
|
||||||
|
- gonna
|
||||||
|
- give
|
||||||
|
- you
|
||||||
|
- up
|
||||||
|
|
||||||
|
# ... COPILOT JUST RICKROLLED ME
|
||||||
|
|
||||||
|
|
||||||
|
# - master
|
||||||
|
# # temporarily include dev branches
|
||||||
|
# - mongodb
|
||||||
|
# - music-streaming
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: self-hosted
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
@@ -22,3 +35,10 @@ jobs:
|
|||||||
run: npm install
|
run: npm install
|
||||||
- name: build check
|
- name: build check
|
||||||
run: npm run build
|
run: npm run build
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
runs-on: self-hosted
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: deploy service
|
||||||
|
run: ""
|
||||||
|
|||||||
@@ -2,18 +2,28 @@ import { AudioGallery } from "@/components/Music/AudioGallery";
|
|||||||
import NotFound from "@/components/NotFound";
|
import NotFound from "@/components/NotFound";
|
||||||
import MusicController from "@/server/controllers/music.controller";
|
import MusicController from "@/server/controllers/music.controller";
|
||||||
import { S3Service } from "@/server/s3";
|
import { S3Service } from "@/server/s3";
|
||||||
|
import { TrackWithURL } from "@/server/s3/service";
|
||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
|
|
||||||
export default async function ListenByCollectionID({ params }: { params: { collectionid?: string }}) {
|
export default async function ListenByCollectionID({ params }: { params: { collectionid?: string }}) {
|
||||||
const { collectionid: id } = params;
|
const { collectionid: id } = params;
|
||||||
if (!id) return <NotFound />
|
if (!id) return <NotFound />
|
||||||
|
|
||||||
const controller = new MusicController();
|
let collection: Awaited<ReturnType<MusicController["getByID"]>>;
|
||||||
const collection = await controller.getByID(id);
|
let trackList: Awaited<ReturnType<typeof S3Service.prepareTrackList>>;
|
||||||
if (!collection) return <NotFound />
|
let thumbnail: TrackWithURL | undefined;
|
||||||
|
|
||||||
const trackList = await S3Service.prepareTrackList(collection.pathtoentry);
|
try {
|
||||||
const thumbnail = trackList.filter(t => t.Key.includes(".png") || t.Key.includes(".jpg") || t.Key.includes(".jpeg"))[0];
|
const controller = new MusicController();
|
||||||
|
|
||||||
|
collection = await controller.getByID(id);
|
||||||
|
if (!collection) return <NotFound />
|
||||||
|
|
||||||
|
trackList = await S3Service.prepareTrackList(collection.pathtoentry);
|
||||||
|
thumbnail = trackList.filter(t => t.Key.includes(".png") || t.Key.includes(".jpg") || t.Key.includes(".jpeg"))[0];
|
||||||
|
} catch {
|
||||||
|
return <NotFound />
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
54
components/Navbar/MobileMenu.tsx
Normal file
54
components/Navbar/MobileMenu.tsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
'use client';
|
||||||
|
import Link from "next/link";
|
||||||
|
import { motion, useAnimate } from "framer-motion";
|
||||||
|
import { useCallback, useEffect } from "react";
|
||||||
|
|
||||||
|
type MobileMenuProps = {
|
||||||
|
mobileMenuOpen: boolean,
|
||||||
|
setMobileMenuOpen: (arg0: boolean) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function MobileMenu({ mobileMenuOpen, setMobileMenuOpen }: MobileMenuProps) {
|
||||||
|
// const [scope, animate] = useAnimate();
|
||||||
|
|
||||||
|
// const handleClickout = useCallback((e: MouseEvent) => {
|
||||||
|
// const target = e.target as HTMLElement;
|
||||||
|
// if (target.id !== 'mobile-sidebar') return;
|
||||||
|
|
||||||
|
// setMobileMenuOpen(false);
|
||||||
|
// animate('-16px', '100%')
|
||||||
|
// }, [setMobileMenuOpen, animate]);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// // handle clickout
|
||||||
|
// document.addEventListener('click', handleClickout)
|
||||||
|
// return () => document.removeEventListener('click', handleClickout);
|
||||||
|
// })
|
||||||
|
|
||||||
|
return (
|
||||||
|
<motion.div
|
||||||
|
// ref={scope}
|
||||||
|
id="mobile-sidebar"
|
||||||
|
animate={{ x: mobileMenuOpen ? '100%' : '-16px'}}
|
||||||
|
onMouseLeave={() => setMobileMenuOpen(false)}
|
||||||
|
className={`md:hidden w-1/3 fixed right-0 top-20 flex flex-col p-8 z-50 rounded-xl justify-end bg-[#131313] bg-opacity-90`}>
|
||||||
|
|
||||||
|
<Link onClick={() => setMobileMenuOpen(false)} passHref href="/" className="w-auto px-2">
|
||||||
|
<p className='text-lg text-center text-white text-opacity-80 hover:text-opacity-100 hover:bg-[#232323] rounded-xl uppercase p-2 border-opacity-50 hover:border-opacity-75'>Home</p>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Link onClick={() => setMobileMenuOpen(false)} passHref href="/about" className="w-auto px-2">
|
||||||
|
<p className='text-lg text-center text-white text-opacity-80 hover:text-opacity-100 hover:bg-[#232323] rounded-xl uppercase p-2 border-opacity-50 hover:border-opacity-75'>About</p>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Link onClick={() => setMobileMenuOpen(false)} passHref href="/projects" className="w-auto px-2">
|
||||||
|
<p className='text-lg text-center text-white text-opacity-80 hover:text-opacity-100 hover:bg-[#232323] rounded-xl hover:border-opacity-75 uppercase p-2 border-opacity-50'>Projects</p>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Link onClick={() => setMobileMenuOpen(false)} passHref href="/contact" className="w-auto px-2">
|
||||||
|
<p className='text-lg text-center text-white text-opacity-80 hover:text-opacity-100 hover:bg-[#232323] rounded-xl uppercase p-2 border-opacity-50 hover:border-opacity-75'>Contact</p>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
</motion.div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import { RxActivityLog } from "react-icons/rx";
|
|||||||
import { NavbarButton } from '../ui/Button';
|
import { NavbarButton } from '../ui/Button';
|
||||||
import useAudio from '@/hooks/useAudio';
|
import useAudio from '@/hooks/useAudio';
|
||||||
import AudioPlayer from '../Music/AudioPlayer/index';
|
import AudioPlayer from '../Music/AudioPlayer/index';
|
||||||
|
import MobileMenu from './MobileMenu';
|
||||||
|
|
||||||
const SHIFT_INTERVAL = 3000;
|
const SHIFT_INTERVAL = 3000;
|
||||||
|
|
||||||
@@ -52,24 +53,8 @@ export default function Navbar() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div onMouseLeave={() => setMobileMenuOpen(false)} className={`flex flex-col z-50 rounded-bl-lg justify-end md:hidden fixed top-24 w-[35vw] text-right place-self-end bg-[#131313] ${mobileMenuOpen ? 'translate-x-[65vw]' : 'translate-x-[100vw]'} transition-all duration-500`}>
|
|
||||||
<div className="bg-slate-300 dark:bg-black h-48" />
|
|
||||||
<Link onClick={() => setMobileMenuOpen(false)} passHref href="/" className="w-auto px-2">
|
|
||||||
<p className='text-lg text-right text-white text-opacity-80 hover:text-opacity-100 uppercase p-2 border-opacity-50 hover:border-opacity-75'>Home</p>
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<Link onClick={() => setMobileMenuOpen(false)} passHref href="/about" className="w-auto px-2">
|
<MobileMenu mobileMenuOpen={mobileMenuOpen} setMobileMenuOpen={setMobileMenuOpen} />
|
||||||
<p className='text-lg text-right text-white text-opacity-80 hover:text-opacity-100 uppercase p-2 border-opacity-50 hover:border-opacity-75'>About</p>
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<Link onClick={() => setMobileMenuOpen(false)} passHref href="/projects" className="w-auto px-2">
|
|
||||||
<p className='text-lg text-right text-white text-opacity-80 hover:text-opacity-100 hover:border-opacity-75 uppercase p-2 border-opacity-50'>Projects</p>
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<Link onClick={() => setMobileMenuOpen(false)} passHref href="/contact" className="w-auto px-2">
|
|
||||||
<p className='text-lg text-right text-white text-opacity-80 hover:text-opacity-100 uppercase p-2 border-opacity-50 hover:border-opacity-75'>Contact</p>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
<AudioPlayer />
|
<AudioPlayer />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
0
mgmt/index.ts
Normal file
0
mgmt/index.ts
Normal file
@@ -11,7 +11,7 @@ type ControllerOptions<T extends { [key: string]: any }> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default abstract class BaseController<T extends { _id?: any, [key: string]: any }> {
|
export default abstract class BaseController<T extends { _id?: any, [key: string]: any }> {
|
||||||
protected client: MongoClient
|
protected client: MongoClient | null;
|
||||||
protected collectionName: string
|
protected collectionName: string
|
||||||
protected parse: FullParserType<T>
|
protected parse: FullParserType<T>
|
||||||
|
|
||||||
@@ -22,6 +22,7 @@ export default abstract class BaseController<T extends { _id?: any, [key: string
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getAll() {
|
async getAll() {
|
||||||
|
if (!this.client) return null;
|
||||||
let result: Maybe<WithId<T>[]>;
|
let result: Maybe<WithId<T>[]>;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -42,6 +43,7 @@ export default abstract class BaseController<T extends { _id?: any, [key: string
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getByID(id: string): Promise<Maybe<WithId<T>>> {
|
async getByID(id: string): Promise<Maybe<WithId<T>>> {
|
||||||
|
if (!this.client) return null;
|
||||||
let result: Maybe<WithId<T>>;
|
let result: Maybe<WithId<T>>;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -58,6 +60,8 @@ export default abstract class BaseController<T extends { _id?: any, [key: string
|
|||||||
}
|
}
|
||||||
|
|
||||||
async post(data: T) {
|
async post(data: T) {
|
||||||
|
if (!this.client) return null;
|
||||||
|
|
||||||
let result: Maybe<InsertOneResult<T>>;
|
let result: Maybe<InsertOneResult<T>>;
|
||||||
this.parse(data);
|
this.parse(data);
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,13 @@ import { env } from "@/env.mjs";
|
|||||||
import { MongoClient } from "mongodb";
|
import { MongoClient } from "mongodb";
|
||||||
|
|
||||||
export function createDBClient() {
|
export function createDBClient() {
|
||||||
return new MongoClient(env.MONGO_URL, {
|
try {
|
||||||
tls: true,
|
return new MongoClient(env.MONGO_URL, {
|
||||||
tlsCertificateKeyFile: process.cwd() + "/certs/mongo_cert.pem",
|
tls: true,
|
||||||
});
|
tlsCertificateKeyFile: process.cwd() + "/certs/mongo_cert.pem",
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user