Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature excel enable multiple templates #590

Closed
wants to merge 37 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
bffed7f
Enable selection of terms to import into excel
Etschbeijer Nov 27, 2024
2aa0ddf
Fix error in swate alpha
Etschbeijer Nov 28, 2024
b179a4a
Move basic modal element creation methods into separat file
Etschbeijer Nov 28, 2024
b46fc28
Replace existing TemplateFromDB with Modal
Etschbeijer Nov 28, 2024
04a2cb7
Add usage of selected columns to swate alpha
Etschbeijer Nov 29, 2024
12d4d78
Adapt box layout
Etschbeijer Dec 2, 2024
450cda8
Enable column selection and import type selection for templates and j…
Etschbeijer Dec 3, 2024
c2064a5
update layout
Etschbeijer Dec 3, 2024
4d11c9a
Improve layout by adding gaps
Etschbeijer Dec 3, 2024
2cf7798
Adapted Cehckbox height
Etschbeijer Dec 3, 2024
ace120f
Apply review changes
Etschbeijer Dec 3, 2024
849b155
Implemente review changes
Etschbeijer Dec 3, 2024
869ade6
Implemented review suggestions
Etschbeijer Dec 3, 2024
ca0a1d4
Implement review changes
Etschbeijer Dec 3, 2024
6ddefa4
Implement review changes
Etschbeijer Dec 3, 2024
5feb2b1
Implement review changes
Etschbeijer Dec 4, 2024
65c36e8
Enable the addition of names in excel
Etschbeijer Dec 4, 2024
9cf7d21
Enable usage of selectedColumns in swate alpha
Etschbeijer Dec 4, 2024
88edd04
Rename Method to origin
Etschbeijer Dec 4, 2024
95dcf24
Enable naming of radioGroup to enable usage in swate alpha
Etschbeijer Dec 4, 2024
76e4422
Merge branch 'Feature_Excel_EnableSelectionOfImportedTermsForTemplate…
Etschbeijer Dec 5, 2024
463a70c
Updated takeover templatename for excel
Etschbeijer Dec 5, 2024
e4d42d8
Rename table in swate alpha
Etschbeijer Dec 5, 2024
b74953d
Create basic structure for adding multiple templates
Etschbeijer Dec 9, 2024
488a75b
Enable viewing of all selected templates
Etschbeijer Dec 10, 2024
dc3e485
Add minor refactoring
Etschbeijer Dec 11, 2024
41c76e6
Removed templateSelected
Etschbeijer Dec 12, 2024
1486fc6
Implement selectImportType
Etschbeijer Dec 12, 2024
57251b3
Enable import of multiple templates with add and join
Etschbeijer Dec 12, 2024
0fee87f
Enable adding and joining of templates
Etschbeijer Dec 13, 2024
8de6cb0
Enable merging of different cell types from template
Etschbeijer Dec 13, 2024
d726241
Implement import of multiple templates in swate alpha
Etschbeijer Dec 16, 2024
d43aae3
implement review changes
Etschbeijer Dec 17, 2024
a8e7eae
Simplify code
Etschbeijer Dec 17, 2024
ec72dc3
Implement regex fix
Etschbeijer Dec 17, 2024
500dc72
Reduce code duplication :fire:
Freymaurer Dec 17, 2024
c5739f1
Move selected box above template search
Etschbeijer Dec 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Client/Client.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
<Compile Include="Messages.fs" />
<Compile Include="ARCitect\Interop.fs" />
<Compile Include="ARCitect\ARCitect.fs" />
<Compile Include="Modals\ModalElements.fs" />
<Compile Include="Modals\Util.fs" />
<Compile Include="Modals\ContextMenus\Util.fs" />
<Compile Include="Modals\ContextMenus\Base.fs" />
Expand Down Expand Up @@ -90,7 +91,7 @@
<Compile Include="Pages\ProtocolTemplates\ProtocolState.fs" />
<Compile Include="Pages\ProtocolTemplates\ProtocolSearchViewComponent.fs" />
<Compile Include="Pages\ProtocolTemplates\ProtocolSearch.fs" />
<Compile Include="Pages\ProtocolTemplates\TemplateFromDB.fs" />
<Compile Include="Pages\ProtocolTemplates\SelectiveTemplateFromDB.fs" />
<Compile Include="Pages\ProtocolTemplates\TemplateFromFile.fs" />
<Compile Include="Pages\ProtocolTemplates\ProtocolView.fs" />
<Compile Include="Pages\FilePicker\FilePickerView.fs" />
Expand Down
1 change: 1 addition & 0 deletions src/Client/GenericComponents.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module DaisyUiExtensions =
static member active = prop.className "modal-open"

type Components =

static member DeleteButton(?children, ?props) =
Daisy.button.button [
button.square
Expand Down
3 changes: 2 additions & 1 deletion src/Client/Helper.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ module Helper

open Fable.Core

open System

let log (a) = Browser.Dom.console.log a

let logw (a) = Browser.Dom.console.warn a
Expand Down Expand Up @@ -121,7 +123,6 @@ let throttleAndDebounce(fn: 'a -> unit, timespan: int) =
timespan
id <- Some timeoutId


type Clipboard =
abstract member writeText: string -> JS.Promise<unit>
abstract member readText: unit -> JS.Promise<string>
Expand Down
31 changes: 16 additions & 15 deletions src/Client/MainComponents/Widgets.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ open Feliz
open Feliz.DaisyUI
open Browser.Types
open LocalStorage.Widgets
open Modals
open Types.JsonImport

module private InitExtensions =

Expand Down Expand Up @@ -31,7 +33,7 @@ module private MoveEventListener =

open Fable.Core.JsInterop

let ensurePositionInsideWindow (element:IRefValue<HTMLElement option>) (position: Rect) =
let ensurePositionInsideWindow (element: IRefValue<HTMLElement option>) (position: Rect) =
let maxX = Browser.Dom.window.innerWidth - element.current.Value.offsetWidth;
let tempX = position.X
let newX = System.Math.Min(System.Math.Max(tempX,0),int maxX)
Expand All @@ -40,18 +42,18 @@ module private MoveEventListener =
let newY = System.Math.Min(System.Math.Max(tempY,0),int maxY)
{X = newX; Y = newY}

let calculatePosition (element:IRefValue<HTMLElement option>) (startPosition: Rect) = fun (e: Event) ->
let calculatePosition (element: IRefValue<HTMLElement option>) (startPosition: Rect) = fun (e: Event) ->
let e : MouseEvent = !!e
let tempX = int e.clientX - startPosition.X
let tempY = int e.clientY - startPosition.Y
let tempPosition = {X = tempX; Y = tempY}
ensurePositionInsideWindow element tempPosition

let onmousemove (element:IRefValue<HTMLElement option>) (startPosition: Rect) setPosition = fun (e: Event) ->
let onmousemove (element: IRefValue<HTMLElement option>) (startPosition: Rect) setPosition = fun (e: Event) ->
let nextPosition = calculatePosition element startPosition e
setPosition (Some nextPosition)

let onmouseup (prefix,element:IRefValue<HTMLElement option>) onmousemove =
let onmouseup (prefix,element: IRefValue<HTMLElement option>) onmousemove =
Browser.Dom.document.removeEventListener("mousemove", onmousemove)
if element.current.IsSome then
let rect = element.current.Value.getBoundingClientRect()
Expand All @@ -74,7 +76,7 @@ module private ResizeEventListener =
let onmouseup (prefix, element: IRefValue<HTMLElement option>) onmousemove =
Browser.Dom.document.removeEventListener("mousemove", onmousemove)
if element.current.IsSome then
Size.write(prefix,{X = int element.current.Value.offsetWidth; Y = int element.current.Value.offsetHeight})
Size.write(prefix, {X = int element.current.Value.offsetWidth; Y = int element.current.Value.offsetHeight})

module private Elements =

Expand Down Expand Up @@ -207,33 +209,32 @@ type Widget =
let prefix = WidgetLiterals.BuildingBlock
Widget.Base(content, prefix, rmv, help)


[<ReactComponent>]
static member Templates (model: Model, dispatch, rmv: MouseEvent -> unit) =
let templates, setTemplates = React.useState(model.ProtocolState.Templates)
let templates = model.ProtocolState.Templates
let config, setConfig = React.useState(TemplateFilterConfig.init)
let filteredTemplates = Protocol.Search.filterTemplates (templates, config)
React.useEffectOnce(fun _ -> Messages.Protocol.GetAllProtocolsRequest |> Messages.ProtocolMsg |> dispatch)
React.useEffect((fun _ -> setTemplates model.ProtocolState.Templates), [|box model.ProtocolState.Templates|])
let selectContent() =
[
Protocol.Search.FileSortElement(model, config, setConfig, "@md/templateWidget:grid-cols-3")
ModalElements.Box("Selected Templates", "fa-solid fa-cog", Search.SelectedTemplatesElement model dispatch)
Protocol.Search.Component (filteredTemplates, model, dispatch, length.px 350)
]
let insertContent() =
[
Html.div [
Protocol.TemplateFromDB.addFromDBToTableButton model dispatch
]
Html.div [
prop.style [style.maxHeight (length.px 350); style.overflow.auto]
prop.children [
Protocol.TemplateFromDB.displaySelectedProtocolEle model dispatch
]
prop.className "flex flex-col gap-2"
prop.children (SelectiveTemplateFromDB.Main(model, dispatch))
]
]

let content =
let switchContent = if model.ProtocolState.TemplateSelected.IsNone then selectContent() else insertContent()
let switchContent =
if model.ProtocolState.TemplatesSelected.Length > 0 && model.PageState.SidebarPage = Routing.SidebarPage.Protocol then
insertContent()
else selectContent()
Html.div [
prop.className "flex flex-col gap-4 @container/templateWidget"
prop.children switchContent
Expand Down
75 changes: 37 additions & 38 deletions src/Client/Messages.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ open Fable.Remoting.Client
open Fable.SimpleJson
open Database

open OfficeInterop
open Model
open Routing
open ARCtrl
open Fable.Core

Expand All @@ -25,13 +23,13 @@ type System.Exception with
| ex ->
ex.Message

let curry f a b = f (a,b)
let curry f a b = f (a, b)

module TermSearch =

type Msg =
| UpdateSelectedTerm of OntologyAnnotation option
| UpdateParentTerm of OntologyAnnotation option
| UpdateSelectedTerm of OntologyAnnotation option
| UpdateParentTerm of OntologyAnnotation option


module AdvancedSearch =
Expand All @@ -53,39 +51,40 @@ type DevMsg =

module PersistentStorage =
type Msg =
| NewSearchableOntologies of Ontology []
| UpdateAppVersion of string
| UpdateShowSidebar of bool
| NewSearchableOntologies of Ontology []
| UpdateAppVersion of string
| UpdateShowSidebar of bool

module FilePicker =
type Msg =
| LoadNewFiles of string list
| UpdateFileNames of newFileNames:(int*string) list
| LoadNewFiles of string list
| UpdateFileNames of newFileNames:(int*string) list

module BuildingBlock =

open TermSearch

type Msg =
| UpdateHeaderWithIO of CompositeHeaderDiscriminate * IOType
| UpdateHeaderCellType of CompositeHeaderDiscriminate
| UpdateHeaderArg of U2<OntologyAnnotation,IOType> option
| UpdateBodyCellType of CompositeCellDiscriminate
| UpdateBodyArg of U2<string, OntologyAnnotation> option
| UpdateHeaderWithIO of CompositeHeaderDiscriminate * IOType
| UpdateHeaderCellType of CompositeHeaderDiscriminate
| UpdateHeaderArg of U2<OntologyAnnotation,IOType> option
| UpdateBodyCellType of CompositeCellDiscriminate
| UpdateBodyArg of U2<string, OntologyAnnotation> option

module Protocol =

type Msg =
// Client
| UpdateTemplates of Template []
| UpdateLoading of bool
| RemoveSelectedProtocol
| UpdateTemplates of Template []
| UpdateLoading of bool
| RemoveSelectedProtocols
// // ------ Protocol from Database ------
| GetAllProtocolsForceRequest
| GetAllProtocolsRequest
| GetAllProtocolsResponse of string
| SelectProtocol of Template
| ProtocolIncreaseTimesUsed of protocolName:string
| GetAllProtocolsResponse of string
| SelectProtocols of Template list
| AddProtocol of Template
| ProtocolIncreaseTimesUsed of protocolName:string

type SettingsDataStewardMsg =
// Client
Expand All @@ -95,26 +94,26 @@ type TopLevelMsg =
| CloseSuggestions

type Msg =
| UpdateModel of Model
| DevMsg of DevMsg
| OntologyMsg of Ontologies.Msg
| TermSearchMsg of TermSearch.Msg
| AdvancedSearchMsg of AdvancedSearch.Msg
| OfficeInteropMsg of OfficeInterop.Msg
| PersistentStorageMsg of PersistentStorage.Msg
| FilePickerMsg of FilePicker.Msg
| BuildingBlockMsg of BuildingBlock.Msg
| ProtocolMsg of Protocol.Msg
| UpdateModel of Model
| DevMsg of DevMsg
| OntologyMsg of Ontologies.Msg
| TermSearchMsg of TermSearch.Msg
| AdvancedSearchMsg of AdvancedSearch.Msg
| OfficeInteropMsg of OfficeInterop.Msg
| PersistentStorageMsg of PersistentStorage.Msg
| FilePickerMsg of FilePicker.Msg
| BuildingBlockMsg of BuildingBlock.Msg
| ProtocolMsg of Protocol.Msg
// | CytoscapeMsg of Cytoscape.Msg
| DataAnnotatorMsg of DataAnnotator.Msg
| SpreadsheetMsg of Spreadsheet.Msg
| DataAnnotatorMsg of DataAnnotator.Msg
| SpreadsheetMsg of Spreadsheet.Msg
/// This is used to forward Msg to SpreadsheetMsg/OfficeInterop
| InterfaceMsg of SpreadsheetInterface.Msg
| Batch of seq<Messages.Msg>
| Run of (unit -> unit)
| UpdateHistory of LocalHistory.Model
| InterfaceMsg of SpreadsheetInterface.Msg
| Batch of seq<Messages.Msg>
| Run of (unit -> unit)
| UpdateHistory of LocalHistory.Model
/// Top level msg to test specific api interactions, only for dev.
| TestMyAPI
| TestMyPostAPI
| UpdateModal of Model.ModalState.ModalTypes option
| UpdateModal of Model.ModalState.ModalTypes option
| DoNothing
85 changes: 85 additions & 0 deletions src/Client/Modals/ModalElements.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
namespace Modals

open Feliz
open Feliz.DaisyUI
open Model
open Messages
open Shared

open ARCtrl
open JsonImport
open Components
open Fable.React.Helpers

type ModalElements =

static member Button(text: string, onClickAction, buttonInput, ?isDisabled: bool) =
let isDisabled = defaultArg isDisabled false
Daisy.button.a [
button.success
button.wide
if isDisabled then
button.error
prop.disabled isDisabled
prop.onClick (fun _ -> onClickAction buttonInput)

prop.text text
]

static member RadioPlugin(radioGroup: string, txt: string, isChecked, onChange: bool -> unit, ?isDisabled: bool) =
let isDisabled = defaultArg isDisabled false
Daisy.formControl [
Daisy.label [
prop.className [
"cursor-pointer transition-colors"
if isDisabled then
"!cursor-not-allowed"
else
"hover:bg-base-300"
]
prop.children [
Daisy.radio [
prop.disabled isDisabled
radio.xs
prop.name radioGroup
prop.isChecked isChecked
prop.onChange onChange
]
Html.span [
prop.className "text-sm"
prop.text txt
]
]
]
]

static member Box(title: string, icon: string, content: ReactElement, ?className: string list) =
Html.div [
prop.className [
"rounded shadow p-2 flex flex-col gap-2 border"
if className.IsSome then
className.Value |> String.concat " "
]
prop.children [
Html.h3 [
prop.className "font-semibold gap-2 flex flex-row items-center"
prop.children [
Html.i [prop.className icon]
Html.span title
]
]
content
]
]

static member SelectorButton<'a when 'a : equality> (targetselector: 'a, selector: 'a, setSelector: 'a -> unit, ?isDisabled) =
Daisy.button.button [
join.item
if isDisabled.IsSome then
prop.disabled isDisabled.Value
prop.style [style.flexGrow 1]
if (targetselector = selector) then
button.primary
prop.onClick (fun _ -> setSelector targetselector)
prop.text (string targetselector)
]
Loading
Loading