diff --git a/src/Client/OfficeInterop/OfficeInterop.fs b/src/Client/OfficeInterop/OfficeInterop.fs
index 58b5c054..460513a6 100644
--- a/src/Client/OfficeInterop/OfficeInterop.fs
+++ b/src/Client/OfficeInterop/OfficeInterop.fs
@@ -1619,6 +1619,59 @@ let getSelectedBuildingBlock (table: Table) (context: RequestContext) =
)
}
+///
+/// Returns a ResizeArray of indices and header names for the selected building block
+/// The indices are rebased to the excel annotation table.
+///
+///
+///
+let getBuildingBlockByColumnIndex (table: Table) (excelColumnIndex: float) (context: RequestContext) =
+ promise {
+ let headerRange = table.getHeaderRowRange()
+ let _ = headerRange.load(U2.Case2 (ResizeArray [|"columnIndex"; "values"; "columnCount"|])) |> ignore
+
+ return! context.sync().``then``(fun _ ->
+ let rebasedIndex = excelColumnIndex - headerRange.columnIndex |> int
+ if rebasedIndex < 0 || rebasedIndex >= (int headerRange.columnCount) then
+ failwith "Cannot select building block outside of annotation table!"
+ let headers: string [] = [|for v in headerRange.values.[0] do v.Value :?> string|]
+ let selectedHeader = rebasedIndex, headers.[rebasedIndex]
+ let buildingBlockGroups = groupToBuildingBlocks headers
+ let selectedBuildingBlock =
+ buildingBlockGroups.Find(fun bb -> bb.Contains selectedHeader)
+ selectedBuildingBlock
+ )
+ }
+
+///
+/// Get the main column of the arc table of the selected building block of the active annotation table
+///
+let getArcIndex (excelTable: Table) (excelColumnIndex: float) (context: RequestContext) =
+ promise {
+ let! selectedBlock = getBuildingBlockByColumnIndex excelTable excelColumnIndex context
+
+ let protoHeaders = excelTable.getHeaderRowRange()
+ let _ = protoHeaders.load(U2.Case2 (ResizeArray(["values"])))
+
+ do! context.sync().``then``(fun _ -> ())
+
+ let headers = protoHeaders.values.Item 0 |> Array.ofSeq |> Array.map (fun c -> c.ToString())
+
+ let arcTableIndices = (groupToBuildingBlocks headers) |> Array.ofSeq |> Array.map (fun i -> i |> Array.ofSeq)
+
+ let arcTableIndex =
+ let potResult = arcTableIndices |> Array.mapi (fun i c -> i, c |> Array.tryFind (fun (_, s) -> s = snd selectedBlock.[0]))
+ let result = potResult |> Array.filter (fun (_, c) -> c.IsSome) |> Array.map (fun (i, c) -> i, c.Value)
+ Array.tryHead result
+
+ let arcTableIndex =
+ if arcTableIndex.IsSome then
+ fst arcTableIndex.Value
+ else failwith "Could not find a fitting arc table index"
+
+ return arcTableIndex
+ }
+
///
/// Returns a ResizeArray of indices and header names for the selected building block
/// The indices are rebased to the excel annotation table.
@@ -2141,6 +2194,50 @@ let validateSelectedAndNeighbouringBuildingBlocks () =
}
)
+let getTermData names =
+ promise {
+ let terms =
+ names
+ |> List.map (fun name ->
+ TermQuery.create(name, searchMode=Database.FullTextSearch.Exact)
+ )
+ |> Array.ofSeq
+ let! result = Async.StartAsPromise (Api.ontology.searchTerms terms)
+
+ return
+ result
+ |> Array.map (fun item -> Array.tryHead item.results)
+ }
+
+let updateSelectedBuildingBlocks (excelTable: Table) (arcTable: ArcTable) (propertyColumns: array) (indexedTerms: list) =
+ promise {
+ let headers = ARCtrl.Spreadsheet.ArcTable.helperColumnStrings |> Array.ofSeq
+
+ for pi in 0..propertyColumns.Length-1 do
+ let pIndex, pcv = propertyColumns.[pi]
+ let values = Array.create (arcTable.RowCount + 1) ""
+ indexedTerms
+ |> List.iter (fun (mainIndex, potTerm) ->
+ match potTerm with
+ | Some term ->
+ match pcv.[0] with
+ | header when header = headers.[2] -> //Unit
+ values.[mainIndex] <- term.Name
+ | header when header.Contains(headers.[0]) -> //Term Source REF
+ values.[mainIndex] <- term.FK_Ontology
+ | header when header.Contains(headers.[1]) -> //Term Accession Number
+ values.[mainIndex] <- term.Accession
+ | _ -> ()
+ | None -> values.[mainIndex] <- pcv.[mainIndex]
+
+ let bodyValues =
+ values
+ |> Array.map (box >> Some)
+ |> Array.map (fun c -> ResizeArray[c])
+ |> ResizeArray
+ excelTable.columns.items.[pIndex].values <- bodyValues
+ )
+ }
///
/// Validates the arc table of the currently selected work sheet
/// When the validations returns an error, an error is returned to the user
@@ -2164,14 +2261,13 @@ let rectifyTermColumns () =
let arcTable = arcTable.Value
let columns = arcTable.Columns
- let _ = excelTable.columns.load(propertyNames = U2.Case2 (ResizeArray[|"items"; "values"; "rowCount"|]))
+ let _ = excelTable.columns.load(propertyNames = U2.Case2 (ResizeArray[|"items"; "rowCount"; "values";|]))
do! context.sync().``then``(fun _ -> ())
let items = excelTable.columns.items
do! context.sync().``then``(fun _ -> ())
let termAndUnitHeaders = columns |> Array.choose (fun item -> if item.Header.IsTermColumn then Some (item.Header.ToString()) else None)
-
let columns =
items
|> Array.ofSeq
@@ -2231,25 +2327,35 @@ let rectifyTermColumns () =
|> Array.map (fun cv -> cv, String.IsNullOrEmpty(cv))
)
+ let mutable names = []
+ let mutable indices = []
+
//Check whether value of property colum is fitting for value of main column and adapt if not
//Delete values of property columns when main column is empty
- propertyColumns
- |> Array.iter (fun (pIndex, pcv) ->
+ for pi in 0..propertyColumns.Length-1 do
+ let pIndex, pcv = propertyColumns.[pi]
let values = Array.create (arcTable.RowCount + 1) ""
- mainColumnHasValues
- |> Array.iteri (fun mainIndex (mc, isNull) ->
- //if isNull for main column, then use empty string as value for properties
+ for mainIndex in 0..mainColumnHasValues.Length-1 do
+ let mc, isNull = mainColumnHasValues.[mainIndex]
if not isNull then
+ names <- mc::names
+ indices <- mainIndex::indices
values.[mainIndex] <- pcv.[mainIndex]
- )
-
let bodyValues =
values
|> Array.map (box >> Some)
|> Array.map (fun c -> ResizeArray[c])
|> ResizeArray
excelTable.columns.items.[pIndex].values <- bodyValues
- )
+
+ let! terms = getTermData names
+
+ let indexedTerms =
+ indices
+ |> List.mapi (fun ii index ->
+ index, terms.[ii])
+
+ do! updateSelectedBuildingBlocks excelTable arcTable propertyColumns indexedTerms
do! ExcelHelper.adoptTableFormats(excelTable, context, true)
diff --git a/src/Client/SidebarComponents/Navbar.fs b/src/Client/SidebarComponents/Navbar.fs
index 26ed39e7..60f70a43 100644
--- a/src/Client/SidebarComponents/Navbar.fs
+++ b/src/Client/SidebarComponents/Navbar.fs
@@ -289,7 +289,7 @@ let private ShortCutIconList navState setNavState model (dispatch: Messages.Msg
| _ ->
()
QuickAccessButton.create(
- "Validate / Update Ontology Terms",
+ "Rectify Ontology Terms",
[
Html.i [prop.className "fa-solid fa-spell-check"]
Html.span model.ExcelState.FillHiddenColsStateStore.toReadableString