Skip to content

Commit

Permalink
Merge branch 'main' into 742-use-localizations
Browse files Browse the repository at this point in the history
  • Loading branch information
katherinejensen00 committed Aug 30, 2024
2 parents 6e0a562 + bf53f5c commit eeff67e
Show file tree
Hide file tree
Showing 42 changed files with 1,963 additions and 1,261 deletions.
23 changes: 22 additions & 1 deletion c-sharp/Checks/CheckResultsRecorder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void RecordError(
{
var chapterVerse = token.ScrRefString.Split(":");
int chapterNumber = int.Parse(chapterVerse[0]);
int verseNumber = int.Parse(chapterVerse[1]);
int verseNumber = GetVerseNumber(chapterVerse[1]);
VerseRef verseRef = new (CurrentBookNumber, chapterNumber, verseNumber);
CheckRunResults.Add(new CheckRunResult(
checkId,
Expand Down Expand Up @@ -58,4 +58,25 @@ public void RecordError(
}

public List<CheckRunResult> CheckRunResults { get; } = [];

private static int GetVerseNumber(string verseNumber)
{
ArgumentException.ThrowIfNullOrWhiteSpace(verseNumber);
if (!IsDigit(verseNumber[0]))
throw new ArgumentException($"verseNumber must start with an integer: {verseNumber}");

int lastIndex = 1;
while (lastIndex < verseNumber.Length)
{
if (!IsDigit(verseNumber[lastIndex]))
break;
lastIndex++;
}
return int.Parse(verseNumber[..lastIndex]);
}

private static bool IsDigit(char c)
{
return c >= '0' && c <= '9';
}
}
7 changes: 7 additions & 0 deletions c-sharp/Checks/CheckRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,13 @@ private ResponseToRequest GetCheckResults()
var retVal = new List<CheckRunResult>();
foreach (var check in _checksByIds.Values)
retVal.AddRange(check.ResultsRecorder.CheckRunResults);
if (retVal.Count > 1000)
{
var fullCount = retVal.Count;
retVal.RemoveRange(1000, fullCount - 1000);
retVal.TrimExcess();
Console.WriteLine($"Trimming {fullCount} check results to 1000");
}
Console.WriteLine($"Returning {retVal.Count} check results");
return ResponseToRequest.Succeeded(retVal);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"%webView_platformScriptureEditor_thickBorders%": "Thick Borders",
"%webView_platformScriptureEditor_charactersInventory%": "Inventory: Characters",
"%webView_platformScriptureEditor_repeatedWordsInventory%": "Inventory: Repeated Words",
"%webView_platformScriptureEditor_runBasicChecks%": "Run Basic Checks...",
"%webView_platformScriptureEditor_publisherInfo%": "Publisher Info",
"%webView_platformScriptureEditor_copyrightInfo%": "Copyright Info",
"%webView_platformScriptureEditor_editable%": "(Editable)",
Expand Down
10 changes: 10 additions & 0 deletions extensions/src/platform-scripture-editor/contributions/menus.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
"platformScriptureEditor.inventory": {
"column": "platformScriptureEditor.tools",
"order": 2
},
"platformScriptureEditor.checks": {
"column": "platformScriptureEditor.tools",
"order": 3
}
},
"items": [
Expand Down Expand Up @@ -80,6 +84,12 @@
"order": 2,
"command": "platformScripture.openRepeatedWordsInventory"
},
{
"label": "%webView_platformScriptureEditor_runBasicChecks%",
"group": "platformScriptureEditor.checks",
"order": 1,
"command": "platformScripture.runBasicChecks"
},
{
"label": "%webView_platformScriptureEditor_thickBorders%",
"group": "platformScriptureEditor.layout",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"%mainMenu_toggleIncludeMyParatext9Projects%": "Toggle Include My Paratext 9 Projects",
"%webView_characterInventory_title%": "Character Inventory",
"%webView_repeatedWordsInventory_title%": "Repeated Words Inventory",
"%webView_checkResultsList_title%": "Check Results",
"%webView_inventory_all%": "All items",
"%webView_inventory_approved%": "Approved items",
"%webView_inventory_unapproved%": "Unapproved items",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
ColumnDef,
Inventory,
ItemData,
Scope,
Status,
inventoryCountColumn,
inventoryItemColumn,
Expand All @@ -20,6 +21,16 @@ const CHARACTER_INVENTORY_STRING_KEYS: LocalizeKey[] = [
'%webView_inventory_table_header_status%',
];

/**
* Function that constructs the column for the inventory component
*
* @param itemLabel Localized label for the item column (e.g. 'Character', 'Repeated Word', etc.)
* @param unicodeValueLabel Localized label for the Unicode Value column
* @param countLabel Localized label for the count column
* @param statusLabel Localized label for the status column
* @param statusChangeHandler Callback function that handles status updates to selected item(s)
* @returns An array of columns that can be passed into the inventory component
*/
const createColumns = (
itemLabel: string,
unicodeValueLabel: string,
Expand Down Expand Up @@ -49,8 +60,8 @@ type CharacterInventoryProps = {
unapprovedItems: string[];
onUnapprovedItemsChange: (items: string[]) => void;
text: string | undefined;
scope: string;
onScopeChange: (scope: string) => void;
scope: Scope;
onScopeChange: (scope: Scope) => void;
};

function CharacterInventory({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.checking-results-list {
height: 500px;
}

.checking-results-list-label {
padding-inline-start: 10px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { WebViewProps } from '@papi/core';
import { Button, Label, ResultsSet, ScriptureResultsViewer } from 'platform-bible-react';
import { useState, useCallback, useEffect, useMemo } from 'react';
import { badLeftoversCheck, engineProblemsCheck } from './testing/test-scripture-checks';

const getLabel = (
projectName: string | undefined,
datetime: string | undefined,
sources: ResultsSet[],
): string => {
let result = '';
if (projectName) {
result = projectName;
}
if (datetime) result += `; ${datetime}`;
if (sources.length > 0) {
result += '; ';
result += sources
.map((s) => s.source.displayName)
.filter(Boolean)
.join(', ');
}
return result;
};

global.webViewComponent = function CheckingResultsListWebView({ useWebViewState }: WebViewProps) {
const [projectName] = useWebViewState('projectName', 'Dummy project');

// This is stub code to get some dummy checking results.
// TODO (#994): Replace this with calls to get actual check results and subscribe to updates.
const onRerun = useCallback(() => {
badLeftoversCheck.reRun();
engineProblemsCheck.reRun();
}, []);

const sources = useMemo(() => [badLeftoversCheck, engineProblemsCheck], []);

const [lastUpdateTimestamp, setLastUpdateTimestamp] = useState<string | undefined>(undefined);
const [currentSources, setCurrentSources] = useState(sources);

useEffect(() => {
setCurrentSources(sources);
}, [sources]);

const handleResultsUpdated = useCallback(() => {
const currentTimestamp = new Date().toLocaleString();
setLastUpdateTimestamp(currentTimestamp);
}, []);

const reRunChecks = useCallback(() => {
if (onRerun) {
onRerun();
// Since onRerun modifies the sources directly, we need to trigger a state update
setCurrentSources([...sources]);
handleResultsUpdated();
}
}, [onRerun, sources, handleResultsUpdated]);

const label = getLabel(projectName, lastUpdateTimestamp, sources);

return (
<div className="checking-results-list">
<Button onClick={reRunChecks}>Rerun</Button>
{label && <Label className="checking-results-list-label">{label}</Label>}
<ScriptureResultsViewer sources={currentSources} />
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import papi, { logger, projectLookup } from '@papi/backend';
import {
GetWebViewOptions,
IWebViewProvider,
SavedWebViewDefinition,
WebViewDefinition,
} from '@papi/core';
import checkingResultsListWebView from './checking-results-list.web-view?inline';
import checkingResultsListStyles from './checking-results-list.web-view.scss?inline';

export const checkResultsListWebViewType = 'platformScripture.checkingResults';

export interface CheckResultsWebViewOptions extends GetWebViewOptions {
projectId: string | undefined;
}

export default class CheckResultsWebViewProvider implements IWebViewProvider {
constructor(public webViewType: string = checkResultsListWebViewType) {}

async getWebView(
savedWebView: SavedWebViewDefinition,
getWebViewOptions: CheckResultsWebViewOptions,
): Promise<WebViewDefinition | undefined> {
if (savedWebView.webViewType !== this.webViewType)
throw new Error(
`${checkResultsListWebViewType} provider received request to provide a ${savedWebView.webViewType} web view`,
);

// We know that the projectId (if present in the state) will be a string.
let projectId =
getWebViewOptions.projectId ||
// eslint-disable-next-line no-type-assertion/no-type-assertion
(savedWebView.state?.projectId as string) ||
undefined;

let title = await papi.localization.getLocalizedString({
localizeKey: '%webView_checkResultsList_title%',
});

let projectName: string | undefined;

if (projectId) {
projectName =
(await (
await papi.projectDataProviders.get('platform.base', projectId)
).getSetting('platform.name')) ?? projectId;

title += ` - ${projectName}`;
}

if (!projectId && globalThis.isNoisyDevModeEnabled) {
logger.debug(`${title} web view did not get a project passed in. Choosing a random one...`);

const projectMetadata = await projectLookup.getMetadataForAllProjects();
if (projectMetadata.length === 0) {
logger.debug('Testing out checks: No projects available');
return undefined;
}
projectId = projectMetadata[0].id;
}

logger.info(`${title} web view opening with ${projectId}`);

return {
title,
...savedWebView,
content: checkingResultsListWebView,
styles: checkingResultsListStyles,
state: {
projectName,
projectId,
...savedWebView.state,
webViewType: this.webViewType,
},
};
}
}
34 changes: 26 additions & 8 deletions extensions/src/platform-scripture/src/inventory-utils.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,38 @@
import { split } from 'platform-bible-utils';

export const extractCharacters = (text: string, item: string | undefined = undefined): string[] => {
/**
* Extracts characters from scripture text. If a target is provided, only extracts occurrences of
* the provided target
*
* @param text The scripture text from which the characters will be extracted
* @param target (Optional) If provided, the function only extracts exact matches of this character
* @returns An array of characters extracted from the provided scripture text
*/
export const extractCharacters = (
text: string,
target: string | undefined = undefined,
): string[] => {
let characters: string[] = split(text, '');
if (item) characters = characters.filter((character) => character === item);
if (target) characters = characters.filter((character) => character === target);
return characters;
};

/**
* Extracts repeated words from scripture text. If a target is provided, only extracts occurences of
* the provided target
*
* @param text The scripture text from which the characters will be extracted
* @param target (Optional) If provided, the function only extracts exact matches of this words
* @returns An array of repeated words extracted from the provided scripture text
*/
export const extractRepeatedWords = (
text: string,
target: string | undefined = undefined,
): string[] => {
const repeatedWords: string[] = [];
const words = split(text, /[\s]+/);
words.forEach((word, index, allWords) => {
if (target && word !== target) return;
if (index + 1 < allWords.length && word === allWords[index + 1]) repeatedWords.push(word);
});
// Finds repeated words, and captures the first occurrence of the word
const repeatedWords = text.match(/\b(\p{L}+)\b(?= \b\1\b)/gu) || [];

if (target) return repeatedWords?.filter((word) => word === target);

return repeatedWords;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import papi from '@papi/backend';
import {
GetWebViewOptions,
IWebViewProvider,
SavedWebViewDefinition,
WebViewDefinition,
} from '@papi/core';
import { LocalizeKey } from 'platform-bible-utils';
import inventoryWebView from './inventory.web-view?inline';
import inventoryWebViewStyles from './inventory.web-view.scss?inline';

export interface InventoryWebViewOptions extends GetWebViewOptions {
projectId: string | undefined;
}

export default class InventoryWebViewProvider implements IWebViewProvider {
constructor(
public titleKey: LocalizeKey,
public webViewType: string,
) {}

async getWebView(
savedWebView: SavedWebViewDefinition,
getWebViewOptions: InventoryWebViewOptions,
): Promise<WebViewDefinition | undefined> {
if (savedWebView.webViewType !== this.webViewType)
throw new Error(
`${this.webViewType} provider received request to provide a ${savedWebView.webViewType} web view`,
);

// We know that the projectId (if present in the state) will be a string.
const projectId =
getWebViewOptions.projectId ||
// eslint-disable-next-line no-type-assertion/no-type-assertion
(savedWebView.state?.projectId as string) ||
undefined;

const title: string = await papi.localization.getLocalizedString({
localizeKey: this.titleKey,
});

return {
title,
...savedWebView,
content: inventoryWebView,
styles: inventoryWebViewStyles,
state: {
...savedWebView.state,
projectId,
webViewType: this.webViewType,
},
};
}
}
Loading

0 comments on commit eeff67e

Please sign in to comment.