Skip to content

Commit

Permalink
#454: Changed checking-results-list to be a webview (#1076)
Browse files Browse the repository at this point in the history
  • Loading branch information
rolfheij-sil authored Aug 30, 2024
2 parents f989c1f + 6e11806 commit bf53f5c
Show file tree
Hide file tree
Showing 15 changed files with 316 additions and 228 deletions.
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",
"%platformScriptureEditor_dialog_openResourceViewer_title%": "Open Resource Viewer",
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
@@ -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,
},
};
}
}
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,
},
};
}
}
81 changes: 31 additions & 50 deletions extensions/src/platform-scripture/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,21 @@
import papi, { logger, projectLookup } from '@papi/backend';
import { VerseRef } from '@sillsdev/scripture';
import {
ExecutionActivationContext,
GetWebViewOptions,
IWebViewProvider,
ProjectSettingValidator,
SavedWebViewDefinition,
WebViewDefinition,
} from '@papi/core';
import { LocalizeKey } from 'platform-bible-utils';
import { ExecutionActivationContext, ProjectSettingValidator } from '@papi/core';
import ScriptureExtenderProjectDataProviderEngineFactory, {
SCRIPTURE_EXTENDER_PDPF_ID,
} from './project-data-provider/platform-scripture-extender-pdpef.model';
import { SCRIPTURE_EXTENDER_PROJECT_INTERFACES } from './project-data-provider/platform-scripture-extender-pdpe.model';
import checkHostingService from './checks/extension-host-check-runner.service';
import checkAggregatorService from './checks/check-aggregator.service';
import inventoryWebView from './inventory.web-view?inline';
import inventoryWebViewStyles from './inventory.web-view.scss?inline';
import InventoryWebViewProvider, { InventoryWebViewOptions } from './inventory.web-view-provider';
import CheckResultsWebViewProvider, {
checkResultsListWebViewType,
CheckResultsWebViewOptions,
} from './checking-results.web-view-provider';

const characterInventoryWebViewType = 'platformScripture.characterInventory';
const repeatedWordsInventoryWebViewType = 'platformScripture.repeatedWordsInventory';

interface InventoryOptions extends GetWebViewOptions {
projectId: string | undefined;
}

// #region Project Setting Validators

// Should be 123 characters long
Expand Down Expand Up @@ -76,52 +67,31 @@ async function openInventory(
return undefined;
}

const options: InventoryOptions = { projectId };
const options: InventoryWebViewOptions = { projectId };
return papi.webViews.getWebView(
webViewType,
{ type: 'float', floatSize: { width: 700, height: 800 } },
options,
);
}

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

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

// 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;
logger.debug('Running checks');

const title: string = await papi.localization.getLocalizedString({
localizeKey: this.titleKey,
});
if (webViewId) {
const webViewDefinition = await papi.webViews.getSavedWebViewDefinition(webViewId);
projectId = webViewDefinition?.projectId;
}

return {
title,
...savedWebView,
content: inventoryWebView,
styles: inventoryWebViewStyles,
state: {
...savedWebView.state,
projectId,
webViewType: this.webViewType,
},
};
if (!projectId) {
logger.debug('No project!');
return undefined;
}

const options: CheckResultsWebViewOptions = { projectId };
return papi.webViews.getWebView(checkResultsListWebViewType, { type: 'tab' }, options);
}

export async function activate(context: ExecutionActivationContext) {
Expand All @@ -142,6 +112,7 @@ export async function activate(context: ExecutionActivationContext) {
'%webView_repeatedWordsInventory_title%',
repeatedWordsInventoryWebViewType,
);
const checkResultsWebViewProvider = new CheckResultsWebViewProvider();

const includeProjectsCommandPromise = papi.commands.registerCommand(
'platformScripture.toggleIncludeMyParatext9Projects',
Expand Down Expand Up @@ -199,6 +170,14 @@ export async function activate(context: ExecutionActivationContext) {
repeatedWordsInventoryWebViewType,
repeatedWordsInventoryWebViewProvider,
);
const runBasicChecksPromise = papi.commands.registerCommand(
'platformScripture.runBasicChecks',
runPlatformBasicChecks,
);
const checkResultsWebViewProviderPromise = papi.webViewProviders.register(
checkResultsListWebViewType,
checkResultsWebViewProvider,
);

await checkHostingService.initialize();
await checkAggregatorService.initialize();
Expand All @@ -217,6 +196,8 @@ export async function activate(context: ExecutionActivationContext) {
await nonRepeatableWordsPromise,
await openRepeatedWordsInventoryPromise,
await repeatableWordsInventoryWebViewProviderPromise,
await runBasicChecksPromise,
await checkResultsWebViewProviderPromise,
checkHostingService.dispose,
checkAggregatorService.dispose,
);
Expand Down
Loading

0 comments on commit bf53f5c

Please sign in to comment.