diff --git a/backend/FwLite/FwDataMiniLcmBridge/FwDataMiniLcmBridge.csproj b/backend/FwLite/FwDataMiniLcmBridge/FwDataMiniLcmBridge.csproj
index 271a269d8..e412078aa 100644
--- a/backend/FwLite/FwDataMiniLcmBridge/FwDataMiniLcmBridge.csproj
+++ b/backend/FwLite/FwDataMiniLcmBridge/FwDataMiniLcmBridge.csproj
@@ -4,6 +4,8 @@
net8.0enableenable
+ $(ApplicationDisplayVersion)
+ $(ApplicationDisplayVersion)
diff --git a/backend/FwLite/FwLiteProjectSync/FwLiteProjectSync.csproj b/backend/FwLite/FwLiteProjectSync/FwLiteProjectSync.csproj
index f62ab2c9c..d6f9976d3 100644
--- a/backend/FwLite/FwLiteProjectSync/FwLiteProjectSync.csproj
+++ b/backend/FwLite/FwLiteProjectSync/FwLiteProjectSync.csproj
@@ -6,6 +6,8 @@
enableenabletrue
+ $(ApplicationDisplayVersion)
+ $(ApplicationDisplayVersion)
diff --git a/backend/FwLite/LcmCrdt/LcmCrdt.csproj b/backend/FwLite/LcmCrdt/LcmCrdt.csproj
index 68176ba8f..c61cc2535 100644
--- a/backend/FwLite/LcmCrdt/LcmCrdt.csproj
+++ b/backend/FwLite/LcmCrdt/LcmCrdt.csproj
@@ -4,6 +4,8 @@
net8.0enableenable
+ $(ApplicationDisplayVersion)
+ $(ApplicationDisplayVersion)
diff --git a/backend/FwLite/LocalWebApp/LocalWebApp.csproj b/backend/FwLite/LocalWebApp/LocalWebApp.csproj
index 6b9a7e5fe..6edb2dfdc 100644
--- a/backend/FwLite/LocalWebApp/LocalWebApp.csproj
+++ b/backend/FwLite/LocalWebApp/LocalWebApp.csproj
@@ -8,6 +8,8 @@
truefalsetrue
+ $(ApplicationDisplayVersion)
+ $(ApplicationDisplayVersion)
diff --git a/backend/FwLite/LocalWebApp/Routes/FeedbackRoute.cs b/backend/FwLite/LocalWebApp/Routes/FeedbackRoute.cs
index 336b855d2..29dda9fdc 100644
--- a/backend/FwLite/LocalWebApp/Routes/FeedbackRoute.cs
+++ b/backend/FwLite/LocalWebApp/Routes/FeedbackRoute.cs
@@ -1,12 +1,15 @@
-namespace LocalWebApp.Routes;
+using System.Reflection;
+
+namespace LocalWebApp.Routes;
public static class FeedbackRoute
{
public static void MapFeedbackRoutes(this IEndpointRouteBuilder endpoints)
{
- endpoints.MapGet("/api/feedback", () =>
+ endpoints.MapGet("/api/feedback/fw-lite", () =>
{
- var version = "alpha";
+ var version = typeof(FeedbackRoute).Assembly
+ .GetCustomAttribute()?.InformationalVersion ?? "dev";
var os = Environment.OSVersion.Platform switch
{
PlatformID.Win32NT => "Windows",
diff --git a/backend/FwLite/MiniLcm/MiniLcm.csproj b/backend/FwLite/MiniLcm/MiniLcm.csproj
index 5e87a4198..dbdbf9ad8 100644
--- a/backend/FwLite/MiniLcm/MiniLcm.csproj
+++ b/backend/FwLite/MiniLcm/MiniLcm.csproj
@@ -4,6 +4,8 @@
net8.0enableenable
+ $(ApplicationDisplayVersion)
+ $(ApplicationDisplayVersion)
diff --git a/backend/LexBoxApi/Controllers/FeedbackController.cs b/backend/LexBoxApi/Controllers/FeedbackController.cs
new file mode 100644
index 000000000..d89308218
--- /dev/null
+++ b/backend/LexBoxApi/Controllers/FeedbackController.cs
@@ -0,0 +1,18 @@
+using LexBoxApi.Services;
+using Microsoft.AspNetCore.Mvc;
+
+namespace LexBoxApi.Controllers;
+
+[ApiController]
+[Route("/api/feedback")]
+public class FeedbackController() : ControllerBase
+{
+ [HttpGet("fw-lite")]
+ public IResult RedirectToFieldWorksLiteFeedbackForm()
+ {
+ var version = AppVersionService.Version;
+ var os = "Web";
+ var url = $"https://docs.google.com/forms/d/e/1FAIpQLSdUdNufT3sdoBscY7vixguYnvtgpaw-hjX-z54BKi9KlYv4vw/viewform?usp=pp_url&entry.2102942583={version}&entry.1772086822={os}";
+ return Results.Redirect(url, preserveMethod: true);
+ }
+}
diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
index 1b8763c6f..fa37047bf 100644
--- a/frontend/pnpm-lock.yaml
+++ b/frontend/pnpm-lock.yaml
@@ -282,6 +282,9 @@ importers:
postcss:
specifier: 'catalog:'
version: 8.4.47
+ svelte-exmarkdown:
+ specifier: ^3.0.5
+ version: 3.0.5(svelte@4.2.19)
svelte-preprocess:
specifier: 'catalog:'
version: 5.1.4(@babel/core@7.24.7)(postcss-load-config@4.0.2(postcss@8.4.47))(postcss@8.4.47)(svelte@4.2.19)(typescript@5.3.3)
@@ -307,6 +310,9 @@ importers:
'@sveltejs/vite-plugin-svelte':
specifier: ^3.1.1
version: 3.1.1(svelte@4.2.19)(vite@5.4.9(@types/node@20.12.12))
+ '@tailwindcss/typography':
+ specifier: ^0.5.13
+ version: 0.5.13(tailwindcss@3.4.3)
'@tsconfig/svelte':
specifier: ^5.0.4
version: 5.0.4
diff --git a/frontend/src/lib/i18n/locales/en.json b/frontend/src/lib/i18n/locales/en.json
index 9299bdabc..61ab2bc92 100644
--- a/frontend/src/lib/i18n/locales/en.json
+++ b/frontend/src/lib/i18n/locales/en.json
@@ -720,5 +720,39 @@ If you don't see a dialog or already closed it, click the button below:",
"any": "Any",
"yes_no": "{value, select, true {Yes} false {No} other {Unknown}}",
"did_you_know": "Did you know?",
+ },
+ "viewer": {
+ "about": "## What is this?\n\
+\
+This is a beta version of a new dictionary building tool that is currently under development.\n\
+\
+The data you see here reflects the current data in the corresponding [Language Forge](https://languageforge.org/) project.\n\
+\
+This read-only version of the new dictionary tool is primarily for gathering early feedback on its look and feel. So, please use the [Feedback](/api/feedback) button in the top right corner of the page.\n\
+\
+## It can edit FieldWorks projects!\n\
+\
+It's true! There's already another version of the tool that you can use today to open and edit your data in FieldWorks.\n\
+It's also loaded with additional features! We're calling it [FieldWorks Lite](https://lexbox.org/fw-lite).\n\
+So, please download and try out the alpha version of [FieldWorks Lite](https://lexbox.org/fw-lite) as well.\n\
+\
+## Should I be excited?\n\
+\
+Yes! FieldWorks Lite will be revolutionary in multiple ways. It will be:\n\
+\
+- Cross-platform: it will work on Windows, Linux, Mac and eventually mobile\n\
+- Usable offline: you won't need an internet connection\n\
+- Collaborative: you will see any changes other users make as they work\n\
+- Faster than you're used to - we're quite confident about that 😀\n\
+\
+Eventually, FieldWorks Lite will replace both [WeSay](https://software.sil.org/wesay/) and [Language Forge](https://languageforge.org/).\n\
+\
+So, please send us your [feedback](/api/feedback). We want this tool to serve you as well as possible.\n\
+\
+## FieldWorks Lite is not\n\
+\
+- A replacement for [FieldWorks](https://software.sil.org/fieldworks/)\n\
+- A replacement for [Dictionary App Builder](https://software.sil.org/dictionaryappbuilder/)\n\
+- A replacement for [Webonary](https://www.webonary.org/)"
}
}
diff --git a/frontend/src/routes/(authenticated)/project/[project_code]/viewer/+page.svelte b/frontend/src/routes/(authenticated)/project/[project_code]/viewer/+page.svelte
index da5c6175b..5433b0f72 100644
--- a/frontend/src/routes/(authenticated)/project/[project_code]/viewer/+page.svelte
+++ b/frontend/src/routes/(authenticated)/project/[project_code]/viewer/+page.svelte
@@ -3,15 +3,18 @@
import {LexboxService} from 'viewer/service-provider';
import {LfClassicLexboxApi} from './lfClassicLexboxApi';
import type {PageData} from './$types';
+ import t from '$lib/i18n';
+ import { derived } from 'svelte/store';
export let data: PageData;
$: project = data.project;
+ const about = derived(t, ($t) => $t('viewer.about'));
const serviceProvider = window.lexbox.ServiceProvider;
let service: LfClassicLexboxApi;
$: {
if (serviceProvider) {
- let localService = new LfClassicLexboxApi($project.code);
+ let localService = new LfClassicLexboxApi($project.code, about);
serviceProvider.setService(LexboxService.LexboxApi, localService);
service = localService;
}
diff --git a/frontend/src/routes/(authenticated)/project/[project_code]/viewer/lfClassicLexboxApi.ts b/frontend/src/routes/(authenticated)/project/[project_code]/viewer/lfClassicLexboxApi.ts
index 2cc8a04a1..5cb381db1 100644
--- a/frontend/src/routes/(authenticated)/project/[project_code]/viewer/lfClassicLexboxApi.ts
+++ b/frontend/src/routes/(authenticated)/project/[project_code]/viewer/lfClassicLexboxApi.ts
@@ -11,6 +11,7 @@ import {
type SemanticDomain
} from 'viewer/lexbox-api';
import { SEMANTIC_DOMAINS_EN } from './semantic-domains.en.generated-data';
+import { type Readable } from 'svelte/store';
function prepareEntriesForUi(entries: IEntry[]): void {
entries.forEach(entry => {
@@ -31,11 +32,14 @@ function preparePartsOfSpeedForUi(partsOfSpeech: PartOfSpeech[]): void {
}
export class LfClassicLexboxApi implements LexboxApiClient {
- constructor(private projectCode: string) {
+ constructor(private projectCode: string, private aboutMarkdown: Readable) {
}
SupportedFeatures(): LexboxApiFeatures {
- return {};
+ return {
+ feedback: true,
+ about: this.aboutMarkdown,
+ };
}
async GetWritingSystems(): Promise {
diff --git a/frontend/viewer/package.json b/frontend/viewer/package.json
index da3e3687a..0b19bfda6 100644
--- a/frontend/viewer/package.json
+++ b/frontend/viewer/package.json
@@ -11,7 +11,6 @@
"main": "dist-web-component/viewer.js",
"exports": {
"./component": "./dist-web-component/viewer.js",
- "./style": "./dist-web-component/style.css",
"./lexbox-api": "./src/lib/services/lexbox-api.ts",
"./service-provider": "./src/lib/services/service-provider.ts"
},
@@ -29,6 +28,7 @@
"@iconify-json/mdi": "^1.1.66",
"@mdi/js": "^7.4.47",
"@sveltejs/vite-plugin-svelte": "^3.1.1",
+ "@tailwindcss/typography": "^0.5.13",
"@tsconfig/svelte": "^5.0.4",
"svelte": "catalog:",
"svelte-check": "catalog:",
@@ -44,6 +44,7 @@
"autoprefixer": "^10.4.19",
"fast-json-patch": "^3.1.1",
"postcss": "catalog:",
+ "svelte-exmarkdown": "^3.0.5",
"svelte-preprocess": "catalog:",
"svelte-routing": "^2.12.0",
"svelte-ux": "^0.66.8",
diff --git a/frontend/viewer/src/ProjectView.svelte b/frontend/viewer/src/ProjectView.svelte
index 3fe23bf66..7a83aa146 100644
--- a/frontend/viewer/src/ProjectView.svelte
+++ b/frontend/viewer/src/ProjectView.svelte
@@ -36,6 +36,7 @@
import {views} from './lib/entry-editor/view-data';
import {initWritingSystems} from './lib/writing-systems';
import {useEventBus} from './lib/services/event-bus';
+ import AboutDialog from './lib/about/AboutDialog.svelte';
export let loading = false;
@@ -286,9 +287,12 @@
{#if $features.history}
{/if}
+ {#if $features.about}
+
+ {/if}
{#if $features.feedback}