Skip to content

Commit bac5e3d

Browse files
committed
SF-3567 Add new books to a project from a draft
1 parent 904cb04 commit bac5e3d

16 files changed

+1193
-25
lines changed

src/SIL.XForge.Scripture/Controllers/SFProjectsRpcController.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Globalization;
34
using System.Threading;
45
using System.Threading.Tasks;
56
using EdjCase.JsonRpc.Router.Abstractions;
@@ -34,6 +35,44 @@ IUserAccessor userAccessor
3435
// Keep a reference in this class to prevent duplicate allocation (Warning CS9107)
3536
private readonly IExceptionHandler _exceptionHandler = exceptionHandler;
3637

38+
public IRpcMethodResult ApplyPreTranslationToProject(
39+
string projectId,
40+
string scriptureRange,
41+
string targetProjectId,
42+
DateTime timestamp
43+
)
44+
{
45+
try
46+
{
47+
// Run the background job
48+
backgroundJobClient.Enqueue<IMachineApiService>(r =>
49+
r.ApplyPreTranslationToProjectAsync(
50+
UserId,
51+
projectId,
52+
scriptureRange,
53+
targetProjectId,
54+
timestamp,
55+
CancellationToken.None
56+
)
57+
);
58+
return Ok();
59+
}
60+
catch (Exception)
61+
{
62+
_exceptionHandler.RecordEndpointInfoForException(
63+
new Dictionary<string, string>
64+
{
65+
{ "method", "ApplyPreTranslationToProject" },
66+
{ "projectId", projectId },
67+
{ "scriptureRange", scriptureRange },
68+
{ "targetProjectId", targetProjectId },
69+
{ "timestamp", timestamp.ToString(CultureInfo.InvariantCulture) },
70+
}
71+
);
72+
throw;
73+
}
74+
}
75+
3776
public async Task<IRpcMethodResult> Create(SFProjectCreateSettings settings)
3877
{
3978
try
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System.Collections.Generic;
2+
3+
namespace SIL.XForge.Scripture.Models;
4+
5+
/// <summary>
6+
/// The result of applying a draft.
7+
/// </summary>
8+
public class DraftApplyResult
9+
{
10+
/// <summary>
11+
/// Whether changes were saved to the database.
12+
/// </summary>
13+
public bool ChangesSaved { get; set; }
14+
15+
/// <summary>
16+
/// A list of any chapters that failed to apply in the format "GEN 1".
17+
/// </summary>
18+
public List<string> Failures = [];
19+
20+
/// <summary>
21+
/// A log containing any warnings or errors that occurred while applying the draft.
22+
/// </summary>
23+
public string Log { get; set; } = string.Empty;
24+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace SIL.XForge.Scripture.Models;
2+
3+
public class DraftApplyState
4+
{
5+
public bool Failed { get; set; }
6+
public string? State { get; set; }
7+
public bool Success { get; set; }
8+
}

src/SIL.XForge.Scripture/Services/DeltaUsxMapper.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Globalization;
44
using System.IO;
55
using System.Linq;
6+
using System.Text.RegularExpressions;
67
using System.Xml.Linq;
78
using System.Xml.Schema;
89
using Microsoft.Extensions.Logging;
@@ -11,7 +12,7 @@
1112

1213
namespace SIL.XForge.Scripture.Services;
1314

14-
public class DeltaUsxMapper(
15+
public partial class DeltaUsxMapper(
1516
IGuidService guidService,
1617
ILogger<DeltaUsxMapper> logger,
1718
IExceptionHandler exceptionHandler
@@ -171,6 +172,15 @@ private static bool CanParaContainVerseText(string? style)
171172
return ParagraphPoetryListStyles.Contains(style);
172173
}
173174

175+
[GeneratedRegex(@"\\id\s+(\w+)", RegexOptions.Compiled)]
176+
private static partial Regex BookIdRegex();
177+
178+
public static string ExtractBookId(string usfm)
179+
{
180+
string firstLine = usfm.Split('\n').FirstOrDefault()?.Trim() ?? string.Empty;
181+
return BookIdRegex().Match(firstLine).Groups[1].Value;
182+
}
183+
174184
/// <summary>
175185
/// Create list of ChapterDelta objects from USX.
176186
///

src/SIL.XForge.Scripture/Services/IMachineApiService.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ namespace SIL.XForge.Scripture.Services;
1414
[Intercept(typeof(EventMetricLogger))]
1515
public interface IMachineApiService
1616
{
17+
[Mutex]
18+
[LogEventMetric(EventScope.Drafting, nameof(curUserId), nameof(sfProjectId), captureReturnValue: true)]
19+
Task<DraftApplyResult> ApplyPreTranslationToProjectAsync(
20+
string curUserId,
21+
string sfProjectId,
22+
string scriptureRange,
23+
string targetProjectId,
24+
DateTime timestamp,
25+
CancellationToken cancellationToken
26+
);
27+
1728
[LogEventMetric(EventScope.Drafting, nameof(sfProjectId))]
1829
Task BuildCompletedAsync(string sfProjectId, string buildId, string buildState, Uri websiteUrl);
1930

src/SIL.XForge.Scripture/Services/INotifier.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ namespace SIL.XForge.Scripture.Services;
66
public interface INotifier
77
{
88
Task NotifyBuildProgress(string sfProjectId, ServalBuildState buildState);
9+
Task NotifyDraftApplyProgress(string sfProjectId, DraftApplyState draftApplyState);
910
Task NotifySyncProgress(string sfProjectId, ProgressState progressState);
1011
Task SubscribeToProject(string projectId);
1112
}

src/SIL.XForge.Scripture/Services/ISFProjectService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ Task UpdatePermissionsAsync(
6464
string curUserId,
6565
IDocument<SFProject> projectDoc,
6666
IReadOnlyList<ParatextProjectUser>? users = null,
67+
IReadOnlyList<int>? books = null,
6768
CancellationToken token = default
6869
);
6970
Task EnsureWritingSystemTagIsSetAsync(string curUserId, string projectId);

0 commit comments

Comments
 (0)