diff --git a/src/Client/MainComponents/Widgets.fs b/src/Client/MainComponents/Widgets.fs index 0a4faec1..05a2d1c2 100644 --- a/src/Client/MainComponents/Widgets.fs +++ b/src/Client/MainComponents/Widgets.fs @@ -264,7 +264,7 @@ type Widget = ModalElements.Box( model.ProtocolState.TemplateSelected.Value.Name, "", - SelectiveTemplateFromDBModal.displaySelectedProtocolElements(model, selectedColumns, setSelectedColumns, dispatch, false)) + SelectiveTemplateFromDBModal.displaySelectedProtocolElements(model.ProtocolState.TemplateSelected, selectedColumns, setSelectedColumns, dispatch, false)) ] Html.div [ SelectiveTemplateFromDBModal.AddFromDBToTableButton model selectedColumns importTypeState useTemplateName.TemplateName dispatch diff --git a/src/Client/Messages.fs b/src/Client/Messages.fs index 94b90179..923d62b6 100644 --- a/src/Client/Messages.fs +++ b/src/Client/Messages.fs @@ -83,6 +83,7 @@ module Protocol = | GetAllProtocolsRequest | GetAllProtocolsResponse of string | SelectProtocol of Template + | SelectProtocols of Template list | AddProtocol of Template | ProtocolIncreaseTimesUsed of protocolName:string diff --git a/src/Client/Pages/ProtocolTemplates/ProtocolSearchViewComponent.fs b/src/Client/Pages/ProtocolTemplates/ProtocolSearchViewComponent.fs index d3f4ea2a..95f913a8 100644 --- a/src/Client/Pages/ProtocolTemplates/ProtocolSearchViewComponent.fs +++ b/src/Client/Pages/ProtocolTemplates/ProtocolSearchViewComponent.fs @@ -618,17 +618,14 @@ type Search = prop.children [ Daisy.button.a [ button.sm - //prop.onClick (fun _ -> - // SelectProtocol template |> ProtocolMsg |> dispatch - //) + prop.onClick (fun _ -> + if model.ProtocolState.TemplatesSelected.Length > 1 then + SelectProtocols model.ProtocolState.TemplatesSelected |> ProtocolMsg |> dispatch + else + SelectProtocol model.ProtocolState.TemplatesSelected.Head |> ProtocolMsg |> dispatch + ) button.wide button.success - - if model.ProtocolState.TemplatesSelected.Length > 0 then - button.active - else - button.disabled - prop.text "Select templates" ] ] @@ -645,6 +642,7 @@ type Search = button ] ] - ModalElements.Box("Selected Templates", "fa-solid fa-cog", element) + if model.ProtocolState.TemplatesSelected.Length > 0 then + ModalElements.Box("Selected Templates", "fa-solid fa-cog", element) ] ] diff --git a/src/Client/Pages/ProtocolTemplates/ProtocolState.fs b/src/Client/Pages/ProtocolTemplates/ProtocolState.fs index 3ba2b9be..9e8667c1 100644 --- a/src/Client/Pages/ProtocolTemplates/ProtocolState.fs +++ b/src/Client/Pages/ProtocolTemplates/ProtocolState.fs @@ -61,6 +61,15 @@ module Protocol = Model.PageState.SidebarPage = Routing.SidebarPage.Protocol } state, Cmd.ofMsg (UpdateModel nextModel) + | SelectProtocols prots -> + log "SelectProtocols" + let newProts = prots |> List.rev + let nextModel = { + model with + Model.ProtocolState.TemplatesSelected = newProts + Model.PageState.SidebarPage = Routing.SidebarPage.Protocol + } + state, Cmd.ofMsg (UpdateModel nextModel) | AddProtocol prot -> log "AddProtocol" let templates = @@ -87,6 +96,7 @@ module Protocol = | RemoveSelectedProtocol -> let nextState = { state with - TemplateSelected = None + TemplateSelected = None + TemplatesSelected = [] } nextState, Cmd.none diff --git a/src/Client/Pages/ProtocolTemplates/SelectiveTemplateFromDB.fs b/src/Client/Pages/ProtocolTemplates/SelectiveTemplateFromDB.fs index 73457284..46320b80 100644 --- a/src/Client/Pages/ProtocolTemplates/SelectiveTemplateFromDB.fs +++ b/src/Client/Pages/ProtocolTemplates/SelectiveTemplateFromDB.fs @@ -35,7 +35,7 @@ type SelectiveTemplateFromDBModal = ] ] - static member ToProtocolSearchElement (model: Model) dispatch = + static member ToProtocolSearchElement(model: Model) dispatch = Daisy.button.button [ prop.onClick(fun _ -> UpdateModel {model with Model.PageState.SidebarPage = Routing.SidebarPage.ProtocolSearch} |> dispatch) button.primary @@ -44,32 +44,37 @@ type SelectiveTemplateFromDBModal = ] [] - static member displaySelectedProtocolElements (model: Model, selectionInformation: SelectedColumns, setSelectedColumns: SelectedColumns -> unit, dispatch, ?hasIcon: bool) = + static member displaySelectedProtocolElements(selectedTemplate: Template option, selectionInformation: SelectedColumns, setSelectedColumns: SelectedColumns -> unit, dispatch, ?hasIcon: bool) = let hasIcon = defaultArg hasIcon true Html.div [ prop.style [style.overflowX.auto; style.marginBottom (length.rem 1)] prop.children [ - if model.ProtocolState.TemplateSelected.IsSome then + if selectedTemplate.IsSome then if hasIcon then Html.i [prop.className "fa-solid fa-cog"] - Html.span $"Template: {model.ProtocolState.TemplateSelected.Value.Name}" - if model.ProtocolState.TemplateSelected.IsSome then - SelectiveImportModal.TableWithImportColumnCheckboxes(model.ProtocolState.TemplateSelected.Value.Table, selectionInformation, setSelectedColumns) + Html.span $"Template: {selectedTemplate.Value.Name}" + if selectedTemplate.IsSome then + SelectiveImportModal.TableWithImportColumnCheckboxes(selectedTemplate.Value.Table, selectionInformation, setSelectedColumns) ] ] static member AddFromDBToTableButton (model: Model) selectionInformation importType useTemplateName dispatch = let addTemplate (templatePot: Template option, selectedColumns) = - if model.ProtocolState.TemplateSelected.IsNone then + if model.ProtocolState.TemplateSelected.IsNone && model.ProtocolState.TemplatesSelected.Length = 0 then failwith "No template selected!" - if templatePot.IsSome then + if templatePot.IsSome || model.ProtocolState.TemplatesSelected.Length = 1 then + let table = templatePot.Value.Table + SpreadsheetInterface.AddTemplate(table, selectedColumns, importType, useTemplateName) |> InterfaceMsg |> dispatch + if model.ProtocolState.TemplatesSelected.Length > 1 then let table = templatePot.Value.Table SpreadsheetInterface.AddTemplate(table, selectedColumns, importType, useTemplateName) |> InterfaceMsg |> dispatch Html.div [ prop.className "join flex flex-row justify-center gap-2" prop.children [ - ModalElements.Button("Add template", addTemplate, (model.ProtocolState.TemplateSelected, selectionInformation.Columns), model.ProtocolState.TemplateSelected.IsNone) - if model.ProtocolState.TemplateSelected.IsSome then + let isDisabled = + model.ProtocolState.TemplateSelected.IsSome || model.ProtocolState.TemplatesSelected.Length = 0 + ModalElements.Button("Add template", addTemplate, (model.ProtocolState.TemplateSelected, selectionInformation.Columns), isDisabled) + if model.ProtocolState.TemplateSelected.IsSome || model.ProtocolState.TemplatesSelected.Length > 0 then Daisy.button.a [ button.outline prop.onClick (fun _ -> Protocol.RemoveSelectedProtocol |> ProtocolMsg |> dispatch) @@ -80,7 +85,7 @@ type SelectiveTemplateFromDBModal = ] [] - static member Main (model: Model, dispatch) = + static member Main(model: Model, dispatch) = let length = if model.ProtocolState.TemplateSelected.IsSome then model.ProtocolState.TemplateSelected.Value.Table.Columns.Length @@ -88,11 +93,12 @@ type SelectiveTemplateFromDBModal = let selectedColumns, setSelectedColumns = React.useState(SelectedColumns.init length) let importTypeState, setImportTypeState = React.useState(SelectiveImportModalState.init) let useTemplateName, setUseTemplateName = React.useState(AdaptTableName.init) + log("model.ProtocolState.TemplatesSelected.Length", model.ProtocolState.TemplatesSelected.Length) SidebarComponents.SidebarLayout.LogicContainer [ Html.div [ SelectiveTemplateFromDBModal.ToProtocolSearchElement model dispatch ] - if model.ProtocolState.TemplateSelected.IsSome then + if model.ProtocolState.TemplateSelected.IsSome || model.ProtocolState.TemplatesSelected.Length > 0 then Html.div [ SelectiveImportModal.RadioPluginsBox( "Import Type", @@ -107,6 +113,12 @@ type SelectiveTemplateFromDBModal = fun importType -> {importTypeState with ImportType = importType} |> setImportTypeState ) ] + if model.ProtocolState.TemplateSelected.IsSome || model.ProtocolState.TemplatesSelected.Length = 1 then + let template = + if model.ProtocolState.TemplateSelected.IsSome then + model.ProtocolState.TemplateSelected.Value + else + model.ProtocolState.TemplatesSelected.Head Html.div [ ModalElements.Box( "Rename Table", @@ -117,8 +129,17 @@ type SelectiveTemplateFromDBModal = ModalElements.Box( model.ProtocolState.TemplateSelected.Value.Name, "fa-solid fa-cog", - SelectiveTemplateFromDBModal.displaySelectedProtocolElements(model, selectedColumns, setSelectedColumns, dispatch, false)) + SelectiveTemplateFromDBModal.displaySelectedProtocolElements(Some template, selectedColumns, setSelectedColumns, dispatch, false)) ] + else if model.ProtocolState.TemplatesSelected.Length > 1 then + for i in 0..model.ProtocolState.TemplatesSelected.Length-1 do + let template = model.ProtocolState.TemplatesSelected.[i] + Html.div [ + ModalElements.Box( + template.Name, + "fa-solid fa-cog", + SelectiveTemplateFromDBModal.displaySelectedProtocolElements(Some template, selectedColumns, setSelectedColumns, dispatch, false)) + ] Html.div [ SelectiveTemplateFromDBModal.AddFromDBToTableButton model selectedColumns importTypeState useTemplateName.TemplateName dispatch ] diff --git a/src/Client/Routing.fs b/src/Client/Routing.fs index 5d014d43..11047b57 100644 --- a/src/Client/Routing.fs +++ b/src/Client/Routing.fs @@ -15,13 +15,13 @@ type SidebarPage = member this.AsStringRdbl = match this with - | BuildingBlock -> "Building Blocks" - | TermSearch -> "Terms" - | FilePicker -> "File Picker" - | Protocol -> "Templates" - | ProtocolSearch -> "Template Search" - | JsonExport -> "Json Export" - | DataAnnotator -> "Data Annotator" + | BuildingBlock -> "Building Blocks" + | TermSearch -> "Terms" + | FilePicker -> "File Picker" + | Protocol -> "Templates" + | ProtocolSearch -> "Template Search" + | JsonExport -> "Json Export" + | DataAnnotator -> "Data Annotator" member this.AsIcon() = let createElem (icons: ReactElement list) = @@ -31,19 +31,19 @@ type SidebarPage = ] match this with - | TermSearch -> + | TermSearch -> createElem [Html.i [prop.className "fa-solid fa-magnifying-glass-plus" ]] - | BuildingBlock -> + | BuildingBlock -> createElem [ Html.i [prop.className "fa-solid fa-circle-plus" ]; Html.i [prop.className "fa-solid fa-table-columns" ]] - | Protocol -> + | Protocol -> createElem [ Html.i [prop.className "fa-solid fa-circle-plus" ];Html.i [prop.className "fa-solid fa-table" ]] - | ProtocolSearch -> + | ProtocolSearch -> createElem [ Html.i [prop.className "fa-solid fa-table" ]; Html.i [prop.className "fa-solid fa-magnifying-glass" ]] - | JsonExport -> + | JsonExport -> createElem [ Html.i [prop.className "fa-solid fa-file-export" ]] - | FilePicker -> + | FilePicker -> createElem [ Html.i [prop.className "fa-solid fa-file-signature" ]] - | DataAnnotator -> + | DataAnnotator -> createElem [ Html.i [prop.className "fa-solid fa-object-group" ]] [] @@ -55,10 +55,10 @@ type MainPage = member this.AsStringRdbl = match this with - | About -> "About" + | About -> "About" | PrivacyPolicy -> "Privacy Policy" - | Settings -> "Settings" - | Default -> "Home" + | Settings -> "Settings" + | Default -> "Home" /// The different pages of the application. If you add a new page, then add an entry here. [] @@ -74,7 +74,7 @@ module Routing = open Elmish.Navigation /// The URL is turned into a Result. - let route : Parser Route,_> = + let route : Parser Route, _> = oneOf [ map Route.Home (s "" intParam "is_swatehost") ] diff --git a/src/Client/Views/SidebarView.fs b/src/Client/Views/SidebarView.fs index 307179d5..5bd733df 100644 --- a/src/Client/Views/SidebarView.fs +++ b/src/Client/Views/SidebarView.fs @@ -10,7 +10,7 @@ open Feliz open Feliz.DaisyUI type SidebarView = - static member private content (model:Model) (dispatch: Msg -> unit) = + static member private content (model: Model) (dispatch: Msg -> unit) = Html.div [ prop.className "grow overflow-y-auto" prop.children [