remove things stoppping a build

This commit is contained in:
Chris Grimmett 2024-02-27 07:52:43 -08:00
parent 4dd1531a9c
commit bd85718107
20 changed files with 285 additions and 900 deletions

8
ARCHITECHTURE.md Normal file
View File

@ -0,0 +1,8 @@
Monorepo. pnpm required for workspaces.
packages/strapi requires Yarn.
Development uses dockerfile with dotenv.
Production uses dokku.

View File

@ -1,25 +0,0 @@
FROM node:20-slim AS base
ENV NEXT_TELEMETRY_DISABLED 1
RUN corepack enable
FROM base AS build
WORKDIR /usr/src/fp-monorepo
RUN mkdir /usr/src/next
COPY ./pnpm-lock.yaml ./
COPY ./pnpm-workspace.yaml ./
COPY ./packages/next/package.json ./packages/next/
RUN --mount=type=cache,id=pnpm-store,target=/root/.pnpm-store pnpm install
COPY . .
RUN pnpm deploy --filter=fp-next /usr/src/next
FROM base AS dev
WORKDIR /app
COPY --from=build /usr/src/next /app
CMD ["pnpm", "run", "dev"]
FROM base AS prod
WORKDIR /app
COPY --from=build /usr/src/next /app
COPY ./packages/next/app.json /app
ENTRYPOINT ["pnpm"]
CMD ["start"]

View File

@ -1,5 +1,2 @@
# futureporn-monorepo
## Dev notes
We are using multiple Dockerfiles which is a inefficiency. We are doing this because we deploy using dokku. We think one Dockerfile per package is the only way for dokku to use monorepo paradigm.

View File

@ -1,103 +0,0 @@
version: '3.4'
services:
link2cid:
container_name: fp-link2cid
image: insanity54/link2cid:latest
ports:
- "3939:3939"
environment:
API_KEY: ${LINK2CID_API_KEY}
IPFS_URL: "http://ipfs0:5001"
ipfs0:
container_name: fp-ipfs0
image: ipfs/kubo:release
ports:
- "5001:5001"
volumes:
- ./packages/ipfs0:/data/ipfs
cluster0:
container_name: fp-cluster0
image: ipfs/ipfs-cluster:latest
depends_on:
- ipfs0
environment:
CLUSTER_PEERNAME: cluster0
CLUSTER_SECRET: ${CLUSTER_SECRET} # From shell variable if set
CLUSTER_IPFSHTTP_NODEMULTIADDRESS: /dns4/ipfs0/tcp/5001
CLUSTER_CRDT_TRUSTEDPEERS: '*' # Trust all peers in Cluster
CLUSTER_RESTAPI_HTTPLISTENMULTIADDRESS: /ip4/0.0.0.0/tcp/9094 # Expose API
CLUSTER_RESTAPI_BASICAUTHCREDENTIALS: ${CLUSTER_RESTAPI_BASICAUTHCREDENTIALS}
CLUSTER_MONITORPINGINTERVAL: 2s # Speed up peer discovery
ports:
- "127.0.0.1:9094:9094"
volumes:
- ./packages/cluster0:/data/ipfs-cluster
strapi:
container_name: fp-strapi
image: elestio/strapi-development
depends_on:
- db
environment:
ADMIN_PASSWORD: ${STRAPI_ADMIN_PASSWORD}
ADMIN_EMAIL: ${STRAPI_ADMIN_EMAIL}
BASE_URL: ${STRAPI_BASE_URL}
SMTP_HOST: 172.17.0.1
SMTP_PORT: 25
SMTP_AUTH_STRATEGY: NONE
SMTP_FROM_EMAIL: sender@email.com
DATABASE_CLIENT: postgres
DATABASE_PORT: ${DATABASE_PORT}
DATABASE_NAME: ${DATABASE_NAME}
DATABASE_USERNAME: ${DATABASE_USERNAME}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
JWT_SECRET: ${STRAPI_JWT_SECRET}
ADMIN_JWT_SECRET: ${STRAPI_ADMIN_JWT_SECRET}
APP_KEYS: ${STRAPI_APP_KEYS}
NODE_ENV: development
DATABASE_HOST: db
API_TOKEN_SALT: ${STRAPI_API_TOKEN_SALT}
TRANSFER_TOKEN_SALT: ${STRAPI_TRANSFER_TOKEN_SALT}
ports:
- "1337:1337"
volumes:
- ./packages/strapi/config:/opt/app/config
- ./packages/strapi/src:/opt/app/src
# - ./packages/strapi/package.json:/opt/package.json
# - ./packages/strapi/yarn.lock:/opt/yarn.lock
- ./packages/strapi/.env:/opt/app/.env
- ./packages/strapi/public/uploads:/opt/app/public/uploads
# - ./packages/strapi/entrypoint.sh:/opt/app/entrypoint.sh
next:
container_name: fp-next
build:
context: ./packages/next
dockerfile: Dockerfile
environment:
REVALIDATION_TOKEN: ${NEXT_REVALIDATION_TOKEN}
NODE_ENV: production
ports:
- "3000:3000"
volumes:
- ./packages/next/
db:
container_name: fp-db
image: postgres:latest
restart: always
environment:
POSTGRES_DB: ${DATABASE_NAME}
POSTGRES_USER: ${DATABASE_USERNAME}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
PGDATA: /var/lib/postgresql/data
volumes:
- ./packages/db/pgdata:/var/lib/postgresql/data
ports:
- "5433:5432"

View File

@ -60,7 +60,7 @@ services:
image: fp-strapi:14
build:
context: ./packages/strapi
dockerfile: Dockerfile.strapi
dockerfile: Dockerfile
restart: on-failure
depends_on:
- db
@ -116,7 +116,7 @@ services:
container_name: fp-next
build:
context: .
dockerfile: Dockerfile.next
dockerfile: Dockerfile
target: dev
restart: on-failure
environment:

View File

@ -1,25 +1,26 @@
FROM node:20-slim AS base
ENV NEXT_TELEMETRY_DISABLED 1
# Install dependencies only when needed
FROM base AS deps
RUN corepack enable
FROM base AS build
WORKDIR /usr/src/fp-monorepo
RUN mkdir /usr/src/next
COPY ./pnpm-lock.yaml ./
COPY ./pnpm-workspace.yaml ./
COPY ./packages/next/package.json ./packages/next/
RUN --mount=type=cache,id=pnpm-store,target=/root/.pnpm-store pnpm install
COPY . .
RUN pnpm deploy --filter=fp-next /usr/src/next
FROM base AS dev
FROM deps AS build
WORKDIR /usr/src/app
COPY . .
ENV NEXT_TELEMETRY_DISABLED 1
RUN --mount=type=cache,id=pnpm-store,target=/root/.pnpm-store pnpm install
RUN pnpm run -r build
RUN pnpm deploy --filter=fp-next /app
FROM deps AS dev
WORKDIR /app
COPY --from=build /usr/src/next /app
COPY --from=build /usr/src/app /app
CMD ["pnpm", "run", "dev"]
FROM base AS next
FROM deps AS next
WORKDIR /app
COPY --from=build /usr/src/next /app
COPY ./packages/next/app.json /app
ENTRYPOINT ["pnpm"]
CMD ["start"]
COPY --from=build /usr/src/app /app
CMD ["pnpm", "start"]

19
package.json Normal file
View File

@ -0,0 +1,19 @@
{
"name": "futureporn",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"kompose": "kompose convert --file compose.yml -c --out ./charts",
"deploy:bot": "echo @todo",
"deploy:next": "git push origin:next main",
"deploy:link2cid": "echo @todo",
"deploy:strapi": "echo @todo",
"deploy:uppy": "echo @todo",
"deploy": "echo @todo"
},
"keywords": [],
"author": "@cj_clippy",
"license": "CC0-1.0"
}

View File

@ -6,18 +6,19 @@ export interface IArchiveProgressProps {
}
export default async function ArchiveProgress ({ vtuber }: IArchiveProgressProps) {
const streams = await getAllStreamsForVtuber(vtuber.id);
const goodStreams = await getAllStreamsForVtuber(vtuber.id, ['good']);
const issueStreams = await getAllStreamsForVtuber(vtuber.id, ['issue']);
const totalStreams = streams.length;
const eligibleStreams = issueStreams.length+goodStreams.length;
// const streams = await getAllStreamsForVtuber(vtuber.id);
// const goodStreams = await getAllStreamsForVtuber(vtuber.id, ['good']);
// const issueStreams = await getAllStreamsForVtuber(vtuber.id, ['issue']);
// const totalStreams = streams.length;
// const eligibleStreams = issueStreams.length+goodStreams.length;
// Check if totalStreams is not zero before calculating completedPercentage
const completedPercentage = (totalStreams !== 0) ? Math.round(eligibleStreams / totalStreams * 100) : 0;
return (
<div>
<p className="heading">{eligibleStreams}/{totalStreams} Streams Archived ({completedPercentage}%)</p>
<progress className="progress is-success" value={eligibleStreams} max={totalStreams}>{completedPercentage}%</progress>
</div>
)
// // Check if totalStreams is not zero before calculating completedPercentage
// const completedPercentage = (totalStreams !== 0) ? Math.round(eligibleStreams / totalStreams * 100) : 0;
// return (
// <div>
// <p className="heading">{eligibleStreams}/{totalStreams} Streams Archived ({completedPercentage}%)</p>
// <progress className="progress is-success" value={eligibleStreams} max={totalStreams}>{completedPercentage}%</progress>
// </div>
// )
return "@todo"
}

View File

@ -1,125 +0,0 @@
'use client';
// greets https://github.com/wa0x6e/cal-heatmap-react-starter/blob/main/src/components/cal-heatmap.tsx
import CalHeatmap from 'cal-heatmap';
// @ts-ignore cal-heatmap is jenk
import Legend from 'cal-heatmap/plugins/Legend';
// @ts-ignore cal-heatmap is jenk
import Tooltip from 'cal-heatmap/plugins/Tooltip';
import { DataRecord } from 'cal-heatmap/src/options/Options';
import 'cal-heatmap/cal-heatmap.css';
import dayjs from 'dayjs';
import { useEffect, useState, useRef } from 'react';
import { useRouter } from 'next/navigation';
import { getSafeDate } from '@/lib/dates';
export interface ICalProps {
data: DataRecord[];
slug: string;
}
export function Cal({ data, slug }: ICalProps) {
const router = useRouter();
const [cellSize, setCellSize] = useState(13);
const [targetElementId, setTargetElementId] = useState('');
const generateUniqueId = () => {
return `cal-${Math.random().toString(36).substring(2, 9)}`;
};
useEffect(() => {
const updateCellSize = () => {
const windowWidth = window.innerWidth;
if (windowWidth > 1400) {
setCellSize(15); // Adjust the cell size for width > 1400px
} else if (windowWidth > 730) {
setCellSize(10); // Adjust the cell size for width > 730px
} else {
setCellSize(3); // Adjust the cell size for width <= 730px
}
}
updateCellSize();
// Event listener to update cell size on window resize
window.addEventListener('resize', updateCellSize);
return () => {
window.removeEventListener('resize', updateCellSize);
};
}, [])
useEffect(() => {
setTargetElementId(generateUniqueId());
}, []);
useEffect(() => {
if (!targetElementId) return;
const cal = new CalHeatmap();
// @ts-ignore
cal.on('click', (
event: string,
timestamp: number,
value: number
) => {
router.push(`/vt/${slug}/stream/${getSafeDate(new Date(timestamp))}`);
// console.log(`slug=${slug} safeDate=${getSafeDate(new Date(timestamp))}`);
});
cal.paint(
{
itemSelector: `#${targetElementId}`,
scale: {
color: {
// @ts-ignore this shit is straight from the example website
domain: ['missing', 'issue', 'good'],
type: 'ordinal',
range: ['red', 'yellow', 'green']
}
},
theme: 'dark',
verticalOrientation: false,
data: {
source: data,
x: 'date',
y: 'value',
// @ts-ignore this shit is straight from the example website
groupY: d => d[0]
},
range: 12,
date: { start: data[0].date },
domain: {
type: 'month',
gutter: 4,
label: { text: 'MMM', textAlign: 'start', position: 'top' }
},
subDomain: {
type: 'ghDay',
radius: 2,
width: cellSize,
height: cellSize,
gutter: 4,
}
}, [
[
Tooltip,
{
text: ((ts: number, value: string, dayjsDate: dayjs.Dayjs) => {
return `${!!value ? value+' - '+dayjsDate.toString() : dayjsDate.toString() }`;
})
}
]
]);
}, [targetElementId, data, cellSize, router, slug]);
return (
<>
<div id={targetElementId}></div>
</>
)
}

View File

@ -83,7 +83,7 @@ export function Tagger({ vod, setTimestamps }: ITaggerProps): React.JSX.Element
if (authData?.accessToken) {
setIsAuthed(true);
}
}, [isAuthed]);
}, [isAuthed, authData]);
async function getRandomSuggestions() {

View File

@ -253,7 +253,7 @@ export default function UploadForm({ vtubers }: IUploadFormProps) {
{...register('vtuber')}
>
{vtubers.map((vtuber: IVtuber) => (
<option value={vtuber.id}>{vtuber.attributes.displayName}</option>
<option key={vtuber.id} value={vtuber.id}>{vtuber.attributes.displayName}</option>
))}
</select>
</div>

View File

@ -10,8 +10,8 @@ import LinkableHeading from './linkable-heading';
export function getVodTitle(vod: IVod): string {
console.log('lets getVodTitle, ey?')
console.log(JSON.stringify(vod, null, 2))
// console.log('lets getVodTitle, ey?')
// console.log(JSON.stringify(vod, null, 2))
return vod.attributes.title || vod.attributes.announceTitle || (vod.attributes?.date2 && vod.attributes?.vtuber?.data?.attributes?.displayName) ? `${vod.attributes.vtuber.data.attributes.displayName} ${vod.attributes.date2}` : `VOD ${vod.id}`;
}

View File

@ -1,11 +1,9 @@
import Tes from '@/assets/svg/tes';
export default async function Page() {
return (
<div className="content">
<div className="box">
<h2>Healthy!</h2>
<Tes></Tes>
</div>
</div>
)

View File

@ -1,7 +1,7 @@
// export const strapiUrl = (process.env.NODE_ENV === 'production') ? 'https://portal.futureporn.net' : 'https://chisel.sbtp:1337'
// export const siteUrl = (process.env.NODE_ENV === 'production') ? 'https://futureporn.net' : 'http://localhost:3000'
export const siteUrl = process.env.NEXT_PUBLIC_SITE_URL
export const strapiUrl = process.env.NEXT_PUBLIC_STRAPI_URL
export const siteUrl = ''+process.env.NEXT_PUBLIC_SITE_URL
export const strapiUrl = ''+process.env.NEXT_PUBLIC_STRAPI_URL
export const patreonSupporterBenefitId: string = '4760169'
export const patreonQuantumSupporterId: string = '10663202'
export const patreonVideoAccessBenefitId: string = '13462019'

View File

@ -1,70 +0,0 @@
import { getVtuberBySlug } from '@/lib/vtubers';
import { getAllStreamsForVtuber } from '@/lib/streams';
import NotFound from '../not-found';
import { DataRecord } from 'cal-heatmap/src/options/Options';
import { Cal } from '@/components/cal';
interface IPageProps {
params: {
slug: string;
};
}
function getArchiveStatusValue(archiveStatus: string): number {
if (archiveStatus === 'good') return 2;
if (archiveStatus === 'issue') return 1;
else return 0 // missing
}
function sortDataRecordsByDate(records: DataRecord[]) {
return records.sort((a, b) => {
if (typeof a.date === 'string' && typeof b.date === 'string') {
return a.date.localeCompare(b.date);
} else {
// Handle comparison when date is not a string (e.g., when it's a number)
// For instance, you might want to convert numbers to strings or use a different comparison logic.
// Example assuming number to string conversion:
return String(a.date).localeCompare(String(b.date));
}
});
}
export default async function Page({ params: { slug } }: IPageProps) {
const vtuber = await getVtuberBySlug(slug);
if (!vtuber) return <NotFound></NotFound>
const streams = await getAllStreamsForVtuber(vtuber.id);
const streamsByYear: { [year: string]: DataRecord[] } = {};
streams.forEach((stream) => {
const date = new Date(stream.attributes.date);
const year = date.getFullYear();
if (!streamsByYear[year]) {
streamsByYear[year] = [];
}
streamsByYear[year].push({
date: new Date(stream.attributes.date).toISOString(),
value: stream.attributes.archiveStatus,
});
});
// Sort the data records within each year's array
for (const year in streamsByYear) {
streamsByYear[year] = sortDataRecordsByDate(streamsByYear[year]);
}
return (
<div>
{Object.keys(streamsByYear).map((year) => {
return (
<div key={year} className='section'>
<h2 className='title'>{year}</h2>
{/* <pre><code>{JSON.stringify(streamsByYear[year], null, 2)}</code></pre> */}
<Cal slug={slug} data={streamsByYear[year]} />
</div>
)
})}
</div>
)
}

View File

@ -30,217 +30,218 @@ export default async function Page({ params }: { params: { slug: string } }) {
const vods = await getVodsForVtuber(vtuber.id, 1, 9);
if (!vods) notFound();
const missingStreams = await getAllStreamsForVtuber(vtuber.id, ['missing']);
const issueStreams = await getAllStreamsForVtuber(vtuber.id, ['issue']);
const goodStreams = await getAllStreamsForVtuber(vtuber.id, ['good']);
return '@todo'
// const missingStreams = await getAllStreamsForVtuber(vtuber.id, ['missing']);
// const issueStreams = await getAllStreamsForVtuber(vtuber.id, ['issue']);
// const goodStreams = await getAllStreamsForVtuber(vtuber.id, ['good']);
// // return (
// // <>
// // <p>hi mom!</p>
// // <pre>
// // <code>
// // {JSON.stringify(missingStreams, null, 2)}
// // </code>
// // </pre>
// // </>
// // )
// return (
// <>
// <p>hi mom!</p>
// <pre>
// <code>
// {JSON.stringify(missingStreams, null, 2)}
// </code>
// </pre>
// {vtuber && (
// <>
// <div className="box">
// <div className="columns is-multiline">
// <div className="column is-full">
// <h1 className="title is-2">{vtuber.attributes.displayName}</h1>
// </div>
// <div className="column is-one-quarter">
// <figure className="image is-rounded is-1by1">
// <Image
// className="is-rounded"
// alt={vtuber.attributes.displayName}
// src={vtuber.attributes.image}
// fill={true}
// placeholder='blur'
// blurDataURL={vtuber.attributes.imageBlur}
// />
// </figure>
// </div>
// <div className="column is-three-quarters">
// <p className="is-size-5 mb-3">{vtuber.attributes.description1}</p>
// <p className="is-size-5">{vtuber.attributes.description2}</p>
// </div>
// </div>
// <h2 id="socials" className="title is-3">
// <Link href="#socials">Socials</Link>
// </h2>
// <div className="column is-full mb-5">
// <div className="columns has-text-centered is-multiline is-centered">
// {vtuber.attributes.patreon && (
// <div className="column is-3 is-narrow">
// <Link href={vtuber.attributes.patreon} className="subtitle is-5">
// <span className="mr-2"><FontAwesomeIcon icon={faPatreon} className="fab fa-patreon" /></span><span className="mr-2">Patreon</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.twitter && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.twitter} className="subtitle is-5">
// <span className="mr-2"><FontAwesomeIcon icon={faXTwitter} className="fab fa-x-twitter" /></span><span className="mr-2">Twitter</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.youtube && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.youtube} className="subtitle is-5">
// <span className="mr-2"><FontAwesomeIcon icon={faYoutube} className="fab fa-youtube" /></span><span className="mr-2">YouTube</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.twitch && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.twitch} className="subtitle is-5">
// <span className="mr-2"><FontAwesomeIcon icon={faTwitch} className="fab fa-twitch" /></span><span className="mr-2">Twitch</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.tiktok && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.tiktok} className="subtitle is-5">
// <span className="mr-2"><FontAwesomeIcon icon={faTiktok} className="fab fa-tiktok" /></span><span className="mr-2">TikTok</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.fansly && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.fansly} className='subtitle is-5'>
// <span className='mr-2'><FanslyIcon width={20} height={20} className={styles.icon}/></span><span className="mr-2">Fansly</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.onlyfans && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.onlyfans} className='subtitle is-5'>
// <span className='mr-2'>
// <OnlyfansIcon width={20} height={20} className={styles.icon}></OnlyfansIcon>
// </span><span className="mr-2">OnlyFans</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.pornhub && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.pornhub} className='subtitle is-5'>
// <span className='mr-2'><PornhubIcon width={20} height={20} className={styles.icon}/></span><span className="mr-2">Pornhub</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.reddit && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.reddit} className="subtitle is-5">
// <span className="mr-2"><FontAwesomeIcon icon={faReddit} className="fab fa-reddit" /></span><span className="mr-2">Reddit</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.discord && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.discord} className="subtitle is-5">
// <span className="mr-2"><FontAwesomeIcon icon={faDiscord} className="fab fa-discord" /></span><span className="mr-2">Discord</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.instagram && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.instagram} className="subtitle is-5">
// <span className="mr-2"><FontAwesomeIcon icon={faInstagram} className="fab fa-instagram" /></span><span className="mr-2">Instagram</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.facebook && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.facebook} className="subtitle is-5">
// <span className="mr-2"><FontAwesomeIcon icon={faFacebook} className="fab fa-facebook" /></span><span className="mr-2">Facebook</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.merch && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.merch} className="subtitle is-5">
// <span className="mr-2"><FontAwesomeIcon icon={faBagShopping} className="fas fa-bag-shopping" /></span><span className="mr-2">Merch</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.chaturbate && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.chaturbate} className='subtitle is-5'>
// <span className='mr-2'><ChaturbateIcon width={20} className={styles.icon}/></span><span className="mr-2">Chaturbate</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.throne && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.throne} className='subtitle is-5'>
// <span className='mr-2'><ThroneIcon width={20} height={20} className={styles.icon}/></span><span className="mr-2">Throne</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.linktree && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.linktree} className='subtitle is-5'>
// <span className='mr-2'><LinktreeIcon width={20} height={20} className={styles.icon}/></span><span className="mr-2">Linktree</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// {vtuber.attributes.carrd && (
// <div className="column is-3 is-narrow">
// <Link target="_blank" href={vtuber.attributes.carrd} className='subtitle is-5'>
// <span className='mr-2'><CarrdIcon width={20} height={20} className={styles.icon}/></span><span className="mr-2">Carrd</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
// </Link>
// </div>
// )}
// </div>
// </div>
// {/* <h2 id="toys" className="title is-3">
// <Link href="#toys">Toys</Link>
// </h2>
// <>
// <ToysList vtuber={vtuber} toys={toys} page={1} pageSize={toySampleCount} />
// {(toys.pagination.total > toySampleCount) && <Link href={`/vt/${vtuber.slug}/toys/1`} className='button mb-5'>See all of {vtuber.displayName}'s toys</Link>}
// </> */}
// <h2 id="vods" className="title is-3">
// <Link href="#vods">Vods</Link>
// </h2>
// <VodsList vtuber={vtuber} vods={vods.data} page={1} pageSize={9} />
// {
// (vtuber.attributes.vods) ? (
// <Link className='button mb-5' href={`/vt/${vtuber.attributes.slug}/vods/1`}>See all {vtuber.attributes.displayName} vods</Link>
// ) : (<p className='section'><i>No VODs have been added, yet.</i></p>)
// }
// <h2 id="streams" className='title is-3'>
// <Link href="#streams">Streams</Link>
// </h2>
// <StreamsCalendar missingStreams={missingStreams} issueStreams={issueStreams} goodStreams={goodStreams} />
// {/*
// <h2 id="progress" className='title is-3'>
// <Link href="#progress">Archive Progress</Link>
// </h2>
// <ArchiveProgress vtuber={vtuber} /> */}
// </div>
// </>
// )
return (
<>
{vtuber && (
<>
<div className="box">
<div className="columns is-multiline">
<div className="column is-full">
<h1 className="title is-2">{vtuber.attributes.displayName}</h1>
</div>
<div className="column is-one-quarter">
<figure className="image is-rounded is-1by1">
<Image
className="is-rounded"
alt={vtuber.attributes.displayName}
src={vtuber.attributes.image}
fill={true}
placeholder='blur'
blurDataURL={vtuber.attributes.imageBlur}
/>
</figure>
</div>
<div className="column is-three-quarters">
<p className="is-size-5 mb-3">{vtuber.attributes.description1}</p>
<p className="is-size-5">{vtuber.attributes.description2}</p>
</div>
</div>
<h2 id="socials" className="title is-3">
<Link href="#socials">Socials</Link>
</h2>
<div className="column is-full mb-5">
<div className="columns has-text-centered is-multiline is-centered">
{vtuber.attributes.patreon && (
<div className="column is-3 is-narrow">
<Link href={vtuber.attributes.patreon} className="subtitle is-5">
<span className="mr-2"><FontAwesomeIcon icon={faPatreon} className="fab fa-patreon" /></span><span className="mr-2">Patreon</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.twitter && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.twitter} className="subtitle is-5">
<span className="mr-2"><FontAwesomeIcon icon={faXTwitter} className="fab fa-x-twitter" /></span><span className="mr-2">Twitter</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.youtube && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.youtube} className="subtitle is-5">
<span className="mr-2"><FontAwesomeIcon icon={faYoutube} className="fab fa-youtube" /></span><span className="mr-2">YouTube</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.twitch && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.twitch} className="subtitle is-5">
<span className="mr-2"><FontAwesomeIcon icon={faTwitch} className="fab fa-twitch" /></span><span className="mr-2">Twitch</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.tiktok && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.tiktok} className="subtitle is-5">
<span className="mr-2"><FontAwesomeIcon icon={faTiktok} className="fab fa-tiktok" /></span><span className="mr-2">TikTok</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.fansly && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.fansly} className='subtitle is-5'>
<span className='mr-2'><FanslyIcon width={20} height={20} className={styles.icon}/></span><span className="mr-2">Fansly</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.onlyfans && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.onlyfans} className='subtitle is-5'>
<span className='mr-2'>
<OnlyfansIcon width={20} height={20} className={styles.icon}></OnlyfansIcon>
</span><span className="mr-2">OnlyFans</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.pornhub && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.pornhub} className='subtitle is-5'>
<span className='mr-2'><PornhubIcon width={20} height={20} className={styles.icon}/></span><span className="mr-2">Pornhub</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.reddit && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.reddit} className="subtitle is-5">
<span className="mr-2"><FontAwesomeIcon icon={faReddit} className="fab fa-reddit" /></span><span className="mr-2">Reddit</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.discord && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.discord} className="subtitle is-5">
<span className="mr-2"><FontAwesomeIcon icon={faDiscord} className="fab fa-discord" /></span><span className="mr-2">Discord</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.instagram && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.instagram} className="subtitle is-5">
<span className="mr-2"><FontAwesomeIcon icon={faInstagram} className="fab fa-instagram" /></span><span className="mr-2">Instagram</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.facebook && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.facebook} className="subtitle is-5">
<span className="mr-2"><FontAwesomeIcon icon={faFacebook} className="fab fa-facebook" /></span><span className="mr-2">Facebook</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.merch && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.merch} className="subtitle is-5">
<span className="mr-2"><FontAwesomeIcon icon={faBagShopping} className="fas fa-bag-shopping" /></span><span className="mr-2">Merch</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.chaturbate && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.chaturbate} className='subtitle is-5'>
<span className='mr-2'><ChaturbateIcon width={20} className={styles.icon}/></span><span className="mr-2">Chaturbate</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.throne && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.throne} className='subtitle is-5'>
<span className='mr-2'><ThroneIcon width={20} height={20} className={styles.icon}/></span><span className="mr-2">Throne</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.linktree && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.linktree} className='subtitle is-5'>
<span className='mr-2'><LinktreeIcon width={20} height={20} className={styles.icon}/></span><span className="mr-2">Linktree</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
{vtuber.attributes.carrd && (
<div className="column is-3 is-narrow">
<Link target="_blank" href={vtuber.attributes.carrd} className='subtitle is-5'>
<span className='mr-2'><CarrdIcon width={20} height={20} className={styles.icon}/></span><span className="mr-2">Carrd</span><span><FontAwesomeIcon icon={faExternalLinkAlt} className="fas fa-external-link-alt" /></span>
</Link>
</div>
)}
</div>
</div>
{/* <h2 id="toys" className="title is-3">
<Link href="#toys">Toys</Link>
</h2>
<>
<ToysList vtuber={vtuber} toys={toys} page={1} pageSize={toySampleCount} />
{(toys.pagination.total > toySampleCount) && <Link href={`/vt/${vtuber.slug}/toys/1`} className='button mb-5'>See all of {vtuber.displayName}'s toys</Link>}
</> */}
<h2 id="vods" className="title is-3">
<Link href="#vods">Vods</Link>
</h2>
<VodsList vtuber={vtuber} vods={vods.data} page={1} pageSize={9} />
{
(vtuber.attributes.vods) ? (
<Link className='button mb-5' href={`/vt/${vtuber.attributes.slug}/vods/1`}>See all {vtuber.attributes.displayName} vods</Link>
) : (<p className='section'><i>No VODs have been added, yet.</i></p>)
}
<h2 id="streams" className='title is-3'>
<Link href="#streams">Streams</Link>
</h2>
<StreamsCalendar missingStreams={missingStreams} issueStreams={issueStreams} goodStreams={goodStreams} />
{/*
<h2 id="progress" className='title is-3'>
<Link href="#progress">Archive Progress</Link>
</h2>
<ArchiveProgress vtuber={vtuber} /> */}
</div>
</>
)}
</>
);
// )}
// </>
// );
}

View File

@ -1,5 +1,5 @@
import * as React from "react"
const SvgComponent = (props) => (
const SvgComponent = (props: any) => (
<svg
xmlns="http://www.w3.org/2000/svg"
xmlSpace="preserve"

View File

@ -43,7 +43,6 @@
"@uppy/remote-sources": "^1.1.0",
"bulma": "^0.9.4",
"bulma-prefers-dark": "0.1.0-beta.1",
"cal-heatmap": "^4.2.4",
"date-fns": "^2.0.0",
"date-fns-tz": "^2.0.0",
"dayjs": "^1.11.10",

View File

@ -41,8 +41,7 @@
"**/*.ts",
"**/*.tsx",
"dist/types/**/*.ts",
".next/types/**/*.ts",
"assets/svg/tes.jsx"
".next/types/**/*.ts"
],
"exclude": [
"node_modules"

View File

@ -129,9 +129,6 @@ importers:
bulma-prefers-dark:
specifier: 0.1.0-beta.1
version: 0.1.0-beta.1
cal-heatmap:
specifier: ^4.2.4
version: 4.2.4
date-fns:
specifier: ^2.0.0
version: 2.30.0
@ -1189,7 +1186,7 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
ajv: 6.12.6
debug: 4.3.4(supports-color@5.5.0)
debug: 4.3.4
espree: 9.6.1
globals: 13.24.0
ignore: 5.3.0
@ -1326,7 +1323,7 @@ packages:
engines: {node: '>=10.10.0'}
dependencies:
'@humanwhocodes/object-schema': 2.0.2
debug: 4.3.4(supports-color@5.5.0)
debug: 4.3.4
minimatch: 3.1.2
transitivePeerDependencies:
- supports-color
@ -1699,25 +1696,12 @@ packages:
fastq: 1.16.0
dev: true
/@observablehq/plot@0.6.13:
resolution: {integrity: sha512-ebQS4ENodOy+O3WUjhqv9jNPZENAZRQMIdO3ziOlAKfUzSf69+gaFAqqc04SGrQA6JwJjPYnbfeN3YIpNsCF/A==}
engines: {node: '>=12'}
dependencies:
d3: 7.8.5
interval-tree-1d: 1.0.4
isoformat: 0.2.1
dev: false
/@paralleldrive/cuid2@2.2.2:
resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==}
dependencies:
'@noble/hashes': 1.3.3
dev: false
/@popperjs/core@2.11.8:
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
dev: false
/@react-hookz/deep-equal@1.0.4:
resolution: {integrity: sha512-N56fTrAPUDz/R423pag+n6TXWbvlBZDtTehaGFjK0InmN+V2OFWLE/WmORhmn6Ce7dlwH5+tQN1LJFw3ngTJVg==}
dev: false
@ -2456,7 +2440,7 @@ packages:
'@typescript-eslint/types': 6.18.1
'@typescript-eslint/typescript-estree': 6.18.1(typescript@5.3.3)
'@typescript-eslint/visitor-keys': 6.18.1
debug: 4.3.4(supports-color@5.5.0)
debug: 4.3.4
eslint: 8.56.0
typescript: 5.3.3
transitivePeerDependencies:
@ -2487,7 +2471,7 @@ packages:
dependencies:
'@typescript-eslint/types': 6.18.1
'@typescript-eslint/visitor-keys': 6.18.1
debug: 4.3.4(supports-color@5.5.0)
debug: 4.3.4
globby: 11.1.0
is-glob: 4.0.3
minimatch: 9.0.3
@ -3137,10 +3121,6 @@ packages:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
engines: {node: '>=8'}
/binary-search-bounds@2.0.5:
resolution: {integrity: sha512-H0ea4Fd3lS1+sTEB2TgcLoK21lLhwEJzlQv3IN47pJS976Gx4zoWe0ak3q+uYh60ppQxg9F16Ri4tS1sfD4+jA==}
dev: false
/bintrees@1.0.2:
resolution: {integrity: sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==}
dev: false
@ -3312,20 +3292,6 @@ packages:
responselike: 2.0.1
dev: false
/cal-heatmap@4.2.4:
resolution: {integrity: sha512-TTNoQTRxHXrttOEbkraKv9vy2VpfQIwVLQJTlAfcBusQK9qrBL/UBO+WloAxv2yrR+P8URA2cuXEdc5iztER9g==}
dependencies:
'@observablehq/plot': 0.6.13
'@popperjs/core': 2.11.8
d3-color: 3.1.0
d3-fetch: 3.0.1
d3-selection: 3.0.0
d3-transition: 3.0.1(d3-selection@3.0.0)
dayjs: 1.11.10
eventemitter3: 5.0.1
lodash-es: 4.17.21
dev: false
/call-bind@1.0.5:
resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==}
dependencies:
@ -3440,11 +3406,6 @@ packages:
delayed-stream: 1.0.0
dev: false
/commander@7.2.0:
resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
engines: {node: '>= 10'}
dev: false
/common-tags@1.8.2:
resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==}
engines: {node: '>=4.0.0'}
@ -3555,254 +3516,6 @@ packages:
resolution: {integrity: sha512-tI+NjVRS485QlSxHeM3JIjdEZSJMLOZVp41/vvWukDmIkZSoYG9gLYl9GFZGBpY42UbRVo1eMlF7XkI/IiDHzQ==}
dev: false
/d3-array@3.2.4:
resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
engines: {node: '>=12'}
dependencies:
internmap: 2.0.3
dev: false
/d3-axis@3.0.0:
resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==}
engines: {node: '>=12'}
dev: false
/d3-brush@3.0.0:
resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==}
engines: {node: '>=12'}
dependencies:
d3-dispatch: 3.0.1
d3-drag: 3.0.0
d3-interpolate: 3.0.1
d3-selection: 3.0.0
d3-transition: 3.0.1(d3-selection@3.0.0)
dev: false
/d3-chord@3.0.1:
resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==}
engines: {node: '>=12'}
dependencies:
d3-path: 3.1.0
dev: false
/d3-color@3.1.0:
resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
engines: {node: '>=12'}
dev: false
/d3-contour@4.0.2:
resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==}
engines: {node: '>=12'}
dependencies:
d3-array: 3.2.4
dev: false
/d3-delaunay@6.0.4:
resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==}
engines: {node: '>=12'}
dependencies:
delaunator: 5.0.0
dev: false
/d3-dispatch@3.0.1:
resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==}
engines: {node: '>=12'}
dev: false
/d3-drag@3.0.0:
resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==}
engines: {node: '>=12'}
dependencies:
d3-dispatch: 3.0.1
d3-selection: 3.0.0
dev: false
/d3-dsv@3.0.1:
resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==}
engines: {node: '>=12'}
hasBin: true
dependencies:
commander: 7.2.0
iconv-lite: 0.6.3
rw: 1.3.3
dev: false
/d3-ease@3.0.1:
resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==}
engines: {node: '>=12'}
dev: false
/d3-fetch@3.0.1:
resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==}
engines: {node: '>=12'}
dependencies:
d3-dsv: 3.0.1
dev: false
/d3-force@3.0.0:
resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==}
engines: {node: '>=12'}
dependencies:
d3-dispatch: 3.0.1
d3-quadtree: 3.0.1
d3-timer: 3.0.1
dev: false
/d3-format@3.1.0:
resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==}
engines: {node: '>=12'}
dev: false
/d3-geo@3.1.0:
resolution: {integrity: sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==}
engines: {node: '>=12'}
dependencies:
d3-array: 3.2.4
dev: false
/d3-hierarchy@3.1.2:
resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==}
engines: {node: '>=12'}
dev: false
/d3-interpolate@3.0.1:
resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
engines: {node: '>=12'}
dependencies:
d3-color: 3.1.0
dev: false
/d3-path@3.1.0:
resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==}
engines: {node: '>=12'}
dev: false
/d3-polygon@3.0.1:
resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==}
engines: {node: '>=12'}
dev: false
/d3-quadtree@3.0.1:
resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==}
engines: {node: '>=12'}
dev: false
/d3-random@3.0.1:
resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==}
engines: {node: '>=12'}
dev: false
/d3-scale-chromatic@3.0.0:
resolution: {integrity: sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==}
engines: {node: '>=12'}
dependencies:
d3-color: 3.1.0
d3-interpolate: 3.0.1
dev: false
/d3-scale@4.0.2:
resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==}
engines: {node: '>=12'}
dependencies:
d3-array: 3.2.4
d3-format: 3.1.0
d3-interpolate: 3.0.1
d3-time: 3.1.0
d3-time-format: 4.1.0
dev: false
/d3-selection@3.0.0:
resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==}
engines: {node: '>=12'}
dev: false
/d3-shape@3.2.0:
resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==}
engines: {node: '>=12'}
dependencies:
d3-path: 3.1.0
dev: false
/d3-time-format@4.1.0:
resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==}
engines: {node: '>=12'}
dependencies:
d3-time: 3.1.0
dev: false
/d3-time@3.1.0:
resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==}
engines: {node: '>=12'}
dependencies:
d3-array: 3.2.4
dev: false
/d3-timer@3.0.1:
resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
engines: {node: '>=12'}
dev: false
/d3-transition@3.0.1(d3-selection@3.0.0):
resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==}
engines: {node: '>=12'}
peerDependencies:
d3-selection: 2 - 3
dependencies:
d3-color: 3.1.0
d3-dispatch: 3.0.1
d3-ease: 3.0.1
d3-interpolate: 3.0.1
d3-selection: 3.0.0
d3-timer: 3.0.1
dev: false
/d3-zoom@3.0.0:
resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==}
engines: {node: '>=12'}
dependencies:
d3-dispatch: 3.0.1
d3-drag: 3.0.0
d3-interpolate: 3.0.1
d3-selection: 3.0.0
d3-transition: 3.0.1(d3-selection@3.0.0)
dev: false
/d3@7.8.5:
resolution: {integrity: sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==}
engines: {node: '>=12'}
dependencies:
d3-array: 3.2.4
d3-axis: 3.0.0
d3-brush: 3.0.0
d3-chord: 3.0.1
d3-color: 3.1.0
d3-contour: 4.0.2
d3-delaunay: 6.0.4
d3-dispatch: 3.0.1
d3-drag: 3.0.0
d3-dsv: 3.0.1
d3-ease: 3.0.1
d3-fetch: 3.0.1
d3-force: 3.0.0
d3-format: 3.1.0
d3-geo: 3.1.0
d3-hierarchy: 3.1.2
d3-interpolate: 3.0.1
d3-path: 3.1.0
d3-polygon: 3.0.1
d3-quadtree: 3.0.1
d3-random: 3.0.1
d3-scale: 4.0.2
d3-scale-chromatic: 3.0.0
d3-selection: 3.0.0
d3-shape: 3.2.0
d3-time: 3.1.0
d3-time-format: 4.1.0
d3-timer: 3.0.1
d3-transition: 3.0.1(d3-selection@3.0.0)
d3-zoom: 3.0.0
dev: false
/damerau-levenshtein@1.0.8:
resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
dev: true
@ -3848,6 +3561,18 @@ packages:
ms: 2.1.3
dev: true
/debug@4.3.4:
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
engines: {node: '>=6.0'}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
dependencies:
ms: 2.1.2
dev: true
/debug@4.3.4(supports-color@5.5.0):
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
engines: {node: '>=6.0'}
@ -3897,12 +3622,6 @@ packages:
has-property-descriptors: 1.0.1
object-keys: 1.1.1
/delaunator@5.0.0:
resolution: {integrity: sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==}
dependencies:
robust-predicates: 3.0.2
dev: false
/delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
@ -4193,7 +3912,7 @@ packages:
eslint: '*'
eslint-plugin-import: '*'
dependencies:
debug: 4.3.4(supports-color@5.5.0)
debug: 4.3.4
enhanced-resolve: 5.15.0
eslint: 8.56.0
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.18.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0)
@ -4362,7 +4081,7 @@ packages:
ajv: 6.12.6
chalk: 4.1.2
cross-spawn: 7.0.3
debug: 4.3.4(supports-color@5.5.0)
debug: 4.3.4
doctrine: 3.0.0
escape-string-regexp: 4.0.0
eslint-scope: 7.2.2
@ -4986,13 +4705,6 @@ packages:
safer-buffer: 2.1.2
dev: false
/iconv-lite@0.6.3:
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
engines: {node: '>=0.10.0'}
dependencies:
safer-buffer: 2.1.2
dev: false
/ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
dev: false
@ -5046,17 +4758,6 @@ packages:
side-channel: 1.0.4
dev: true
/internmap@2.0.3:
resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
engines: {node: '>=12'}
dev: false
/interval-tree-1d@1.0.4:
resolution: {integrity: sha512-wY8QJH+6wNI0uh4pDQzMvl+478Qh7Rl4qLmqiluxALlNvl+I+o5x38Pw3/z7mDPTPS1dQalZJXsmbvxx5gclhQ==}
dependencies:
binary-search-bounds: 2.0.5
dev: false
/ipaddr.js@1.9.1:
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
engines: {node: '>= 0.10'}
@ -5262,10 +4963,6 @@ packages:
/isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
/isoformat@0.2.1:
resolution: {integrity: sha512-tFLRAygk9NqrRPhJSnNGh7g7oaVWDwR0wKh/GM2LgmPa50Eg4UfyaCO4I8k6EqJHl1/uh2RAD6g06n5ygEnrjQ==}
dev: false
/iterator.prototype@1.1.2:
resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==}
dependencies:
@ -5436,10 +5133,6 @@ packages:
p-locate: 5.0.0
dev: true
/lodash-es@4.17.21:
resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
dev: false
/lodash._baseiteratee@4.7.0:
resolution: {integrity: sha512-nqB9M+wITz0BX/Q2xg6fQ8mLkyfF7MU7eE+MNBNjTHFKeKaZAPEzEg+E8LWxKWf1DQVflNEn9N49yAuqKh2mWQ==}
dependencies:
@ -6495,20 +6188,12 @@ packages:
glob: 7.2.3
dev: true
/robust-predicates@3.0.2:
resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==}
dev: false
/run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
dependencies:
queue-microtask: 1.2.3
dev: true
/rw@1.3.3:
resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==}
dev: false
/safe-array-concat@1.0.1:
resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==}
engines: {node: '>=0.4'}