From ab34da8bedbe337a070222ca7abb456f07365ab9 Mon Sep 17 00:00:00 2001 From: Rolf Heij Date: Tue, 19 Dec 2023 11:44:47 +0100 Subject: [PATCH 1/9] Add WEB proj --- c-sharp/JsonUtils/ProjectMetadataConverter.cs | 16 +++++ c-sharp/Projects/LocalParatextProjects.cs | 58 ++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/c-sharp/JsonUtils/ProjectMetadataConverter.cs b/c-sharp/JsonUtils/ProjectMetadataConverter.cs index 3bebb2d518..376dcc136c 100644 --- a/c-sharp/JsonUtils/ProjectMetadataConverter.cs +++ b/c-sharp/JsonUtils/ProjectMetadataConverter.cs @@ -57,5 +57,21 @@ public static string ToJsonString(ProjectMetadata projectMetadata) [PROJECT_TYPE] = projectMetadata.ProjectType }.ToString(); } + + public static string ToJsonString( + string id, + string name, + string storageType, + string projectType + ) + { + return new JObject + { + [ID] = id, + [NAME] = name, + [STORAGE_TYPE] = storageType, + [PROJECT_TYPE] = projectType + }.ToString(); + } } } diff --git a/c-sharp/Projects/LocalParatextProjects.cs b/c-sharp/Projects/LocalParatextProjects.cs index ab4cf5e9c6..5c44108b7d 100644 --- a/c-sharp/Projects/LocalParatextProjects.cs +++ b/c-sharp/Projects/LocalParatextProjects.cs @@ -1,4 +1,5 @@ using System.Collections.Concurrent; +using System.ComponentModel.DataAnnotations; using Paranext.DataProvider.JsonUtils; using Paratext.Data; using Paratext.Data.Users; @@ -17,7 +18,9 @@ internal class LocalParatextProjects protected const string PROJECT_METADATA_FILE = "meta.json"; // Inside of the project subdirectory, this is the subdirectory for Paratext projects + // A subdirectory for extensions is also located here protected const string PARATEXT_DATA_SUBDIRECTORY = "paratext"; + protected const string EXTENSIONS_SUBDIRECTORY = "extensions"; protected readonly ConcurrentDictionary _projectDetailsMap = new(); @@ -41,7 +44,18 @@ public virtual void Initialize() CreateDirectory(ProjectRootFolder); - foreach (var projectDetails in LoadAllProjectDetails()) + IEnumerable allProjectDetails = LoadAllProjectDetails(); + + if (!allProjectDetails.Any()) + { + Console.WriteLine("Rolf: Sample project set up"); + + SetUpSampleProject(); + + allProjectDetails = LoadAllProjectDetails(); + } + + foreach (ProjectDetails projectDetails in allProjectDetails) { if (projectDetails.Metadata.ProjectStorageType != ProjectStorageType.ParatextFolders) continue; @@ -58,6 +72,44 @@ public virtual void Initialize() } } + private void SetUpSampleProject() + { + string projectName = "WEB"; + string projectId = "32664dc3288a28df2e2bb75ded887fc8f17a15fb"; + string projectFolderName = projectName + "_" + projectId; + string projectFolder = Path.Join(ProjectRootFolder, projectFolderName); + ProjectMetadata metadata = + new(projectId, projectName, "paratextFolders", "ParatextStandard"); + string metadataString = ProjectMetadataConverter.ToJsonString( + metadata.ID, + metadata.Name, + metadata.ProjectStorageType, + metadata.ProjectType + ); + + CreateDirectory(projectFolder); + CreateDirectory(Path.Join(projectFolder, PROJECT_SUBDIRECTORY)); + CreateDirectory(Path.Join(projectFolder, PROJECT_SUBDIRECTORY, EXTENSIONS_SUBDIRECTORY)); + CreateDirectory(Path.Join(projectFolder, PROJECT_SUBDIRECTORY, PARATEXT_DATA_SUBDIRECTORY)); + + File.WriteAllText(Path.Join(projectFolder, PROJECT_METADATA_FILE), metadataString); + + foreach (string newPath in Directory.GetFiles("assets/" + projectName, "*.*")) + { + File.Copy( + newPath, + newPath.Replace( + "assets/" + projectName, + Path.Join(projectFolder, PROJECT_SUBDIRECTORY, PARATEXT_DATA_SUBDIRECTORY) + ) + ); + } + + // is this required? + ProjectDetails projectDetails = new(metadata, Path.Join(projectFolder)); + AddProjectToMaps(projectDetails); + } + public IList GetAllProjectDetails() { return _projectDetailsMap.Values.ToList(); @@ -158,8 +210,12 @@ private void AddProjectToMaps(ProjectDetails projectDetails) /// Enumeration of (ProjectMetadata, project directory) tuples for all projects private IEnumerable LoadAllProjectDetails() { + Console.WriteLine("Rolf: Loading projects"); + Console.WriteLine(ProjectRootFolder); foreach (var dir in Directory.EnumerateDirectories(ProjectRootFolder)) { + Console.WriteLine("Rolf: Loading project"); + ProjectMetadata? projectMetadata; string errorMessage; try From ce13b7bee295f20e6bc320804417d200864e3990 Mon Sep 17 00:00:00 2001 From: Rolf Heij Date: Tue, 19 Dec 2023 11:59:16 +0100 Subject: [PATCH 2/9] Rename path var --- c-sharp/Projects/LocalParatextProjects.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/c-sharp/Projects/LocalParatextProjects.cs b/c-sharp/Projects/LocalParatextProjects.cs index 5c44108b7d..b6dffbc06f 100644 --- a/c-sharp/Projects/LocalParatextProjects.cs +++ b/c-sharp/Projects/LocalParatextProjects.cs @@ -94,20 +94,20 @@ private void SetUpSampleProject() File.WriteAllText(Path.Join(projectFolder, PROJECT_METADATA_FILE), metadataString); - foreach (string newPath in Directory.GetFiles("assets/" + projectName, "*.*")) + foreach (string filePath in Directory.GetFiles("assets/" + projectName, "*.*")) { File.Copy( - newPath, - newPath.Replace( + filePath, + filePath.Replace( "assets/" + projectName, Path.Join(projectFolder, PROJECT_SUBDIRECTORY, PARATEXT_DATA_SUBDIRECTORY) ) ); } - // is this required? - ProjectDetails projectDetails = new(metadata, Path.Join(projectFolder)); - AddProjectToMaps(projectDetails); + // is this required? Don't think so + // ProjectDetails projectDetails = new(metadata, Path.Join(projectFolder)); + // AddProjectToMaps(projectDetails); } public IList GetAllProjectDetails() From 8ea05b23e2be960fe35573bdaf7365431ed2a745 Mon Sep 17 00:00:00 2001 From: Rolf Heij Date: Tue, 19 Dec 2023 13:41:01 +0100 Subject: [PATCH 3/9] Remove comment --- c-sharp/Projects/LocalParatextProjects.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/c-sharp/Projects/LocalParatextProjects.cs b/c-sharp/Projects/LocalParatextProjects.cs index b6dffbc06f..7c1fad0db4 100644 --- a/c-sharp/Projects/LocalParatextProjects.cs +++ b/c-sharp/Projects/LocalParatextProjects.cs @@ -104,10 +104,6 @@ private void SetUpSampleProject() ) ); } - - // is this required? Don't think so - // ProjectDetails projectDetails = new(metadata, Path.Join(projectFolder)); - // AddProjectToMaps(projectDetails); } public IList GetAllProjectDetails() From 87423bb90c85f8693dbfe7344f0d96cf547df900 Mon Sep 17 00:00:00 2001 From: Rolf Heij Date: Tue, 19 Dec 2023 14:26:52 +0100 Subject: [PATCH 4/9] Reactivate tests --- .../services/project-lookup.service-host.ts | 13 ++++++++++++ src/main/main.ts | 21 ++++--------------- .../run-basic-checks-tab.component.tsx | 7 +------ 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/extension-host/services/project-lookup.service-host.ts b/src/extension-host/services/project-lookup.service-host.ts index 02afcb3ae8..f721fa1a7e 100644 --- a/src/extension-host/services/project-lookup.service-host.ts +++ b/src/extension-host/services/project-lookup.service-host.ts @@ -17,8 +17,16 @@ const METADATA_FILE = 'meta.json'; /** Get URIs to all projects stored locally on the file system */ async function getProjectUris(): Promise { // Get all the directories in the projects root + console.log('Rolf: ', PROJECTS_ROOT_URI); + + const stats = await nodeFS.getStats(PROJECTS_ROOT_URI); + + console.log('Rolf Stats: ', stats); + const entries = await nodeFS.readDir(PROJECTS_ROOT_URI); + console.log('Rolf: Entries: ', entries); + return entries.directory; } @@ -37,6 +45,7 @@ function convertToMetadata(jsonString: string): ProjectMetadata { /** Load the contents of all 'meta.json' files from disk */ async function loadAllProjectsMetadata(): Promise> { const retVal = new Set(); + console.log('Rolf: Trigger1'); const uris = await getProjectUris(); await Promise.all( @@ -71,6 +80,7 @@ const localProjects = new Map(); /** Refresh the map of all project 'meta.json' data */ async function reloadMetadata(): Promise { + console.log('Rolf: Trigger2'); const allMetadata = await loadAllProjectsMetadata(); localProjects.clear(); allMetadata.forEach((metadata) => { @@ -84,6 +94,8 @@ async function initialize(): Promise { initializationPromise = new Promise((resolve, reject) => { const executor = async () => { try { + // This is unreached when opening Resource Viewer select project dialog + console.log('Rolf: Trigger3'); await reloadMetadata(); resolve(); } catch (error) { @@ -97,6 +109,7 @@ async function initialize(): Promise { } async function getMetadataForAllProjects(): Promise { + console.log('Rolf: Trigger4'); await initialize(); return [...localProjects.values()]; } diff --git a/src/main/main.ts b/src/main/main.ts index 1d04079adf..6f1b02c6d9 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -23,10 +23,9 @@ import { wait } from '@shared/utils/util'; import { CommandNames } from 'papi-shared-types'; import { SerializedRequestType, serialize } from '@shared/utils/papi-util'; import networkObjectStatusService from '@shared/services/network-object-status.service'; +import { get } from '@shared/services/project-data-provider.service'; +import { VerseRef } from '@sillsdev/scripture'; import { startNetworkObjectStatusService } from './services/network-object-status.service-host'; -// Used with the commented out code at the bottom of this file to test the ParatextProjectDataProvider -// import { get } from '@shared/services/project-data-provider.service'; -// import { VerseRef } from '@sillsdev/scripture'; const PROCESS_CLOSE_TIME_OUT = 2000; @@ -331,20 +330,9 @@ async function main() { // #endregion // #region Test a .NET data provider - // TODO: Uncomment this or similar sample code once https://github.com/paranext/paranext-core/issues/440 is resolved - // In the meantime, if you want to try this, copy an existing project into - // /.platform.bible/_/project/paratext - // For example: "~/.platform.bible/projects/TPKJ_b4c501ad2538989d6fb723518e92408406e232d3/project/paratext" - // Then create a file named "meta.json" in the "_" directory with this JSON: - // { - // "id": "REPLACE_THIS_WITH_PROJECT_ID_FROM_SETTINGS_XML", - // "name": "REPLACE_THIS_WITH_PROJECT_SHORT_NAME", - // "storageType": "paratextFolders", - // "projectType": "ParatextStandard" - // } - /* setTimeout(async () => { - const paratextPdp = await get<'ParatextStandard'>('ParatextStandard', + const paratextPdp = await get<'ParatextStandard'>( + 'ParatextStandard', '32664dc3288a28df2e2bb75ded887fc8f17a15fb', ); const verse = await paratextPdp.getChapterUSX(new VerseRef('JHN', '1', '1')); @@ -357,7 +345,6 @@ async function main() { 'This is the data from extension foo', ); }, 10000); - */ // #endregion } diff --git a/src/renderer/components/run-basic-checks-dialog/run-basic-checks-tab.component.tsx b/src/renderer/components/run-basic-checks-dialog/run-basic-checks-tab.component.tsx index a374f350c9..295edf062e 100644 --- a/src/renderer/components/run-basic-checks-dialog/run-basic-checks-tab.component.tsx +++ b/src/renderer/components/run-basic-checks-dialog/run-basic-checks-tab.component.tsx @@ -137,12 +137,7 @@ export const loadRunBasicChecksTab = (savedTabInfo: SavedTabInfo): TabInfo => { content: ( /.platform.bible/_/project/paratext - // For example: "~/.platform.bible/projects/TPKJ_b4c501ad2538989d6fb723518e92408406e232d3/project/paratext" - // Then create a file named "meta.json" in the "_" directory with this JSON: - currentProjectId="INSERT YOUR PROJECT ID HERE" + currentProjectId="32664dc3288a28df2e2bb75ded887fc8f17a15fb" currentScriptureReference={settingsService.get('platform.verseRef')} /> ), From ce9c34d199159ba04b0af66ee087b3df4dab57c8 Mon Sep 17 00:00:00 2001 From: Rolf Heij Date: Tue, 19 Dec 2023 17:33:58 +0100 Subject: [PATCH 5/9] Temporary fix --- .../services/project-lookup.service-host.ts | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/extension-host/services/project-lookup.service-host.ts b/src/extension-host/services/project-lookup.service-host.ts index f721fa1a7e..58a1dc4979 100644 --- a/src/extension-host/services/project-lookup.service-host.ts +++ b/src/extension-host/services/project-lookup.service-host.ts @@ -17,16 +17,7 @@ const METADATA_FILE = 'meta.json'; /** Get URIs to all projects stored locally on the file system */ async function getProjectUris(): Promise { // Get all the directories in the projects root - console.log('Rolf: ', PROJECTS_ROOT_URI); - - const stats = await nodeFS.getStats(PROJECTS_ROOT_URI); - - console.log('Rolf Stats: ', stats); - const entries = await nodeFS.readDir(PROJECTS_ROOT_URI); - - console.log('Rolf: Entries: ', entries); - return entries.directory; } @@ -45,7 +36,6 @@ function convertToMetadata(jsonString: string): ProjectMetadata { /** Load the contents of all 'meta.json' files from disk */ async function loadAllProjectsMetadata(): Promise> { const retVal = new Set(); - console.log('Rolf: Trigger1'); const uris = await getProjectUris(); await Promise.all( @@ -80,7 +70,6 @@ const localProjects = new Map(); /** Refresh the map of all project 'meta.json' data */ async function reloadMetadata(): Promise { - console.log('Rolf: Trigger2'); const allMetadata = await loadAllProjectsMetadata(); localProjects.clear(); allMetadata.forEach((metadata) => { @@ -94,8 +83,6 @@ async function initialize(): Promise { initializationPromise = new Promise((resolve, reject) => { const executor = async () => { try { - // This is unreached when opening Resource Viewer select project dialog - console.log('Rolf: Trigger3'); await reloadMetadata(); resolve(); } catch (error) { @@ -109,8 +96,8 @@ async function initialize(): Promise { } async function getMetadataForAllProjects(): Promise { - console.log('Rolf: Trigger4'); - await initialize(); + // await initialize(); + await reloadMetadata(); return [...localProjects.values()]; } From 99317296d8334d318788e1e424283adb2b249e92 Mon Sep 17 00:00:00 2001 From: Rolf Heij Date: Tue, 19 Dec 2023 17:38:49 +0100 Subject: [PATCH 6/9] Remove comments --- c-sharp/Projects/LocalParatextProjects.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/c-sharp/Projects/LocalParatextProjects.cs b/c-sharp/Projects/LocalParatextProjects.cs index 7c1fad0db4..5f2c652437 100644 --- a/c-sharp/Projects/LocalParatextProjects.cs +++ b/c-sharp/Projects/LocalParatextProjects.cs @@ -48,8 +48,6 @@ public virtual void Initialize() if (!allProjectDetails.Any()) { - Console.WriteLine("Rolf: Sample project set up"); - SetUpSampleProject(); allProjectDetails = LoadAllProjectDetails(); @@ -206,12 +204,9 @@ private void AddProjectToMaps(ProjectDetails projectDetails) /// Enumeration of (ProjectMetadata, project directory) tuples for all projects private IEnumerable LoadAllProjectDetails() { - Console.WriteLine("Rolf: Loading projects"); Console.WriteLine(ProjectRootFolder); foreach (var dir in Directory.EnumerateDirectories(ProjectRootFolder)) { - Console.WriteLine("Rolf: Loading project"); - ProjectMetadata? projectMetadata; string errorMessage; try From 7764a9f1789fb954a86289b97d1097e9a454711b Mon Sep 17 00:00:00 2001 From: Rolf Heij Date: Tue, 19 Dec 2023 17:43:19 +0100 Subject: [PATCH 7/9] Remove unused import --- c-sharp/Projects/LocalParatextProjects.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/c-sharp/Projects/LocalParatextProjects.cs b/c-sharp/Projects/LocalParatextProjects.cs index 5f2c652437..3a25064179 100644 --- a/c-sharp/Projects/LocalParatextProjects.cs +++ b/c-sharp/Projects/LocalParatextProjects.cs @@ -1,5 +1,4 @@ using System.Collections.Concurrent; -using System.ComponentModel.DataAnnotations; using Paranext.DataProvider.JsonUtils; using Paratext.Data; using Paratext.Data.Users; From 3df24d761475fd868f2cc336ff554f9cae415afd Mon Sep 17 00:00:00 2001 From: Rolf Heij Date: Wed, 20 Dec 2023 18:45:45 +0100 Subject: [PATCH 8/9] Process review comments --- c-sharp/Projects/LocalParatextProjects.cs | 67 +++++++++---------- .../services/project-lookup.service-host.ts | 10 ++- 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/c-sharp/Projects/LocalParatextProjects.cs b/c-sharp/Projects/LocalParatextProjects.cs index 3a25064179..508fad40ac 100644 --- a/c-sharp/Projects/LocalParatextProjects.cs +++ b/c-sharp/Projects/LocalParatextProjects.cs @@ -69,40 +69,6 @@ public virtual void Initialize() } } - private void SetUpSampleProject() - { - string projectName = "WEB"; - string projectId = "32664dc3288a28df2e2bb75ded887fc8f17a15fb"; - string projectFolderName = projectName + "_" + projectId; - string projectFolder = Path.Join(ProjectRootFolder, projectFolderName); - ProjectMetadata metadata = - new(projectId, projectName, "paratextFolders", "ParatextStandard"); - string metadataString = ProjectMetadataConverter.ToJsonString( - metadata.ID, - metadata.Name, - metadata.ProjectStorageType, - metadata.ProjectType - ); - - CreateDirectory(projectFolder); - CreateDirectory(Path.Join(projectFolder, PROJECT_SUBDIRECTORY)); - CreateDirectory(Path.Join(projectFolder, PROJECT_SUBDIRECTORY, EXTENSIONS_SUBDIRECTORY)); - CreateDirectory(Path.Join(projectFolder, PROJECT_SUBDIRECTORY, PARATEXT_DATA_SUBDIRECTORY)); - - File.WriteAllText(Path.Join(projectFolder, PROJECT_METADATA_FILE), metadataString); - - foreach (string filePath in Directory.GetFiles("assets/" + projectName, "*.*")) - { - File.Copy( - filePath, - filePath.Replace( - "assets/" + projectName, - Path.Join(projectFolder, PROJECT_SUBDIRECTORY, PARATEXT_DATA_SUBDIRECTORY) - ) - ); - } - } - public IList GetAllProjectDetails() { return _projectDetailsMap.Values.ToList(); @@ -203,7 +169,6 @@ private void AddProjectToMaps(ProjectDetails projectDetails) /// Enumeration of (ProjectMetadata, project directory) tuples for all projects private IEnumerable LoadAllProjectDetails() { - Console.WriteLine(ProjectRootFolder); foreach (var dir in Directory.EnumerateDirectories(ProjectRootFolder)) { ProjectMetadata? projectMetadata; @@ -254,5 +219,37 @@ out string errorMessage return metadata; } + private void SetUpSampleProject() + { + string projectName = "WEB"; + string projectId = "32664dc3288a28df2e2bb75ded887fc8f17a15fb"; + string projectFolderName = projectName + "_" + projectId; + string projectFolder = Path.Join(ProjectRootFolder, projectFolderName); + ProjectMetadata metadata = + new(projectId, projectName, "paratextFolders", "ParatextStandard"); + string metadataString = ProjectMetadataConverter.ToJsonString( + metadata.ID, + metadata.Name, + metadata.ProjectStorageType, + metadata.ProjectType + ); + + CreateDirectory(Path.Join(projectFolder, PROJECT_SUBDIRECTORY, EXTENSIONS_SUBDIRECTORY)); + CreateDirectory(Path.Join(projectFolder, PROJECT_SUBDIRECTORY, PARATEXT_DATA_SUBDIRECTORY)); + + File.WriteAllText(Path.Join(projectFolder, PROJECT_METADATA_FILE), metadataString); + + foreach (string filePath in Directory.GetFiles("assets/" + projectName, "*.*")) + { + File.Copy( + filePath, + filePath.Replace( + "assets/" + projectName, + Path.Join(projectFolder, PROJECT_SUBDIRECTORY, PARATEXT_DATA_SUBDIRECTORY) + ) + ); + } + } + #endregion } diff --git a/src/extension-host/services/project-lookup.service-host.ts b/src/extension-host/services/project-lookup.service-host.ts index 58a1dc4979..f4d04d0fa5 100644 --- a/src/extension-host/services/project-lookup.service-host.ts +++ b/src/extension-host/services/project-lookup.service-host.ts @@ -9,6 +9,7 @@ import logger from '@shared/services/logger.service'; import networkObjectService from '@shared/services/network-object.service'; import * as nodeFS from '@node/services/node-file-system.service'; import { deserialize } from '@shared/utils/papi-util'; +import { wait } from '@shared/utils/util'; /** This points to the directory where all of the project subdirectories live */ const PROJECTS_ROOT_URI = joinUriPaths('file://', os.homedir(), '.platform.bible', 'projects'); @@ -17,7 +18,11 @@ const METADATA_FILE = 'meta.json'; /** Get URIs to all projects stored locally on the file system */ async function getProjectUris(): Promise { // Get all the directories in the projects root - const entries = await nodeFS.readDir(PROJECTS_ROOT_URI); + let entries = await nodeFS.readDir(PROJECTS_ROOT_URI); + if (entries.directory.length === 0) { + await wait(5000); + entries = await nodeFS.readDir(PROJECTS_ROOT_URI); + } return entries.directory; } @@ -96,8 +101,7 @@ async function initialize(): Promise { } async function getMetadataForAllProjects(): Promise { - // await initialize(); - await reloadMetadata(); + await initialize(); return [...localProjects.values()]; } From b848a7b6485658ec0bc38542a89fe3eb27d7f54a Mon Sep 17 00:00:00 2001 From: Rolf Heij Date: Fri, 22 Dec 2023 13:11:25 +0100 Subject: [PATCH 9/9] Add TODO --- src/extension-host/services/project-lookup.service-host.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/extension-host/services/project-lookup.service-host.ts b/src/extension-host/services/project-lookup.service-host.ts index f4d04d0fa5..e4ddbce390 100644 --- a/src/extension-host/services/project-lookup.service-host.ts +++ b/src/extension-host/services/project-lookup.service-host.ts @@ -20,6 +20,10 @@ async function getProjectUris(): Promise { // Get all the directories in the projects root let entries = await nodeFS.readDir(PROJECTS_ROOT_URI); if (entries.directory.length === 0) { + // TODO: This is a temporary solution that waits for a project directory when none are found. + // Ideally we would want to run `reloadMetadata()` whenever + // a project is added to or removed from the projects directory. + // https://github.com/paranext/paranext-core/issues/691 await wait(5000); entries = await nodeFS.readDir(PROJECTS_ROOT_URI); }