Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion backend/FwLite/FwDataMiniLcmBridge/Api/FwDataMiniLcmApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,10 @@
}
}

public async Task<WritingSystem> CreateWritingSystem(WritingSystemType type, WritingSystem writingSystem)
public async Task<WritingSystem> CreateWritingSystem(WritingSystem writingSystem)
{
await validators.ValidateAndThrow(writingSystem);
var type = writingSystem.Type;
var exitingWs = type == WritingSystemType.Analysis ? Cache.ServiceLocator.WritingSystems.AnalysisWritingSystems : Cache.ServiceLocator.WritingSystems.VernacularWritingSystems;
if (exitingWs.Any(ws => ws.Id == writingSystem.WsId))
{
Expand Down Expand Up @@ -186,13 +187,14 @@

public async Task<WritingSystem> UpdateWritingSystem(WritingSystemId id, WritingSystemType type, UpdateObjectInput<WritingSystem> update)
{
await validators.ValidateAndThrow(update);
if (!Cache.ServiceLocator.WritingSystemManager.TryGet(id.Code, out var lcmWritingSystem))
{
throw new InvalidOperationException($"Writing system {id.Code} not found");
}
await Cache.DoUsingNewOrCurrentUOW("Update WritingSystem",
"Revert WritingSystem",
async () =>

Check warning on line 197 in backend/FwLite/FwDataMiniLcmBridge/Api/FwDataMiniLcmApi.cs

View workflow job for this annotation

GitHub Actions / Build FwHeadless / publish-fw-headless

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 197 in backend/FwLite/FwDataMiniLcmBridge/Api/FwDataMiniLcmApi.cs

View workflow job for this annotation

GitHub Actions / Build FW Lite and run tests

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 197 in backend/FwLite/FwDataMiniLcmBridge/Api/FwDataMiniLcmApi.cs

View workflow job for this annotation

GitHub Actions / Publish FW Lite app for Mac

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 197 in backend/FwLite/FwDataMiniLcmBridge/Api/FwDataMiniLcmApi.cs

View workflow job for this annotation

GitHub Actions / Publish FW Lite app for Mac

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 197 in backend/FwLite/FwDataMiniLcmBridge/Api/FwDataMiniLcmApi.cs

View workflow job for this annotation

GitHub Actions / Publish FW Lite app for Linux

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 197 in backend/FwLite/FwDataMiniLcmBridge/Api/FwDataMiniLcmApi.cs

View workflow job for this annotation

GitHub Actions / Publish FW Lite app for Windows

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
var updateProxy = new UpdateWritingSystemProxy(lcmWritingSystem)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public async Task EnsureDefaultVernacularWritingSystemExistsInCrdt()
if ((await CrdtApi.GetWritingSystems()).Vernacular.Length == 0)
{
var firstVernacularWs = (await FwDataApi.GetWritingSystems()).Vernacular.First();
await CrdtApi.CreateWritingSystem(WritingSystemType.Vernacular, firstVernacularWs);
await CrdtApi.CreateWritingSystem(firstVernacularWs);
}
}
finally
Expand Down
2 changes: 1 addition & 1 deletion backend/FwLite/FwLiteProjectSync.Tests/Sena3SyncTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ private async Task BypassImport(bool wsImported = false)
private async Task WorkaroundMissingWritingSystems()
{
//must have at least one writing system to query for entries
await _crdtApi.CreateWritingSystem(WritingSystemType.Vernacular, (await _fwDataApi.GetWritingSystems()).Vernacular.First());
await _crdtApi.CreateWritingSystem((await _fwDataApi.GetWritingSystems()).Vernacular.First());

}

Expand Down
4 changes: 2 additions & 2 deletions backend/FwLite/FwLiteProjectSync.Tests/SyncTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -415,8 +415,8 @@ public async Task UpdatingAnEntryInEachProjectSyncsAcrossBoth()
{
var crdtApi = _fixture.CrdtApi;
var fwdataApi = _fixture.FwDataApi;
await fwdataApi.CreateWritingSystem(WritingSystemType.Vernacular, new WritingSystem() { Id = Guid.NewGuid(), Type = WritingSystemType.Vernacular, WsId = new WritingSystemId("es"), Name = "Spanish", Abbreviation = "es", Font = "Arial" });
await fwdataApi.CreateWritingSystem(WritingSystemType.Vernacular, new WritingSystem() { Id = Guid.NewGuid(), Type = WritingSystemType.Vernacular, WsId = new WritingSystemId("fr"), Name = "French", Abbreviation = "fr", Font = "Arial" });
await fwdataApi.CreateWritingSystem(new WritingSystem() { Id = Guid.NewGuid(), Type = WritingSystemType.Vernacular, WsId = new WritingSystemId("es"), Name = "Spanish", Abbreviation = "es", Font = "Arial" });
await fwdataApi.CreateWritingSystem(new WritingSystem() { Id = Guid.NewGuid(), Type = WritingSystemType.Vernacular, WsId = new WritingSystemId("fr"), Name = "French", Abbreviation = "fr", Font = "Arial" });
await _syncService.Sync(crdtApi, fwdataApi);

await crdtApi.UpdateEntry(_testEntry.Id, new UpdateObjectInput<Entry>().Set(entry => entry.LexemeForm["es"], "Manzana"));
Expand Down
4 changes: 2 additions & 2 deletions backend/FwLite/FwLiteProjectSync/DryRunMiniLcmApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@

public record DryRunRecord(string Method, string Description);

public Task<WritingSystem> CreateWritingSystem(WritingSystemType type, WritingSystem writingSystem)
public Task<WritingSystem> CreateWritingSystem(WritingSystem writingSystem)
{
DryRunRecords.Add(new DryRunRecord(nameof(CreateWritingSystem), $"Create writing system {type}"));
DryRunRecords.Add(new DryRunRecord(nameof(CreateWritingSystem), $"Create writing system {writingSystem.Type}"));
return Task.FromResult(writingSystem);
}

Expand All @@ -31,7 +31,7 @@
DryRunRecords.Add(new DryRunRecord(nameof(UpdateWritingSystem),
$"Update writing system {type}, changes: {update.Summarize()}"));
var ws = await _api.GetWritingSystems();
return (type switch

Check warning on line 34 in backend/FwLite/FwLiteProjectSync/DryRunMiniLcmApi.cs

View workflow job for this annotation

GitHub Actions / Build FwHeadless / publish-fw-headless

The switch expression does not handle some values of its input type (it is not exhaustive) involving an unnamed enum value. For example, the pattern '(MiniLcm.Models.WritingSystemType)2' is not covered.

Check warning on line 34 in backend/FwLite/FwLiteProjectSync/DryRunMiniLcmApi.cs

View workflow job for this annotation

GitHub Actions / Build FW Lite and run tests

The switch expression does not handle some values of its input type (it is not exhaustive) involving an unnamed enum value. For example, the pattern '(MiniLcm.Models.WritingSystemType)2' is not covered.

Check warning on line 34 in backend/FwLite/FwLiteProjectSync/DryRunMiniLcmApi.cs

View workflow job for this annotation

GitHub Actions / Publish FW Lite app for Mac

The switch expression does not handle some values of its input type (it is not exhaustive) involving an unnamed enum value. For example, the pattern '(MiniLcm.Models.WritingSystemType)2' is not covered.

Check warning on line 34 in backend/FwLite/FwLiteProjectSync/DryRunMiniLcmApi.cs

View workflow job for this annotation

GitHub Actions / Publish FW Lite app for Mac

The switch expression does not handle some values of its input type (it is not exhaustive) involving an unnamed enum value. For example, the pattern '(MiniLcm.Models.WritingSystemType)2' is not covered.

Check warning on line 34 in backend/FwLite/FwLiteProjectSync/DryRunMiniLcmApi.cs

View workflow job for this annotation

GitHub Actions / Publish FW Lite app for Linux

The switch expression does not handle some values of its input type (it is not exhaustive) involving an unnamed enum value. For example, the pattern '(MiniLcm.Models.WritingSystemType)2' is not covered.

Check warning on line 34 in backend/FwLite/FwLiteProjectSync/DryRunMiniLcmApi.cs

View workflow job for this annotation

GitHub Actions / Publish FW Lite app for Windows

The switch expression does not handle some values of its input type (it is not exhaustive) involving an unnamed enum value. For example, the pattern '(MiniLcm.Models.WritingSystemType)2' is not covered.
{
WritingSystemType.Vernacular => ws.Vernacular,
WritingSystemType.Analysis => ws.Analysis
Expand Down
4 changes: 2 additions & 2 deletions backend/FwLite/FwLiteProjectSync/MiniLcmImport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ internal async Task ImportWritingSystems(IMiniLcmApi importTo, IMiniLcmApi impor
var writingSystems = await importFrom.GetWritingSystems();
foreach (var ws in writingSystems.Analysis)
{
await importTo.CreateWritingSystem(WritingSystemType.Analysis, ws);
await importTo.CreateWritingSystem(ws);
logger.LogInformation("Imported ws {WsId}", ws.WsId);
}

foreach (var ws in writingSystems.Vernacular)
{
await importTo.CreateWritingSystem(WritingSystemType.Vernacular, ws);
await importTo.CreateWritingSystem(ws);
logger.LogInformation("Imported ws {WsId}", ws.WsId);
}
}
Expand Down
2 changes: 1 addition & 1 deletion backend/FwLite/FwLiteShared/Services/MiniLcmJsInvokable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public ValueTask<Entry[]> SearchEntries(string query, QueryOptions? options = nu
[JSInvokable]
public Task<WritingSystem> CreateWritingSystem(WritingSystemType type, WritingSystem writingSystem)
{
return _wrappedApi.CreateWritingSystem(type, writingSystem);
return _wrappedApi.CreateWritingSystem(writingSystem);
}

[JSInvokable]
Expand Down
4 changes: 2 additions & 2 deletions backend/FwLite/FwLiteWeb/Hubs/CrdtMiniLcmApiHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ public override IAsyncEnumerable<Entry> SearchEntries(string query, QueryOptions
return base.SearchEntries(query, options);
}

public override async Task<WritingSystem> CreateWritingSystem(WritingSystemType type, WritingSystem writingSystem)
public override async Task<WritingSystem> CreateWritingSystem(WritingSystem writingSystem)
{
var newWritingSystem = await base.CreateWritingSystem(type, writingSystem);
var newWritingSystem = await base.CreateWritingSystem(writingSystem);
TriggerSync();
return newWritingSystem;
}
Expand Down
4 changes: 2 additions & 2 deletions backend/FwLite/FwLiteWeb/Hubs/MiniLcmApiHubBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ public async Task<WritingSystems> GetWritingSystems()
return await miniLcmApi.GetWritingSystems();
}

public virtual async Task<WritingSystem> CreateWritingSystem(WritingSystemType type, WritingSystem writingSystem)
public virtual async Task<WritingSystem> CreateWritingSystem(WritingSystem writingSystem)
{
var newWritingSystem = await miniLcmApi.CreateWritingSystem(type, writingSystem);
var newWritingSystem = await miniLcmApi.CreateWritingSystem(writingSystem);
return newWritingSystem;
}

Expand Down
2 changes: 1 addition & 1 deletion backend/FwLite/LcmCrdt.Tests/Changes/UseChangesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ private static IEnumerable<ChangeWithDependencies> GetAllChanges()
yield return new ChangeWithDependencies(createSemanticDomainChange);

var writingSystem = new WritingSystem { Id = Guid.NewGuid(), WsId = "de", Name = "test ws", Abbreviation = "tws", Font = "Arial", Type = WritingSystemType.Vernacular };
var createWritingSystemChange = new CreateWritingSystemChange(writingSystem, writingSystem.Type, writingSystem.Id, 0);
var createWritingSystemChange = new CreateWritingSystemChange(writingSystem, writingSystem.Id, 0);
yield return new ChangeWithDependencies(createWritingSystemChange);

var complexFormTypeName = new MultiString { { "en", "test cft" } };
Expand Down
46 changes: 46 additions & 0 deletions backend/FwLite/LcmCrdt.Tests/Changes/WritingSystemChangeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using LcmCrdt.Changes;

namespace LcmCrdt.Tests.Changes;

public class WritingSystemChangeTests(MiniLcmApiFixture fixture) : IClassFixture<MiniLcmApiFixture>
{
[Fact]
public async Task CreatingTheSameWritingSystemShouldResultInOnlyOne()
{
var writingSystem = new WritingSystem()
{
Id = Guid.NewGuid(),
WsId = "es",
Abbreviation = "Es",
Font = "test",
Name = "Spanish",
Type = WritingSystemType.Analysis
};
await fixture.Api.CreateWritingSystem(writingSystem);

//added via sync
await fixture.DataModel.AddChange(Guid.NewGuid(),
new CreateWritingSystemChange(writingSystem, Guid.NewGuid(), 2));
var writingSystems = await fixture.Api.GetWritingSystems();
writingSystems.Analysis.Should().ContainSingle(ws => ws.WsId == "es");
}

[Fact]
public async Task Creating2SimilarWritingSystemsWorks()
{
var writingSystem = new WritingSystem()
{
Id = Guid.NewGuid(),
WsId = "de",
Abbreviation = "De",
Font = "test",
Name = "German",
Type = WritingSystemType.Analysis
};
await fixture.Api.CreateWritingSystem(writingSystem);
await fixture.Api.CreateWritingSystem(writingSystem with {Type = WritingSystemType.Vernacular});
var writingSystems = await fixture.Api.GetWritingSystems();
writingSystems.Analysis.Should().ContainSingle(ws => ws.WsId == "de");
writingSystems.Vernacular.Should().ContainSingle(ws => ws.WsId == "de");
}
}
40 changes: 19 additions & 21 deletions backend/FwLite/LcmCrdt.Tests/MiniLcmApiFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,25 @@ await CrdtProjectsService.InitProjectDb(_crdtDbContext,
new ProjectData("Sena 3", "sena-3", Guid.NewGuid(), null, Guid.NewGuid()));
await _services.ServiceProvider.GetRequiredService<CurrentProjectService>().RefreshProjectData();

await Api.CreateWritingSystem(WritingSystemType.Vernacular,
new WritingSystem()
{
Id = Guid.NewGuid(),
WsId = "en",
Name = "English",
Abbreviation = "en",
Font = "Arial",
Exemplars = ["a", "b"],
Type = WritingSystemType.Vernacular
});
await Api.CreateWritingSystem(WritingSystemType.Analysis,
new WritingSystem()
{
Id = Guid.NewGuid(),
WsId = "en",
Name = "English",
Abbreviation = "en",
Font = "Arial",
Type = WritingSystemType.Analysis
});
await Api.CreateWritingSystem(new WritingSystem()
{
Id = Guid.NewGuid(),
WsId = "en",
Name = "English",
Abbreviation = "en",
Font = "Arial",
Exemplars = ["a", "b"],
Type = WritingSystemType.Vernacular
});
await Api.CreateWritingSystem(new WritingSystem()
{
Id = Guid.NewGuid(),
WsId = "en",
Name = "English",
Abbreviation = "en",
Font = "Arial",
Type = WritingSystemType.Analysis
});
}

ITestOutputHelper? _outputHelper;
Expand Down
15 changes: 9 additions & 6 deletions backend/FwLite/LcmCrdt/Changes/CreateWritingSystemChange.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
using LcmCrdt.Utils;
using SIL.Harmony;
using SIL.Harmony.Changes;
using SIL.Harmony.Core;
Expand All @@ -18,15 +19,15 @@ public class CreateWritingSystemChange : CreateChange<WritingSystem>, ISelfNamed
public required double Order { get; init; }

[SetsRequiredMembers]
public CreateWritingSystemChange(WritingSystem writingSystem, WritingSystemType type, Guid entityId, double order) :
public CreateWritingSystemChange(WritingSystem writingSystem, Guid entityId, double order) :
base(entityId)
{
WsId = writingSystem.WsId;
Name = writingSystem.Name;
Abbreviation = writingSystem.Abbreviation;
Font = writingSystem.Font;
Exemplars = writingSystem.Exemplars;
Type = type;
Type = writingSystem.Type;
Order = order;
}

Expand All @@ -35,9 +36,10 @@ private CreateWritingSystemChange(Guid entityId) : base(entityId)
{
}

public override ValueTask<WritingSystem> NewEntity(Commit commit, IChangeContext context)
public override async ValueTask<WritingSystem> NewEntity(Commit commit, IChangeContext context)
{
return ValueTask.FromResult(new WritingSystem
var alreadyExists = await context.GetObjectsOfType<WritingSystem>().AnyAsync(ws => ws.WsId == WsId && ws.Type == Type);
return new WritingSystem
{
Id = EntityId,
WsId = WsId,
Expand All @@ -46,7 +48,8 @@ public override ValueTask<WritingSystem> NewEntity(Commit commit, IChangeContext
Font = Font,
Exemplars = Exemplars,
Type = Type,
Order = Order
});
Order = Order,
DeletedAt = alreadyExists ? commit.DateTime : null
};
}
}
18 changes: 7 additions & 11 deletions backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,24 +93,20 @@ public async Task<WritingSystems> GetWritingSystems()
};
}

public async Task<WritingSystem> CreateWritingSystem(WritingSystemType type, WritingSystem writingSystem)
public async Task<WritingSystem> CreateWritingSystem(WritingSystem writingSystem)
{
await validators.ValidateAndThrow(writingSystem);
var entityId = Guid.NewGuid();
var wsCount = await WritingSystems.CountAsync(ws => ws.Type == type);
try
{
await AddChange(new CreateWritingSystemChange(writingSystem, type, entityId, wsCount));
}
catch (Microsoft.EntityFrameworkCore.DbUpdateException e) when (e.CausedByUniqueConstraintViolation())
{
throw new DuplicateObjectException($"Writing system {writingSystem.WsId.Code} already exists", e);
}
return await GetWritingSystem(writingSystem.WsId, type) ?? throw new NullReferenceException();
var exists = await WritingSystems.AnyAsync(ws => ws.WsId == writingSystem.WsId && ws.Type == writingSystem.Type);
if (exists) throw new DuplicateObjectException($"Writing system {writingSystem.WsId.Code} already exists");
var wsCount = await WritingSystems.CountAsync(ws => ws.Type == writingSystem.Type);
await AddChange(new CreateWritingSystemChange(writingSystem, entityId, wsCount));
return await GetWritingSystem(writingSystem.WsId, writingSystem.Type) ?? throw new NullReferenceException();
}

public async Task<WritingSystem> UpdateWritingSystem(WritingSystemId id, WritingSystemType type, UpdateObjectInput<WritingSystem> update)
{
await validators.ValidateAndThrow(update);
var ws = await GetWritingSystem(id, type);
if (ws is null) throw new NullReferenceException($"unable to find writing system with id {id}");
var patchChange = new JsonPatchChange<WritingSystem>(ws.Id, update.Patch);
Expand Down
84 changes: 40 additions & 44 deletions backend/FwLite/LcmCrdt/CrdtProjectsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,52 +206,48 @@ internal static async Task SeedSystemData(DataModel dataModel, Guid clientId)
public static async Task SampleProjectData(IServiceProvider provider, CrdtProject project)
{
var lexboxApi = provider.GetRequiredService<IMiniLcmApi>();
await lexboxApi.CreateWritingSystem(WritingSystemType.Vernacular,
new()
{
Id = Guid.NewGuid(),
Type = WritingSystemType.Vernacular,
WsId = "de",
Name = "German",
Abbreviation = "de",
Font = "Arial",
Exemplars = WritingSystem.LatinExemplars
});
await lexboxApi.CreateWritingSystem(new()
{
Id = Guid.NewGuid(),
Type = WritingSystemType.Vernacular,
WsId = "de",
Name = "German",
Abbreviation = "de",
Font = "Arial",
Exemplars = WritingSystem.LatinExemplars
});

await lexboxApi.CreateWritingSystem(WritingSystemType.Vernacular,
new()
{
Id = Guid.NewGuid(),
Type = WritingSystemType.Vernacular,
WsId = "en",
Name = "English",
Abbreviation = "en",
Font = "Arial",
Exemplars = WritingSystem.LatinExemplars
});
await lexboxApi.CreateWritingSystem(new()
{
Id = Guid.NewGuid(),
Type = WritingSystemType.Vernacular,
WsId = "en",
Name = "English",
Abbreviation = "en",
Font = "Arial",
Exemplars = WritingSystem.LatinExemplars
});

await lexboxApi.CreateWritingSystem(WritingSystemType.Analysis,
new()
{
Id = Guid.NewGuid(),
Type = WritingSystemType.Analysis,
WsId = "en",
Name = "English",
Abbreviation = "en",
Font = "Arial",
Exemplars = WritingSystem.LatinExemplars
});
await lexboxApi.CreateWritingSystem(WritingSystemType.Analysis,
new()
{
Id = Guid.NewGuid(),
Type = WritingSystemType.Analysis,
WsId = "fr",
Name = "French",
Abbreviation = "fr",
Font = "Arial",
Exemplars = WritingSystem.LatinExemplars
});
await lexboxApi.CreateWritingSystem(new()
{
Id = Guid.NewGuid(),
Type = WritingSystemType.Analysis,
WsId = "en",
Name = "English",
Abbreviation = "en",
Font = "Arial",
Exemplars = WritingSystem.LatinExemplars
});
await lexboxApi.CreateWritingSystem(new()
{
Id = Guid.NewGuid(),
Type = WritingSystemType.Analysis,
WsId = "fr",
Name = "French",
Abbreviation = "fr",
Font = "Arial",
Exemplars = WritingSystem.LatinExemplars
});

await lexboxApi.CreateEntry(new()
{
Expand Down
Loading
Loading