From d2da853974fceade75252697f773fbefa08da07d Mon Sep 17 00:00:00 2001 From: Nick Grato Date: Mon, 29 Jul 2024 11:40:20 -0700 Subject: [PATCH 1/4] adding auth0 --- .dockerignore | 7 + .gitignore | 3 +- appserver/.prettierignore | 1 + appserver/app/api/auth/[auth0]/route.ts | 84 +++ appserver/app/layout.tsx | 45 ++ appserver/app/page.tsx | 12 + appserver/app/profile/page.tsx | 22 + appserver/hooks/useDarkMode.tsx | 23 + appserver/hooks/useMediaQuery.tsx | 65 ++ appserver/knex.ts | 5 + appserver/knexfile.js | 6 +- .../20240726181241_create_users_table.js | 17 + .../navigation/MainNav/MainNav.module.scss | 134 ++++ .../modules/navigation/MainNav/MainNav.tsx | 75 +++ appserver/package.json | 4 + appserver/src/knex.ts | 6 - appserver/src/pages/_app.tsx | 6 - appserver/src/pages/_document.tsx | 13 - appserver/src/pages/api/hello.ts | 13 - appserver/src/pages/index.tsx | 27 - appserver/src/styles/globals.css | 0 appserver/styles/core/boilerplate.scss | 20 + appserver/styles/core/theme.scss | 264 ++++++++ appserver/styles/core/variables.scss | 190 ++++++ appserver/styles/globals.scss | 72 +++ appserver/styles/tools/functions.scss | 4 + appserver/styles/tools/media-queries.scss | 115 ++++ appserver/styles/tools/mixins.scss | 190 ++++++ appserver/styles/tools/utility.scss | 592 ++++++++++++++++++ appserver/tsconfig.json | 36 +- appserver/types.d.ts | 22 + appserver/yarn.lock | 253 +++++++- compose.yaml | 2 +- env-dev | 2 + yarn.lock | 253 ++++++++ 35 files changed, 2505 insertions(+), 78 deletions(-) create mode 100644 .dockerignore create mode 100644 appserver/.prettierignore create mode 100644 appserver/app/api/auth/[auth0]/route.ts create mode 100644 appserver/app/layout.tsx create mode 100644 appserver/app/page.tsx create mode 100644 appserver/app/profile/page.tsx create mode 100644 appserver/hooks/useDarkMode.tsx create mode 100644 appserver/hooks/useMediaQuery.tsx create mode 100644 appserver/knex.ts create mode 100644 appserver/migrations/20240726181241_create_users_table.js create mode 100644 appserver/modules/navigation/MainNav/MainNav.module.scss create mode 100644 appserver/modules/navigation/MainNav/MainNav.tsx delete mode 100644 appserver/src/knex.ts delete mode 100644 appserver/src/pages/_app.tsx delete mode 100644 appserver/src/pages/_document.tsx delete mode 100644 appserver/src/pages/api/hello.ts delete mode 100644 appserver/src/pages/index.tsx delete mode 100644 appserver/src/styles/globals.css create mode 100644 appserver/styles/core/boilerplate.scss create mode 100644 appserver/styles/core/theme.scss create mode 100644 appserver/styles/core/variables.scss create mode 100644 appserver/styles/globals.scss create mode 100644 appserver/styles/tools/functions.scss create mode 100644 appserver/styles/tools/media-queries.scss create mode 100644 appserver/styles/tools/mixins.scss create mode 100644 appserver/styles/tools/utility.scss create mode 100644 appserver/types.d.ts create mode 100644 yarn.lock diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..175f95f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +node_modules +npm-debug.log +Dockerfile +.dockerignore +.git +.gitignore +.env \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3e2a180..d8d4afd 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,8 @@ node_modules .vscode *.swp *.swo -.env +# local env files +.env*.local # credentials .*.json diff --git a/appserver/.prettierignore b/appserver/.prettierignore new file mode 100644 index 0000000..536d88c --- /dev/null +++ b/appserver/.prettierignore @@ -0,0 +1 @@ +.next/ diff --git a/appserver/app/api/auth/[auth0]/route.ts b/appserver/app/api/auth/[auth0]/route.ts new file mode 100644 index 0000000..0635f78 --- /dev/null +++ b/appserver/app/api/auth/[auth0]/route.ts @@ -0,0 +1,84 @@ +// import { UserService } from "@/services/UserService"; + +import { + handleAuth, + handleCallback, + handleLogin, + Session, + updateSession, +} from "@auth0/nextjs-auth0"; +import { NextRequest } from "next/server"; + +// const afterCallback = async ( +// req: NextRequest, +// session: Session +// ): Promise => { +// if (!session) { +// throw new Error("Unable to authenticate user"); +// } + +// const { user } = session; +// const { sub, email_verified, email } = user; +// const storedUser = await UserService.getByAccountProviderId(sub); + +// if (storedUser) { +// const newSession = { +// ...session, +// user: { ...user, id: storedUser.id, username: storedUser.username }, +// }; + +// await updateSession(newSession); +// return newSession; +// //create user record +// } + +// const providerData = { +// id_token: session.idToken, +// refresh_token: session.refreshToken, +// access_token: session.accessToken, +// access_token_expires: session.accessTokenExpiresAt, +// provider: "auth0", +// provider_account_id: user.sub, +// }; + +// const newUser = await UserService.create( +// { +// email_verified, +// email, +// }, +// providerData +// ); + +// if (newUser) { +// const newSession = { +// ...session, +// user: { ...user, id: newUser.id, username: newUser.username }, +// }; +// await updateSession(newSession); +// return newSession; +// } +// throw new Error("Unable to authenticate user"); +// }; + +export const GET = handleAuth({ + login: handleLogin((req) => { + return { + returnTo: "/", + }; + }), + signup: handleLogin({ + authorizationParams: { + screen_hint: "signup", + }, + returnTo: "/profile", + }), + signIn: handleLogin({ + authorizationParams: { + screen_hint: "signin", + }, + returnTo: "/profile", + }), + callback: handleCallback((req) => { + return { redirectUri: "http://localhost:3000" }; + }), +}); diff --git a/appserver/app/layout.tsx b/appserver/app/layout.tsx new file mode 100644 index 0000000..2883c4e --- /dev/null +++ b/appserver/app/layout.tsx @@ -0,0 +1,45 @@ +import "../styles/globals.scss"; +import "react-element-forge/dist/style.css"; +import { Inter, Space_Grotesk } from "next/font/google"; +import { UserProvider } from "@auth0/nextjs-auth0/client"; +import MainNav from "@Modules/navigation/MainNav/MainNav"; +import { getSession } from "@auth0/nextjs-auth0"; + +const inter = Inter({ + variable: "--inter-font", + subsets: ["latin"], + display: "swap", + preload: true, +}); + +const space_grotesk = Space_Grotesk({ + variable: "--space_grotesk-font", + subsets: ["latin"], + display: "swap", + preload: true, +}); + +export default async function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + const session = await getSession(); + const user = session?.user; + + return ( + + + + + + + +
+ + {children} + +
+ + ); +} diff --git a/appserver/app/page.tsx b/appserver/app/page.tsx new file mode 100644 index 0000000..cf569d5 --- /dev/null +++ b/appserver/app/page.tsx @@ -0,0 +1,12 @@ +import { getSession } from "@auth0/nextjs-auth0"; + +export default async function Page() { + const session = await getSession(); + const user = session?.user; + console.log("user", user); + return ( +
+ Login +
+ ); +} diff --git a/appserver/app/profile/page.tsx b/appserver/app/profile/page.tsx new file mode 100644 index 0000000..6433575 --- /dev/null +++ b/appserver/app/profile/page.tsx @@ -0,0 +1,22 @@ +import { getSession } from '@auth0/nextjs-auth0' +// import { useUser } from "@auth0/nextjs-auth0/client"; +import { redirect } from 'next/navigation' + +export default async function Page() { + const session = await getSession() + const user = session?.user + + if (!user) { + redirect('/') + } + console.log('user', user.sub) + + return user ? ( +
+

Hi {user.name}

+ Logout +
+ ) : ( +
No user found
+ ) +} diff --git a/appserver/hooks/useDarkMode.tsx b/appserver/hooks/useDarkMode.tsx new file mode 100644 index 0000000..e769522 --- /dev/null +++ b/appserver/hooks/useDarkMode.tsx @@ -0,0 +1,23 @@ +import { useState, useEffect } from 'react'; + +const useDarkMode = () => { + const [darkMode, setDarkMode] = useState(false); + + const eventHandler = (event: MediaQueryListEvent) => { + setDarkMode(event.matches); + }; + + useEffect(() => { + const darkmodeQuery = window.matchMedia('(prefers-color-scheme: dark)'); + setDarkMode(darkmodeQuery.matches); + darkmodeQuery.addEventListener('change', eventHandler); + + return () => { + darkmodeQuery.removeEventListener('change', eventHandler); + }; + }, []); + + return darkMode; +}; + +export default useDarkMode; diff --git a/appserver/hooks/useMediaQuery.tsx b/appserver/hooks/useMediaQuery.tsx new file mode 100644 index 0000000..6e6811f --- /dev/null +++ b/appserver/hooks/useMediaQuery.tsx @@ -0,0 +1,65 @@ +import { useState, useEffect } from 'react'; +const mobileBreak = 580; +const tabletBreak = 768; +const desktopBreak = 1024; + +/** + * React Hook Media Queries are used when you need to track window size outside of the SCSS ecosystem. + * Simply import hook and use its boolean response to track if a specific media query is being met. This can + * be used to add or remove a CSS class or render or remove a component in the JSX. + */ + +/** + * Base MediaQuery Hook + * + * Use this hook to create custom media query hooks. Please use pre-calibrated hooks below (ie 'useMobileDown' ) unless + * absolutely necessary to create your own hook. + * @param query + * @returns + */ +const useMediaQuery = (query: string) => { + const [matches, setMatches] = useState(false); + + useEffect(() => { + const media = window.matchMedia(query); + if (media.matches !== matches) { + setMatches(media.matches); + } + const listener = () => setMatches(media.matches); + window.addEventListener('resize', listener); + return () => window.removeEventListener('resize', listener); + }, [matches, query]); + + return matches; +}; + +export default useMediaQuery; + +/** + * Mobile + */ +export const useMobileDown = () => { + return useMediaQuery(`(max-width: ${mobileBreak}px)`); +}; + +/** + * Tablet + */ +export const useTabletDown = () => { + return useMediaQuery(`(max-width: ${tabletBreak}px)`); +}; + +export const useTabletUp = () => { + return useMediaQuery(`(min-width: ${tabletBreak}px)`); +}; + +/** + * Desktop + */ +export const useDesktopDown = () => { + return useMediaQuery(`(max-width: ${desktopBreak}px)`); +}; + +export const usDesktopUp = () => { + return useMediaQuery(`(min-width: ${desktopBreak}px)`); +}; diff --git a/appserver/knex.ts b/appserver/knex.ts new file mode 100644 index 0000000..1d3de00 --- /dev/null +++ b/appserver/knex.ts @@ -0,0 +1,5 @@ +import config from './knexfile.js' +import Knex from 'knex' + +const _knex = Knex(config) +export default _knex diff --git a/appserver/knexfile.js b/appserver/knexfile.js index 094d198..541799d 100644 --- a/appserver/knexfile.js +++ b/appserver/knexfile.js @@ -1,6 +1,6 @@ const config = { - client: "pg", + client: 'pg', connection: process.env.DATABASE_URL, -}; +} -module.exports = config; +module.exports = config diff --git a/appserver/migrations/20240726181241_create_users_table.js b/appserver/migrations/20240726181241_create_users_table.js new file mode 100644 index 0000000..02ecfc9 --- /dev/null +++ b/appserver/migrations/20240726181241_create_users_table.js @@ -0,0 +1,17 @@ +exports.up = function (knex) { + return knex.schema.createTable('users', function (table) { + table.string('id').primary() + table.string('given_name').notNullable() + table.string('nickname').notNullable() + table.string('name').notNullable() + table.string('picture').notNullable() + table.timestamp('updated_at').notNullable() + table.string('email').notNullable().unique() + table.boolean('email_verified').notNullable() + table.string('sid').notNullable() + }) +} + +exports.down = function (knex) { + return knex.schema.dropTable('users') +} diff --git a/appserver/modules/navigation/MainNav/MainNav.module.scss b/appserver/modules/navigation/MainNav/MainNav.module.scss new file mode 100644 index 0000000..3efb446 --- /dev/null +++ b/appserver/modules/navigation/MainNav/MainNav.module.scss @@ -0,0 +1,134 @@ +@use "styles/core/boilerplate" as *; + +.main_nav { + width: 100%; + box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.25); + position: fixed; + z-index: 2; + top: 0; + + &_wrapper { + height: 80px; + width: 100%; + padding: 20px; + display: flex; + justify-content: center; + background: $color-background-reverse; + + @include tablet-down { + padding: 10px; + } + } + + &_container { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + max-width: $container-max-width; + } + + &_contents { + display: flex; + align-items: center; + } + + &_links { + margin-left: 50px; + display: flex; + } + + &_link { + @include navigation-link; + margin-right: 40px; + } + + &_account { + display: flex; + margin: 10px; + } + + &_actions { + @include mobile-down { + display: none; + } + } +} + +.mobile { + &_menu { + display: none; + margin-right: 20px; + + @include tablet-down { + display: block; + } + } +} + +/*********************** + ANNOUNCEMENT BANNER +***********************/ + +.banner { + &_gradient { + padding: 4px 12px; + background: $gradient-warm; + } + + &_text { + padding: 4px; + display: flex; + justify-content: center; + @include mobile-down { + white-space: nowrap; + overflow-y: scroll; + scrollbar-width: none; + justify-content: flex-start; + + &::-webkit-scrollbar { + display: none; + width: 0 !important; + } + } + + p { + text-align: center; + } + } +} + +.marquee { + &_container { + display: flex; + justify-content: center; + align-items: center; + @include mobile-down { + padding: 20px; + } + } + + & section { + @include mobile-down { + display: inline-block; + padding-left: 100%; + animation: marquee 20s linear infinite; + } + } + + @include mobile-down { + white-space: nowrap; + overflow: hidden; + position: absolute; + width: 100vw; + } +} + +@keyframes marquee { + 0% { + transform: translate(0, 0); + } + 100% { + transform: translate(-100%, 0); + } +} diff --git a/appserver/modules/navigation/MainNav/MainNav.tsx b/appserver/modules/navigation/MainNav/MainNav.tsx new file mode 100644 index 0000000..0c2cd76 --- /dev/null +++ b/appserver/modules/navigation/MainNav/MainNav.tsx @@ -0,0 +1,75 @@ +import { useCallback, useState } from "react"; +import styles from "./MainNav.module.scss"; +import { Button, Icon, Modal, LinkComponentT } from "react-element-forge"; +import { NavigationT } from "types"; +import Link from "next/link"; +import { Claims } from "@auth0/nextjs-auth0"; + +type MainNavPropsT = { + navData?: NavigationT; + mobileMenuClick?: () => void; + user?: Claims; + className?: string; +}; + +const MainNav = ({ + navData, + mobileMenuClick, + user, + className = "", +}: MainNavPropsT) => { + return ( + <> + + + ); +}; + +export default MainNav; diff --git a/appserver/package.json b/appserver/package.json index 786f88c..6538537 100644 --- a/appserver/package.json +++ b/appserver/package.json @@ -9,10 +9,12 @@ "lint": "next lint" }, "dependencies": { + "@auth0/nextjs-auth0": "^3.5.0", "@types/node": "18.15.11", "@types/react": "18.0.34", "@types/react-dom": "18.0.11", "autoprefixer": "10.4.14", + "axios": "^1.7.2", "eslint": "8.38.0", "eslint-config-next": "13.3.0", "knex": "^2.4.2", @@ -21,6 +23,8 @@ "postcss": "8.4.31", "react": "18.2.0", "react-dom": "18.2.0", + "react-element-forge": "0.0.7", + "sass": "^1.77.8", "typescript": "5.0.4" } } diff --git a/appserver/src/knex.ts b/appserver/src/knex.ts deleted file mode 100644 index c4b788e..0000000 --- a/appserver/src/knex.ts +++ /dev/null @@ -1,6 +0,0 @@ -import Knex from 'knex'; -import config from '@/../knexfile.js'; - -const knex = Knex(config); - -export default knex; diff --git a/appserver/src/pages/_app.tsx b/appserver/src/pages/_app.tsx deleted file mode 100644 index 021681f..0000000 --- a/appserver/src/pages/_app.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import '@/styles/globals.css' -import type { AppProps } from 'next/app' - -export default function App({ Component, pageProps }: AppProps) { - return -} diff --git a/appserver/src/pages/_document.tsx b/appserver/src/pages/_document.tsx deleted file mode 100644 index 54e8bf3..0000000 --- a/appserver/src/pages/_document.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { Html, Head, Main, NextScript } from 'next/document' - -export default function Document() { - return ( - - - -
- - - - ) -} diff --git a/appserver/src/pages/api/hello.ts b/appserver/src/pages/api/hello.ts deleted file mode 100644 index f8bcc7e..0000000 --- a/appserver/src/pages/api/hello.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Next.js API route support: https://nextjs.org/docs/api-routes/introduction -import type { NextApiRequest, NextApiResponse } from 'next' - -type Data = { - name: string -} - -export default function handler( - req: NextApiRequest, - res: NextApiResponse -) { - res.status(200).json({ name: 'John Doe' }) -} diff --git a/appserver/src/pages/index.tsx b/appserver/src/pages/index.tsx deleted file mode 100644 index 403b2a0..0000000 --- a/appserver/src/pages/index.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import knex from "@/knex"; - -export default function Home({ dbResult }: { dbResult: string }) { - return ( -
-
-

Appserver hello world from Next.js

-

database query result: {dbResult}

-
-
- ); -} - -// export async function getServerSideProps() { -// let dbResult; -// if (process.env.FLAG_USE_DB === "true") { -// try { -// dbResult = await knex('dummy_records').first(); -// dbResult = dbResult ? JSON.stringify(dbResult) : 'no rows found'; -// } catch (e: unknown) { -// dbResult = `db error: ${String(e)}`; -// } -// } else { -// dbResult = "FLAG_USE_DB is false"; -// } -// return { props: { dbResult } }; -// } diff --git a/appserver/src/styles/globals.css b/appserver/src/styles/globals.css deleted file mode 100644 index e69de29..0000000 diff --git a/appserver/styles/core/boilerplate.scss b/appserver/styles/core/boilerplate.scss new file mode 100644 index 0000000..d1d669b --- /dev/null +++ b/appserver/styles/core/boilerplate.scss @@ -0,0 +1,20 @@ +/* + + Boilerplate is a collection of all the SCSS partials + that do not output CSS when compiled. + + Include this file in components to pull in theme + variables, functions, and mixins for use in scoped + styling. + + TODO : Break this up better so that variables/mixins/function are being imported to css modules only + and utility classes and styles are being imported to the global style sheet so that in + the TSX code we can use utilities there... + +*/ + +// tools +@forward './variables'; +@forward '../tools/functions'; +@forward '../tools/media-queries'; +@forward '../tools/mixins'; diff --git a/appserver/styles/core/theme.scss b/appserver/styles/core/theme.scss new file mode 100644 index 0000000..eed1d3b --- /dev/null +++ b/appserver/styles/core/theme.scss @@ -0,0 +1,264 @@ +:root { + --font-primary: var(--inter-font); + --font-seondary: var(--space_grotesk-font); + --font-secondary: var(--space_grotesk-font); + + /** + BUTTON + **/ + --button-font-size: 0.875rem; + --button-font-weight: 500; + --button-border-radius: 20px; + --button-border-stroke: 2px; + --button-padding-large: 12px 18px; + --button-padding-large-round: 12px; + --button-padding-medium: 8px 16px; + --button-padding-medium-round: 8px; + --button-padding-small: 6px 12px; + --button-padding-small-round: 6px; + + /** + COPY BUTTON + **/ + --copy-button-font-size: 0.875rem; + --copy-button-font-weight: 500; + + /** + CHECKBOX + **/ + --checkbox-label-font-size: 0.875rem; + --checkbox-label-font-weight: 500; + + /** + INPUTS + **/ + --input-label-font-size: 0.875rem; + --input-label-font-weight: 600; + --input-font-size: 0.875rem; + --input-info-font-size: 0.875rem; + --input-border-radius: 12px; + --input-padding: 12px; + + /** + DROPDOWN + **/ + --dropdown-margin-top: 12px; + --dropdown-border-radius: 4px; + + /** + BADGE + **/ + --badge-font-size: 0.875rem; + --badge-font-weight: 500; + --badge-padding: 5px 12px; + --badge-border-radius: 56px; + --badge-line-height: 26px; + --badge-line-height: 26px; + + /** + RADIO + **/ + --radio-label-font-size: 0.875rem; + --radio-label-font-weight: 500; + + /** + SWITCH + **/ + --switch-font-weight: 500; + + /** + TOOLTIP + **/ + --tooltip-font-size: 0.875rem; + --tooltip-font-weight: 500; + --tooltip-width: 250px; +} + +div[data-theme="buzz"] { + --font-primary: var(--inter-font); + --font-seondary: var(--space_grotesk-font); + --font-secondary: var(--space_grotesk-font); + --color-interaction-primary: #e36d28; + --color-interaction-primary-hover: #aa4810; + + --color-background-neutral-0: #101010; + + --color-neutral-0: #101010; + + --color-text-main: #bcbcbc; + + --color-background-subtle-callout: #2d2d2d; + + --color-border-1: #272727; + + --button-border-radius: 10px; +} + +div[data-theme="chat"] { + --font-primary: var(--inter-font); + --font-seondary: var(--space_grotesk-font); + --font-secondary: var(--space_grotesk-font); + + --color-interaction-primary: #00de9b; + --color-interaction-primary-active: #00de9b; + --color-interaction-primary-hover: rgb(104, 199, 105); + --color-logo: rgb(93, 135, 89); + + --color-background-neutral-0: #242f37; + + --color-background-overlay: #181717; + + --color-neutral-0: #101010; + + --color-text-main: #f3f3f3; + --color-text-reverse: #101010; + + --color-background-subtle-callout: #162129; + + --color-border-1: #878787; + + --button-border-radius: 10px; + + /** + BUTTONS + **/ + --button-font-size: 0.875rem; + --button-font-weight: 500; + --button-border-stroke: 2px; + --button-border-radius: 6px; + --button-padding-large: 12px 18px; + --button-padding-large-round: 12px; + --button-padding-medium: 4px 8px; + --button-padding-medium-round: 4px; + --button-padding-small: 6px 12px; + --button-padding-small-round: 6px; +} + +main[data-theme="zebra"], +:root { + --font-primary: var(--inter-font); + --font-seondary: var(--space_grotesk-font); + --font-secondary: var(--space_grotesk-font); + /** + BRAND COLORS + **/ + --color-brand-1: #5b40ae; + --color-brand-2: #383838; + + /** + PRIMARY INTERACTION + **/ + --color-interaction-primary: #8912c9; + --color-interaction-primary-hover: #170696; + --color-interaction-primary-active: #170696; + --color-interaction-primary-disabled: rgba(176, 176, 176, 0.5); + --color-interaction-primary-alt: #ffffff; + --color-interaction-primary-alt-hover: #e8effd; + --color-interaction-primary-alt-active: #cbd8f0; + --color-interaction-primary-alt-disabled: #e7e7e7; + + /** + SECONDARY INTERACTION + **/ + --color-interaction-secondary: #ffffff; + --color-interaction-secondary-hover: #d3d3d3; + --color-interaction-secondary-active: #ccccd1; + --color-interaction-secondary-disabled: rgba(176, 176, 176, 0.5); + --color-interaction-secondary-alt: #ffffff; + --color-interaction-secondary-alt-hover: #e8e8e8; + --color-interaction-secondary-alt-active: #d9d9d9; + --color-interaction-secondary-alt-disabled: #e7e7e7; + + /** + SEMANTIC + **/ + --color-semantic-info: #0073bd; + --color-semantic-info-hover: #1c84cc; + --color-semantic-info-active: #3895d8; + --color-semantic-disabled: #6f6f6f; + --color-semantic-success: #009465; + --color-semantic-success-hover: #229a60; + --color-semantic-success-active: #39ab74; + --color-semantic-success-disabled: #767676; + --color-semantic-warning: #a86500; + --color-semantic-warning-hover: #b8771c; + --color-semantic-warning-active: #c78938; + --color-semantic-warning-disabled: #747474; + --color-semantic-critical: #d32947; + --color-semantic-critical-hover: #de3a57; + --color-semantic-critical-active: #e84d68; + --color-semantic-critical-disabled: #6e6e6e; + --color-semantic-critical-bg-alt: #f9e1e5; + --color-semantic-neutral: #222222; + --color-semantic-neutral-hover: #3a3a3a; + --color-semantic-neutral-active: #535353; + --color-semantic-neutral-inactive: #6e6e6e; + + /** + TEXT + **/ + --color-text-main: #000000; + --color-text-subtle: #757575; + --color-text-reverse: #ffffff; + --color-text-reverse-subtle: #e7e7e7; + --color-text-disabled: #b0b0b0; + --color-text-info: #000000; + --color-text-success: #000000; + --color-text-warning: #000000; + --color-text-critical: #000000; + + /** + BORDER + **/ + --color-border-1: #e6e6e6; + --color-border-2: #cacaca; + + /** + NEUTRALS + **/ + --color-neutral-0: #ffffff; + --color-neutral-0-reverse: #000000; + --color-neutral-1: #f5f5f5; + --color-neutral-2: #ededed; + --color-neutral-3: #e7e7e7; + + /** + STATUS + **/ + --color-status-ready: #7ed320; + --color-status-offline: #ada7a8; + --color-status-busy: #f19b53; + + /** + BACKGROUNDS + **/ + --color-background-overlay: rgba(23, 10, 122, 0.4); + --color-background-subtle-callout: #e8effd; + --color-background-modal-overlay: rgba(0, 0, 0, 0.3); + --color-background-neutral-0: #ffffff; + --color-background-reverse: #000000; + --color-background-reverse-alt: #262626; + --color-background-critical: #f9e1e5; + --color-background-chat-outgoing: #1b85ee; + --color-background-chat-incomming: #242f37; + + /** + MENU + **/ + --color-interactions-menu: #000000; + --color-interactions-menu-hover: #2f2f2f; + --color-interactions-menu-inactive: #757575; + + --button-border-radius: 10px; + + /** + LAYOUT + **/ + + --max-container-width: 1800px; + + /** + BADGE + **/ + --badge-line-height: 26px; +} diff --git a/appserver/styles/core/variables.scss b/appserver/styles/core/variables.scss new file mode 100644 index 0000000..c734244 --- /dev/null +++ b/appserver/styles/core/variables.scss @@ -0,0 +1,190 @@ +// ----------------- +// Font Setup +// ----------------- +$font-size-base: 16; // base size in px +$primary-font: var(--inter-font); +$secondary-font: var(--space_grotesk-font); +$backup-font: "Times New Roman"; + +/** + BRAND COLORS +**/ +$color-brand-1: var(--color-brand-1); +$color-brand-2: var(--color-brand-2); +$color-logo: var(--color-logo); + +/** + PRIMARY INTERACTION +**/ +$color-interaction-primary: var(--color-interaction-primary); +$color-interaction-primary-hover: var(--color-interaction-primary-hover); +$color-interaction-primary-active: var(--color-interaction-primary-active); +$color-interaction-primary-disabled: var(--color-interaction-primary-disabled); +$color-interaction-primary-alt: var(--color-interaction-primary-alt); +$color-interaction-primary-alt-hover: var( + --color-interaction-primary-alt-hover +); +$color-interaction-primary-alt-active: var( + --color-interaction-primary-alt-active +); +$color-interaction-primary-alt-disabled: var( + --color-interaction-primary-alt-disabled +); + +/** + SECONDARY INTERACTION +**/ +$color-interaction-secondary: var(--color-interaction-secondary); +$color-interaction-secondary-hover: var(--color-interaction-secondary-hover); +$color-interaction-secondary-active: var(--color-interaction-secondary-active); +$color-interaction-secondary-disabled: var( + --color-interaction-secondary-disabled +); +$color-interaction-secondary-alt: var(--color-interaction-secondary-alt); +$color-interaction-secondary-alt-hover: var( + --color-interaction-secondary-alt-hover +); +$color-interaction-secondary-alt-active: var( + --color-interaction-secondary-alt-active +); +$color-interaction-secondary-alt-disabled: var( + --color-interaction-secondary-alt-disabled +); + +/** + SEMANTIC +**/ +$color-semantic-info: var(--color-semantic-info); +$color-semantic-info-hover: var(--color-semantic-info-hover); +$color-semantic-info-active: var(--color-semantic-info-active); +$color-semantic-disabled: var(--color-semantic-disabled); +$color-semantic-success: var(--color-semantic-success); +$color-semantic-success-hover: var(--color-semantic-success-hover); +$color-semantic-success-active: var(--color-semantic-success-active); +$color-semantic-success-disabled: var(--color-semantic-success-disabled); +$color-semantic-warning: var(--color-semantic-warning); +$color-semantic-warning-hover: var(--color-semantic-warning-hover); +$color-semantic-warning-active: var(--color-semantic-warning-active); +$color-semantic-warning-disabled: var(--color-semantic-warning-disabled); +$color-semantic-critical: var(--color-semantic-critical); +$color-semantic-critical-hover: var(--color-semantic-critical-hover); +$color-semantic-critical-active: var(--color-semantic-critical-active); +$color-semantic-critical-disabled: var(--color-semantic-critical-disabled); +$color-semantic-critical-bg-alt: var(--color-semantic-critical-bg-alt); +$color-semantic-neutral: var(--color-semantic-neutral); +$color-semantic-neutral-hover: var(--color-semantic-neutral-hover); +$color-semantic-neutral-active: var(--color-semantic-neutral-active); +$color-semantic-neutral-inactive: var(--color-semantic-neutral-inactive); + +/** + TEXT +**/ +$color-text-main: var(--color-text-main); +$color-text-subtle: var(--color-text-subtle); +$color-text-reverse: var(--color-text-reverse); +$color-text-reverse-subtle: var(--color-text-reverse-subtle); +$color-text-disabled: var(--color-text-disabled); +$color-text-info: var(--color-text-info); +$color-text-success: var(--color-text-success); +$color-text-warning: var(--color-text-warning); +$color-text-critical: var(--color-text-critical); + +/** + BORDER +**/ +$color-border-1: var(--color-border-1); +$color-border-2: var(--color-border-2); + +/** + NEUTRALS +**/ +$color-neutral-0: var(--color-neutral-0); +$color-neutral-0-reverse: var(--color-neutral-0-reverse); +$color-neutral-1: var(--color-neutral-1); +$color-neutral-2: var(--color-neutral-2); +$color-neutral-3: var(--color-neutral-3); + +/** + STATUS +**/ +$color-status-ready: var(--color-status-ready); +$color-status-offline: var(--color-status-offline); +$color-status-busy: var(--color-status-busy); + +/** + BACKGROUNDS +**/ +$color-background-overlay: var(--color-background-overlay); +$color-background-subtle-callout: var(--color-background-subtle-callout); +$color-background-modal-overlay: var(--color-background-modal-overlay); +$color-background-neutral-0: var(--color-background-neutral-0); +$color-background-critical: var(--color-background-critical); +$color-background-reverse: var(--color-background-reverse); +$color-background-reverse-alt: var(--color-background-reverse-alt); +$color-background-chat-outgoing: var(--color-background-chat-outgoing); +$color-background-chat-incomming: var(--color-background-chat-incomming); + +/** + MENU +**/ +$color-interactions-menu: var(--color-interactions-menu); +$color-interactions-menu-hover: var(--color-interactions-menu-hover); +$color-interactions-menu-inactive: var(--color-interactions-menu-inactive); + +/** + LAYOUT +**/ +$max-container-width: var(--max-container-width); + +// ---- Primary Brand Colors --------------------- +$black: #231f20; +$dark-teal: #1c7f8d; +$blue: #0d73a6; +$light-blue: #e0f5ff; +$link-blue: #007ab8; +$purple: #663df5; +$gradient-warm: linear-gradient(270deg, #ff806f 0%, #ffff98 100%); +$gradient-rainbow: linear-gradient( + 107.97deg, + #489cbe 6.73%, + #5427c9 39.4%, + #a8527c 77.18%, + #a67878 104.75% +); +$gradient-cool: linear-gradient(90deg, #6ae1d9 0%, #9898ff 100%); + +// ---- Accent Colors --------------------- +$teal: #23a2b3; +$light-teal: rgba($teal, 0.1); +$pink: #d83a94; +$blue-neon: #4d4dff; +$yellow-neon: #f1ea57; +$peach: #d96868; +$tan: #e5dfd8; + +// ---- Utility Colors --------------------- +$white: #ffffff; +$off-white: #ddd; +$grey: #868686; +$accent-grey: #e0e0e0; +$form-gray: #c9c9c9; +$semi-dark-grey: #767474; +$dark-grey: #393536; +$red: #d42828; +$green: #3dc278; +$loading-grey: #f8f8f8; +$light-grey: #f5f5f5; + +// ---- Break Points --------------------- +$breakpoint-mobile: 580px; +$breakpoint-tablet: 768px; +$breakpoint-tablet-large: 992px; +$breakpoint-desktop: 1024px; +$breakpoint-desktop-large: 1220px; +$breakpoint-hd: 1312px; +$container-max-width: 1200px; + +// ---- Misc --------------------- +$drop-shadow: 0 3px 8px rgba($black, 0.3); +$drop-shadow-right: 3px 3px 8px rgba($black, 0.3); +$drop-shadow-light: 0 3px 8px rgba($black, 0.05); diff --git a/appserver/styles/globals.scss b/appserver/styles/globals.scss new file mode 100644 index 0000000..cf9e761 --- /dev/null +++ b/appserver/styles/globals.scss @@ -0,0 +1,72 @@ +@use "./core/boilerplate.scss" as *; +@use "./core/theme.scss" as *; +@use "./tools/utility.scss" as *; + +html, +body { + @include primary-font(); + padding: 0; + margin: 0; + font-size: 16px; + color: $color-text-reverse; + background-color: $color-background-reverse-alt; +} + +a { + color: inherit; + text-decoration: none; +} + +fieldset { + padding: 0; + border: 0; +} + +h1, +h2, +h3, +h4, +h5, +h6, +p { + margin: 0px; +} + +* { + box-sizing: border-box; +} + +button { + background: transparent; + border: 0; +} + +/** +GLOBAL PAGE STYLES +**/ +.page_wrapper { + display: flex; + flex: 1; + flex-direction: column; + min-height: calc(100vh - 532px); + margin-top: 80px; +} + +hr { + border: none; + height: 2px; + background: $gradient-rainbow; + margin: 20px auto; +} + +.markdown { + h1 { + @include heading-md; + margin-bottom: 12px; + } + h2 { + @include heading-xxs; + margin-bottom: 12px; + // line-height: px; + } +} diff --git a/appserver/styles/tools/functions.scss b/appserver/styles/tools/functions.scss new file mode 100644 index 0000000..9181afe --- /dev/null +++ b/appserver/styles/tools/functions.scss @@ -0,0 +1,4 @@ +@function rem($size) { + $rem-size: $size / 16; + @return #{$rem-size}rem; +} diff --git a/appserver/styles/tools/media-queries.scss b/appserver/styles/tools/media-queries.scss new file mode 100644 index 0000000..e02fdee --- /dev/null +++ b/appserver/styles/tools/media-queries.scss @@ -0,0 +1,115 @@ +@use '../core/variables' as *; + +@mixin mobile-to-tablet { + @media (min-width: 600px) and (max-width: 1000px) { + @content; + } +} + +@mixin mobile-down { + @media (max-width: $breakpoint-mobile) { + @content; + } +} + +@mixin mobile-up { + @media (min-width: $breakpoint-mobile) { + @content; + } +} + +@mixin mobile-only { + @media (max-width: $breakpoint-tablet - 1) { + @content; + } +} + +@mixin mobile-tablet { + @media (max-width: $breakpoint-desktop - 1) { + @content; + } +} + +@mixin tablet-up { + @media (min-width: $breakpoint-tablet) { + @content; + } +} + +@mixin tablet-down { + @media (max-width: $breakpoint-tablet) { + @content; + } +} + +@mixin tablet-large-up { + @media (min-width: $breakpoint-tablet-large) { + @content; + } +} + +@mixin tablet-large-down { + @media (max-width: $breakpoint-tablet-large) { + @content; + } +} + +@mixin tablet-only { + @media (min-width: $breakpoint-tablet) and (max-width: $breakpoint-desktop - 1) { + @content; + } +} + +@mixin desktop-up { + @media (min-width: $breakpoint-desktop) { + @content; + } +} + +@mixin desktop-only { + @media (min-width: $breakpoint-desktop) and (max-width: $breakpoint-hd - 1) { + @content; + } +} + +@mixin desktop-down { + @media (max-width: $breakpoint-desktop) { + @content; + } +} + +@mixin desktop-large-up { + @media (min-width: $breakpoint-desktop-large) { + @content; + } +} + +@mixin desktop-large-only { + @media (min-width: $breakpoint-desktop-large) and (max-width: $breakpoint-hd - 1) { + @content; + } +} + +@mixin desktop-large-down { + @media (max-width: $breakpoint-desktop-large) { + @content; + } +} + +@mixin desktop-large-to-tablet { + @media (min-width: $breakpoint-tablet) and (max-width: $breakpoint-desktop-large) { + @content; + } +} + +@mixin hd-up { + @media (min-width: $breakpoint-hd) { + @content; + } +} + +@mixin max-width-up { + @media (min-width: $container-max-width) { + @content; + } +} diff --git a/appserver/styles/tools/mixins.scss b/appserver/styles/tools/mixins.scss new file mode 100644 index 0000000..f1777df --- /dev/null +++ b/appserver/styles/tools/mixins.scss @@ -0,0 +1,190 @@ +@use '../core/variables.scss' as *; +@use '../tools/media-queries.scss' as *; +@use '../tools/functions.scss' as *; + +/*------------------------------- + TYPOGRAPHY STYLES +-------------------------------*/ +@mixin font-size($size: 16) { + -font-size-: $size; + font-size: rem($size); +} + +@mixin primary-font($weight: 600) { + font-family: $primary-font, $backup-font; + font-weight: $weight; +} + +@mixin secondary-font($weight: 700) { + font-family: $secondary-font, $backup-font; + font-weight: $weight; +} + +/*------------------------------- + HEADLINE STYLES +-------------------------------*/ +@mixin heading-xxl { + @include font-size(40); + @include secondary-font(700); + line-height: 51px; + + @include tablet-down { + @include font-size(28.8); + line-height: 37px; + } +} + +@mixin heading-xl { + @include font-size(36); + @include secondary-font(700); + line-height: 46px; + + @include tablet-down { + @include font-size(25.6); + line-height: 33px; + } +} + +@mixin heading-lg { + @include font-size(32); + @include secondary-font(700); + line-height: 41px; + + @include tablet-down { + @include font-size(24); + line-height: 31px; + } +} + +@mixin heading-md { + @include font-size(28); + @include secondary-font(700); + line-height: 36px; + + @include tablet-down { + @include font-size(21); + line-height: 27px; + } +} + +@mixin heading-sm { + @include font-size(24); + @include secondary-font(700); + line-height: 31px; + + @include tablet-down { + @include font-size(19.2); + line-height: 24px; + } +} + +@mixin heading-xs { + @include font-size(20); + @include secondary-font(700); + line-height: 26px; +} + +@mixin heading-xxs { + @include font-size(16); + @include secondary-font(700); + line-height: 20px; +} + +/*------------------------------- + PARAGRPH STYLES +-------------------------------*/ +@mixin paragraph { + @include font-size(18); + @include primary-font(500); + line-height: 150%; +} + +@mixin paragraph-sm { + @include font-size(16); + @include primary-font(500); + line-height: 150%; +} + +/*------------------------------- + BODY STYLES +-------------------------------*/ +@mixin body-lg($weight: 700) { + @include font-size(14); + @include primary-font($weight); + line-height: 21px; + letter-spacing: 0; + + @include tablet-up { + @include font-size(16); + line-height: 24px; + letter-spacing: 0; + } +} + +@mixin body-md { + @include primary-font(500); + @include font-size(16); + line-height: 24px; + + @include tablet-down { + @include font-size(14); + } +} + +@mixin body-md-bold { + @include primary-font(700); + @include font-size(16); + line-height: 24px; +} + +@mixin body-sm { + @include font-size(14); + @include primary-font(400); + letter-spacing: 0; + line-height: 25px; +} + +@mixin body-sm-bold { + @include font-size(14); + @include primary-font(700); + letter-spacing: 0; + line-height: 25px; +} + +@mixin body-xs { + @include font-size(10); + @include primary-font(300); + line-height: 13px; +} + +@mixin navigation-link { + @include font-size(16); + @include secondary-font(700); + color: $color-text-reverse; + padding-bottom: 0; + text-decoration: none; +} + +@mixin primary-link { + @include primary-font(500); + @include font-size(16); + line-height: 24px; + color: $color-interaction-primary; + text-decoration-line: underline; +} + +/*------------------------------- + UTILITY MIXINS +-------------------------------*/ +@mixin size($size) { + height: #{$size}px; + width: #{$size}px; +} + +@mixin webkit($attr, $time, $type) { + -webkit-transition: $attr $time $type; + -moz-transition: $attr $time $type; + -o-transition: $attr $time $type; + -ms-transition: $attr $time $type; + transition: $attr $time $type; +} diff --git a/appserver/styles/tools/utility.scss b/appserver/styles/tools/utility.scss new file mode 100644 index 0000000..64d322a --- /dev/null +++ b/appserver/styles/tools/utility.scss @@ -0,0 +1,592 @@ +@use '../tools/media-queries.scss' as *; +@use '../tools/mixins.scss' as *; +@use '../core/variables.scss' as *; + +// --------------------------------- +// Quick Typograpjhy +// --------------------------------- +.font-12 { + @include font-size(12); +} + +.font-14 { + @include font-size(14); +} + +.font-16 { + @include font-size(16); +} + +.font-18 { + @include font-size(18); +} + +.capitalize { + text-transform: capitalize; +} + +// Body Text +.body-md { + @include body-md(); +} + +.body-md-bold { + @include body-md-bold(); +} + +.body-sm { + @include body-sm(); +} + +.body-sm-bold { + @include body-sm-bold(); +} + +// paragraph +.paragraph { + @include paragraph(); +} + +.paragraph-sm { + @include paragraph-sm(); +} + +// Link +.primary-link { + @include primary-link(); +} + +// Heading +.heading-xxl { + @include heading-xxl(); +} + +.heading-xl { + @include heading-xl(); +} + +.heading-lg { + @include heading-lg(); +} + +.heading-md { + @include heading-md(); +} + +.heading-sm { + @include heading-sm(); +} + +.heading-xs { + @include heading-xs(); +} + +.heading-xxs { + @include heading-xxs(); +} + +// --------------------------------- +// Colors +// --------------------------------- +.color-text-reverse { + color: $color-text-reverse; +} + +.color-text-main { + color: $color-text-main; +} + +.color-logo { + color: $color-logo; +} + +.color-interaction-primary { + color: $color-interaction-primary; +} + +.color-semantic-success { + color: $color-semantic-success; +} + +.background-neutral { + background: $color-background-neutral-0; +} + +.background-rainbow { + background: $gradient-rainbow; +} + +// --------------------------------- +// Visibility +// --------------------------------- + +.hidden { + display: none !important; +} + +.hidden-mobile-only { + @include mobile-only { + display: none !important; + } +} + +.hidden-tablet-up { + @include tablet-up { + display: none !important; + } +} + +.hidden-tablet-only { + @include tablet-only { + display: none !important; + } +} + +.hidden-desktop-up { + @include desktop-up { + display: none !important; + } +} + +.hidden-desktop-only { + @include desktop-only { + display: none !important; + } +} + +.hidden-hd-up { + @include hd-up { + display: none !important; + } +} + +// --------------------------------- +// Misc +// --------------------------------- + +.z-1 { + z-index: 1; +} + +.z-2 { + z-index: 2; +} + +.z-3 { + z-index: 3; +} + +.z-4 { + z-index: 4; +} + +.z-5 { + z-index: 5; +} + +.sr-only { + border: 0 !important; + clip: rect(1px, 1px, 1px, 1px) !important; + -webkit-clip-path: inset(50%) !important; + clip-path: inset(50%) !important; + height: 1px !important; + margin: -1px !important; + overflow: hidden !important; + padding: 0 !important; + position: absolute !important; + width: 1px !important; + white-space: nowrap !important; +} + +.clear-button { + cursor: pointer; + border: none; + background-color: transparent; + display: inline-block; + margin: 0; + padding: 0; +} + +.pointer { + cursor: pointer; +} + +.no-link { + &, + &:hover { + text-decoration: none; + color: inherit; + } +} + +.opacity { + &-20 { + opacity: 0.2; + } +} + +.overflow-x-hidden { + overflow-x: hidden; +} + +.text-center { + text-align: center; +} + +.text-right { + text-align: right; +} + +.text-left { + text-align: left; +} + +.uppercase { + text-transform: uppercase; +} + +.title-case { + text-transform: capitalize; +} + +.left-absolute { + position: absolute; + left: 0; +} + +.right-absolute { + position: absolute; + right: 0; +} + +.width-100 { + width: 100%; +} + +.content-box { + &, + & * { + box-sizing: content-box; + } +} + +.flex { + &-column { + display: flex; + + flex-direction: column; + } + + &-space { + &-between { + display: flex; + justify-content: space-between; + } + } + + &-justify { + &-end { + display: flex; + justify-content: flex-end; + } + } +} + +.justify { + &-end { + display: flex; + justify-content: flex-end; + } + &-between { + display: flex; + justify-content: space-between; + } +} + +.items { + &-center { + display: flex; + align-items: center; + } +} + +.z-1 { + z-index: 1; +} + +// Create Size Value Array +$start: 0; +$end: 50; +$array: ''; +$unit: 'px'; +$array: set-nth($array, 1, $start); + +@for $i from $start + 1 through $end { + $array: append($array, $i, comma); +} + +@each $size in $array { + .gap-#{$size} { + display: flex; + gap: #{$size}#{$unit}; + &-dt { + @include mobile-up { + display: flex; + gap: #{$size}#{$unit}; + } + } + &-mb { + @include mobile-down { + display: flex; + gap: #{$size}#{$unit}; + } + } + } +} + +// --------------------------------- +// Layout +// --------------------------------- + +// Create Size Value Array +$start: 0; +$end: 100; +$array: ''; +$unit: 'px'; + +@for $i from $start + 1 through $end { + $array: append($array, $i, comma); + $array: set-nth($array, 1, $start); +} + +@each $size in $array { + /** + PADDING + **/ + + // Padding: General + .p-#{$size} { + padding: #{$size}#{$unit}; + &-dt-px { + @include mobile-up { + padding: #{$size}#{$unit}; + } + } + &-mb-px { + @include mobile-down { + padding: #{$size}#{$unit}; + } + } + } + + // Padding: Horizontal + .px-#{$size} { + padding-left: #{$size}#{$unit}; + padding-right: #{$size}#{$unit}; + &-dt-px { + @include mobile-up { + padding-left: #{$size}#{$unit}; + padding-right: #{$size}#{$unit}; + } + } + &-mb-px { + @include mobile-down { + padding-left: #{$size}#{$unit}; + padding-right: #{$size}#{$unit}; + } + } + } + + // Padding: Vertical + .py-#{$size} { + padding-top: #{$size}#{$unit}; + padding-bottom: #{$size}#{$unit}; + &-dt-px { + @include mobile-up { + padding-top: #{$size}#{$unit}; + padding-bottom: #{$size}#{$unit}; + } + } + &-mb-px { + @include mobile-down { + padding-top: #{$size}#{$unit}; + padding-bottom: #{$size}#{$unit}; + } + } + } + + // Padding: Top + .pt-#{$size} { + padding-top: #{$size}#{$unit}; + &-dt-px { + @include mobile-up { + padding-top: #{$size}#{$unit}; + } + } + &-mb-px { + @include mobile-down { + padding-top: #{$size}#{$unit}; + } + } + } + + // Padding: bottom + .pb-#{$size} { + padding-bottom: #{$size}#{$unit}; + &-dt-px { + @include mobile-up { + padding-bottom: #{$size}#{$unit}; + } + } + &-mb-px { + @include mobile-down { + padding-bottom: #{$size}#{$unit}; + } + } + } + + // Padding: Right + .pr-#{$size} { + padding-right: #{$size}#{$unit}; + &-dt-px { + @include mobile-up { + padding-right: #{$size}#{$unit}; + } + } + &-mb-px { + @include mobile-down { + padding-right: #{$size}#{$unit}; + } + } + } + + // Padding: Left + .pl-#{$size} { + padding-left: #{$size}#{$unit}; + &-dt-px { + @include mobile-up { + padding-left: #{$size}#{$unit}; + } + } + &-mb-px { + @include mobile-down { + padding-left: #{$size}#{$unit}; + } + } + } + + /** + MARGIN + **/ + + // Margin: General + .m-#{$size} { + margin: #{$size}#{$unit}; + &-dt-px { + @include mobile-up { + margin: #{$size}#{$unit}; + } + } + &-mb-px { + @include mobile-down { + margin: #{$size}#{$unit}; + } + } + } + + // Margin: Horizontal + .mx-#{$size} { + margin-left: #{$size}#{$unit}; + margin-right: #{$size}#{$unit}; + &-dt-px { + @include mobile-up { + margin-left: #{$size}#{$unit}; + margin-right: #{$size}#{$unit}; + } + } + &-mb-px { + @include mobile-down { + margin-left: #{$size}#{$unit}; + margin-right: #{$size}#{$unit}; + } + } + } + + // Margin: Vertical + .my-#{$size} { + margin-top: #{$size}#{$unit}; + margin-bottom: #{$size}#{$unit}; + &-dt-px { + @include mobile-up { + margin-top: #{$size}#{$unit}; + margin-bottom: #{$size}#{$unit}; + } + } + &-mb-px { + @include mobile-down { + margin-top: #{$size}#{$unit}; + margin-bottom: #{$size}#{$unit}; + } + } + } + + // Margin: Top + .mt-#{$size} { + margin-top: #{$size}#{$unit}; + &-dt-px { + @include mobile-up { + margin-top: #{$size}#{$unit}; + } + } + &-mb-px { + @include mobile-down { + margin-top: #{$size}#{$unit}; + } + } + } + + // Margin: Top + .mb-#{$size} { + margin-bottom: #{$size}#{$unit}; + &-dt-px { + @include mobile-up { + margin-bottom: #{$size}#{$unit}; + } + } + &-mb-px { + @include mobile-down { + margin-bottom: #{$size}#{$unit}; + } + } + } + + // Margin: Right + .mr-#{$size} { + margin-right: #{$size}#{$unit}; + &-dt-px { + @include mobile-up { + margin-right: #{$size}#{$unit}; + } + } + &-mb-px { + @include mobile-down { + margin-right: #{$size}#{$unit}; + } + } + } + + // Margin: Left + .ml-#{$size} { + margin-left: #{$size}#{$unit}; + &-dt-px { + @include mobile-up { + margin-left: #{$size}#{$unit}; + } + } + &-mb-px { + @include mobile-down { + margin-left: #{$size}#{$unit}; + } + } + } +} diff --git a/appserver/tsconfig.json b/appserver/tsconfig.json index 61c19ab..28c1926 100644 --- a/appserver/tsconfig.json +++ b/appserver/tsconfig.json @@ -1,7 +1,11 @@ { "compilerOptions": { "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -14,10 +18,34 @@ "isolatedModules": true, "jsx": "preserve", "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "baseUrl": ".", "paths": { - "@/*": ["./src/*"] + "@Shared/*": [ + "components/shared/*" + ], + "@Navigation/*": [ + "modules/navigation/*" + ], + "@Modules/*": [ + "modules/*" + ], + "@Modals/*": [ + "modals/*" + ] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], - "exclude": ["node_modules"] + "include": [ + "appserver/**/*.ts", + "appserver/**/*.tsx", + "next-env.d.ts", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] } diff --git a/appserver/types.d.ts b/appserver/types.d.ts new file mode 100644 index 0000000..c525c2c --- /dev/null +++ b/appserver/types.d.ts @@ -0,0 +1,22 @@ +export type NavigationT = { + bannerText: string; + links: LinkT; +}; + +export type LinkT = { + href: string; + label: string; + text: string; +}; + +export type UserT = { + given_name: string; + nickname: string; + name: string; + picture: string; + updated_at: string; + email: string; + email_verified: boolean; + sub: string; + sid: string; +}; diff --git a/appserver/yarn.lock b/appserver/yarn.lock index 9d289c8..b5c23da 100644 --- a/appserver/yarn.lock +++ b/appserver/yarn.lock @@ -2,6 +2,21 @@ # yarn lockfile v1 +"@auth0/nextjs-auth0@^3.5.0": + version "3.5.0" + resolved "https://registry.yarnpkg.com/@auth0/nextjs-auth0/-/nextjs-auth0-3.5.0.tgz#f596d641cba7a96b924481fda384e7feb811bb26" + integrity sha512-uFZEE2QQf1zU+jRK2fwqxRQt+WSqDPYF2tnr7d6BEa7b6L6tpPJ3evzoImbWSY1a7gFdvD7RD/Rvrsx7B5CKVg== + dependencies: + "@panva/hkdf" "^1.0.2" + cookie "^0.6.0" + debug "^4.3.4" + joi "^17.6.0" + jose "^4.9.2" + oauth4webapi "^2.3.0" + openid-client "^5.2.1" + tslib "^2.4.0" + url-join "^4.0.1" + "@babel/runtime@^7.20.7": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673" @@ -41,6 +56,18 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.38.0.tgz#73a8a0d8aa8a8e6fe270431c5e72ae91b5337892" integrity sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g== +"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== + +"@hapi/topo@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" + integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + dependencies: + "@hapi/hoek" "^9.0.0" + "@humanwhocodes/config-array@^0.11.8": version "0.11.8" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" @@ -138,6 +165,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@panva/hkdf@^1.0.2": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@panva/hkdf/-/hkdf-1.2.1.tgz#cb0d111ef700136f4580349ff0226bf25c853f23" + integrity sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw== + "@pkgr/utils@^2.3.1": version "2.3.1" resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.3.1.tgz#0a9b06ffddee364d6642b3cd562ca76f55b34a03" @@ -155,6 +187,23 @@ resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz#8be36a1f66f3265389e90b5f9c9962146758f728" integrity sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg== +"@sideway/address@^4.1.5": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" + integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" + integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + "@swc/helpers@0.5.2": version "0.5.2" resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.2.tgz#85ea0c76450b61ad7d10a37050289eded783c27d" @@ -274,6 +323,14 @@ ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -346,6 +403,11 @@ ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + autoprefixer@10.4.14: version "10.4.14" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.14.tgz#e28d49902f8e759dd25b153264e862df2705f79d" @@ -368,6 +430,15 @@ axe-core@^4.6.2: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.6.3.tgz#fc0db6fdb65cc7a80ccf85286d91d64ababa3ece" integrity sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg== +axios@^1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" + integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + axobject-query@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.1.1.tgz#3b6e5c6d4e43ca7ba51c5babf99d22a9c68485e1" @@ -380,6 +451,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -388,7 +464,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== @@ -443,6 +519,21 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +"chokidar@>=3.0.0 <4.0.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + client-only@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" @@ -465,6 +556,13 @@ colorette@2.0.19: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + commander@^9.1.0: version "9.5.0" resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" @@ -475,6 +573,11 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +cookie@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== + cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -549,6 +652,11 @@ define-properties@^1.1.3, define-properties@^1.1.4: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -957,6 +1065,11 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== +follow-redirects@^1.15.6: + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -964,6 +1077,15 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + fraction.js@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950" @@ -974,6 +1096,11 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -1026,7 +1153,7 @@ getopts@2.3.0: resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.3.0.tgz#71e5593284807e03e2427449d4f6712a268666f4" integrity sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA== -glob-parent@^5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -1174,6 +1301,11 @@ ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== +immutable@^4.0.0: + version "4.3.7" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" + integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== + import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -1238,6 +1370,13 @@ is-bigint@^1.0.1: dependencies: has-bigints "^1.0.1" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-boolean-object@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" @@ -1275,7 +1414,7 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -1391,6 +1530,22 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +joi@^17.6.0: + version "17.13.3" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec" + integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA== + dependencies: + "@hapi/hoek" "^9.3.0" + "@hapi/topo" "^5.1.0" + "@sideway/address" "^4.1.5" + "@sideway/formula" "^3.0.1" + "@sideway/pinpoint" "^2.0.0" + +jose@^4.15.5, jose@^4.9.2: + version "4.15.9" + resolved "https://registry.yarnpkg.com/jose/-/jose-4.15.9.tgz#9b68eda29e9a0614c042fa29387196c7dd800100" + integrity sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA== + js-sdsl@^4.1.4: version "4.4.0" resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430" @@ -1497,6 +1652,13 @@ loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -1510,6 +1672,18 @@ micromatch@^4.0.4: braces "^3.0.2" picomatch "^2.3.1" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -1570,16 +1744,31 @@ node-releases@^2.0.8: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + normalize-range@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== +oauth4webapi@^2.3.0: + version "2.11.1" + resolved "https://registry.yarnpkg.com/oauth4webapi/-/oauth4webapi-2.11.1.tgz#8d79e6b0d54ead203094f185a11031f3f9978465" + integrity sha512-aNzOnL98bL6izG97zgnZs1PFEyO4WDVRhz2Pd066NPak44w5ESLRCYmJIyey8avSBPOMtBjhF3ZDDm7bIb7UOg== + object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== +object-hash@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" + integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== + object-inspect@^1.12.3, object-inspect@^1.9.0: version "1.12.3" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" @@ -1643,6 +1832,11 @@ object.values@^1.1.6: define-properties "^1.1.4" es-abstract "^1.20.4" +oidc-token-hash@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz#9a229f0a1ce9d4fc89bcaee5478c97a889e7b7b6" + integrity sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw== + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -1659,6 +1853,16 @@ open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" +openid-client@^5.2.1: + version "5.6.5" + resolved "https://registry.yarnpkg.com/openid-client/-/openid-client-5.6.5.tgz#c149ad07b9c399476dc347097e297bbe288b8b00" + integrity sha512-5P4qO9nGJzB5PI0LFlhj4Dzg3m4odt0qsJTfyEtZyOlkgpILwEioOhVVJOrS1iVH494S4Ee5OCjjg6Bf5WOj3w== + dependencies: + jose "^4.15.5" + lru-cache "^6.0.0" + object-hash "^2.2.0" + oidc-token-hash "^5.0.3" + optionator@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" @@ -1778,7 +1982,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -1833,6 +2037,11 @@ prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + punycode@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" @@ -1851,6 +2060,11 @@ react-dom@18.2.0: loose-envify "^1.1.0" scheduler "^0.23.0" +react-element-forge@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/react-element-forge/-/react-element-forge-0.0.7.tgz#f4af209dcd72e943152dc2b01c73c837874eb38a" + integrity sha512-P68Ku/rqa3SaDvFTMe9HSG4LLXXr4VjDCvchRpeOpgdc9PAj+JgvBK9wu2pmmfy45ZsZg7sBV+6twWvpQkYmDQ== + react-is@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -1863,6 +2077,13 @@ react@18.2.0: dependencies: loose-envify "^1.1.0" +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + rechoir@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" @@ -1940,6 +2161,15 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" +sass@^1.77.8: + version "1.77.8" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.77.8.tgz#9f18b449ea401759ef7ec1752a16373e296b52bd" + integrity sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ== + dependencies: + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" + scheduler@^0.23.0: version "0.23.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" @@ -1988,6 +2218,11 @@ slash@^4.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== +"source-map-js@>=0.6.2 <2.0.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== + source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" @@ -2208,6 +2443,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +url-join@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" + integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -2263,6 +2503,11 @@ xtend@^4.0.0: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" diff --git a/compose.yaml b/compose.yaml index ae32501..1dfd551 100644 --- a/compose.yaml +++ b/compose.yaml @@ -13,7 +13,7 @@ services: - ./appserver:/appserver working_dir: /appserver command: yarn dev - env_file: env-dev + env_file: .env.local environment: PORT: 3000 DATABASE_URL: "postgresql://devuser:devdummypass@pgserver:5432/devdb" diff --git a/env-dev b/env-dev index 7c1e558..1a8db09 100644 --- a/env-dev +++ b/env-dev @@ -1,3 +1,5 @@ APP_NAME=tfboilerplate ENV_NAME=dev FLAG_USE_DB=true + + \ No newline at end of file diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..ab614d8 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,253 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@auth0/nextjs-auth0@^3.5.0": + version "3.5.0" + resolved "https://registry.yarnpkg.com/@auth0/nextjs-auth0/-/nextjs-auth0-3.5.0.tgz#f596d641cba7a96b924481fda384e7feb811bb26" + integrity sha512-uFZEE2QQf1zU+jRK2fwqxRQt+WSqDPYF2tnr7d6BEa7b6L6tpPJ3evzoImbWSY1a7gFdvD7RD/Rvrsx7B5CKVg== + dependencies: + "@panva/hkdf" "^1.0.2" + cookie "^0.6.0" + debug "^4.3.4" + joi "^17.6.0" + jose "^4.9.2" + oauth4webapi "^2.3.0" + openid-client "^5.2.1" + tslib "^2.4.0" + url-join "^4.0.1" + +"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== + +"@hapi/topo@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" + integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@panva/hkdf@^1.0.2": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@panva/hkdf/-/hkdf-1.2.1.tgz#cb0d111ef700136f4580349ff0226bf25c853f23" + integrity sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw== + +"@sideway/address@^4.1.5": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" + integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" + integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +"chokidar@>=3.0.0 <4.0.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +cookie@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== + +debug@^4.3.4: + version "4.3.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + dependencies: + ms "2.1.2" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +immutable@^4.0.0: + version "4.3.7" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" + integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +joi@^17.6.0: + version "17.13.3" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec" + integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA== + dependencies: + "@hapi/hoek" "^9.3.0" + "@hapi/topo" "^5.1.0" + "@sideway/address" "^4.1.5" + "@sideway/formula" "^3.0.1" + "@sideway/pinpoint" "^2.0.0" + +jose@^4.15.5, jose@^4.9.2: + version "4.15.9" + resolved "https://registry.yarnpkg.com/jose/-/jose-4.15.9.tgz#9b68eda29e9a0614c042fa29387196c7dd800100" + integrity sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +oauth4webapi@^2.3.0: + version "2.11.1" + resolved "https://registry.yarnpkg.com/oauth4webapi/-/oauth4webapi-2.11.1.tgz#8d79e6b0d54ead203094f185a11031f3f9978465" + integrity sha512-aNzOnL98bL6izG97zgnZs1PFEyO4WDVRhz2Pd066NPak44w5ESLRCYmJIyey8avSBPOMtBjhF3ZDDm7bIb7UOg== + +object-hash@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" + integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== + +oidc-token-hash@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz#9a229f0a1ce9d4fc89bcaee5478c97a889e7b7b6" + integrity sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw== + +openid-client@^5.2.1: + version "5.6.5" + resolved "https://registry.yarnpkg.com/openid-client/-/openid-client-5.6.5.tgz#c149ad07b9c399476dc347097e297bbe288b8b00" + integrity sha512-5P4qO9nGJzB5PI0LFlhj4Dzg3m4odt0qsJTfyEtZyOlkgpILwEioOhVVJOrS1iVH494S4Ee5OCjjg6Bf5WOj3w== + dependencies: + jose "^4.15.5" + lru-cache "^6.0.0" + object-hash "^2.2.0" + oidc-token-hash "^5.0.3" + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +sass@^1.77.8: + version "1.77.8" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.77.8.tgz#9f18b449ea401759ef7ec1752a16373e296b52bd" + integrity sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ== + dependencies: + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" + +"source-map-js@>=0.6.2 <2.0.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tslib@^2.4.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" + integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== + +url-join@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" + integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== From a6419eb96d636eb2b41726e7e8a9beaa973beb3d Mon Sep 17 00:00:00 2001 From: Nick Grato Date: Wed, 31 Jul 2024 10:23:43 -0700 Subject: [PATCH 2/4] addin auth and database --- appserver/app/api/chat/route.ts | 17 + appserver/app/api/github/[actions]/routes.ts | 58 + appserver/app/dashboard/code/page.module.scss | 7 + appserver/app/dashboard/code/page.tsx | 92 ++ appserver/app/dashboard/layout.module.scss | 6 + appserver/app/dashboard/layout.tsx | 12 + appserver/app/dashboard/page.tsx | 3 + .../app/dashboard/sandbox/page.module.scss | 7 + appserver/app/dashboard/sandbox/page.tsx | 10 + appserver/app/layout.tsx | 37 +- appserver/app/profile/layout.tsx | 16 + appserver/knexfile.js | 3 + ...0240726181242_artifact_embeddings_table.js | 15 + .../chat/ChatMessage/ChatMessage.module.scss | 57 + .../modules/chat/ChatMessage/ChatMessage.tsx | 88 ++ .../chat/ChatWrapper/ChatWrapper.module.scss | 8 + .../modules/chat/ChatWrapper/ChatWrapper.tsx | 89 ++ .../navigation/MainNav/MainNav.module.scss | 3 +- .../modules/navigation/MainNav/MainNav.tsx | 31 +- .../navigation/SideNav/SideNav.module.scss | 35 + .../modules/navigation/SideNav/SideNav.tsx | 66 + .../navigation/SideNav/SideNavSelect.tsx | 29 + appserver/modules/navigation/SideNav/const.ts | 74 ++ appserver/package.json | 12 +- appserver/public/logo.png | Bin 0 -> 1714 bytes appserver/services/server/github.service.ts | 67 + appserver/styles/core/theme.scss | 76 +- appserver/styles/core/variables.scss | 53 +- appserver/styles/globals.scss | 53 +- appserver/styles/tools/mixins.scss | 12 +- appserver/styles/tools/utility.scss | 13 +- appserver/tsconfig.json | 39 +- appserver/types.d.ts | 197 ++- appserver/yarn.lock | 1131 ++++++++++++++++- compose.yaml | 2 +- 35 files changed, 2198 insertions(+), 220 deletions(-) create mode 100644 appserver/app/api/chat/route.ts create mode 100644 appserver/app/api/github/[actions]/routes.ts create mode 100644 appserver/app/dashboard/code/page.module.scss create mode 100644 appserver/app/dashboard/code/page.tsx create mode 100644 appserver/app/dashboard/layout.module.scss create mode 100644 appserver/app/dashboard/layout.tsx create mode 100644 appserver/app/dashboard/page.tsx create mode 100644 appserver/app/dashboard/sandbox/page.module.scss create mode 100644 appserver/app/dashboard/sandbox/page.tsx create mode 100644 appserver/app/profile/layout.tsx create mode 100644 appserver/migrations/20240726181242_artifact_embeddings_table.js create mode 100644 appserver/modules/chat/ChatMessage/ChatMessage.module.scss create mode 100644 appserver/modules/chat/ChatMessage/ChatMessage.tsx create mode 100644 appserver/modules/chat/ChatWrapper/ChatWrapper.module.scss create mode 100644 appserver/modules/chat/ChatWrapper/ChatWrapper.tsx create mode 100644 appserver/modules/navigation/SideNav/SideNav.module.scss create mode 100644 appserver/modules/navigation/SideNav/SideNav.tsx create mode 100644 appserver/modules/navigation/SideNav/SideNavSelect.tsx create mode 100644 appserver/modules/navigation/SideNav/const.ts create mode 100644 appserver/public/logo.png create mode 100644 appserver/services/server/github.service.ts diff --git a/appserver/app/api/chat/route.ts b/appserver/app/api/chat/route.ts new file mode 100644 index 0000000..2ec633e --- /dev/null +++ b/appserver/app/api/chat/route.ts @@ -0,0 +1,17 @@ +import { openai } from '@ai-sdk/openai' +import { convertToCoreMessages, streamText } from 'ai' + +// Allow streaming responses up to 30 seconds +export const maxDuration = 30 + +export async function POST(req: Request) { + const { messages } = await req.json() + + const result = await streamText({ + model: openai('gpt-4o'), + system: 'You are a helpful assistant.', + messages: convertToCoreMessages(messages), + }) + + return result.toDataStreamResponse() +} diff --git a/appserver/app/api/github/[actions]/routes.ts b/appserver/app/api/github/[actions]/routes.ts new file mode 100644 index 0000000..a32f350 --- /dev/null +++ b/appserver/app/api/github/[actions]/routes.ts @@ -0,0 +1,58 @@ +import { NextApiRequest, NextApiResponse } from 'next' +import GithubService from '@Services/server/github.service' + +const githubService = new GithubService(process.env.GITHUB_TOKEN || '') + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + const { action, owner, repo, path } = req.query + + try { + let data + switch (action) { + case 'getRepo': + data = await githubService.getRepo(owner as string, repo as string) + break + case 'getContributors': + data = await githubService.getContributors( + owner as string, + repo as string + ) + break + case 'getIssues': + data = await githubService.getIssues(owner as string, repo as string) + break + case 'getPullRequests': + data = await githubService.getPullRequests( + owner as string, + repo as string + ) + break + case 'getBranches': + data = await githubService.getBranches(owner as string, repo as string) + break + case 'getTags': + data = await githubService.getTags(owner as string, repo as string) + break + case 'getContents': + data = await githubService.getContents( + owner as string, + repo as string, + path as string + ) + break + case 'getCommits': + data = await githubService.getCommits(owner as string, repo as string) + break + default: + return res.status(400).json({ message: 'Invalid action' }) + } + + res.status(200).json(data) + } catch (error) { + console.error(error) + res.status(500).json({ message: 'there was an error see logs' }) + } +} diff --git a/appserver/app/dashboard/code/page.module.scss b/appserver/app/dashboard/code/page.module.scss new file mode 100644 index 0000000..e4bf4cc --- /dev/null +++ b/appserver/app/dashboard/code/page.module.scss @@ -0,0 +1,7 @@ +@use 'styles/core/boilerplate' as *; + +.contributor { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-gap: 20px; +} diff --git a/appserver/app/dashboard/code/page.tsx b/appserver/app/dashboard/code/page.tsx new file mode 100644 index 0000000..323c185 --- /dev/null +++ b/appserver/app/dashboard/code/page.tsx @@ -0,0 +1,92 @@ +import GithubService from '@Services/server/github.service' +import styles from './page.module.scss' +import Markdown from 'react-markdown' + +export default async function Page() { + const githubService = new GithubService(process.env.GITHUB_TOKEN || '') + + const repo = await githubService.getRepo('Facebook', 'React') + const contributors = await githubService.getContributors('Facebook', 'React') + const issues = await githubService.getIssues('Facebook', 'React') + const content = await githubService.getContents( + 'Facebook', + 'React', + 'README.md' + ) + console.log('content', content) + console.log( + 'buffer content', + Buffer.from(content.content, 'base64').toString('utf-8') + ) + + return ( +
+

Code Base

+
+

File content test

+
+ + {Buffer.from(content.content, 'base64').toString('utf-8')} + +
+
+
+
+

Repo Details

+
+

+ Owner: {repo.owner.login} +

+

+ Private: {repo.private ? 'Yes' : 'No'} +

+

+ Default Branch: {repo.default_branch} +

+

+ Language: {repo.language} +

+

+ Size: {repo.size} +

+
+
+
+

Top Contributors

+
+ {contributors.map((contributor) => ( +
+

+ Login: {contributor.login} +

+

+ Contributions: {contributor.contributions} +

+
+ ))} +
+
+
+
+
+

Repo Issues

+
+ {issues.map((issue) => ( +
+

+ Title: {issue.title} +

+

+ State: {issue.state} +

+

+ Comments: {issue.comments} +

+
+ ))} +
+
+
+
+ ) +} diff --git a/appserver/app/dashboard/layout.module.scss b/appserver/app/dashboard/layout.module.scss new file mode 100644 index 0000000..26b6aa2 --- /dev/null +++ b/appserver/app/dashboard/layout.module.scss @@ -0,0 +1,6 @@ +@use 'styles/core/boilerplate' as *; + +.wrapper { + display: grid; + grid-template-columns: 300px 1fr; +} diff --git a/appserver/app/dashboard/layout.tsx b/appserver/app/dashboard/layout.tsx new file mode 100644 index 0000000..05d658c --- /dev/null +++ b/appserver/app/dashboard/layout.tsx @@ -0,0 +1,12 @@ +import { ReactNode } from 'react' +import SideNav from '@Navigation/SideNav/SideNav' +import styles from './layout.module.scss' + +export default function RootLayout({ children }: { children: ReactNode }) { + return ( +
+ + {children} +
+ ) +} diff --git a/appserver/app/dashboard/page.tsx b/appserver/app/dashboard/page.tsx new file mode 100644 index 0000000..b37c5f2 --- /dev/null +++ b/appserver/app/dashboard/page.tsx @@ -0,0 +1,3 @@ +export default async function Page() { + return
im the main page content
+} diff --git a/appserver/app/dashboard/sandbox/page.module.scss b/appserver/app/dashboard/sandbox/page.module.scss new file mode 100644 index 0000000..e4bf4cc --- /dev/null +++ b/appserver/app/dashboard/sandbox/page.module.scss @@ -0,0 +1,7 @@ +@use 'styles/core/boilerplate' as *; + +.contributor { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-gap: 20px; +} diff --git a/appserver/app/dashboard/sandbox/page.tsx b/appserver/app/dashboard/sandbox/page.tsx new file mode 100644 index 0000000..057c76d --- /dev/null +++ b/appserver/app/dashboard/sandbox/page.tsx @@ -0,0 +1,10 @@ +import ChatWrapper from '@Modules/chat/ChatWrapper/ChatWrapper' + +export default async function Page() { + return ( +
+

Sandbox Chat

+ +
+ ) +} diff --git a/appserver/app/layout.tsx b/appserver/app/layout.tsx index 2883c4e..b62b90f 100644 --- a/appserver/app/layout.tsx +++ b/appserver/app/layout.tsx @@ -1,31 +1,31 @@ -import "../styles/globals.scss"; -import "react-element-forge/dist/style.css"; -import { Inter, Space_Grotesk } from "next/font/google"; -import { UserProvider } from "@auth0/nextjs-auth0/client"; -import MainNav from "@Modules/navigation/MainNav/MainNav"; -import { getSession } from "@auth0/nextjs-auth0"; +import '../styles/globals.scss' +import 'react-element-forge/dist/style.css' +import { Inter, Space_Grotesk } from 'next/font/google' +import { UserProvider } from '@auth0/nextjs-auth0/client' +import { getSession } from '@auth0/nextjs-auth0' +import { ReactNode } from 'react' const inter = Inter({ - variable: "--inter-font", - subsets: ["latin"], - display: "swap", + variable: '--inter-font', + subsets: ['latin'], + display: 'swap', preload: true, -}); +}) const space_grotesk = Space_Grotesk({ - variable: "--space_grotesk-font", - subsets: ["latin"], - display: "swap", + variable: '--space_grotesk-font', + subsets: ['latin'], + display: 'swap', preload: true, -}); +}) export default async function RootLayout({ children, }: { - children: React.ReactNode; + children: ReactNode }) { - const session = await getSession(); - const user = session?.user; + const session = await getSession() + const user = session?.user return ( @@ -36,10 +36,9 @@ export default async function RootLayout({
- {children}
- ); + ) } diff --git a/appserver/app/profile/layout.tsx b/appserver/app/profile/layout.tsx new file mode 100644 index 0000000..a14e64f --- /dev/null +++ b/appserver/app/profile/layout.tsx @@ -0,0 +1,16 @@ +export const metadata = { + title: 'Next.js', + description: 'Generated by Next.js', +} + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} diff --git a/appserver/knexfile.js b/appserver/knexfile.js index 541799d..e1f6e16 100644 --- a/appserver/knexfile.js +++ b/appserver/knexfile.js @@ -1,6 +1,9 @@ +const { pgvector } = require('pgvector/knex') + const config = { client: 'pg', connection: process.env.DATABASE_URL, + ...pgvector, } module.exports = config diff --git a/appserver/migrations/20240726181242_artifact_embeddings_table.js b/appserver/migrations/20240726181242_artifact_embeddings_table.js new file mode 100644 index 0000000..1c6ed46 --- /dev/null +++ b/appserver/migrations/20240726181242_artifact_embeddings_table.js @@ -0,0 +1,15 @@ +const { pgvector } = require('pgvector/knex') + +exports.up = async function (knex) { + const resp = await knex.schema.enableExtension('vector') + return knex.schema.createTable('artifact_embeddings', (table) => { + table.uuid('id').primary().defaultTo(knex.raw('gen_random_uuid()')) + table.specificType('embedding', 'vector(1536)') + table.string('name') + table.timestamps(true, true) + }) +} + +exports.down = async function (knex) { + return knex.schema.dropTable('artifact_embeddings') +} diff --git a/appserver/modules/chat/ChatMessage/ChatMessage.module.scss b/appserver/modules/chat/ChatMessage/ChatMessage.module.scss new file mode 100644 index 0000000..87b1f7d --- /dev/null +++ b/appserver/modules/chat/ChatMessage/ChatMessage.module.scss @@ -0,0 +1,57 @@ +@use 'styles/core/boilerplate' as *; + +.out_going_wrapper { + display: flex; + justify-content: flex-start; + margin-bottom: 12px; + color: $color-text-main; + + .message { + background-color: $color-background-chat-outgoing; + } +} + +.incomming_wrapper { + display: flex; + justify-content: flex-end; + margin-bottom: 12px; + color: $color-text-reverse; + + .message { + background-color: $color-background-chat-incomming; + --copy-button-text-color: $color-text-reverse; + } +} + +.container { + max-width: 80%; + position: relative; +} + +.name_tag { + display: flex; + align-items: center; + margin-bottom: 12px; +} + +.message { + display: inline-block; + padding: 12px; + border-radius: 12px; + margin-bottom: 12px; + max-width: 100%; + overflow-x: auto; +} + +.actions { + display: flex; + position: absolute; + bottom: -40px; + right: 0px; +} + +.copy_button { + svg { + stroke: $color-text-reverse; + } +} diff --git a/appserver/modules/chat/ChatMessage/ChatMessage.tsx b/appserver/modules/chat/ChatMessage/ChatMessage.tsx new file mode 100644 index 0000000..966475a --- /dev/null +++ b/appserver/modules/chat/ChatMessage/ChatMessage.tsx @@ -0,0 +1,88 @@ +'use client' + +import styles from './ChatMessage.module.scss' +import { CopyButton } from 'react-element-forge' +import { MessageT } from 'types' +import Markdown from 'react-markdown' +import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter' +import { darcula } from 'react-syntax-highlighter/dist/esm/styles/prism' + +type MessageBubblePropsT = { + message: string + type: 'incomming' | 'out_going' + hasActions?: boolean + onInject?: Function +} +const MessageBubble = ({ + message, + type, + hasActions, + onInject, +}: MessageBubblePropsT) => { + console.log('rendering message bubble') + return ( +
+
+
+
+ + +
+ +
+ + ) : ( + + {children} + + ) + }, + }} + /> +
+
+ {hasActions && ( +
+ +
+ )} +
+
+ ) +} + +type ChatMessagePropsT = { + message: MessageT +} +const ChatMessage = ({ message }: ChatMessagePropsT) => { + return ( +
+ {message.role === 'assistant' && ( + + )} + {message.role === 'user' && ( + + )} +
+ ) +} + +export default ChatMessage diff --git a/appserver/modules/chat/ChatWrapper/ChatWrapper.module.scss b/appserver/modules/chat/ChatWrapper/ChatWrapper.module.scss new file mode 100644 index 0000000..dc40f99 --- /dev/null +++ b/appserver/modules/chat/ChatWrapper/ChatWrapper.module.scss @@ -0,0 +1,8 @@ +@use 'styles/core/boilerplate' as *; + +.messages_wrapper { + height: calc(100vh - 440px); + margin-bottom: 40px; + overflow-y: scroll; + padding: 12px; +} diff --git a/appserver/modules/chat/ChatWrapper/ChatWrapper.tsx b/appserver/modules/chat/ChatWrapper/ChatWrapper.tsx new file mode 100644 index 0000000..62eb1aa --- /dev/null +++ b/appserver/modules/chat/ChatWrapper/ChatWrapper.tsx @@ -0,0 +1,89 @@ +'use client' + +import { useChat } from 'ai/react' +import ChatMessage from '../ChatMessage/ChatMessage' +import { useEffect, useCallback, useRef } from 'react' +import { Button, TextArea } from 'react-element-forge' +export type LlmT = 'openAi' | 'local' +import styles from './ChatWrapper.module.scss' + +const ChatWrapper = () => { + const { messages, input, handleInputChange, handleSubmit } = useChat({ + keepLastMessageOnError: true, + }) + + const messagesEndRef = useRef(null) + + const action = useCallback( + (event: KeyboardEvent) => { + const textarea = event.target as HTMLTextAreaElement + + // This just creates a new line when shift + enter is pressed, + if (event.shiftKey && event.key === 'Enter') { + event.preventDefault() + const start = textarea.selectionStart + const end = textarea.selectionEnd + + textarea.value = + textarea.value.substring(0, start) + + '\n' + + textarea.value.substring(end) + + textarea.selectionStart = textarea.selectionEnd = start + 1 + return + } + + if (event.key === 'Enter') { + event.preventDefault() + handleSubmit() + } + }, + [handleSubmit] + ) + + useEffect(() => { + scrollToBottom() + }, [messages]) + + useEffect(() => { + const chatBox = document.getElementById('chat-box') + chatBox?.addEventListener('keydown', action) + + return () => { + chatBox?.removeEventListener('keydown', action) + } + }, [action]) + + const scrollToBottom = () => { + messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }) + } + + return ( + <> +
+ {messages.map((message) => ( + + ))} +
+
+ +
+