fix(Codex): only allow inbounds time intervals on edit archive

This commit is contained in:
2026-01-16 10:08:40 +01:00
parent ec109328fb
commit eaea4b2e21
4 changed files with 108 additions and 1 deletions

View File

@@ -168,6 +168,18 @@ type Archives =
let form, setForm = React.useState initForm
let isOpen, setIsOpen = React.useState false
let errMsg, setErrMsg = React.useState None
let dataSet, setDataSet = React.useState None
React.useEffectOnce (fun _ ->
Remoting.adminApi.getArchiveDataSet archive.archiveId
|> Async.StartAsPromise
|> Promise.iter (fun res ->
match res with
| Ok ds -> setDataSet (Some ds)
| Error msg ->
Browser.Dom.console.error("Error fetching dataset: %s", msg)
)
)
let handleEditArchive () =
let utcTime = System.DateTime(form.StartTime.Year, form.StartTime.Month, form.StartTime.Day, 0, 0, 0, System.DateTimeKind.Utc)
@@ -184,6 +196,13 @@ type Archives =
setErrMsg (Some msg)
)
let framesExceedEnd =
dataSet
|> Option.map (fun ds ->
form.StartTime.AddHours(form.Frames) > ds.EndTime
)
|> Option.defaultValue false
Fui.dialog [
dialog.open' isOpen
dialog.onOpenChange (fun (d: DialogOpenChangeData<Browser.Types.MouseEvent>) ->
@@ -258,6 +277,11 @@ type Archives =
datePicker.placeholder "Select a date..."
datePicker.showWeekNumbers true
datePicker.formatDate (fun d -> d.ToShortDateString())
match dataSet with
| None -> ()
| Some ds ->
datePicker.minDate ds.StartTime
datePicker.maxDate ds.EndTime
datePicker.value (Some form.StartTime)
datePicker.onSelectDate (fun d ->
d |> Option.iter (fun d' ->
@@ -292,8 +316,17 @@ type Archives =
]
]
Fui.text.caption1 [
if framesExceedEnd then
text.style [style.color Theme.tokens.colorStatusDangerForeground1]
let endDate = form.StartTime.AddHours(form.Frames).ToShortDateString()
text.text (sprintf "End Date: %s, %d frames" endDate form.Frames)
text.text
($"End Date: {endDate}, {form.Frames} frames"
+
if framesExceedEnd then
" (Exceeds DataSet Bounds!)"
else
"")
]
Fui.checkbox [
checkbox.label "Published"

View File

@@ -292,6 +292,20 @@ module Admin =
return Error "Error fetching dataSets"
}
let getArchiveDataSet (ctx: HttpContext) (archiveId: System.Guid) =
async {
let user = ctx.User.Identity.Name
let logger = ctx.GetLogger<Remoting.Api.Admin> ()
try
do logger.LogInformation("getArchiveDataSet {Archive} from {User}", archiveId, user)
let db = ctx.GetService<NpgsqlDataSource> ()
let! dataSet = Archmaester.Dapper.queryArchiveDataSet db archiveId
return Ok dataSet
with e ->
do logger.LogError (e, "getArchiveDataSet {Archive} from {User}", archiveId, user)
return Error "Error fetching dataset"
}
let addArchive (ctx: HttpContext) (archive: Remoting.AddArchiveRequest) =
let archmaesterAdd (db: Entity.ArchiveContext) =
async {
@@ -528,6 +542,7 @@ module Admin =
getGroupUsers = Handler.getGroupUsers ctx
removeUsers = Handler.removeUsers ctx
getDataSets = fun () -> Handler.getAllDataSets ctx
getArchiveDataSet = Handler.getArchiveDataSet ctx
addArchive = Handler.addArchive ctx
updateArchive = Handler.updateArchive ctx
}

View File

@@ -201,6 +201,64 @@ module Archmaester =
)
}
let queryArchiveDataSet (db: NpgsqlDataSource) (archiveId: System.Guid) =
async {
use conn = db.OpenConnection ()
let query =
"""
SELECT
a.id AS a_id,
a.base_path,
m.id AS m_id,
m.name AS m_name,
MIN(f.start_time) AS start_time,
MAX(f.start_time) AS end_time
FROM
attribs AS a
JOIN
model_areas AS m
ON m.id = a.model_area_id
LEFT JOIN
files AS f
ON f.attribs_id = a.id
LEFT JOIN
archives as ar
ON ar.attribs_id = a.id
WHERE
ar.id = @archive_id
GROUP BY
a.id,
a.base_path,
m.id,
m.name
;
"""
let param =
dict [
"archive_id", box archiveId
]
let! res =
conn.QueryAsync<DataSetTable>(query, param)
|> Async.AwaitTask
return
res
|> Array.ofSeq
|> Array.map (fun x ->
{
Id = x.a_id
BasePath = x.base_path
ModelAreaId = x.m_id
ModelAreaName = x.m_name
StartTime = x.start_time
EndTime = x.end_time.AddHours(24)
} : Remoting.DataSet
) // TODO: is there a better way to select single rows?
|> Array.head
}
module EFCore =
open System.Linq

View File

@@ -214,6 +214,7 @@ module Remoting =
getGroupUsers: string -> Async<string array>
removeUsers: string array -> Async<Result<unit, string>>
getDataSets: unit -> Async<Result<DataSet array, string>>
getArchiveDataSet: System.Guid -> Async<Result<DataSet, string>>
addArchive: AddArchiveRequest -> Async<Result<Archive, string>>
updateArchive: System.Guid -> EditArchiveRequest -> Async<Result<Archive, string>>
}