Miscellaneous fixes (#23155)

* Change order

* Improve title

* add loading spinner to exports

* Simplify JSON since not all providers see or use this the same

* Add fields to primary prompt

* Adjust centering for no overrides

* Use GenAI title for exports when available

* detect form-root objects by field path instead of schema identity

* add bosnian

* Strip v1 if included in url

* prevent fast clicks in video controls from selecting text

* Use title for metadata chapters

---------

Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
This commit is contained in:
Nicolas Mowen
2026-05-10 12:09:28 -05:00
committed by GitHub
co-authored by Josh Hawkins
parent 0d4f1ec369
commit c4b74c9148
13 changed files with 48 additions and 30 deletions
+6 -1
View File
@@ -79,10 +79,15 @@ export default function ReviewCard({
? event.end_time + REVIEW_PADDING
: Date.now() / 1000;
const genAiTitle = event.data.metadata?.title?.trim();
axios
.post(
`export/${event.camera}/start/${event.start_time - REVIEW_PADDING}/end/${endTime}`,
{ playback: "realtime" },
{
playback: "realtime",
...(genAiTitle ? { name: genAiTitle } : {}),
},
)
.then((response) => {
if (response.status < 300) {
@@ -52,12 +52,11 @@ export function ObjectFieldTemplate(props: ObjectFieldTemplateProps) {
} = props;
const formContext = registry?.formContext as ConfigFormContext | undefined;
// Check if this is a root-level object
const isRoot = registry?.rootSchema === schema;
const overrides = formContext?.overrides;
const baselineFormData = formContext?.baselineFormData;
const hiddenFields = formContext?.hiddenFields;
const fieldPath = props.fieldPathId.path;
const isRoot = fieldPath.length === 0;
const restartRequired = formContext?.restartRequired;
const defaultRequiresRestart = formContext?.requiresRestart ?? true;
@@ -178,6 +178,7 @@ export default function MultiExportDialog({
start_time: review.start_time - REVIEW_PADDING,
end_time: (review.end_time ?? Date.now() / 1000) + REVIEW_PADDING,
image_path: review.thumb_path || undefined,
friendly_name: review.data.metadata?.title?.trim() || undefined,
client_item_id: review.id,
}));
+1 -1
View File
@@ -198,7 +198,7 @@ export default function VideoControls({
return (
<div
className={cn(
"z-50 flex w-auto items-center justify-between gap-4 rounded-lg bg-background/60 px-4 py-2 text-primary sm:flex-nowrap sm:gap-8",
"z-50 flex w-auto select-none items-center justify-between gap-4 rounded-lg bg-background/60 px-4 py-2 text-primary sm:flex-nowrap sm:gap-8",
className,
isMobileOnly &&
Object.values(features).filter((feat) => feat).length >
@@ -91,7 +91,7 @@ export function ProfileSectionDropdown({
className="group flex items-start justify-between gap-2"
onClick={() => onSelectProfile(profile)}
>
<div className="flex flex-col items-center gap-2">
<div className="flex flex-col items-start gap-2">
<div className="flex w-full flex-row items-center justify-start gap-2">
{isActive && <Check className="h-3.5 w-3.5 shrink-0" />}
<span
+1
View File
@@ -38,6 +38,7 @@ const localeMap: Record<string, () => Promise<Locale>> = {
th: () => import("date-fns/locale/th").then((module) => module.th),
ca: () => import("date-fns/locale/ca").then((module) => module.ca),
hr: () => import("date-fns/locale/hr").then((module) => module.hr),
bs: () => import("date-fns/locale/bs").then((module) => module.bs),
sl: () => import("date-fns/locale/sl").then((module) => module.sl),
};
+1
View File
@@ -29,6 +29,7 @@ export const supportedLanguageKeys = [
"tr",
"pl",
"hr",
"bs",
"sk",
"sl",
"lt",
+13
View File
@@ -5,6 +5,7 @@ import {
CaseCard,
ExportCard,
} from "@/components/card/ExportCard";
import ActivityIndicator from "@/components/indicators/activity-indicator";
import {
AlertDialog,
AlertDialogCancel,
@@ -864,6 +865,7 @@ function Exports() {
search={search}
selectedExports={selectedExports}
selectionMode={selectionMode}
isLoading={cases === undefined || rawExports === undefined}
onSelectExport={onSelectExport}
setSelected={setSelected}
renameClip={onHandleRename}
@@ -882,6 +884,7 @@ function Exports() {
activeJobs={activeJobsByCase["none"] || []}
selectedExports={selectedExports}
selectionMode={selectionMode}
isLoading={cases === undefined || rawExports === undefined}
onSelectExport={onSelectExport}
setSelectedCaseId={setSelectedCaseId}
setSelected={setSelected}
@@ -903,6 +906,7 @@ type AllExportsViewProps = {
activeJobs: ExportJob[];
selectedExports: Export[];
selectionMode: boolean;
isLoading: boolean;
onSelectExport: (e: Export) => void;
setSelectedCaseId: (id: string) => void;
setSelected: (e: Export) => void;
@@ -919,6 +923,7 @@ function AllExportsView({
activeJobs,
selectedExports,
selectionMode,
isLoading,
onSelectExport,
setSelectedCaseId,
setSelected,
@@ -1027,6 +1032,8 @@ function AllExportsView({
</div>
)}
</div>
) : isLoading ? (
<ActivityIndicator className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2" />
) : (
<div className="absolute left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 flex-col items-center justify-center text-center">
<LuFolderX className="size-16" />
@@ -1046,6 +1053,7 @@ type CaseViewProps = {
search: string;
selectedExports: Export[];
selectionMode: boolean;
isLoading: boolean;
onSelectExport: (e: Export) => void;
setSelected: (e: Export) => void;
renameClip: (id: string, update: string) => void;
@@ -1063,6 +1071,7 @@ function CaseView({
search,
selectedExports,
selectionMode,
isLoading,
onSelectExport,
setSelected,
renameClip,
@@ -1201,6 +1210,10 @@ function CaseView({
/>
))}
</div>
) : isLoading ? (
<div className="flex min-h-[16rem] flex-1 items-center justify-center">
<ActivityIndicator />
</div>
) : (
<div className="flex min-h-[16rem] flex-col items-center justify-center p-6 text-center">
<LuFolderX className="size-12" />