Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
myieye committed May 10, 2024
2 parents 1c60e0b + 6869617 commit ebb8e5e
Show file tree
Hide file tree
Showing 26 changed files with 202 additions and 87 deletions.
2 changes: 1 addition & 1 deletion Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ tasks:
setup-win:
platforms: [ windows ]
cmds:
- cmd: powershell rm -r {{.HG_REPO_DIR}}/sena-3
- cmd: powershell "if (test-path {{.HG_REPO_DIR}}/sena-3) { rm -r {{.HG_REPO_DIR}}/sena-3 }"
ignore_error: true
silent: true
- powershell -Command "Invoke-WebRequest 'https://drive.google.com/uc?export=download&id=1I-hwc0RHoQqW774gbS5qR-GHa1E7BlsS' -OutFile sena-3.zip"
Expand Down
36 changes: 20 additions & 16 deletions backend/LfClassicData/LfClassicLexboxApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,13 @@ public async Task<WritingSystems> GetWritingSystems()
Abbreviation = inputSystem.Abbreviation
};
//ws type might not be stored, we will add it anyway, otherwise nothing works
if (inputSystem.AnalysisWS is not false) analysis.Add(writingSystem);
if (inputSystem.VernacularWS is not false) vernacular.Add(writingSystem);
if (inputSystem is { AnalysisWS: null, VernacularWS: null })
{
analysis.Add(writingSystem);
vernacular.Add(writingSystem);
}
if (inputSystem.AnalysisWS is true) analysis.Add(writingSystem);
if (inputSystem.VernacularWS is true) vernacular.Add(writingSystem);
}
return new WritingSystems
{
Expand Down Expand Up @@ -59,29 +64,28 @@ public IAsyncEnumerable<Entry> SearchEntries(string query, QueryOptions? options
private async IAsyncEnumerable<Entry> Query(QueryOptions? options = null)
{
options ??= QueryOptions.Default;
var ws = await GetWritingSystems();
if (ws is { Vernacular: [], Analysis: [] })
{
yield break;
}

var sortWs = options.Order.WritingSystem;
if (sortWs == "default")
{
var ws = await GetWritingSystems();
if (ws is { Vernacular: [], Analysis: [] })
{
yield break;
}
sortWs = ws.Vernacular[0].Id;
}

await foreach (var entry in Entries.ToAsyncEnumerable()
await foreach (var entry in Entries.AsQueryable()
//todo, you can only sort by headword for now
.OrderBy(e => e.CitationForm?.TryGetValue(sortWs, out var val) == true
? val.Value
: e.Lexeme?.TryGetValue(sortWs, out val) == true
? val.Value
: string.Empty)
.ThenBy(e => e.MorphologyType)
.ThenBy(e => e.Guid)//todo should sort by homograph number
.Select(entry => new {entry, headword = entry.CitationForm![sortWs].Value ?? entry.Lexeme![sortWs].Value ?? string.Empty})
.OrderBy(e => e.headword)
.ThenBy(e => e.entry.MorphologyType)
.ThenBy(e => e.entry.Guid) //todo should sort by homograph number
.Skip(options.Offset)
.Take(options.Count)
.Select(ToEntry))
.ToAsyncEnumerable()
.Select(e => ToEntry(e.entry)))
{
yield return entry;
}
Expand Down
11 changes: 11 additions & 0 deletions backend/LfClassicData/MongoExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,15 @@ public static async IAsyncEnumerable<T> ToAsyncEnumerable<T>(this IMongoCollecti
}
}
}
public static async IAsyncEnumerable<T> ToAsyncEnumerable<T>(this IAsyncCursorSource<T> cursorSource)
{
using var entriesCursor = await cursorSource.ToCursorAsync();
while (await entriesCursor.MoveNextAsync())
{
foreach (var entry in entriesCursor.Current)
{
yield return entry;
}
}
}
}
1 change: 1 addition & 0 deletions backend/Testing/ApiTests/NewProjectRaceCondition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ private async Task CreateQueryAndVerifyProject(Guid id)
type: FL_EX,
id: "{{id}}",
code: "{{id}}",
isConfidential: false,
description: "this is just a testing project for testing a race condition",
retentionPolicy: DEV
}) {
Expand Down
29 changes: 17 additions & 12 deletions backend/Testing/Fixtures/IntegrationFixture.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System.IO.Compression;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using LexCore.Utils;
using Shouldly;
Expand All @@ -13,11 +11,15 @@ namespace Testing.Fixtures;

public class IntegrationFixture : IAsyncLifetime
{
private static readonly string _templateRepoName = "test-template-repo.zip";
public FileInfo TemplateRepoZip { get; } = new(_templateRepoName);
public DirectoryInfo TemplateRepo { get; } = new(Path.Join(BasePath, "_template-repo_"));
private const string TemplateRepoZipName = "test-template-repo.zip";
public static readonly FileInfo TemplateRepoZip = new(TemplateRepoZipName);
public static readonly DirectoryInfo TemplateRepo = new(Path.Join(BasePath, "_template-repo_"));
public ApiTestBase AdminApiTester { get; private set; } = new();
private string AdminJwt = string.Empty;

static IntegrationFixture()
{
DeletePreviousTestFiles();
}

public async Task InitializeAsync(ApiTestBase apiTester)
{
Expand All @@ -27,10 +29,9 @@ public async Task InitializeAsync(ApiTestBase apiTester)

public async Task InitializeAsync()
{
DeletePreviousTestFiles();
Directory.CreateDirectory(BasePath);
InitTemplateRepo();
AdminJwt = await AdminApiTester.LoginAs(AdminAuth.Username, AdminAuth.Password);
await AdminApiTester.LoginAs(AdminAuth.Username, AdminAuth.Password);
}

public Task DisposeAsync()
Expand All @@ -43,11 +44,15 @@ private static void DeletePreviousTestFiles()
if (Directory.Exists(BasePath)) Directory.Delete(BasePath, true);
}

private void InitTemplateRepo()
private static void InitTemplateRepo()
{
if (TemplateRepo.Exists) return;
using var stream = TemplateRepoZip.OpenRead();
ZipFile.ExtractToDirectory(stream, TemplateRepo.FullName);
lock (TemplateRepo)
{
if (TemplateRepo.Exists) return;
using var stream = TemplateRepoZip.OpenRead();
ZipFile.ExtractToDirectory(stream, TemplateRepo.FullName);
TemplateRepo.Refresh();
}
}

public ProjectConfig InitLocalFlexProjectWithRepo(HgProtocol? protocol = null, [CallerMemberName] string projectName = "")
Expand Down
26 changes: 6 additions & 20 deletions backend/Testing/Fixtures/IntegrationFixtureTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Moq;
using Shouldly;
using Testing.ApiTests;
using Testing.Services;

namespace Testing.Fixtures;

Expand All @@ -10,46 +9,33 @@ namespace Testing.Fixtures;
/// </summary>
public class IntegrationFixtureTests
{
// A static shared instance for the whole test class, because that's how xunit uses fixtures
private static readonly IntegrationFixture fixture = new();

[Fact]
public async Task InitCreatesARepoWithTheProject()
{
var fixture = new IntegrationFixture();
await fixture.InitializeAsync(Mock.Of<ApiTestBase>());
fixture.TemplateRepo.EnumerateFiles()
IntegrationFixture.TemplateRepo.EnumerateFiles()
.Select(f => f.Name)
.ShouldContain("kevin-test-01.fwdata");
}

[Fact]
public async Task CanFindTheProjectZipFile()
{
var fixture = new IntegrationFixture();
await fixture.InitializeAsync(Mock.Of<ApiTestBase>());
fixture.TemplateRepoZip
IntegrationFixture.TemplateRepoZip
.Directory!.EnumerateFiles().Select(f => f.Name)
.ShouldContain(fixture.TemplateRepoZip.Name);
.ShouldContain(IntegrationFixture.TemplateRepoZip.Name);
}

[Fact]
public async Task CanInitFlexProjectRepo()
{
var fixture = new IntegrationFixture();
await fixture.InitializeAsync(Mock.Of<ApiTestBase>());
var projectConfig = fixture.InitLocalFlexProjectWithRepo();
Directory.EnumerateFiles(projectConfig.Dir)
.ShouldContain(projectConfig.FwDataFile);
}

[Fact]
public async Task InitCleansUpPreviousRun()
{
var fixture = new IntegrationFixture();
await fixture.InitializeAsync(Mock.Of<ApiTestBase>());
var filePath = Path.Join(Constants.BasePath, "test.txt");
await File.WriteAllTextAsync(filePath, "test");
Directory.EnumerateFiles(Constants.BasePath).ShouldContain(filePath);

await fixture.InitializeAsync();
Directory.EnumerateFiles(Constants.BasePath).ShouldNotContain(filePath);
}
}
1 change: 1 addition & 0 deletions backend/Testing/Services/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ await apiTester.ExecuteGql($$"""
type: FL_EX,
id: "{{config.Id}}",
code: "{{config.Code}}",
isConfidential: false,
description: "Project created by an integration test",
retentionPolicy: DEV
}) {
Expand Down
7 changes: 7 additions & 0 deletions deployment/base/hg-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ spec:
podSelector:
matchLabels:
app: lexbox
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: languagedepot-dev
# Do NOT put a hyphen in front of podSelector on the next line
podSelector:
matchLabels:
app: lexbox

---

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
</script>

<Checkbox
id="confidentiality"
label={$t('project.confidential.label')}
description={$t('project.confidential.description')}
variant="checkbox-warning"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { Select } from '$lib/forms';
import t, { type I18nKey } from '$lib/i18n';
import { helpLinks } from '../help';
import type { Confidentiality } from './ProjectFilter.svelte';
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents -- false positive
Expand All @@ -13,7 +14,7 @@
</script>

<div class="relative">
<Select label={$t('project.confidential.confidentiality')} bind:value on:change>
<Select label={$t('project.confidential.confidentiality')} helpLink={helpLinks.confidentiality} bind:value on:change>
<option value={undefined}>{$t('common.any')}</option>
{#each Object.entries(options) as [value, label]}
<option value={value}>{$t(label)}</option>
Expand Down
7 changes: 6 additions & 1 deletion frontend/src/lib/components/Projects/ProjectFilter.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
import t from '$lib/i18n';
import IconButton from '../IconButton.svelte';
import ProjectConfidentialityFilterSelect from './ProjectConfidentialityFilterSelect.svelte';
import SupHelp from '../help/SupHelp.svelte';
import { helpLinks } from '../help';
type Filters = Partial<ProjectFilters> & Pick<ProjectFilters, 'projectSearch'>;
export let filters: Writable<Filters>;
Expand Down Expand Up @@ -157,7 +159,10 @@
<div class="form-control">
<label class="cursor-pointer label gap-4">
<span class="label-text inline-flex items-center gap-2">
{$t('project.filter.hide_drafts')}
<span>
{$t('project.filter.hide_drafts')}
<SupHelp helpLink={helpLinks.projectRequest} />
</span>
<Icon icon="i-mdi-script" color="text-warning" />
</span>
<input bind:checked={$filters.hideDraftProjects} type="checkbox" class="toggle toggle-warning" />
Expand Down
12 changes: 12 additions & 0 deletions frontend/src/lib/components/help/SupHelp.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script lang="ts">
import { Icon } from '$lib/icons';
import type { HelpLink } from '.';
export let helpLink: HelpLink;
</script>

<sup>
<a href={helpLink} target="_blank" rel="external">
<Icon icon="i-mdi-help-circle-outline" color="text-info" size="text-md" />
</a>
</sup>
12 changes: 12 additions & 0 deletions frontend/src/lib/components/help/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export { default as SupHelp } from './SupHelp.svelte';

export const helpLinks = {
helpList: 'https://scribehow.com/page/Language_Depot_How-tos__Jy5qu62XRQ-pVGGw6-Cqbw',
createProject: 'https://scribehow.com/shared/Create_a_Project__3LFa5XTHSmOLbSSOm8hZKQ',
addProjectMember: 'https://scribehow.com/shared/Add_Project_Member__bUJVVK2QT9KhWMqtiPYckA',
confidentiality: 'https://scribehow.com/shared/Project_Confidentiality__s6TX8_wFQ1ejVpH1s5Bsmw',
bulkAddCreate: 'https://scribehow.com/shared/Bulk_AddCreate_Project_Members__3wwDKk3TTGaAwMEmT4rrXQ',
projectRequest: 'https://scribehow.com/shared/Project_requests__zOdcHT8KRGygGmPgr5z2_A',
};

export type HelpLink = typeof helpLinks[keyof typeof helpLinks];
2 changes: 1 addition & 1 deletion frontend/src/lib/components/modals/FormModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@

<Modal bind:this={modal} on:close={() => reset()} bottom closeOnClickOutside={!$tainted}>
<Form id="modalForm" {enhance}>
<p class="mb-4"><slot name="title" /></p>
<p class="mb-4 text-lg"><slot name="title" /></p>
<slot errors={$errors} />
</Form>
<FormError error={$message} right />
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/lib/forms/FormField.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
import { randomFormId } from './utils';
import Markdown from 'svelte-exmarkdown';
import { NewTabLinkRenderer } from '$lib/components/Markdown';
import type { HelpLink } from '$lib/components/help';
import SupHelp from '$lib/components/help/SupHelp.svelte';
export let label: string;
export let description: string | undefined = undefined;
export let error: string | string[] | undefined = undefined;
export let id: string = randomFormId();
export let helpLink: HelpLink | undefined = undefined;
/**
* For login pages, EditableText, admin pages etc. auto focus is not a real accessibility problem.
* So we allow/support it and disable a11y-autofocus warnings in generic places.
Expand All @@ -28,12 +31,15 @@
<label for={id} class="label">
<span class="label-text">
{label}
{#if helpLink}
<SupHelp {helpLink} />
{/if}
</span>
</label>
<slot />
{#if description}
<label for={id} class="label pb-0">
<span class="label-text-alt">
<span class="label-text-alt description">
<Markdown md={description} plugins={[{ renderer: { a: NewTabLinkRenderer } }]} />
</span>
</label>
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/lib/forms/Select.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script lang="ts">
import type { HelpLink } from '$lib/components/help';
import FormField from './FormField.svelte';
import { randomFormId } from './utils';
Expand All @@ -8,9 +9,10 @@
export let autofocus = false;
export let error: string | string[] | undefined = undefined;
export let disabled = false;
export let helpLink: HelpLink | undefined = undefined;
</script>

<FormField {id} {label} {error} {autofocus}>
<FormField {id} {label} {error} {autofocus} {helpLink}>
<!-- svelte-ignore a11y-autofocus -->
<select {disabled} bind:value {id} class="select select-bordered" {autofocus} on:change>
<slot />
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lib/forms/TextArea.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import FormField from './FormField.svelte';
export let label: string;
export let description: string | undefined = undefined;
export let value: string | undefined = undefined;
export let id = randomFormId();
export let autofocus = false;
Expand All @@ -12,7 +13,7 @@
</script>

<!-- https://daisyui.com/components/input -->
<FormField {id} {error} {label} {autofocus}>
<FormField {id} {error} {label} {autofocus} {description}>
<!-- svelte-ignore a11y-autofocus -->
<textarea
{id}
Expand Down
Loading

0 comments on commit ebb8e5e

Please sign in to comment.