Compare commits
5 Commits
main
...
simkir/cod
| Author | SHA1 | Date | |
|---|---|---|---|
| c66cda70be | |||
| bff84f8ff2 | |||
| 8d09b544a5 | |||
|
|
af527a6754 | ||
|
|
6b64d9e197 |
3
.envrc
3
.envrc
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
export APP_ENV=$USER
|
||||
|
||||
# the shebang is ignored, but nice for editors
|
||||
watch_file nix/sources.json
|
||||
|
||||
|
||||
@@ -13,18 +13,14 @@ module Archive =
|
||||
let! acl = Remoting.aclApi.getAcl id |> Async.StartAsPromise
|
||||
return acl
|
||||
with e ->
|
||||
console.error("Error fetching archive ACL: %o", e)
|
||||
console.error ("Error fetching archive ACL: %o", e)
|
||||
return Error "Error fetching archive ACL"
|
||||
}
|
||||
|
||||
let private fetchSubArchives (id: System.Guid) : JS.Promise<Result<Archmaester.Dto.ArchiveProps array, string>> =
|
||||
promise {
|
||||
let archiveType = Archmaester.Dto.ArchiveType.FromString "*:*:*"
|
||||
let filter = {
|
||||
Archmaester.Dto.ArchiveFilter.empty with
|
||||
id = Some id
|
||||
archiveType = Some archiveType
|
||||
}
|
||||
let filter = { Archmaester.Dto.ArchiveFilter.empty with id = Some id; archiveType = Some archiveType }
|
||||
let! subs = Remoting.adminApi.getArchiveRefs filter |> Async.StartAsPromise
|
||||
return subs
|
||||
}
|
||||
@@ -35,7 +31,7 @@ module Archive =
|
||||
let! res = Remoting.adminApi.deleteArchive id |> Async.StartAsPromise
|
||||
return res
|
||||
with e ->
|
||||
console.error("Error deleting archive: %o", e)
|
||||
console.error ("Error deleting archive: %o", e)
|
||||
return Error "Error deleting archive"
|
||||
}
|
||||
|
||||
@@ -50,7 +46,7 @@ module Archive =
|
||||
|
||||
[<ReactComponent>]
|
||||
let private GroupSelect (onChange: string option -> unit) =
|
||||
let groupsReq = Groups.useGroups()
|
||||
let groupsReq = Groups.useGroups ()
|
||||
|
||||
let options =
|
||||
let groupOptions =
|
||||
@@ -73,7 +69,7 @@ module Archive =
|
||||
|
||||
Html.select [
|
||||
prop.onChange (fun (ev: Types.Event) ->
|
||||
let group : string = ev.target?value
|
||||
let group: string = ev.target?value
|
||||
if group = "none" then
|
||||
onChange None
|
||||
else
|
||||
@@ -85,14 +81,13 @@ module Archive =
|
||||
|
||||
[<ReactComponent>]
|
||||
let private GroupFGAList (object: string) (id: string) relation userFilter ctx =
|
||||
let groups = OpenFGA.useUsers(object, id, relation, userFilter, ctx)
|
||||
let groups = OpenFGA.useUsers (object, id, relation, userFilter, ctx)
|
||||
|
||||
if Array.isEmpty groups.Objects then
|
||||
Html.p "No objects"
|
||||
else
|
||||
match groups.Error with
|
||||
| Some err ->
|
||||
Html.p err
|
||||
| Some err -> Html.p err
|
||||
| None ->
|
||||
Html.ul [
|
||||
prop.children (
|
||||
@@ -102,7 +97,7 @@ module Archive =
|
||||
prop.key object
|
||||
prop.children [
|
||||
Html.a [
|
||||
prop.href (Router.format("groups", object))
|
||||
prop.href (Router.format ("groups", object))
|
||||
prop.text object
|
||||
]
|
||||
]
|
||||
@@ -113,14 +108,13 @@ module Archive =
|
||||
|
||||
[<ReactComponent>]
|
||||
let private UserFGAList (object: string) (id: string) relation userFilter ctx =
|
||||
let groups = OpenFGA.useUsers(object, id, relation, userFilter, ctx)
|
||||
let groups = OpenFGA.useUsers (object, id, relation, userFilter, ctx)
|
||||
|
||||
if Array.isEmpty groups.Objects then
|
||||
Html.p "No objects"
|
||||
else
|
||||
match groups.Error with
|
||||
| Some msg ->
|
||||
Html.p msg
|
||||
| Some msg -> Html.p msg
|
||||
| None ->
|
||||
Html.ul [
|
||||
prop.children (
|
||||
@@ -130,7 +124,7 @@ module Archive =
|
||||
prop.key object
|
||||
prop.children [
|
||||
Html.a [
|
||||
prop.href (Router.format("user", object))
|
||||
prop.href (Router.format ("user", object))
|
||||
prop.text object
|
||||
]
|
||||
]
|
||||
@@ -140,7 +134,7 @@ module Archive =
|
||||
]
|
||||
|
||||
[<ReactComponent>]
|
||||
let SubArchives (archiveId: System.Guid) =
|
||||
let private SubArchives (archiveId: System.Guid) =
|
||||
let loading, setLoading = React.useState true
|
||||
let archives, setArchives = React.useState<Archmaester.Dto.ArchiveProps array> [||]
|
||||
|
||||
@@ -166,8 +160,7 @@ module Archive =
|
||||
|> Promise.iter (fun res ->
|
||||
match res with
|
||||
| Ok archives -> setArchives archives
|
||||
| Error err ->
|
||||
console.error("Error fetching archive %s", err)
|
||||
| Error err -> console.error ("Error fetching archive %s", err)
|
||||
setLoading false
|
||||
)
|
||||
),
|
||||
@@ -178,47 +171,62 @@ module Archive =
|
||||
Html.div [
|
||||
prop.classes [ "grow" ]
|
||||
prop.style [
|
||||
style.flexBasis (length.px 512)
|
||||
style.minWidth (length.px 512)
|
||||
style.maxWidth (length.px 768)
|
||||
style.flexBasis (length.px 384)
|
||||
style.minWidth (length.px 384)
|
||||
style.maxWidth (length.px 512)
|
||||
]
|
||||
prop.children [
|
||||
Html.h2 "Sub archives"
|
||||
|
||||
if loading then
|
||||
Html.p "Loading ..."
|
||||
else
|
||||
if Array.isEmpty archives then
|
||||
Html.p "No sub archives"
|
||||
else
|
||||
Html.ul [
|
||||
prop.children [
|
||||
Html.li [
|
||||
prop.children [
|
||||
Html.text "Archives"
|
||||
Html.div [
|
||||
prop.style [
|
||||
style.maxHeight (length.px 512)
|
||||
style.overflowY.auto
|
||||
]
|
||||
prop.children [
|
||||
if loading then
|
||||
Html.p "Loading ..."
|
||||
else if Array.isEmpty archives then
|
||||
Html.p "No sub archives"
|
||||
else
|
||||
Html.ul [
|
||||
prop.children [
|
||||
Html.li [
|
||||
prop.children [
|
||||
Html.text "Archives"
|
||||
|
||||
Html.ul [
|
||||
prop.children (
|
||||
rest
|
||||
|> Array.map (fun archive ->
|
||||
Html.li [
|
||||
prop.key archive.archiveId
|
||||
prop.children [
|
||||
Html.a [
|
||||
prop.href (Router.format ("archives", string archive.archiveId))
|
||||
prop.text archive.name
|
||||
Html.ul [
|
||||
prop.children (
|
||||
rest
|
||||
|> Array.map (fun archive ->
|
||||
Html.li [
|
||||
prop.key archive.archiveId
|
||||
prop.children [
|
||||
Html.a [
|
||||
prop.href (
|
||||
Router.format (
|
||||
"archives",
|
||||
string archive.archiveId
|
||||
)
|
||||
)
|
||||
prop.text archive.name
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
Drifters.List (drifters |> Array.map (fun prop -> { Props = prop; CanView = false; CanExec = false }))
|
||||
Drifters.List (
|
||||
drifters
|
||||
|> Array.map (fun prop -> { Props = prop; CanView = false; CanExec = false })
|
||||
)
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
@@ -231,7 +239,8 @@ module Archive =
|
||||
let deleting, setDeleting = React.useState false
|
||||
let deleted, setDeleted = React.useState false
|
||||
let selectedGroup, setSelectedGroup = React.useState<string option> None
|
||||
let archiveOpt, setArchive = React.useState<Archmaester.Dto.ArchiveProps option> None
|
||||
let archiveOpt, setArchive =
|
||||
React.useState<Archmaester.Dto.ArchiveProps option> None
|
||||
let aclOpt, setAcl = React.useState<Archmaester.Dto.ArchiveAcl option> None
|
||||
|
||||
let handleAddGroupToArchiveAcl (archiveId: System.Guid) =
|
||||
@@ -239,23 +248,17 @@ module Archive =
|
||||
| Some acl ->
|
||||
match selectedGroup with
|
||||
| Some group ->
|
||||
console.debug("Adding group %s to archive %s", selectedGroup, archiveId)
|
||||
console.debug ("Adding group %s to archive %s", selectedGroup, archiveId)
|
||||
addArchiveGroup archiveId group
|
||||
|> Promise.iter (fun res ->
|
||||
match res with
|
||||
| Ok () ->
|
||||
let newAcl = {
|
||||
acl with
|
||||
groups = [| group |] |> Array.append acl.groups
|
||||
}
|
||||
let newAcl = { acl with groups = [| group |] |> Array.append acl.groups }
|
||||
setAcl (Some newAcl)
|
||||
| Error err ->
|
||||
setError (Some err)
|
||||
| Error err -> setError (Some err)
|
||||
)
|
||||
| None ->
|
||||
console.warn("No group selected to add to archive %s", archiveId)
|
||||
| None ->
|
||||
console.warn("ACL has not been downloaded")
|
||||
| None -> console.warn ("No group selected to add to archive %s", archiveId)
|
||||
| None -> console.warn ("ACL has not been downloaded")
|
||||
|
||||
let handleDeleteArchive (id: System.Guid) =
|
||||
deleteArchive id
|
||||
@@ -263,17 +266,17 @@ module Archive =
|
||||
match res with
|
||||
| Ok deleted ->
|
||||
if deleted then
|
||||
console.info("Archive deleted successfully")
|
||||
console.info ("Archive deleted successfully")
|
||||
setDeleted true
|
||||
else
|
||||
setError (Some "Failed to delete archive")
|
||||
| Error err ->
|
||||
console.error("Error deleting archive: %s", err)
|
||||
console.error ("Error deleting archive: %s", err)
|
||||
setError (Some err)
|
||||
)
|
||||
|
||||
let handleSelectedGroupChange (groupOpt: string option) =
|
||||
console.debug("Selected group: %s", groupOpt)
|
||||
console.debug ("Selected group: %s", groupOpt)
|
||||
setSelectedGroup groupOpt
|
||||
|
||||
React.useEffect (
|
||||
@@ -290,13 +293,12 @@ module Archive =
|
||||
| Ok acl ->
|
||||
setArchive (Some archive)
|
||||
setAcl (Some acl)
|
||||
| Error err ->
|
||||
setError (Some err)
|
||||
| Error err -> setError (Some err)
|
||||
|
||||
setLoading false
|
||||
)
|
||||
| Error err ->
|
||||
console.error("Error fetching archive: %s", err)
|
||||
console.error ("Error fetching archive: %s", err)
|
||||
setLoading false
|
||||
setError (Some err)
|
||||
)
|
||||
@@ -338,7 +340,10 @@ module Archive =
|
||||
]
|
||||
else
|
||||
Html.div [
|
||||
prop.classes [ "flex-row"; "gap-8" ]
|
||||
prop.classes [
|
||||
"flex-row"
|
||||
"gap-8"
|
||||
]
|
||||
prop.children [
|
||||
if deleting then
|
||||
Html.button [
|
||||
@@ -350,37 +355,27 @@ module Archive =
|
||||
]
|
||||
|
||||
Html.button [
|
||||
prop.onClick (fun ev ->
|
||||
setDeleting false
|
||||
)
|
||||
prop.onClick (fun ev -> setDeleting false)
|
||||
prop.text "Cancel"
|
||||
]
|
||||
elif editing then
|
||||
Html.button [
|
||||
prop.onClick (fun ev ->
|
||||
setEditing false
|
||||
)
|
||||
prop.onClick (fun ev -> setEditing false)
|
||||
prop.text "Save"
|
||||
]
|
||||
|
||||
Html.button [
|
||||
prop.onClick (fun ev ->
|
||||
setEditing false
|
||||
)
|
||||
prop.onClick (fun ev -> setEditing false)
|
||||
prop.text "Cancel"
|
||||
]
|
||||
else
|
||||
Html.button [
|
||||
prop.onClick (fun ev ->
|
||||
setEditing true
|
||||
)
|
||||
prop.onClick (fun ev -> setEditing true)
|
||||
prop.text "Edit"
|
||||
]
|
||||
|
||||
Html.button [
|
||||
prop.onClick (fun ev ->
|
||||
setDeleting true
|
||||
)
|
||||
prop.onClick (fun ev -> setDeleting true)
|
||||
prop.text "Delete"
|
||||
]
|
||||
]
|
||||
@@ -411,8 +406,14 @@ module Archive =
|
||||
Archives.InfoSection archive
|
||||
|
||||
Html.div [
|
||||
prop.classes [ "flex-row"; "flex-wrap"; "gap-32" ]
|
||||
prop.classes [
|
||||
"flex-row"
|
||||
"flex-wrap"
|
||||
"gap-32"
|
||||
]
|
||||
prop.children [
|
||||
SubArchives archiveId
|
||||
|
||||
match aclOpt with
|
||||
| Some acl ->
|
||||
Html.div [
|
||||
@@ -426,7 +427,10 @@ module Archive =
|
||||
Html.h2 "Groups"
|
||||
|
||||
Html.div [
|
||||
prop.classes [ "flex-row"; "gap-8" ]
|
||||
prop.classes [
|
||||
"flex-row"
|
||||
"gap-8"
|
||||
]
|
||||
prop.children [
|
||||
Html.button [
|
||||
prop.disabled selectedGroup.IsNone
|
||||
@@ -441,7 +445,11 @@ module Archive =
|
||||
]
|
||||
|
||||
Html.div [
|
||||
prop.classes [ "flex-row"; "flex-wrap"; "gap-32" ]
|
||||
prop.classes [
|
||||
"flex-row"
|
||||
"flex-wrap"
|
||||
"gap-32"
|
||||
]
|
||||
prop.children [
|
||||
Html.div [
|
||||
prop.classes [ "grow" ]
|
||||
@@ -465,7 +473,12 @@ module Archive =
|
||||
prop.key group
|
||||
prop.children [
|
||||
Html.a [
|
||||
prop.href (Router.format("groups", group))
|
||||
prop.href (
|
||||
Router.format (
|
||||
"groups",
|
||||
group
|
||||
)
|
||||
)
|
||||
prop.text group
|
||||
]
|
||||
]
|
||||
@@ -487,7 +500,11 @@ module Archive =
|
||||
Html.h3 "OpenFGA"
|
||||
|
||||
Html.div [
|
||||
prop.classes [ "flex-row"; "flex-wrap"; "gap-32" ]
|
||||
prop.classes [
|
||||
"flex-row"
|
||||
"flex-wrap"
|
||||
"gap-32"
|
||||
]
|
||||
prop.children [
|
||||
Html.div [
|
||||
prop.classes [ "grow" ]
|
||||
@@ -497,7 +514,10 @@ module Archive =
|
||||
"archive"
|
||||
(string archive.archiveId)
|
||||
"view"
|
||||
{ Type = "group"; Relation = Some "member" }
|
||||
{
|
||||
Type = "group"
|
||||
Relation = Some "member"
|
||||
}
|
||||
{| time = System.DateTime.Now |}
|
||||
]
|
||||
]
|
||||
@@ -506,12 +526,16 @@ module Archive =
|
||||
prop.classes [ "grow" ]
|
||||
prop.children [
|
||||
Html.h4 "Groups who's members can exec"
|
||||
Html.p "With task '*', usage '-1' and current time"
|
||||
Html.p
|
||||
"With task '*', usage '-1' and current time"
|
||||
GroupFGAList
|
||||
"archive"
|
||||
(string archive.archiveId)
|
||||
"exec"
|
||||
{ Type = "group"; Relation = Some "member" }
|
||||
{
|
||||
Type = "group"
|
||||
Relation = Some "member"
|
||||
}
|
||||
{|
|
||||
task = "*"
|
||||
usage = "-1"
|
||||
@@ -539,7 +563,11 @@ module Archive =
|
||||
Html.h2 "Owners"
|
||||
|
||||
Html.div [
|
||||
prop.classes [ "flex-row"; "flex-wrap"; "gap-8" ]
|
||||
prop.classes [
|
||||
"flex-row"
|
||||
"flex-wrap"
|
||||
"gap-8"
|
||||
]
|
||||
prop.children [
|
||||
Html.div [
|
||||
prop.classes [ "grow" ]
|
||||
@@ -558,7 +586,12 @@ module Archive =
|
||||
prop.key owner
|
||||
prop.children [
|
||||
Html.a [
|
||||
prop.href (Router.format("users", owner))
|
||||
prop.href (
|
||||
Router.format (
|
||||
"users",
|
||||
owner
|
||||
)
|
||||
)
|
||||
prop.text owner
|
||||
]
|
||||
]
|
||||
@@ -608,7 +641,9 @@ module Archive =
|
||||
prop.key user
|
||||
prop.children [
|
||||
Html.a [
|
||||
prop.href (Router.format("users", user))
|
||||
prop.href (
|
||||
Router.format ("users", user)
|
||||
)
|
||||
prop.text user
|
||||
]
|
||||
]
|
||||
@@ -624,7 +659,11 @@ module Archive =
|
||||
Html.h3 "OpenFGA"
|
||||
|
||||
Html.div [
|
||||
prop.classes [ "flex-row"; "flex-wrap"; "gap-32" ]
|
||||
prop.classes [
|
||||
"flex-row"
|
||||
"flex-wrap"
|
||||
"gap-32"
|
||||
]
|
||||
prop.children [
|
||||
Html.div [
|
||||
prop.classes [ "grow" ]
|
||||
@@ -703,21 +742,14 @@ module Archive =
|
||||
|> Array.map (fun share ->
|
||||
Html.li [
|
||||
prop.key share
|
||||
prop.children [
|
||||
Html.a [
|
||||
prop.text (string share)
|
||||
]
|
||||
]
|
||||
prop.children [ Html.a [ prop.text (string share) ] ]
|
||||
]
|
||||
)
|
||||
)
|
||||
]
|
||||
]
|
||||
]
|
||||
| None ->
|
||||
Html.h2 "No ACL found"
|
||||
|
||||
SubArchives archiveId
|
||||
| None -> Html.h2 "No ACL found"
|
||||
|
||||
match Utils.tryStr archive.json with
|
||||
| Some jsonStr ->
|
||||
@@ -731,17 +763,13 @@ module Archive =
|
||||
style.maxHeight (length.px 512)
|
||||
style.overflowY.scroll
|
||||
]
|
||||
prop.children [
|
||||
Html.pre (JS.JSON.stringify(json, space = 4))
|
||||
]
|
||||
prop.children [ Html.pre (JS.JSON.stringify (json, space = 4)) ]
|
||||
]
|
||||
]
|
||||
]
|
||||
| None ->
|
||||
Html.none
|
||||
| None -> Html.none
|
||||
]
|
||||
]
|
||||
|
||||
| None ->
|
||||
Html.h1 "Archive not found"
|
||||
]
|
||||
| None -> Html.h1 "Archive not found"
|
||||
]
|
||||
@@ -1,8 +1,34 @@
|
||||
namespace Oceanbox.Codex
|
||||
|
||||
open Feliz
|
||||
open Feliz.Router
|
||||
|
||||
type Archives =
|
||||
[<ReactComponent>]
|
||||
static member RefLink (archiveId: System.Guid) =
|
||||
let archiveOpt, setArchive = React.useState<Archmaester.Dto.ArchiveProps option> None
|
||||
|
||||
React.useEffect (
|
||||
(fun () ->
|
||||
Archives.Utils.fetchArchive archiveId
|
||||
|> Promise.iter (fun res ->
|
||||
match res with
|
||||
| Ok archive ->
|
||||
setArchive (Some archive)
|
||||
| Error err ->
|
||||
Browser.Dom.console.error ("Error fetching archive: %s", err)
|
||||
)
|
||||
),
|
||||
[| box archiveId |]
|
||||
)
|
||||
|
||||
Html.a [
|
||||
prop.href (Router.format("archives", string archiveId))
|
||||
match archiveOpt with
|
||||
| Some archive -> prop.text archive.name
|
||||
| None -> prop.text "link"
|
||||
]
|
||||
|
||||
[<ReactComponent>]
|
||||
static member InfoSection(archive: Archmaester.Dto.ArchiveProps) =
|
||||
let archiveLength : System.TimeSpan = archive.endTime - archive.startTime
|
||||
@@ -13,49 +39,67 @@ type Archives =
|
||||
Html.section [
|
||||
prop.classes [ "flex-row"; "flex-wrap"; "gap-16" ]
|
||||
prop.children [
|
||||
Html.ul [
|
||||
Html.div [
|
||||
prop.style [
|
||||
style.flexBasis (length.px 384)
|
||||
]
|
||||
prop.children [
|
||||
Html.li [
|
||||
prop.text (sprintf "Description: %s" archive.description)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Archive type: %s" (string archive.archiveType))
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Projection: %s" archive.projection)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Frequency: %d" archive.freq)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Frames: %d" archive.frames)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Created: %s" (archive.created.ToLongDateString()))
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Start time: %s" (archive.startTime.ToLongDateString()))
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "End time: %s" (archive.endTime.ToLongDateString()))
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Length: %d days %d hours" archiveLength.Days archiveLength.Hours)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Owner: %s" archive.owner)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Expires: %s" (archive.expires |> Option.map string |> Option.defaultValue ""))
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Publised: %b" archive.isPublished)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Public: %b" archive.isPublic)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Location: %s" "tos")
|
||||
Html.h2 "Props"
|
||||
|
||||
Html.ul [
|
||||
prop.children [
|
||||
Html.li [
|
||||
prop.text (sprintf "Description: %s" archive.description)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Archive type: %s" (string archive.archiveType))
|
||||
]
|
||||
match archive.reference with
|
||||
| Some refId ->
|
||||
Html.li [
|
||||
prop.children [
|
||||
Html.text "Parent: "
|
||||
Archives.RefLink refId
|
||||
]
|
||||
]
|
||||
| None -> ()
|
||||
Html.li [
|
||||
prop.text (sprintf "Projection: %s" archive.projection)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Frequency: %d" archive.freq)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Frames: %d" archive.frames)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Created: %s" (archive.created.ToLongDateString()))
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Start time: %s" (archive.startTime.ToLongDateString()))
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "End time: %s" (archive.endTime.ToLongDateString()))
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Length: %d days %d hours" archiveLength.Days archiveLength.Hours)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Owner: %s" archive.owner)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Expires: %s" (archive.expires |> Option.map string |> Option.defaultValue ""))
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Publised: %b" archive.isPublished)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Public: %b" archive.isPublic)
|
||||
]
|
||||
Html.li [
|
||||
prop.text (sprintf "Location: %s" "tos")
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
@@ -69,4 +113,4 @@ type Archives =
|
||||
prop.children (Map.View focalPoint [||])
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
@@ -179,8 +179,8 @@ module Admin =
|
||||
else
|
||||
return Error "Filter must include archive id"
|
||||
with e ->
|
||||
do logger.LogError (e, "Error in getArchives from {User}", user)
|
||||
return Error "Error fetching archive count"
|
||||
do logger.LogError (e, "Error in getArchiveRefs from {User}", user)
|
||||
return Error "Error fetching archive refs"
|
||||
}
|
||||
|
||||
let getArchives
|
||||
@@ -325,4 +325,4 @@ module Admin =
|
||||
|> Remoting.withErrorHandler Utils.rpcErrorHandler
|
||||
|> Remoting.fromContext impl
|
||||
|> Remoting.withRouteBuilder Remoting.routeBuilder
|
||||
|> Remoting.buildHttpHandler
|
||||
|> Remoting.buildHttpHandler
|
||||
@@ -280,12 +280,22 @@ module Archmaester =
|
||||
async {
|
||||
let archiveId = filter.id |> Option.toNullable
|
||||
|
||||
let! wantedArchive =
|
||||
db.Archives
|
||||
.AsNoTracking()
|
||||
.SingleAsync(fun archive -> if filter.id.IsSome then archive.ArchiveId = filter.id.Value else false)
|
||||
|> Async.AwaitTask
|
||||
let! entities =
|
||||
db.Archives
|
||||
.AsNoTracking()
|
||||
.Where(fun archive -> archive.RefId ?=? archiveId)
|
||||
.Include(fun archive -> archive.Attribs)
|
||||
.ThenInclude(fun attribs -> attribs.Type)
|
||||
.Where(fun archive ->
|
||||
archive.RefId ?=? archiveId
|
||||
|| archive.Attribs.Associations.Any(fun ass ->
|
||||
ass.RefId = wantedArchive.AttribsId
|
||||
)
|
||||
)
|
||||
.ToArrayAsync ()
|
||||
|> Async.AwaitTask
|
||||
|
||||
@@ -420,4 +430,4 @@ module Archmaester =
|
||||
|> Async.AwaitTask
|
||||
|
||||
return entities
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user