diff --git a/Swate.sln b/Swate.sln index 58de84b4..d27bc3f8 100644 --- a/Swate.sln +++ b/Swate.sln @@ -14,8 +14,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .assets\assets\install.cmd = .assets\assets\install.cmd build\manifest.xml = build\manifest.xml package.json = package.json - paket.dependencies = paket.dependencies - paket.lock = paket.lock README.md = README.md RELEASE_NOTES.md = RELEASE_NOTES.md EndProjectSection @@ -24,8 +22,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E0FF3176-0B7 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ISSUE_TEMPLATE", "ISSUE_TEMPLATE", "{54B2B950-6393-4086-8AF4-3D211495433C}" ProjectSection(SolutionItems) = preProject - .github\ISSUE_TEMPLATE\config.yml = .github\ISSUE_TEMPLATE\config.yml .github\ISSUE_TEMPLATE\bug_report.yml = .github\ISSUE_TEMPLATE\bug_report.yml + .github\ISSUE_TEMPLATE\config.yml = .github\ISSUE_TEMPLATE\config.yml .github\ISSUE_TEMPLATE\feature_request.yml = .github\ISSUE_TEMPLATE\feature_request.yml EndProjectSection EndProject diff --git a/package-lock.json b/package-lock.json index 9daadba9..227a21a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,7 @@ "requires": true, "packages": { "": { + "name": "Swate", "dependencies": { "@dnd-kit/core": "^6.1.0", "@dnd-kit/sortable": "^8.0.0", @@ -21,6 +22,7 @@ "use-sync-external-store": "^1.2.0" }, "devDependencies": { + "@tailwindcss/typography": "^0.5.15", "@types/node": "^20.10.3", "@vitejs/plugin-basic-ssl": "^1.0.2", "@vitejs/plugin-react": "^4.2.1", @@ -1204,6 +1206,36 @@ "win32" ] }, + "node_modules/@tailwindcss/typography": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.15.tgz", + "integrity": "sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "postcss-selector-parser": "6.0.10" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20" + } + }, + "node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -2533,6 +2565,13 @@ "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==" }, + "node_modules/lodash.castarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", + "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", @@ -2588,6 +2627,13 @@ "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", "integrity": "sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.union": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", diff --git a/package.json b/package.json index a0430965..88823a70 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ }, "scripts": {}, "devDependencies": { + "@tailwindcss/typography": "^0.5.15", "@types/node": "^20.10.3", "@vitejs/plugin-basic-ssl": "^1.0.2", "@vitejs/plugin-react": "^4.2.1", diff --git a/src/Client/MainComponents/FooterTabs.fs b/src/Client/MainComponents/FooterTabs.fs index e189de8b..c06013d1 100644 --- a/src/Client/MainComponents/FooterTabs.fs +++ b/src/Client/MainComponents/FooterTabs.fs @@ -318,7 +318,7 @@ let MainMetadata(model: Model, dispatch: Messages.Msg -> unit) = prop.children [ Html.a [ Bulma.icon [Html.i [prop.className "fa-solid fa-circle-info"]] - Html.text "Metadata" + Html.text model.SpreadsheetModel.FileType ] ] ] diff --git a/src/Client/MainComponents/Navbar.fs b/src/Client/MainComponents/Navbar.fs index 69f0e58c..838bdc3a 100644 --- a/src/Client/MainComponents/Navbar.fs +++ b/src/Client/MainComponents/Navbar.fs @@ -9,14 +9,29 @@ open Messages open Components.QuickAccessButton open MainComponents open Model +open Shared -let private quickAccessButtonListStart (state: LocalHistory.Model) dispatch = +let private FileName (model: Model) = + let txt = + match model.SpreadsheetModel.ArcFile with + | Some (ArcFiles.Assay a) -> a.Identifier + | Some (ArcFiles.Study (s,_)) -> s.Identifier + | Some (ArcFiles.Investigation i) -> i.Identifier + | Some (ArcFiles.Template t) -> t.FileName + | _ -> "" + Html.div [ + prop.className "text-white text-lg font-bold flex items-center max-w-[125px] p-2 truncate inline-block" + prop.text txt + prop.title txt + ] + +let private quickAccessButtonListStart (model: Model) (state: LocalHistory.Model) dispatch = Html.div [ prop.style [ style.display.flex; style.flexDirection.row ] prop.children [ - + FileName model QuickAccessButton.create( "Back", [ @@ -167,7 +182,7 @@ let Main(model: Model, dispatch, widgets, setWidgets) = Bulma.navbarStart.div [ prop.style [style.display.flex; style.alignItems.stretch; style.justifyContent.flexStart; style.custom("marginRight", "auto")] prop.children [ - quickAccessButtonListStart model.History dispatch + quickAccessButtonListStart model model.History dispatch WidgetNavbarList(model, dispatch, addWidget) ] ] diff --git a/src/Client/Messages.fs b/src/Client/Messages.fs index 47404905..d278cb1d 100644 --- a/src/Client/Messages.fs +++ b/src/Client/Messages.fs @@ -71,10 +71,10 @@ module BuildingBlock = open TermSearch type Msg = - | UpdateHeaderWithIO of BuildingBlock.HeaderCellType * IOType - | UpdateHeaderCellType of BuildingBlock.HeaderCellType + | UpdateHeaderWithIO of CompositeHeaderDiscriminate * IOType + | UpdateHeaderCellType of CompositeHeaderDiscriminate | UpdateHeaderArg of U2 option - | UpdateBodyCellType of BuildingBlock.BodyCellType + | UpdateBodyCellType of CompositeCellDiscriminate | UpdateBodyArg of U2 option module Protocol = diff --git a/src/Client/Modals/EditColumn.fs b/src/Client/Modals/EditColumn.fs index 28d64eca..b5b9fc2a 100644 --- a/src/Client/Modals/EditColumn.fs +++ b/src/Client/Modals/EditColumn.fs @@ -13,7 +13,7 @@ open ARCtrl type private State = { - NextHeaderType: BuildingBlock.HeaderCellType option + NextHeaderType: CompositeHeaderDiscriminate option NextIOType: IOType option } with static member init() = { @@ -37,33 +37,34 @@ module private EditColumnComponents = prop.onClick submit ] - let SelectHeaderTypeOption(headerType: BuildingBlock.HeaderCellType) = + let SelectHeaderTypeOption(headerType: CompositeHeaderDiscriminate) = let txt = headerType.ToString() Html.option [ prop.value txt prop.text txt ] - let SelectHeaderType(state, setState) = + let SelectHeaderType(header, state, setState) = Bulma.select [ - prop.onChange (fun (e: string) -> {state with NextHeaderType = Some (BuildingBlock.HeaderCellType.fromString e)} |> setState ) + prop.value (header.ToString()) + prop.onChange (fun (e: string) -> {state with NextHeaderType = Some (CompositeHeaderDiscriminate.fromString e)} |> setState ) prop.children [ // -- term columns -- - SelectHeaderTypeOption BuildingBlock.HeaderCellType.Characteristic - SelectHeaderTypeOption BuildingBlock.HeaderCellType.Component - SelectHeaderTypeOption BuildingBlock.HeaderCellType.Factor - SelectHeaderTypeOption BuildingBlock.HeaderCellType.Parameter + SelectHeaderTypeOption CompositeHeaderDiscriminate.Characteristic + SelectHeaderTypeOption CompositeHeaderDiscriminate.Component + SelectHeaderTypeOption CompositeHeaderDiscriminate.Factor + SelectHeaderTypeOption CompositeHeaderDiscriminate.Parameter // -- io columns -- - SelectHeaderTypeOption BuildingBlock.HeaderCellType.Input - SelectHeaderTypeOption BuildingBlock.HeaderCellType.Output + SelectHeaderTypeOption CompositeHeaderDiscriminate.Input + SelectHeaderTypeOption CompositeHeaderDiscriminate.Output // -- single columns -- - SelectHeaderTypeOption BuildingBlock.HeaderCellType.Date - SelectHeaderTypeOption BuildingBlock.HeaderCellType.Performer - SelectHeaderTypeOption BuildingBlock.HeaderCellType.ProtocolDescription - SelectHeaderTypeOption BuildingBlock.HeaderCellType.ProtocolREF - SelectHeaderTypeOption BuildingBlock.HeaderCellType.ProtocolType - SelectHeaderTypeOption BuildingBlock.HeaderCellType.ProtocolUri - SelectHeaderTypeOption BuildingBlock.HeaderCellType.ProtocolVersion + SelectHeaderTypeOption CompositeHeaderDiscriminate.Date + SelectHeaderTypeOption CompositeHeaderDiscriminate.Performer + SelectHeaderTypeOption CompositeHeaderDiscriminate.ProtocolDescription + SelectHeaderTypeOption CompositeHeaderDiscriminate.ProtocolREF + SelectHeaderTypeOption CompositeHeaderDiscriminate.ProtocolType + SelectHeaderTypeOption CompositeHeaderDiscriminate.ProtocolUri + SelectHeaderTypeOption CompositeHeaderDiscriminate.ProtocolVersion ] ] @@ -136,43 +137,44 @@ let Main (columnIndex: int) (model: Model) (dispatch) (rmv: _ -> unit) = match state.NextHeaderType, state.NextIOType with | None, _ -> column // -- term columns -- - | Some BuildingBlock.HeaderCellType.Characteristic, _ -> + | Some CompositeHeaderDiscriminate.Characteristic, _ -> CompositeColumn.create(CompositeHeader.Characteristic (header.ToTerm()), cellsToTermCells(column)) - | Some BuildingBlock.HeaderCellType.Parameter, _ -> + | Some CompositeHeaderDiscriminate.Parameter, _ -> CompositeColumn.create(CompositeHeader.Parameter (header.ToTerm()), cellsToTermCells(column)) - | Some BuildingBlock.HeaderCellType.Component, _ -> + | Some CompositeHeaderDiscriminate.Component, _ -> CompositeColumn.create(CompositeHeader.Component (header.ToTerm()), cellsToTermCells(column)) - | Some BuildingBlock.HeaderCellType.Factor, _ -> + | Some CompositeHeaderDiscriminate.Factor, _ -> CompositeColumn.create(CompositeHeader.Factor (header.ToTerm()), cellsToTermCells(column)) // -- input columns -- - | Some BuildingBlock.HeaderCellType.Input, Some IOType.Data -> + | Some CompositeHeaderDiscriminate.Input, Some IOType.Data -> CompositeColumn.create(CompositeHeader.Input IOType.Data, cellsToDataOrFreeText(column)) - | Some BuildingBlock.HeaderCellType.Input, Some io -> + | Some CompositeHeaderDiscriminate.Input, Some io -> CompositeColumn.create(CompositeHeader.Input io, cellsToFreeText(column)) - | Some BuildingBlock.HeaderCellType.Input, None -> + | Some CompositeHeaderDiscriminate.Input, None -> CompositeColumn.create(CompositeHeader.Input IOType.Sample, cellsToFreeText(column)) // -- output columns -- - | Some BuildingBlock.HeaderCellType.Output, Some IOType.Data -> + | Some CompositeHeaderDiscriminate.Output, Some IOType.Data -> CompositeColumn.create(CompositeHeader.Output IOType.Data, cellsToDataOrFreeText(column)) - | Some BuildingBlock.HeaderCellType.Output, Some io -> + | Some CompositeHeaderDiscriminate.Output, Some io -> CompositeColumn.create(CompositeHeader.Output io, cellsToFreeText(column)) - | Some BuildingBlock.HeaderCellType.Output, None -> + | Some CompositeHeaderDiscriminate.Output, None -> CompositeColumn.create(CompositeHeader.Output IOType.Sample, cellsToFreeText(column)) // -- single columns -- - | Some BuildingBlock.HeaderCellType.ProtocolREF, _ -> + | Some CompositeHeaderDiscriminate.ProtocolREF, _ -> CompositeColumn.create(CompositeHeader.ProtocolREF, cellsToFreeText(column)) - | Some BuildingBlock.HeaderCellType.Date, _ -> + | Some CompositeHeaderDiscriminate.Date, _ -> CompositeColumn.create(CompositeHeader.Date, cellsToFreeText(column)) - | Some BuildingBlock.HeaderCellType.Performer, _ -> + | Some CompositeHeaderDiscriminate.Performer, _ -> CompositeColumn.create(CompositeHeader.Performer, cellsToFreeText(column)) - | Some BuildingBlock.HeaderCellType.ProtocolDescription, _ -> + | Some CompositeHeaderDiscriminate.ProtocolDescription, _ -> CompositeColumn.create(CompositeHeader.ProtocolDescription, cellsToFreeText(column)) - | Some BuildingBlock.HeaderCellType.ProtocolType, _ -> + | Some CompositeHeaderDiscriminate.ProtocolType, _ -> CompositeColumn.create(CompositeHeader.ProtocolType, cellsToTermCells(column)) - | Some BuildingBlock.HeaderCellType.ProtocolUri, _ -> + | Some CompositeHeaderDiscriminate.ProtocolUri, _ -> CompositeColumn.create(CompositeHeader.ProtocolUri, cellsToFreeText(column)) - | Some BuildingBlock.HeaderCellType.ProtocolVersion, _ -> + | Some CompositeHeaderDiscriminate.ProtocolVersion, _ -> CompositeColumn.create(CompositeHeader.ProtocolVersion, cellsToFreeText(column)) + | Some CompositeHeaderDiscriminate.Comment, _ -> failwith "Comment header type is not yet implemented" let submit (e) = let nxtCol = updateColumn column0 Spreadsheet.SetColumn (columnIndex, nxtCol) |> SpreadsheetMsg |> dispatch @@ -196,9 +198,9 @@ let Main (columnIndex: int) (model: Model) (dispatch) (rmv: _ -> unit) = Bulma.field.div [ Bulma.buttons [ prop.children [ - SelectHeaderType(state, setState) + SelectHeaderType(column0.Header.AsDiscriminate, state, setState) match state.NextHeaderType with - | Some BuildingBlock.HeaderCellType.Output | Some BuildingBlock.HeaderCellType.Input -> + | Some CompositeHeaderDiscriminate.Output | Some CompositeHeaderDiscriminate.Input -> SelectIOType(state, setState) | _ -> Html.none ] diff --git a/src/Client/Modals/TermModal.fs b/src/Client/Modals/TermModal.fs index a8a4af72..6c284438 100644 --- a/src/Client/Modals/TermModal.fs +++ b/src/Client/Modals/TermModal.fs @@ -4,6 +4,7 @@ open Shared.TermTypes open Feliz open Feliz.Bulma open ARCtrl +open Shared type private State = | Loading @@ -46,9 +47,9 @@ let Main (oa: OntologyAnnotation, dispatch) (rmv: _ -> unit) = ] ] Bulma.modalCardBody [ - prop.className "has-text-justified" + prop.className "content" prop.children [ - Bulma.content [ + Html.div [ match state with | Loading -> Html.p "loading .." | NotFound -> @@ -56,15 +57,26 @@ let Main (oa: OntologyAnnotation, dispatch) (rmv: _ -> unit) = prop.dangerouslySetInnerHTML $"Unable to find term with id {oa.TermAccessionShort} in database." ] | Found term -> - Html.h6 "Description" + Html.h5 "Description" Html.p term.Description - Html.h6 "Source Ontology" + Html.h5 "Source Ontology" Html.p term.FK_Ontology if term.IsObsolete then Html.p [ color.hasTextDanger prop.text "Obsolete" - ] + ] + Html.a [ + prop.className "space-x-2 float-right" + prop.href (OntologyAnnotation.fromTerm term |> _.TermAccessionOntobeeUrl) + prop.target.blank + prop.children [ + Html.span "Ref" + Html.i [ + prop.className "fas fa-external-link-alt" + ] + ] + ] ] ] ] diff --git a/src/Client/Model.fs b/src/Client/Model.fs index d63956eb..dc0d4cb4 100644 --- a/src/Client/Model.fs +++ b/src/Client/Model.fs @@ -181,78 +181,13 @@ open Fable.Core module BuildingBlock = open ARCtrl - - [] - type HeaderCellType = - | Component - | Characteristic - | Factor - | Parameter - | ProtocolType - | ProtocolDescription - | ProtocolUri - | ProtocolVersion - | ProtocolREF - | Performer - | Date - | Input - | Output - with - /// - /// Returns true if the Building Block is a term column - /// - member this.IsTermColumn() = - match this with - | Component - | Characteristic - | Factor - | Parameter - | ProtocolType -> true - | _ -> false - member this.HasOA() = - match this with - | Component - | Characteristic - | Factor - | Parameter -> true - | _ -> false - - member this.HasIOType() = - match this with - | Input - | Output -> true - | _ -> false - - static member fromString(str: string) = - match str with - | "Component" -> Component - | "Characteristic" -> Characteristic - | "Factor" -> Factor - | "Parameter" -> Parameter - | "ProtocolType" -> ProtocolType - | "ProtocolDescription" -> ProtocolDescription - | "ProtocolUri" -> ProtocolUri - | "ProtocolVersion" -> ProtocolVersion - | "ProtocolREF" -> ProtocolREF - | "Performer" -> Performer - | "Date" -> Date - | "Input" -> Input - | "Output" -> Output - | anyElse -> failwithf "BuildingBlock.HeaderCellType.fromString: '%s' is not a valid HeaderCellType" anyElse - - - [] - type BodyCellType = - | Term - | Unitized - | Text - | Data + open ARCtrl.Helper [] type DropdownPage = | Main | More - | IOTypes of HeaderCellType + | IOTypes of CompositeHeaderDiscriminate member this.toString = match this with @@ -277,17 +212,17 @@ module BuildingBlock = type Model = { - HeaderCellType : HeaderCellType + HeaderCellType : CompositeHeaderDiscriminate HeaderArg : U2 option - BodyCellType : BodyCellType + BodyCellType : CompositeCellDiscriminate BodyArg : U2 option } with static member init () = { - HeaderCellType = HeaderCellType.Parameter + HeaderCellType = CompositeHeaderDiscriminate.Parameter HeaderArg = None - BodyCellType = BodyCellType.Term + BodyCellType = CompositeCellDiscriminate.Term BodyArg = None } diff --git a/src/Client/Pages/BuildingBlock/BuildingBlockView.fs b/src/Client/Pages/BuildingBlock/BuildingBlockView.fs index 77a5ca46..5c90416f 100644 --- a/src/Client/Pages/BuildingBlock/BuildingBlockView.fs +++ b/src/Client/Pages/BuildingBlock/BuildingBlockView.fs @@ -3,6 +3,7 @@ module BuildingBlock.Core open Model open Messages open Messages.BuildingBlock +open Shared open Elmish @@ -16,12 +17,12 @@ let update (addBuildingBlockMsg:BuildingBlock.Msg) (state: BuildingBlock.Model) nextState, Cmd.none | UpdateHeaderCellType next -> let nextState = - if Helper.isSameMajorHeaderCellType state.HeaderCellType next then + if Helper.isSameMajorCompositeHeaderDiscriminate state.HeaderCellType next then { state with HeaderCellType = next } else - let nextBodyCellType = if next.IsTermColumn() then BuildingBlock.BodyCellType.Term else BuildingBlock.BodyCellType.Text + let nextBodyCellType = if next.IsTermColumn() then CompositeCellDiscriminate.Term else CompositeCellDiscriminate.Text { state with HeaderCellType = next BodyCellType = nextBodyCellType @@ -35,7 +36,7 @@ let update (addBuildingBlockMsg:BuildingBlock.Msg) (state: BuildingBlock.Model) HeaderCellType = hct HeaderArg = Some (Fable.Core.U2.Case2 iotype) BodyArg = None - BodyCellType = BuildingBlock.BodyCellType.Text + BodyCellType = CompositeCellDiscriminate.Text } nextState, Cmd.none | UpdateBodyCellType next -> diff --git a/src/Client/Pages/BuildingBlock/CellConvertComponent.fs b/src/Client/Pages/BuildingBlock/CellConvertComponent.fs index 03a9c6bf..a8353080 100644 --- a/src/Client/Pages/BuildingBlock/CellConvertComponent.fs +++ b/src/Client/Pages/BuildingBlock/CellConvertComponent.fs @@ -4,10 +4,12 @@ open Feliz open Feliz.Bulma open OfficeInterop.Core +open Shared +open ARCtrl.Helper module private CellConvertComponentHelpers = - let getSelectedCellType (setState: Model.BuildingBlock.BodyCellType option -> unit) = + let getSelectedCellType (setState: CompositeCellDiscriminate option -> unit) = promise { //Write function to access current header state of excel @@ -17,22 +19,22 @@ module private CellConvertComponentHelpers = match mainColumn with | Some column when column.Header.isInput -> None | Some column when column.Header.isOutput -> None - | Some column when column.Cells.[0].isUnitized -> Model.BuildingBlock.BodyCellType.Unitized |> Some - | Some column when column.Cells.[0].isTerm -> Model.BuildingBlock.BodyCellType.Term |> Some - | Some column when column.Cells.[0].isFreeText -> Model.BuildingBlock.BodyCellType.Text |> Some - | Some column when column.Cells.[0].isData -> Model.BuildingBlock.BodyCellType.Data |> Some + | Some column when column.Cells.[0].isUnitized -> CompositeCellDiscriminate.Unitized |> Some + | Some column when column.Cells.[0].isTerm -> CompositeCellDiscriminate.Term |> Some + | Some column when column.Cells.[0].isFreeText -> CompositeCellDiscriminate.Text |> Some + | Some column when column.Cells.[0].isData -> CompositeCellDiscriminate.Data |> Some | _ -> None setState result } - let getTargetConversionType (cellType: Model.BuildingBlock.BodyCellType option) = + let getTargetConversionType (cellType: CompositeCellDiscriminate option) = if cellType.IsSome then match cellType.Value with - | Model.BuildingBlock.BodyCellType.Unitized -> Model.BuildingBlock.BodyCellType.Term |> Some - | Model.BuildingBlock.BodyCellType.Term -> Model.BuildingBlock.BodyCellType.Unitized |> Some - | Model.BuildingBlock.BodyCellType.Text -> Model.BuildingBlock.BodyCellType.Data |> Some - | Model.BuildingBlock.BodyCellType.Data -> Model.BuildingBlock.BodyCellType.Text |> Some + | CompositeCellDiscriminate.Unitized -> CompositeCellDiscriminate.Term |> Some + | CompositeCellDiscriminate.Term -> CompositeCellDiscriminate.Unitized |> Some + | CompositeCellDiscriminate.Text -> CompositeCellDiscriminate.Data |> Some + | CompositeCellDiscriminate.Data -> CompositeCellDiscriminate.Text |> Some else None type CellConvertComponent = @@ -40,7 +42,7 @@ type CellConvertComponent = [] static member Main () = - let (state: Model.BuildingBlock.BodyCellType option), setState = React.useState(None) + let (state: CompositeCellDiscriminate option), setState = React.useState(None) React.useEffectOnce(fun () -> CellConvertComponentHelpers.getSelectedCellType setState diff --git a/src/Client/Pages/BuildingBlock/Dropdown.fs b/src/Client/Pages/BuildingBlock/Dropdown.fs index 05d3ad45..8382f92d 100644 --- a/src/Client/Pages/BuildingBlock/Dropdown.fs +++ b/src/Client/Pages/BuildingBlock/Dropdown.fs @@ -6,6 +6,7 @@ open Model.BuildingBlock open Model open Messages open ARCtrl +open Shared [] @@ -94,19 +95,19 @@ module private DropdownElements = ] ] - let createBuildingBlockDropdownItem (model: Model) dispatch setUiState (headerType: BuildingBlock.HeaderCellType) = + let createBuildingBlockDropdownItem (model: Model) dispatch setUiState (headerType: CompositeHeaderDiscriminate) = Bulma.dropdownItem.a [ prop.onClick (fun e -> e.stopPropagation() - Helper.selectHeaderCellType headerType setUiState dispatch + Helper.selectCompositeHeaderDiscriminate headerType setUiState dispatch ) prop.onKeyDown(fun k -> - if (int k.which) = 13 then Helper.selectHeaderCellType headerType setUiState dispatch + if (int k.which) = 13 then Helper.selectCompositeHeaderDiscriminate headerType setUiState dispatch ) prop.text (headerType.ToString()) ] - let createIOTypeDropdownItem (model: Model) dispatch setUiState (headerType: BuildingBlock.HeaderCellType) (iotype: IOType) = + let createIOTypeDropdownItem (model: Model) dispatch setUiState (headerType: CompositeHeaderDiscriminate) (iotype: IOType) = let setIO (ioType) = { DropdownPage = DropdownPage.Main; DropdownIsActive = false } |> setUiState (headerType,ioType) |> BuildingBlock.UpdateHeaderWithIO |> BuildingBlockMsg |> dispatch @@ -128,15 +129,15 @@ module private DropdownElements = /// Main column types subpage for dropdown let dropdownContentMain state setState (model:Model) dispatch = [ - DropdownPage.IOTypes BuildingBlock.HeaderCellType.Input |> createSubBuildingBlockDropdownLink state setState + DropdownPage.IOTypes CompositeHeaderDiscriminate.Input |> createSubBuildingBlockDropdownLink state setState Bulma.dropdownDivider [] - BuildingBlock.HeaderCellType.Parameter |> createBuildingBlockDropdownItem model dispatch setState - BuildingBlock.HeaderCellType.Factor |> createBuildingBlockDropdownItem model dispatch setState - BuildingBlock.HeaderCellType.Characteristic |> createBuildingBlockDropdownItem model dispatch setState - BuildingBlock.HeaderCellType.Component |> createBuildingBlockDropdownItem model dispatch setState + CompositeHeaderDiscriminate.Parameter |> createBuildingBlockDropdownItem model dispatch setState + CompositeHeaderDiscriminate.Factor |> createBuildingBlockDropdownItem model dispatch setState + CompositeHeaderDiscriminate.Characteristic |> createBuildingBlockDropdownItem model dispatch setState + CompositeHeaderDiscriminate.Component |> createBuildingBlockDropdownItem model dispatch setState Model.BuildingBlock.DropdownPage.More |> createSubBuildingBlockDropdownLink state setState Bulma.dropdownDivider [] - DropdownPage.IOTypes BuildingBlock.HeaderCellType.Output |> createSubBuildingBlockDropdownLink state setState + DropdownPage.IOTypes CompositeHeaderDiscriminate.Output |> createSubBuildingBlockDropdownLink state setState Bulma.dropdownItem.div [ prop.style [style.textAlign.right] prop.children annotationsPrinciplesUrl @@ -146,13 +147,13 @@ module private DropdownElements = /// Protocol Type subpage for dropdown let dropdownContentProtocolTypeColumns state setState (model:Model) dispatch = [ - BuildingBlock.HeaderCellType.Date |> createBuildingBlockDropdownItem model dispatch setState - BuildingBlock.HeaderCellType.Performer |> createBuildingBlockDropdownItem model dispatch setState - BuildingBlock.HeaderCellType.ProtocolDescription |> createBuildingBlockDropdownItem model dispatch setState - BuildingBlock.HeaderCellType.ProtocolREF |> createBuildingBlockDropdownItem model dispatch setState - BuildingBlock.HeaderCellType.ProtocolType |> createBuildingBlockDropdownItem model dispatch setState - BuildingBlock.HeaderCellType.ProtocolUri |> createBuildingBlockDropdownItem model dispatch setState - BuildingBlock.HeaderCellType.ProtocolVersion |> createBuildingBlockDropdownItem model dispatch setState + CompositeHeaderDiscriminate.Date |> createBuildingBlockDropdownItem model dispatch setState + CompositeHeaderDiscriminate.Performer |> createBuildingBlockDropdownItem model dispatch setState + CompositeHeaderDiscriminate.ProtocolDescription |> createBuildingBlockDropdownItem model dispatch setState + CompositeHeaderDiscriminate.ProtocolREF |> createBuildingBlockDropdownItem model dispatch setState + CompositeHeaderDiscriminate.ProtocolType |> createBuildingBlockDropdownItem model dispatch setState + CompositeHeaderDiscriminate.ProtocolUri |> createBuildingBlockDropdownItem model dispatch setState + CompositeHeaderDiscriminate.ProtocolVersion |> createBuildingBlockDropdownItem model dispatch setState // Navigation element back to main page backToMainDropdownButton setState ] diff --git a/src/Client/Pages/BuildingBlock/Helper.fs b/src/Client/Pages/BuildingBlock/Helper.fs index be1a410d..0e5019eb 100644 --- a/src/Client/Pages/BuildingBlock/Helper.fs +++ b/src/Client/Pages/BuildingBlock/Helper.fs @@ -6,11 +6,11 @@ open Messages open ARCtrl open Model.BuildingBlock -let isSameMajorHeaderCellType (hct1: BuildingBlock.HeaderCellType) (hct2: BuildingBlock.HeaderCellType) = +let isSameMajorCompositeHeaderDiscriminate (hct1: CompositeHeaderDiscriminate) (hct2: CompositeHeaderDiscriminate) = (hct1.IsTermColumn() = hct2.IsTermColumn()) && (hct1.HasIOType() = hct2.HasIOType()) -let selectHeaderCellType (hct: BuildingBlock.HeaderCellType) setUiState dispatch = +let selectCompositeHeaderDiscriminate (hct: CompositeHeaderDiscriminate) setUiState dispatch = BuildingBlock.UpdateHeaderCellType hct |> BuildingBlockMsg |> dispatch { DropdownPage = DropdownPage.Main; DropdownIsActive = false }|> setUiState @@ -20,26 +20,27 @@ let createCompositeHeaderFromState (state: BuildingBlock.Model) = let getOA() = state.TryHeaderOA() |> Option.defaultValue (OntologyAnnotation.empty()) let getIOType() = state.TryHeaderIO() |> Option.defaultValue (IOType.FreeText "") match state.HeaderCellType with - | HeaderCellType.Component -> CompositeHeader.Component <| getOA() - | HeaderCellType.Characteristic -> CompositeHeader.Characteristic <| getOA() - | HeaderCellType.Factor -> CompositeHeader.Factor <| getOA() - | HeaderCellType.Parameter -> CompositeHeader.Parameter <| getOA() - | HeaderCellType.ProtocolType -> CompositeHeader.ProtocolType - | HeaderCellType.ProtocolDescription -> CompositeHeader.ProtocolDescription - | HeaderCellType.ProtocolUri -> CompositeHeader.ProtocolUri - | HeaderCellType.ProtocolVersion -> CompositeHeader.ProtocolVersion - | HeaderCellType.ProtocolREF -> CompositeHeader.ProtocolREF - | HeaderCellType.Performer -> CompositeHeader.Performer - | HeaderCellType.Date -> CompositeHeader.Date - | HeaderCellType.Input -> CompositeHeader.Input <| getIOType() - | HeaderCellType.Output -> CompositeHeader.Output <| getIOType() + | CompositeHeaderDiscriminate.Component -> CompositeHeader.Component <| getOA() + | CompositeHeaderDiscriminate.Characteristic -> CompositeHeader.Characteristic <| getOA() + | CompositeHeaderDiscriminate.Factor -> CompositeHeader.Factor <| getOA() + | CompositeHeaderDiscriminate.Parameter -> CompositeHeader.Parameter <| getOA() + | CompositeHeaderDiscriminate.ProtocolType -> CompositeHeader.ProtocolType + | CompositeHeaderDiscriminate.ProtocolDescription -> CompositeHeader.ProtocolDescription + | CompositeHeaderDiscriminate.ProtocolUri -> CompositeHeader.ProtocolUri + | CompositeHeaderDiscriminate.ProtocolVersion -> CompositeHeader.ProtocolVersion + | CompositeHeaderDiscriminate.ProtocolREF -> CompositeHeader.ProtocolREF + | CompositeHeaderDiscriminate.Performer -> CompositeHeader.Performer + | CompositeHeaderDiscriminate.Date -> CompositeHeader.Date + | CompositeHeaderDiscriminate.Input -> CompositeHeader.Input <| getIOType() + | CompositeHeaderDiscriminate.Output -> CompositeHeader.Output <| getIOType() + | CompositeHeaderDiscriminate.Comment -> failwith "Comment header type is not yet implemented" let tryCreateCompositeCellFromState (state: BuildingBlock.Model) = match state.HeaderArg, state.BodyCellType, state.BodyArg with | Some (U2.Case2 IOType.Data), _, _ -> CompositeCell.emptyData |> Some - | _, BodyCellType.Term, Some (U2.Case2 oa) -> CompositeCell.createTerm (oa) |> Some - | _, BodyCellType.Unitized, Some (U2.Case2 oa) -> CompositeCell.createUnitized ("", oa) |> Some - | _, BodyCellType.Text, Some (U2.Case1 s) -> CompositeCell.createFreeText s |> Some + | _, CompositeCellDiscriminate.Term, Some (U2.Case2 oa) -> CompositeCell.createTerm (oa) |> Some + | _, CompositeCellDiscriminate.Unitized, Some (U2.Case2 oa) -> CompositeCell.createUnitized ("", oa) |> Some + | _, CompositeCellDiscriminate.Text, Some (U2.Case1 s) -> CompositeCell.createFreeText s |> Some | _ -> None let isValidColumn (header : CompositeHeader) = diff --git a/src/Client/Pages/BuildingBlock/SearchComponent.fs b/src/Client/Pages/BuildingBlock/SearchComponent.fs index d3944a7c..ce051dca 100644 --- a/src/Client/Pages/BuildingBlock/SearchComponent.fs +++ b/src/Client/Pages/BuildingBlock/SearchComponent.fs @@ -7,6 +7,7 @@ open Model.BuildingBlock open Model open Messages open ARCtrl +open Shared let private termOrUnitizedSwitch (model:Model) dispatch = @@ -16,16 +17,16 @@ let private termOrUnitizedSwitch (model:Model) dispatch = prop.style [style.flexWrap.nowrap; style.marginBottom 0; style.marginRight (length.rem 1)] prop.children [ Bulma.button.a [ - let isActive = state.BodyCellType = BodyCellType.Term + let isActive = state.BodyCellType = CompositeCellDiscriminate.Term if isActive then Bulma.color.isSuccess - prop.onClick (fun _ -> BuildingBlock.UpdateBodyCellType BodyCellType.Term |> BuildingBlockMsg |> dispatch) + prop.onClick (fun _ -> BuildingBlock.UpdateBodyCellType CompositeCellDiscriminate.Term |> BuildingBlockMsg |> dispatch) prop.classes ["pr-2 pl-2 mb-0"; if isActive then "is-selected"] prop.text "Term" ] Bulma.button.a [ - let isActive = state.BodyCellType = BodyCellType.Unitized + let isActive = state.BodyCellType = CompositeCellDiscriminate.Unitized if isActive then Bulma.color.isSuccess - prop.onClick (fun _ -> BuildingBlock.UpdateBodyCellType BodyCellType.Unitized |> BuildingBlockMsg |> dispatch) + prop.onClick (fun _ -> BuildingBlock.UpdateBodyCellType CompositeCellDiscriminate.Unitized |> BuildingBlockMsg |> dispatch) prop.classes ["pr-2 pl-2 mb-0"; if isActive then "is-selected"] prop.text "Unit" ] diff --git a/src/Client/Pages/FilePicker/FilePickerView.fs b/src/Client/Pages/FilePicker/FilePickerView.fs index f74db9e1..9de2f30a 100644 --- a/src/Client/Pages/FilePicker/FilePickerView.fs +++ b/src/Client/Pages/FilePicker/FilePickerView.fs @@ -36,8 +36,6 @@ let uploadButton (model:Model) dispatch = let fileNames = files |> List.map (fun f -> f.name) - Browser.Dom.console.log fileNames - fileNames |> LoadNewFiles |> FilePickerMsg |> dispatch //let picker = Browser.Dom.document.getElementById(inputId) diff --git a/src/Client/States/Spreadsheet.fs b/src/Client/States/Spreadsheet.fs index e80e3f1a..d3e985ff 100644 --- a/src/Client/States/Spreadsheet.fs +++ b/src/Client/States/Spreadsheet.fs @@ -81,6 +81,13 @@ type Model = { ActiveCell = None ArcFile = None } + member this.FileType = + match this.ArcFile with + | Some (Assay _) -> "Assay" + | Some (Study _) -> "Study" + | Some (Investigation _) -> "Investigation" + | Some (Template _) -> "Template" + | None -> "No File" static member init(arcFile: ArcFiles) = { diff --git a/src/Client/tailwind.config.js b/src/Client/tailwind.config.js index 45aa42b0..8f6950ef 100644 --- a/src/Client/tailwind.config.js +++ b/src/Client/tailwind.config.js @@ -8,6 +8,8 @@ module.exports = { theme: { extend: {}, }, - plugins: [], + plugins: [ + require('@tailwindcss/typography') + ], darkMode: ['selector', '[data-theme="dark"]'] } diff --git a/src/Shared/ARCtrl.Helper.fs b/src/Shared/ARCtrl.Helper.fs index 143cbcb5..fcede44f 100644 --- a/src/Shared/ARCtrl.Helper.fs +++ b/src/Shared/ARCtrl.Helper.fs @@ -133,6 +133,73 @@ module Helper = let updatedKey = (newColumnIndex, rowIndex) table.[updatedKey] <- value +[] +type CompositeHeaderDiscriminate = +| Component +| Characteristic +| Factor +| Parameter +| ProtocolType +| ProtocolDescription +| ProtocolUri +| ProtocolVersion +| ProtocolREF +| Performer +| Date +| Input +| Output +| Comment +with + /// + /// Returns true if the Building Block is a term column + /// + member this.IsTermColumn() = + match this with + | Component + | Characteristic + | Factor + | Parameter + | ProtocolType -> true + | _ -> false + member this.HasOA() = + match this with + | Component + | Characteristic + | Factor + | Parameter -> true + | _ -> false + + member this.HasIOType() = + match this with + | Input + | Output -> true + | _ -> false + + static member fromString(str: string) = + match str with + | "Component" -> Component + | "Characteristic" -> Characteristic + | "Factor" -> Factor + | "Parameter" -> Parameter + | "ProtocolType" -> ProtocolType + | "ProtocolDescription" -> ProtocolDescription + | "ProtocolUri" -> ProtocolUri + | "ProtocolVersion" -> ProtocolVersion + | "ProtocolREF" -> ProtocolREF + | "Performer" -> Performer + | "Date" -> Date + | "Input" -> Input + | "Output" -> Output + | "Comment" -> Comment + | anyElse -> failwithf "BuildingBlock.HeaderCellType.fromString: '%s' is not a valid HeaderCellType" anyElse + +[] +type CompositeCellDiscriminate = +| Term +| Unitized +| Text +| Data + [] module Extensions = @@ -292,6 +359,23 @@ module Extensions = | CompositeHeader.Factor oa -> Some oa | _ -> None + member this.AsDiscriminate = + match this with + | CompositeHeader.Component _ -> CompositeHeaderDiscriminate.Component + | CompositeHeader.Characteristic _ -> CompositeHeaderDiscriminate.Characteristic + | CompositeHeader.Factor _ -> CompositeHeaderDiscriminate.Factor + | CompositeHeader.Parameter _ -> CompositeHeaderDiscriminate.Parameter + | CompositeHeader.ProtocolType -> CompositeHeaderDiscriminate.ProtocolType + | CompositeHeader.ProtocolDescription -> CompositeHeaderDiscriminate.ProtocolDescription + | CompositeHeader.ProtocolUri -> CompositeHeaderDiscriminate.ProtocolUri + | CompositeHeader.ProtocolVersion -> CompositeHeaderDiscriminate.ProtocolVersion + | CompositeHeader.ProtocolREF -> CompositeHeaderDiscriminate.ProtocolREF + | CompositeHeader.Performer -> CompositeHeaderDiscriminate.Performer + | CompositeHeader.Date -> CompositeHeaderDiscriminate.Date + | CompositeHeader.Input _ -> CompositeHeaderDiscriminate.Input + | CompositeHeader.Output _ -> CompositeHeaderDiscriminate.Output + | CompositeHeader.Comment _ -> CompositeHeaderDiscriminate.Comment + type CompositeCell with ///