Browse Source

more stuff

main
Gisle Aune 4 years ago
parent
commit
c878c87e63
  1. 3
      next.config.js
  2. 3244
      package-lock.json
  3. 18
      package.json
  4. 18
      src/components/layout/Layout.module.sass
  5. 3
      src/components/layout/Layout.tsx
  6. 7
      src/components/layout/Sidebar.module.sass
  7. 14
      src/hooks/LogListContext.tsx
  8. 69
      src/lib/posts.ts
  9. 20
      src/pages/_error.tsx
  10. 56
      src/pages/index.tsx
  11. 62
      src/pages/logs/index.tsx
  12. 1
      src/styles/global.css

3
next.config.js

@ -5,5 +5,6 @@ const config = yaml.parse(fs.readFileSync("/etc/aiterp/rpdata-frontend2.yaml", {
module.exports = { module.exports = {
serverRuntimeConfig: config, serverRuntimeConfig: config,
publicRuntimeConfig: {}
publicRuntimeConfig: {},
trailingSlash: true,
} }

3244
package-lock.json
File diff suppressed because it is too large
View File

18
package.json

@ -13,11 +13,11 @@
"@fortawesome/free-regular-svg-icons": "^5.14.0", "@fortawesome/free-regular-svg-icons": "^5.14.0",
"@fortawesome/free-solid-svg-icons": "^5.14.0", "@fortawesome/free-solid-svg-icons": "^5.14.0",
"@fortawesome/react-fontawesome": "^0.1.11", "@fortawesome/react-fontawesome": "^0.1.11",
"date-fns": "^2.16.0",
"gql-compress": "^2.0.18",
"date-fns": "^2.16.1",
"gql-compress": "^2.0.20",
"gray-matter": "^4.0.2", "gray-matter": "^4.0.2",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"next": "9.3.5",
"next": "^9.5.3",
"next-auth": "^3.1.0", "next-auth": "^3.1.0",
"node-sass": "^4.14.1", "node-sass": "^4.14.1",
"react": "16.13.1", "react": "16.13.1",
@ -28,12 +28,12 @@
}, },
"devDependencies": { "devDependencies": {
"@types/jsonwebtoken": "^8.5.0", "@types/jsonwebtoken": "^8.5.0",
"@types/next-auth": "^3.1.1",
"@types/node": "^14.6.2",
"@types/react": "^16.9.48",
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"eslint": "^7.8.1",
"@types/next-auth": "^3.1.4",
"@types/node": "^14.10.2",
"@types/react": "^16.9.49",
"@typescript-eslint/eslint-plugin": "^4.1.1",
"@typescript-eslint/parser": "^4.1.1",
"eslint": "^7.9.0",
"eslint-config-google": "^0.14.0", "eslint-config-google": "^0.14.0",
"eslint-plugin-react": "^7.20.6", "eslint-plugin-react": "^7.20.6",
"typescript": "^4.0.2" "typescript": "^4.0.2"

18
src/components/layout/Layout.module.sass

@ -5,20 +5,4 @@
margin-left: 4ch margin-left: 4ch
width: calc(90% - 4ch) width: calc(90% - 4ch)
padding: 1rem 1rem padding: 1rem 1rem
.header
display: flex
flex-direction: column
align-items: center
.headerImage
width: 6rem
height: 6rem
.headerHomeImage
width: 8rem
height: 8rem
.backToHome
margin: 3rem 0 0
background: none

3
src/components/layout/Layout.tsx

@ -14,7 +14,7 @@ interface LayoutProps {
export default function Layout(props: LayoutProps) { export default function Layout(props: LayoutProps) {
return ( return (
<div className={styles.wrapper}> <div className={styles.wrapper}>
<MagicImage opacity={0.50} alignH="right" fixed src="https://files.aiterp.net/misc/renders/2020-08-30%20-%20Archive.jpg">
<MagicImage opacity={0.50} alignH="right" fixed src="https://files.aiterp.net/misc/renders/2020-08-30%20-%20Archive.jpg" />
<Sidebar /> <Sidebar />
<div className={styles.container}> <div className={styles.container}>
<Head> <Head>
@ -28,7 +28,6 @@ export default function Layout(props: LayoutProps) {
</Head> </Head>
<main>{props.children}</main> <main>{props.children}</main>
</div> </div>
</MagicImage>
</div> </div>
); );
} }

7
src/components/layout/Sidebar.module.sass

@ -16,11 +16,12 @@
.sidebarItemText .sidebarItemText
opacity: 1 opacity: 1
width: 16ch
div.sidebarItem div.sidebarItem
color: white color: white
padding-top: 0.333em padding-top: 0.333em
transition: 250ms
transition: 75ms
color: #333 color: #333
white-space: nowrap white-space: nowrap
@ -32,18 +33,20 @@ div.sidebarItem
background-color: #222 background-color: #222
color: #fc1 !important color: #fc1 !important
.sidebarItemIcon .sidebarItemIcon
display: inline-block display: inline-block
height: 2em height: 2em
width: 3.5ch width: 3.5ch
text-align: center text-align: center
transition: 75ms
.sidebarItemText .sidebarItemText
display: inline-block display: inline-block
vertical-align: top vertical-align: top
opacity: 0 opacity: 0
height: 2em height: 2em
margin-left: 1ch margin-left: 1ch
width: 0px
transition: 75ms
div.sidebarItemSkip div.sidebarItemSkip
margin: auto 0 0 0 margin: auto 0 0 0

14
src/hooks/LogListContext.tsx

@ -24,18 +24,26 @@ interface StaticLogListContextProviderProps {
} }
export function StaticLogListContextProvider(props: StaticLogListContextProviderProps) { export function StaticLogListContextProvider(props: StaticLogListContextProviderProps) {
const updateFilterCallback = useCallback((_) => {
throw new Error("StaticLogListContextProvider's filter cannot be updated");
}, []);
const refreshCallback = useCallback(() => {
throw new Error("StaticLogListContextProvider cannot be refreshed");
}, []);
return ( return (
<LogListContext.Provider value={{ <LogListContext.Provider value={{
filter: props.filter, filter: props.filter,
headers: props.header, headers: props.header,
updateFilter: (_) => {throw new Error("StaticLogListContextProvider's filter cannot be updated")},
refresh: () => {throw new Error("StaticLogListContextProvider cannot be refreshed")},
updateFilter: updateFilterCallback,
refresh: refreshCallback,
loading: false, loading: false,
error: null, error: null,
}}> }}>
{props.children} {props.children}
</LogListContext.Provider> </LogListContext.Provider>
)
);
} }
interface LogListContextProviderProps { interface LogListContextProviderProps {

69
src/lib/posts.ts

@ -1,69 +0,0 @@
import fs from "fs"
import path from "path"
import matter from "gray-matter"
import remark from "remark"
import html from "remark-html"
const postsDirectory = path.join(process.cwd(), "posts")
export function getSortedPostsData() {
// Get file names under /posts
const fileNames = fs.readdirSync(postsDirectory)
const allPostsData = fileNames.map(fileName => {
// Remove ".md" from file name to get id
const id = fileName.replace(/\.md$/, "")
// Read markdown file as string
const fullPath = path.join(postsDirectory, fileName)
const fileContents = fs.readFileSync(fullPath, "utf8")
// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents)
// Combine the data with the id
return {
id,
...(matterResult.data as { date: string; title: string })
}
})
// Sort posts by date
return allPostsData.sort((a, b) => {
if (a.date < b.date) {
return 1
} else {
return -1
}
})
}
export function getAllPostIds() {
const fileNames = fs.readdirSync(postsDirectory)
return fileNames.map(fileName => {
return {
params: {
id: fileName.replace(/\.md$/, "")
}
}
})
}
export async function getPostData(id: string) {
const fullPath = path.join(postsDirectory, `${id}.md`)
const fileContents = fs.readFileSync(fullPath, "utf8")
// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents)
// Use remark to convert markdown into HTML string
const processedContent = await remark()
.use(html)
.process(matterResult.content)
const contentHtml = processedContent.toString()
// Combine the data with the id and contentHtml
return {
id,
contentHtml,
...(matterResult.data as { date: string; title: string })
}
}

20
src/pages/_error.tsx

@ -0,0 +1,20 @@
import React from "react";
interface ErrorPageProps {
statusCode: number
};
export default function Error(props: ErrorPageProps) {
return (
<p>
{props.statusCode
? `An error ${props.statusCode} occurred on server`
: "An error occurred on client"}
</p>
)
}
export const getInitialProps = ({ res, err }) => {
const statusCode = res ? res.statusCode : err ? err.statusCode : 404
return { props: { statusCode } };
};

56
src/pages/index.tsx

@ -1,59 +1,11 @@
import React from "react"; import React from "react";
import { GetServerSideProps } from "next";
import Head from "next/head";
import { LogHeader, listLogs, LogFilter, logFilterFromQueryString } from "../lib/rpdata/logs";
import gqlSsrClient from "../lib/client/graphql-ssr";
import LogListContext, { LogListContextProvider } from "../hooks/LogListContext";
import { parse } from "url";
import { useContext, useEffect } from "react";
interface HomeProps {
headers: LogHeader[]
filter: LogFilter
interface HomePageProps {
}; };
export default function Home(props: HomeProps) {
export default function HomePage(props: HomePageProps) {
return ( return (
<LogListContextProvider initialFilter={props.filter} initialHeader={props.headers}>
<Head>
<title>Logs - Aite RP</title>
</Head>
<LogList />
</LogListContextProvider>
)
<></>
);
} }
function LogList() {
const {headers, filter, updateFilter} = useContext(LogListContext);
useEffect(() => {
const timeout = setTimeout(() => {
updateFilter({...filter, limit: 10});
}, 3000);
return () => clearTimeout(timeout);
}, [updateFilter])
return (
<>
<ol>
{headers.map(l => <li key={l.shortId}>{l.title || `${l.channelName}${l.date}`}</li>)}
</ol>
<pre>{JSON.stringify(filter, null, 4)}</pre>
</>
)
}
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const u = parse(ctx.req.url);
const filter = logFilterFromQueryString(u.search || "");
const headers = await listLogs(gqlSsrClient, filter)
return {
props: {
filter,
headers,
}
}
}

62
src/pages/logs/index.tsx

@ -0,0 +1,62 @@
import React, { useContext, useEffect } from "react";
import { parse } from "url";
import { GetServerSideProps } from "next";
import Head from "next/head";
import { LogHeader, listLogs, LogFilter, logFilterFromQueryString } from "../../lib/rpdata/logs";
import gqlSsrClient from "../../lib/client/graphql-ssr";
import LogListContext, { LogListContextProvider } from "../../hooks/LogListContext";
interface LogsPageProps {
headers: LogHeader[]
filter: LogFilter
};
export default function LogsPage(props: LogsPageProps) {
return (
<LogListContextProvider initialFilter={props.filter} initialHeader={props.headers}>
<Head>
<title>Logs - Aite RP</title>
</Head>
<LogList />
</LogListContextProvider>
);
}
function LogList() {
const {headers, filter, updateFilter} = useContext(LogListContext);
useEffect(() => {
const timeout = setTimeout(() => {
updateFilter({...filter, limit: 10});
}, 3000);
return () => clearTimeout(timeout);
}, [updateFilter]);
return (
<>
<ol>
{headers.map(l => <li key={l.shortId}>{l.title || `${l.channelName}${l.date}`}</li>)}
</ol>
<pre>{JSON.stringify(filter, null, 4)}</pre>
</>
);
}
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const u = parse(ctx.req.url);
const filter = logFilterFromQueryString(u.search || "");
const headers = await listLogs(gqlSsrClient, filter)
return {
props: {
filter,
headers,
},
};
}
export const experimental = {
trailingSlash: true
}

1
src/styles/global.css

@ -6,7 +6,6 @@ body {
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
line-height: 1.6; line-height: 1.6;
font-size: 18px; font-size: 18px;
background: #111922;
color: #abc; color: #abc;
} }

Loading…
Cancel
Save