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 #592

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
7d14e3a
removed line
Etschbeijer Dec 17, 2024
5b22abf
Replace worksheet name with template name instead of table name
Etschbeijer Dec 18, 2024
f6aa09a
Add summaries
Etschbeijer Dec 18, 2024
f568dcd
implemented review changes
Etschbeijer Dec 18, 2024
4f0359c
Implement review changes
Etschbeijer Dec 19, 2024
31a0d13
Undo changes to pagestate
Etschbeijer Dec 19, 2024
286e7dc
Implement review changes
Etschbeijer Dec 19, 2024
02780e2
implement review requests
Etschbeijer Dec 20, 2024
2046195
Implement review changes
Etschbeijer Dec 21, 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
6 changes: 0 additions & 6 deletions src/Client/Helper.fs
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,6 @@ let throttleAndDebounce(fn: 'a -> unit, timespan: int) =
timespan
id <- Some timeoutId

let charsToRemove = " -/\()[]{}"

//Regex is incapable to remove the whitespaces
let removeChars (stripChars:string) (text:string) =
text.Split(stripChars.ToCharArray(), StringSplitOptions.RemoveEmptyEntries) |> String.Concat

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

module private InitExtensions =
Expand All @@ -22,7 +21,6 @@ module private InitExtensions =
| Some p -> Some p
| None -> None


open InitExtensions

open Fable.Core
Expand All @@ -34,7 +32,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 @@ -43,18 +41,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 @@ -77,7 +75,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 @@ -210,71 +208,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 selectedColumnsLength =
if model.ProtocolState.TemplateSelected.IsSome then
model.ProtocolState.TemplateSelected.Value.Table.Columns.Length
else 0
let selectedColumns, setSelectedColumns = React.useState(SelectedColumns.init selectedColumnsLength)
let importTypeState, setImportTypeState = React.useState(SelectiveImportModalState.init)
let useTemplateName, setUseTemplateName = React.useState(AdaptTableName.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 [
prop.style [style.maxHeight (length.px 350); style.overflow.auto]
prop.children [
SidebarComponents.SidebarLayout.LogicContainer [
Html.div [
SelectiveTemplateFromDBModal.ToProtocolSearchElement model dispatch
]
if model.ProtocolState.TemplateSelected.IsSome then
Html.div [
SelectiveImportModal.RadioPluginsBox(
"Import Type",
"fa-solid fa-cog",
importTypeState.ImportType,
"importType ",
[|
ARCtrl.TableJoinOptions.Headers, " Column Headers";
ARCtrl.TableJoinOptions.WithUnit, " ..With Units";
ARCtrl.TableJoinOptions.WithValues, " ..With Values";
|],
fun importType -> {importTypeState with ImportType = importType} |> setImportTypeState
)
]
Html.div [
ModalElements.Box(
"Rename Table",
"fa-solid fa-cog",
SelectiveTemplateFromDBModal.CheckBoxForTakeOverTemplateName(useTemplateName, setUseTemplateName, model.ProtocolState.TemplateSelected.Value.Name))
]
Html.div [
ModalElements.Box(
model.ProtocolState.TemplateSelected.Value.Name,
"",
SelectiveTemplateFromDBModal.displaySelectedProtocolElements(model, selectedColumns, setSelectedColumns, dispatch, false))
]
Html.div [
SelectiveTemplateFromDBModal.AddFromDBToTableButton model selectedColumns importTypeState useTemplateName.TemplateName 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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

model.PageState.SidebarPage = Routing.SidebarPage.Protocol we are still in the widget? Why check for sidebar pagestate?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise, the view for the protocolsearch is left immediately, when a single template is added, without the possibility to add additional templates.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then you must adjust the Msg that triggers this.

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
23 changes: 0 additions & 23 deletions src/Client/Modals/ModalElements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ open Feliz.DaisyUI
open Model
open Messages
open Shared
open Types.TableImport

open ARCtrl
open JsonImport
Expand Down Expand Up @@ -73,28 +72,6 @@ type ModalElements =
]
]

static member BoxWithChildren(children: ReactElement list, ?title: string, ?icon: string, ?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"
if icon.IsSome || title.IsSome then
prop.children [
if icon.IsSome then
Html.i [prop.className icon.Value]
if title.IsSome then
Html.span title.Value
]
prop.children children
]
]
]

static member SelectorButton<'a when 'a : equality> (targetselector: 'a, selector: 'a, setSelector: 'a -> unit, ?isDisabled) =
Daisy.button.button [
join.item
Expand Down
Loading
Loading