mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2026-03-21 22:56:47 +00:00
fix: remaining dependabot security issues (#890)
* Upgrade docs deps * Upgrade frontend to latest deps * Update package overrides * Remove redundant deps * Add tailwind postcss plugin * Replace language select with chakra * Fix main nav * Patch gray matter * Fix webpack override * Replace python-jose with pyjwt * Override kv url for frontend in compose * Upgrade hatchet sdk * Update docs * Supress pydantic warnings
This commit is contained in:
@@ -1,10 +1,8 @@
|
||||
import { Container, Flex } from "@chakra-ui/react";
|
||||
import { featureEnabled } from "../lib/features";
|
||||
import NextLink from "next/link";
|
||||
import Image from "next/image";
|
||||
import UserInfo from "../(auth)/userInfo";
|
||||
import AuthWrapper from "./AuthWrapper";
|
||||
import { RECORD_A_MEETING_URL } from "../api/urls";
|
||||
import MainNav from "../components/MainNav";
|
||||
|
||||
export default async function AppLayout({
|
||||
children,
|
||||
@@ -47,44 +45,7 @@ export default async function AppLayout({
|
||||
</p>
|
||||
</div>
|
||||
</NextLink>
|
||||
<div>
|
||||
{/* Text link on the right */}
|
||||
<NextLink href={RECORD_A_MEETING_URL} className="font-light px-2">
|
||||
Create
|
||||
</NextLink>
|
||||
{featureEnabled("browse") ? (
|
||||
<>
|
||||
·
|
||||
<NextLink href="/browse" className="font-light px-2">
|
||||
Browse
|
||||
</NextLink>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
{featureEnabled("rooms") ? (
|
||||
<>
|
||||
·
|
||||
<NextLink href="/rooms" className="font-light px-2">
|
||||
Rooms
|
||||
</NextLink>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
{featureEnabled("requireLogin") ? (
|
||||
<>
|
||||
·
|
||||
<NextLink href="/settings/api-keys" className="font-light px-2">
|
||||
Settings
|
||||
</NextLink>
|
||||
·
|
||||
<UserInfo />
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
<MainNav />
|
||||
</Flex>
|
||||
|
||||
<AuthWrapper>{children}</AuthWrapper>
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
"use client";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import useAudioDevice from "../useAudioDevice";
|
||||
import "react-select-search/style.css";
|
||||
import "../../../styles/form.scss";
|
||||
import About from "../../../(aboutAndPrivacy)/about";
|
||||
import Privacy from "../../../(aboutAndPrivacy)/privacy";
|
||||
import { useRouter } from "next/navigation";
|
||||
import useCreateTranscript from "../createTranscript";
|
||||
import SelectSearch from "react-select-search";
|
||||
import { supportedLanguages } from "../../../supportedLanguages";
|
||||
import {
|
||||
Flex,
|
||||
@@ -21,6 +19,7 @@ import {
|
||||
} from "@chakra-ui/react";
|
||||
import { useAuth } from "../../../lib/AuthProvider";
|
||||
import { featureEnabled } from "../../../lib/features";
|
||||
import { SearchableLanguageSelect } from "../../../components/SearchableLanguageSelect";
|
||||
|
||||
const TranscriptCreate = () => {
|
||||
const router = useRouter();
|
||||
@@ -147,31 +146,27 @@ const TranscriptCreate = () => {
|
||||
p={8}
|
||||
flexDir="column"
|
||||
my={4}
|
||||
className="form-on-primary"
|
||||
>
|
||||
<Heading size="xl" mb={4}>
|
||||
Try Reflector
|
||||
</Heading>
|
||||
<Box mb={4}>
|
||||
<Text>Recording name</Text>
|
||||
<div className="select-search-container">
|
||||
<input
|
||||
className="select-search-input"
|
||||
type="text"
|
||||
onChange={nameChange}
|
||||
placeholder="Optional"
|
||||
/>
|
||||
</div>
|
||||
<Text mb={1}>Recording name</Text>
|
||||
<input
|
||||
className="form-field-input"
|
||||
type="text"
|
||||
onChange={nameChange}
|
||||
placeholder="Optional"
|
||||
/>
|
||||
</Box>
|
||||
<Box mb={4}>
|
||||
<Text>Do you want to enable live translation?</Text>
|
||||
<SelectSearch
|
||||
search
|
||||
<Text mb={1}>Do you want to enable live translation?</Text>
|
||||
<SearchableLanguageSelect
|
||||
options={supportedLanguages}
|
||||
value={targetLanguage}
|
||||
onChange={onLanguageChange}
|
||||
onBlur={() => {}}
|
||||
onFocus={() => {}}
|
||||
placeholder="Choose your language"
|
||||
placeholder="No translation"
|
||||
/>
|
||||
</Box>
|
||||
{!loading ? (
|
||||
|
||||
46
www/app/components/MainNav.tsx
Normal file
46
www/app/components/MainNav.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import NextLink from "next/link";
|
||||
import { featureEnabled } from "../lib/features";
|
||||
import UserInfo from "../(auth)/userInfo";
|
||||
import { RECORD_A_MEETING_URL } from "../api/urls";
|
||||
|
||||
function NavLink({
|
||||
href,
|
||||
children,
|
||||
}: {
|
||||
href: string;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<NextLink href={href} className="font-light px-10">
|
||||
{children}
|
||||
</NextLink>
|
||||
);
|
||||
}
|
||||
|
||||
export default function MainNav() {
|
||||
return (
|
||||
<nav>
|
||||
<NavLink href={RECORD_A_MEETING_URL}>Create</NavLink>
|
||||
{featureEnabled("browse") && (
|
||||
<>
|
||||
·
|
||||
<NavLink href="/browse">Browse</NavLink>
|
||||
</>
|
||||
)}
|
||||
{featureEnabled("rooms") && (
|
||||
<>
|
||||
·
|
||||
<NavLink href="/rooms">Rooms</NavLink>
|
||||
</>
|
||||
)}
|
||||
{featureEnabled("requireLogin") && (
|
||||
<>
|
||||
·
|
||||
<NavLink href="/settings/api-keys">Settings</NavLink>
|
||||
·
|
||||
<UserInfo />
|
||||
</>
|
||||
)}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
98
www/app/components/SearchableLanguageSelect.tsx
Normal file
98
www/app/components/SearchableLanguageSelect.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
"use client";
|
||||
|
||||
import React, { useMemo } from "react";
|
||||
import {
|
||||
Combobox,
|
||||
createListCollection,
|
||||
useComboboxContext,
|
||||
} from "@chakra-ui/react";
|
||||
|
||||
export type LangOption = { value: string | undefined; name: string };
|
||||
|
||||
type Item = { label: string; value: string };
|
||||
|
||||
function FilteredComboboxItems({ items }: { items: Item[] }) {
|
||||
const ctx = useComboboxContext();
|
||||
const inputValue = (ctx as { inputValue?: string }).inputValue ?? "";
|
||||
const filtered = useMemo(() => {
|
||||
const q = inputValue.trim().toLowerCase();
|
||||
if (!q) return items;
|
||||
return items.filter((item) => item.label.toLowerCase().includes(q));
|
||||
}, [items, inputValue]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Combobox.Empty>No matches</Combobox.Empty>
|
||||
{filtered.map((item) => (
|
||||
<Combobox.Item key={item.value} item={item}>
|
||||
{item.label}
|
||||
</Combobox.Item>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
type Props = {
|
||||
options: LangOption[];
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
placeholder: string;
|
||||
};
|
||||
|
||||
export function SearchableLanguageSelect({
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
placeholder,
|
||||
}: Props) {
|
||||
const items = useMemo(() => {
|
||||
const result: Item[] = [];
|
||||
let addedNone = false;
|
||||
for (const opt of options) {
|
||||
const val = opt.value ?? "NOTRANSLATION";
|
||||
if (val === "NOTRANSLATION" || val === "") {
|
||||
if (addedNone) continue;
|
||||
addedNone = true;
|
||||
result.push({ label: "No translation", value: "NOTRANSLATION" });
|
||||
} else {
|
||||
result.push({ label: opt.name, value: val });
|
||||
}
|
||||
}
|
||||
return result.sort((a, b) => {
|
||||
if (a.value === "NOTRANSLATION") return -1;
|
||||
if (b.value === "NOTRANSLATION") return 1;
|
||||
return a.label.localeCompare(b.label);
|
||||
});
|
||||
}, [options]);
|
||||
|
||||
const collection = useMemo(() => createListCollection({ items }), [items]);
|
||||
|
||||
const selectedValues = value && value !== "NOTRANSLATION" ? [value] : [];
|
||||
|
||||
return (
|
||||
<Combobox.Root
|
||||
collection={collection}
|
||||
value={selectedValues}
|
||||
onValueChange={(e) => onChange(e.value[0] ?? "NOTRANSLATION")}
|
||||
openOnClick
|
||||
closeOnSelect
|
||||
selectionBehavior="replace"
|
||||
placeholder={placeholder}
|
||||
className="form-combobox"
|
||||
size="md"
|
||||
positioning={{ strategy: "fixed", hideWhenDetached: true }}
|
||||
>
|
||||
<Combobox.Control>
|
||||
<Combobox.Input />
|
||||
<Combobox.IndicatorGroup>
|
||||
<Combobox.Trigger />
|
||||
</Combobox.IndicatorGroup>
|
||||
</Combobox.Control>
|
||||
<Combobox.Positioner>
|
||||
<Combobox.Content>
|
||||
<FilteredComboboxItems items={items} />
|
||||
</Combobox.Content>
|
||||
</Combobox.Positioner>
|
||||
</Combobox.Root>
|
||||
);
|
||||
}
|
||||
@@ -1,42 +1,74 @@
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.select-search-container,
|
||||
.input-container {
|
||||
--select-search-background: #fff;
|
||||
--select-search-border: #dce0e8;
|
||||
--select-search-selected: #1e66f5;
|
||||
--select-search-text: #000;
|
||||
--select-search-subtle-text: #6c6f85;
|
||||
--select-search-highlight: #eff1f5;
|
||||
/* Form fields on primary (blue) card – white inputs like previous react-select */
|
||||
.form-on-primary {
|
||||
--form-bg: #fff;
|
||||
--form-border: #dce0e8;
|
||||
--form-focus-border: #1e66f5;
|
||||
--form-text: #000;
|
||||
--form-placeholder: #6c6f85;
|
||||
--form-option-bg: #fff;
|
||||
--form-option-hover: #eff1f5;
|
||||
--form-dropdown-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
--form-radius: 0.5rem; /* 8px, matches rounded-lg elsewhere */
|
||||
}
|
||||
|
||||
.form-on-primary .form-field-input,
|
||||
.form-on-primary .form-field-select,
|
||||
.form-on-primary .form-field-search-input {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border-radius: var(--form-radius);
|
||||
border: 1px solid var(--form-border);
|
||||
background-color: var(--form-bg);
|
||||
color: var(--form-text);
|
||||
font-size: 0.9375rem;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
|
||||
&::placeholder {
|
||||
color: var(--form-placeholder);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: var(--form-focus-border);
|
||||
}
|
||||
}
|
||||
|
||||
body.is-dark-mode .select-search-container,
|
||||
body.is-dark-mode .input-container {
|
||||
--select-search-background: #fff;
|
||||
--select-search-border: #dce0e8;
|
||||
--select-search-selected: #1e66f5;
|
||||
--select-search-text: #000;
|
||||
--select-search-subtle-text: #6c6f85;
|
||||
--select-search-highlight: #eff1f5;
|
||||
.form-on-primary .form-field-select option {
|
||||
background: var(--form-option-bg);
|
||||
color: var(--form-text);
|
||||
}
|
||||
|
||||
body.is-light-mode .select-search-container,
|
||||
body.is-light-mode .input-container {
|
||||
--select-search-background: #fff;
|
||||
--select-search-border: #dce0e8;
|
||||
--select-search-selected: #1e66f5;
|
||||
--select-search-text: #000;
|
||||
--select-search-subtle-text: #6c6f85;
|
||||
--select-search-highlight: #eff1f5;
|
||||
}
|
||||
/* Chakra Combobox inside form-on-primary: white input + dropdown, dark text */
|
||||
.form-on-primary .form-combobox {
|
||||
width: 100%;
|
||||
|
||||
.input-container,
|
||||
.select-search-container {
|
||||
max-width: 100%;
|
||||
width: auto;
|
||||
}
|
||||
[data-part="control"],
|
||||
& input {
|
||||
border-radius: var(--form-radius);
|
||||
border-color: var(--form-border);
|
||||
background-color: var(--form-bg);
|
||||
color: var(--form-text);
|
||||
|
||||
body .select-search-container .select-search--top.select-search-select {
|
||||
top: auto;
|
||||
bottom: 46px;
|
||||
&:focus,
|
||||
&[data-focus] {
|
||||
border-color: var(--form-focus-border);
|
||||
}
|
||||
}
|
||||
|
||||
[data-part="content"] {
|
||||
border-radius: var(--form-radius);
|
||||
border: 1px solid var(--form-border);
|
||||
background: var(--form-bg);
|
||||
box-shadow: var(--form-dropdown-shadow);
|
||||
color: var(--form-text);
|
||||
}
|
||||
|
||||
[data-part="item"] {
|
||||
color: var(--form-text);
|
||||
|
||||
&:hover {
|
||||
background: var(--form-option-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,61 +13,66 @@
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@chakra-ui/react": "^3.24.2",
|
||||
"@daily-co/daily-js": "^0.84.0",
|
||||
"@chakra-ui/react": "^3.33.0",
|
||||
"@daily-co/daily-js": "^0.87.0",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.4.0",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@fortawesome/fontawesome-svg-core": "^7.2.0",
|
||||
"@fortawesome/free-solid-svg-icons": "^7.2.0",
|
||||
"@fortawesome/react-fontawesome": "^3.2.0",
|
||||
"@sentry/nextjs": "^10.40.0",
|
||||
"@tanstack/react-query": "^5.85.9",
|
||||
"@whereby.com/browser-sdk": "^3.3.4",
|
||||
"autoprefixer": "10.4.20",
|
||||
"axios": "^1.13.5",
|
||||
"eslint": "^9.33.0",
|
||||
"@tanstack/react-query": "^5.90.21",
|
||||
"@whereby.com/browser-sdk": "^3.18.21",
|
||||
"autoprefixer": "10.4.27",
|
||||
"axios": "^1.13.6",
|
||||
"eslint": "^10.0.2",
|
||||
"eslint-config-next": "^16.1.6",
|
||||
"fontawesome": "^5.6.3",
|
||||
"ioredis": "^5.7.0",
|
||||
"jest-worker": "^29.6.2",
|
||||
"lucide-react": "^0.525.0",
|
||||
"ioredis": "^5.10.0",
|
||||
"jest-worker": "^30.2.0",
|
||||
"lucide-react": "^0.575.0",
|
||||
"next": "^16.1.6",
|
||||
"next-auth": "^4.24.12",
|
||||
"next-auth": "^4.24.13",
|
||||
"next-themes": "^0.4.6",
|
||||
"nuqs": "^2.4.3",
|
||||
"openapi-fetch": "^0.14.0",
|
||||
"openapi-react-query": "^0.5.0",
|
||||
"postcss": "8.4.31",
|
||||
"nuqs": "^2.8.9",
|
||||
"openapi-fetch": "^0.17.0",
|
||||
"openapi-react-query": "^0.5.4",
|
||||
"postcss": "8.5.6",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4",
|
||||
"react-dropdown": "^1.11.0",
|
||||
"react-icons": "^5.0.1",
|
||||
"react-markdown": "^9.0.0",
|
||||
"react-qr-code": "^2.0.12",
|
||||
"react-select-search": "^4.1.7",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-qr-code": "^2.0.18",
|
||||
"react-uuid-hook": "^0.0.6",
|
||||
"redlock": "5.0.0-beta.2",
|
||||
"remeda": "^2.31.1",
|
||||
"sass": "^1.63.6",
|
||||
"remeda": "^2.33.6",
|
||||
"sass": "^1.97.3",
|
||||
"simple-peer": "^9.11.1",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"typescript": "^5.1.6",
|
||||
"wavesurfer.js": "^7.4.2",
|
||||
"zod": "^4.1.5"
|
||||
"tailwindcss": "^4.2.1",
|
||||
"typescript": "^5.9.3",
|
||||
"wavesurfer.js": "^7.12.1",
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
"main": "index.js",
|
||||
"repository": "https://github.com/Monadical-SAS/reflector-ui.git",
|
||||
"author": "Andreas <andreas@monadical.com>",
|
||||
"license": "All Rights Reserved",
|
||||
"devDependencies": {
|
||||
"@types/ioredis": "^5.0.0",
|
||||
"@tailwindcss/postcss": "^4.2.1",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@types/react": "19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"jest": "^30.2.0",
|
||||
"openapi-typescript": "^7.9.1",
|
||||
"prettier": "^3.0.0",
|
||||
"openapi-typescript": "^7.13.0",
|
||||
"prettier": "^3.8.1",
|
||||
"ts-jest": "^29.4.6"
|
||||
},
|
||||
"packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748"
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"minimatch@>=5.0.0 <5.1.8": "5.1.8",
|
||||
"js-yaml@<4.1.1": "4.1.1",
|
||||
"webpack": "5.105.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4559
www/pnpm-lock.yaml
generated
4559
www/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
"@tailwindcss/postcss": {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user