Skip to content

Commit

Permalink
Added platform.isEditable, filtered Open Scripture Editor and Open Re…
Browse files Browse the repository at this point in the history
…source Viewer dialogs by isEditable (#903)
  • Loading branch information
tjcouch-sil authored May 22, 2024
2 parents 40b8066 + 83557e0 commit 59f04c3
Show file tree
Hide file tree
Showing 29 changed files with 1,004 additions and 757 deletions.
4 changes: 3 additions & 1 deletion assets/localization/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,7 @@
"%project_settings_platform_group1_label%": "Platform Settings",
"%project_settings_platform_group1_description%": "Project settings pertaining to the software overall",
"%project_settings_platform_fullName_label%": "Project Full Name",
"%project_settings_platform_language_label%": "Project Primary Language"
"%project_settings_platform_language_label%": "Project Primary Language",
"%project_settings_platform_isEditable_label%": "Is Editable",
"%project_settings_platform_isEditable_description%": "Whether this project is editable. A project that is not editable is sometimes called a resource."
}
12 changes: 12 additions & 0 deletions c-sharp/Projects/ParatextProjectDataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,18 @@ public ResponseToRequest GetProjectSetting(string jsonKey)
ProjectSettings.GetParatextSettingNameFromPlatformBibleSettingName(settingName) ??
settingName;
var scrText = LocalParatextProjects.GetParatextProject(ProjectDetails.Metadata.ID);

if (scrText.Settings.ParametersDictionary.TryGetValue(settingName, out string? settingValue)) {
// Paratext project setting value found, so return the value with the appropriate type
if (ProjectSettings.IsParatextSettingABoolean(settingName))
{
return settingValue switch
{
"T" => ResponseToRequest.Succeeded(true),
"F" => ResponseToRequest.Succeeded(false),
_ => ResponseToRequest.Failed($"Failed to convert Paratext setting {settingName} to boolean. Value was not T or F"),
};
}
return ResponseToRequest.Succeeded(settingValue);
}

Expand All @@ -238,6 +249,7 @@ public ResponseToRequest GetProjectSetting(string jsonKey)
public ResponseToRequest SetProjectSetting(string jsonKey, string value)
{
var settingName = JToken.Parse(jsonKey).ToString();

var scrText = LocalParatextProjects.GetParatextProject(ProjectDetails.Metadata.ID);

// If there is no Paratext setting for the name given, we'll create one lower down
Expand Down
19 changes: 19 additions & 0 deletions c-sharp/Projects/ProjectSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ public sealed class ProjectSettings
public const string PB_VERSIFICATION = "platformScripture.versification";
public const string PT_VERSIFICATION = "Versification";

public const string PB_IS_EDITABLE = "platform.isEditable";
public const string PT_IS_EDITABLE = "Editable";

/// <summary>
/// Paratext setting names that are either T or F and need to be converted to booleans
/// </summary>
private static readonly List<string> PT_SETTING_BOOLEANS = ["Editable", "MatchBasedOnStems", "AllowReadAccess", "AllowSharingWithSLDR", ];

// Make sure this dictionary gets updated whenever new settings are added
private static readonly Dictionary<string, string> s_platformBibleToParatextSettingsNames =
new()
Expand All @@ -22,6 +30,7 @@ public sealed class ProjectSettings
{ PB_FULL_NAME, PT_FULL_NAME },
{ PB_LANGUAGE, PT_LANGUAGE },
{ PB_VERSIFICATION, PT_VERSIFICATION },
{ PB_IS_EDITABLE, PT_IS_EDITABLE },
};

private static readonly Dictionary<string, string> s_paratextToPlatformBibleSettingsNames =
Expand Down Expand Up @@ -50,4 +59,14 @@ public sealed class ProjectSettings
? retVal
: null;
}

/// <summary>
/// Determines whether a Paratext Setting is expected to be a boolean ("T" or "F" only)
/// </summary>
/// <param name="ptSettingName"></param>
/// <returns></returns>
public static bool IsParatextSettingABoolean(string ptSettingName)
{
return PT_SETTING_BOOLEANS.Contains(ptSettingName);
}
}
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"hopkinson",
"iframes",
"IIFE",
"localizable",
"localstorage",
"maximizable",
"networkable",
Expand Down
16 changes: 16 additions & 0 deletions extensions/src/hello-world/src/web-views/hello-world.web-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,22 @@ globalThis.webViewComponent = function HelloWorld({
<div>
<Button onClick={selectProject}>Select Project</Button>
</div>
<div>
<Button
onClick={() =>
papi.commands.sendCommand('platformScriptureEditor.openScriptureEditor', project)
}
>
Open in Scripture Editor
</Button>
<Button
onClick={() =>
papi.commands.sendCommand('platformScriptureEditor.openResourceViewer', project)
}
>
Open in Resource Viewer
</Button>
</div>
<h3 style={headerStyle}>{verseRef.toString()}</h3>
<div>{currentProjectVerse}</div>
<ProjectSettingsEditor {...helloWorldProjectSettings} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
"%webView_platformScriptureEditor_textColor%": "Text Color",
"%webView_platformScriptureEditor_thickBorders%": "Thick Borders",
"%webView_platformScriptureEditor_publisherInfo%": "Publisher Info",
"%webView_platformScriptureEditor_copyrightInfo%": "Copyright Info"
"%webView_platformScriptureEditor_copyrightInfo%": "Copyright Info",
"%platformScriptureEditor_dialog_openResourceViewer_title%": "Open Resource Viewer",
"%platformScriptureEditor_dialog_openResourceViewer_prompt%": "Choose a resource to open:",
"%platformScriptureEditor_dialog_openScriptureEditor_title%": "Open Scripture Editor",
"%platformScriptureEditor_dialog_openScriptureEditor_prompt%": "Choose a project to open:"
}
}
}
47 changes: 39 additions & 8 deletions extensions/src/platform-scripture-editor/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,47 @@ async function open(
projectId: string | undefined,
isReadOnly: boolean,
): Promise<string | undefined> {
let projectIdForWebView = projectId;
if (!projectIdForWebView) {
projectIdForWebView = await papi.dialogs.selectProject({
title: 'Select Resource',
prompt: 'Choose the resource project:',
includeProjectTypes: '^ParatextStandard$',
const projectForWebView = { projectId, isEditable: !isReadOnly };
if (!projectForWebView.projectId) {
// Get a list of projects that are editable or not editable to show in the select project dialog
const projectMetadatas = (await papi.projectLookup.getMetadataForAllProjects()).filter(
(projectMetadata) => projectMetadata.projectType === 'ParatextStandard',
);
const projectsWithEditable = await Promise.all(
projectMetadatas.map(async (projectMetadata) => {
const pdp = await papi.projectDataProviders.get('ParatextStandard', projectMetadata.id);
return {
projectId: projectMetadata.id,
isEditable: await pdp.getSetting('platform.isEditable'),
};
}),
);

projectForWebView.projectId = await papi.dialogs.selectProject({
title: isReadOnly
? '%platformScriptureEditor_dialog_openResourceViewer_title%'
: '%platformScriptureEditor_dialog_openScriptureEditor_title%',
prompt: isReadOnly
? '%platformScriptureEditor_dialog_openResourceViewer_prompt%'
: '%platformScriptureEditor_dialog_openScriptureEditor_prompt%',
// Include projects whose editable matches readonly
includeProjectIds: projectsWithEditable
.filter(({ isEditable }) => isEditable !== isReadOnly)
.map(({ projectId: pId }) => pId),
});
} else {
// Get whether the provided project is editable
const pdp = await papi.projectDataProviders.get(
'ParatextStandard',
projectForWebView.projectId,
);
projectForWebView.isEditable = await pdp.getSetting('platform.isEditable');
}
if (projectIdForWebView) {
const options: PlatformScriptureEditorOptions = { projectId: projectIdForWebView, isReadOnly };
if (projectForWebView.projectId) {
const options: PlatformScriptureEditorOptions = {
projectId: projectForWebView.projectId,
isReadOnly: !projectForWebView.isEditable,
};
// REVIEW: If an editor is already open for the selected project, we open another.
// This matches the current behavior in P9, though it might not be what we want long-term.
return papi.webViews.getWebView(scriptureEditorWebViewType, undefined, options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ declare module 'papi-shared-types' {
/**
* Opens a new editor WebView and returns the WebView id
*
* @param projectId Optional project ID of the resource to open. Prompts the user to select a
* resource project if not provided
* @param projectId Optional project ID of the project/resource to open. If a resource ID (not
* editable) is provided, this will properly open the resource viewer. Prompts the user to
* select a project if this parameter is not provided.
* @returns WebView id for new editor WebView or `undefined` if the user canceled the dialog
*/
'platformScriptureEditor.openScriptureEditor': (
Expand All @@ -16,8 +17,9 @@ declare module 'papi-shared-types' {
/**
* Opens a new read-only editor WebView and returns the WebView id
*
* @param projectId Optional project ID of the resource to open. Prompts the user to select a
* resource project if not provided
* @param projectId Optional project ID of the project/resource to open. If a project ID
* (editable) is provided, this will properly open the Scripture editor. Prompts the user to
* select a resource if this parameter is not provided.
* @returns WebView id for new editor WebView or `undefined` if the user canceled the dialog
*/
'platformScriptureEditor.openResourceViewer': (
Expand Down
34 changes: 28 additions & 6 deletions lib/papi-dts/papi.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2352,6 +2352,13 @@ declare module 'papi-shared-types' {
* @example 'World English Bible'
*/
'platform.fullName': string;
/**
* Whether or not the project is editable. This is a general "editable", not necessarily that it
* is editable by the current user.
*
* Projects that are not editable are sometimes called "resources".
*/
'platform.isEditable': boolean;
}
/**
* Names for each user setting available on the papi.
Expand Down Expand Up @@ -3572,6 +3579,8 @@ declare module 'shared/models/project-lookup.service-model' {
export type ProjectMetadataFilterOptions = {
/** Project IDs to exclude */
excludeProjectIds?: string | string[];
/** Project IDs to include */
includeProjectIds?: string | string[];
/**
* String representation of `RegExp` pattern(s) to match against projects' `projectType` (using
* the
Expand Down Expand Up @@ -3663,15 +3672,28 @@ declare module 'extension-host/extension-types/extension-activation-context.mode
};
}
declare module 'shared/models/dialog-options.model' {
import { LocalizeKey } from 'platform-bible-utils';
/** General options to adjust dialogs (created from `papi.dialogs`) */
export type DialogOptions = {
/** Dialog title to display in the header. Default depends on the dialog */
title?: string;
/**
* Dialog title to display in the header. If you provide a {@link LocalizeKey}, it will be
* localized before displaying.
*
* Default depends on the dialog
*/
title?: string | LocalizeKey;
/** Url of dialog icon to display in the header. Default is Platform.Bible logo */
iconUrl?: string;
/** The message to show the user in the dialog. Default depends on the dialog */
prompt?: string;
/**
* The message to show the user in the dialog. If you provide a {@link LocalizeKey}, it will be
* localized before displaying.
*
* Default depends on the dialog
*/
prompt?: string | LocalizeKey;
};
/** Keys of properties on {@link DialogOptions} that should be localized if they are LocalizeKeys */
export const DIALOG_OPTIONS_LOCALIZABLE_PROPERTY_KEYS: readonly ['title', 'prompt'];
/** Data in each tab that is a dialog. Added to DialogOptions in `dialog.service-host.ts` */
export type DialogData = DialogOptions & {
isDialog: true;
Expand Down Expand Up @@ -4881,8 +4903,8 @@ declare module 'shared/services/menu-data.service' {
}
declare module 'shared/services/localization.service' {
import { ILocalizationService } from 'shared/services/localization.service-model';
const localizationDataService: ILocalizationService;
export default localizationDataService;
const localizationService: ILocalizationService;
export default localizationService;
}
declare module 'shared/services/settings.service' {
import { ISettingsService } from 'shared/services/settings.service-model';
Expand Down
2 changes: 1 addition & 1 deletion lib/platform-bible-utils/dist/index.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion lib/platform-bible-utils/dist/index.cjs.map

Large diffs are not rendered by default.

Loading

0 comments on commit 59f04c3

Please sign in to comment.