Skip to content

Commit

Permalink
Merge pull request #551 from nfdi4plants/Feature_Excel_UpdateValidate…
Browse files Browse the repository at this point in the history
…Button

Feature, Excel. Restore full finctionality of the button: "Rectify Ontology Terms"
  • Loading branch information
Freymaurer authored Oct 31, 2024
2 parents 2dbca9d + 249edd1 commit caa3acd
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 11 deletions.
126 changes: 116 additions & 10 deletions src/Client/OfficeInterop/OfficeInterop.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1619,6 +1619,59 @@ let getSelectedBuildingBlock (table: Table) (context: RequestContext) =
)
}

/// <summary>
/// Returns a ResizeArray of indices and header names for the selected building block
/// The indices are rebased to the excel annotation table.
/// </summary>
/// <param name="columns"></param>
/// <param name="selectedIndex"></param>
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
)
}

/// <summary>
/// Get the main column of the arc table of the selected building block of the active annotation table
/// </summary>
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
}

/// <summary>
/// Returns a ResizeArray of indices and header names for the selected building block
/// The indices are rebased to the excel annotation table.
Expand Down Expand Up @@ -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<int*string []>) (indexedTerms: list<int*Term option>) =
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
)
}
/// <summary>
/// Validates the arc table of the currently selected work sheet
/// When the validations returns an error, an error is returned to the user
Expand All @@ -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
Expand Down Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion src/Client/SidebarComponents/Navbar.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit caa3acd

Please sign in to comment.