Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Big viewer cleanup #1131

Merged
merged 11 commits into from
Oct 21, 2024
Merged
4 changes: 2 additions & 2 deletions .github/workflows/develop-ui.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ jobs:
cache-dependency-path: './frontend/pnpm-lock.yaml'
- run: pnpm install
- run: pnpm run -r build # We need code/types generated by the build (e.g. gql/generated)
- run: pnpm run check --output machine
- run: pnpm run lint:report
- run: pnpm run -r check --output machine
- run: pnpm run -r lint:report
- name: Annotate Code Linting REsults
uses: ataylorme/eslint-annotate-action@d57a1193d4c59cbfbf3f86c271f42612f9dbd9e9 # v3.0.0
if: always()
Expand Down
331 changes: 153 additions & 178 deletions frontend/pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions frontend/pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
catalog:
vite: ^5.4.9
svelte: ^4.2.19
svelte-check: ^3.7.1
svelte-preprocess: ^5.1.4
svelte-check: ^4.0.5
svelte-preprocess: ^6.0.3
postcss: ^8.4.47
typescript: ^5.3.3
tslib: ^2.6.2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,14 @@ export class LfClassicLexboxApi implements LexboxApiClient {
const asc = options.order.ascending ?? true;
const params = new URLSearchParams({
SortField: options.order.field,
SortWritingSystem: options.order.writingSystem,
SortWritingSystem: options.order.writingSystem as string,
Ascending: asc ? 'true' : 'false',
Count: options.count.toString(),
Offset: options.offset.toString()
});
if (options.exemplar) {
params.set('ExemplarValue', options.exemplar.value);
params.set('ExemplarWritingSystem', options.exemplar.writingSystem);
params.set('ExemplarWritingSystem', options.exemplar.writingSystem as string);
}
/* eslint-enable @typescript-eslint/no-unsafe-assignment */
return '?' + params.toString();
Expand Down
141 changes: 141 additions & 0 deletions frontend/viewer/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import { FlatCompat } from '@eslint/eslintrc';
import { fileURLToPath } from 'url';
import globals from 'globals';
import js from '@eslint/js';
import path from 'path';
import svelteParser from 'svelte-eslint-parser';
import tsParser from '@typescript-eslint/parser';

// mimic CommonJS variables
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname
});

export default [
{
ignores: [
'**/*js',
'**/generated/**',
'**/vite.config.*',
],
},
js.configs.recommended,
// TypeScript and Svelte plugins don't seem to support the new config format yet
// So, using backwards compatibility util: https://eslint.org/blog/2022/08/new-config-system-part-2/#backwards-compatibility-utility
...compat.config({
plugins: ['@typescript-eslint'],
extends: ['plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended-requiring-type-checking'],
overrides: [
{
files: ['*.svelte'],
rules: {
// The Svelte plugin doesn't seem to have typing quite figured out
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',
},
}
]
}),
...compat.config({
extends: ['plugin:svelte/recommended'],
}),
{
rules: {
// https://typescript-eslint.io/rules/
'@typescript-eslint/naming-convention': [
'error',
{
'selector': 'default',
'format': ['camelCase'],
'leadingUnderscore': 'allow',
},
{
'selector': 'function',
'filter': {'regex': 'GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS', 'match': true},
'format': ['UPPER_CASE'],
},
{
'selector': 'default',
'modifiers': ['const'],
'format': ['camelCase', 'UPPER_CASE'],
'leadingUnderscore': 'allow',
},
{
'selector': ['typeLike', 'enumMember'],
'format': ['PascalCase'],
},
{
'selector': 'default',
'modifiers': ['requiresQuotes'],
'format': null,
},
{
'selector': 'import',
'format': ['camelCase', 'PascalCase'],
}
],
'@typescript-eslint/quotes': ['error', 'single', { 'allowTemplateLiterals': true }],
'@typescript-eslint/no-unused-vars': [
'error',
{
'argsIgnorePattern': '^_',
'destructuredArrayIgnorePattern': '^_',
'caughtErrors': 'all',
'ignoreRestSiblings': true,
},
],
'@typescript-eslint/explicit-function-return-type': [
'off',
{
'allowExpressions': true,
},
],
'@typescript-eslint/consistent-type-imports': ['error', {'fixStyle': 'inline-type-imports'}],
// https://sveltejs.github.io/eslint-plugin-svelte/rules/
'svelte/html-quotes': 'error',
'svelte/no-dom-manipulating': 'warn',
'svelte/no-reactive-reassign': ['warn', { 'props': false }],
'svelte/no-store-async': 'error',
'svelte/require-store-reactive-access': 'error',
'svelte/mustache-spacing': 'error',
'func-style': ['warn', 'declaration'],
"no-restricted-imports": ["error", {
"patterns": [{
"group": ["svelte-intl-precompile"],
"message": "Use $lib/i18n instead."
}]
}]
},
},
{
languageOptions: {
parser: tsParser,
parserOptions: {
project: true,
tsconfigRootDir: __dirname,
extraFileExtensions: ['.svelte'], // Yes, TS-Parser, relax when you're fed svelte files
},
globals: {
...globals.browser,
...globals.node,
},
},
},
{
files: ['**/*.svelte'],
languageOptions: {
parser: svelteParser,
parserOptions: {
parser: tsParser,
},
globals: {
'$$Generic': 'readonly',
}
},
},
];
5 changes: 3 additions & 2 deletions frontend/viewer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"build": "vite build -m web-component",
"build-app": "vite build",
"preview": "vite preview",
"check": "svelte-check --tsconfig ./tsconfig.json"
"check": "svelte-check --tsconfig ./tsconfig.json",
"lint": "eslint ."
},
"devDependencies": {
"@egoist/tailwindcss-icons": "^1.8.0",
Expand All @@ -47,7 +48,7 @@
"svelte-exmarkdown": "^3.0.5",
"svelte-preprocess": "catalog:",
"svelte-routing": "^2.12.0",
"svelte-ux": "^0.74.9",
"svelte-ux": "^0.75.1",
"type-fest": "^4.18.2"
}
}
7 changes: 6 additions & 1 deletion frontend/viewer/postcss.config.cjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
const path = require('path');
const tailwindConfig = path.join(__dirname, 'tailwind.config.cjs');

module.exports = {
plugins: {
'tailwindcss/nesting': {},
tailwindcss: {},
tailwindcss: {
config: tailwindConfig,
},
autoprefixer: {},
},
};
5 changes: 3 additions & 2 deletions frontend/viewer/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

export let url = '';

/* eslint-disable @typescript-eslint/naming-convention */
settings({
components: {
MenuItem: {
Expand All @@ -36,7 +37,7 @@
}
},
});

/* eslint-enable @typescript-eslint/naming-convention */
</script>

<Router {url}>
Expand Down Expand Up @@ -69,7 +70,7 @@
<Sandbox />
</Route>
<Route path="/*">
{setTimeout(() => navigate("/", { replace: true }))}
{setTimeout(() => navigate('/', { replace: true }))}
</Route>
</div>
</Router>
Expand Down
2 changes: 1 addition & 1 deletion frontend/viewer/src/CrdtProjectView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import ProjectView from './ProjectView.svelte';

export let projectName: string;
const {connected, lexboxApi} = SetupSignalR(`/api/hub/${projectName}/lexbox`, {
const {connected} = SetupSignalR(`/api/hub/${projectName}/lexbox`, {
history: true,
write: true,
feedback: true,
Expand Down
2 changes: 1 addition & 1 deletion frontend/viewer/src/FwDataProjectView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import {useEventBus} from './lib/services/event-bus';

export let projectName: string;
const {connected, lexboxApi} = SetupSignalR(`/api/hub/${projectName}/fwdata`, {
const {connected} = SetupSignalR(`/api/hub/${projectName}/fwdata`, {
history: false,
write: true,
openWithFlex: true,
Expand Down
20 changes: 11 additions & 9 deletions frontend/viewer/src/HomeView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,13 @@
let createError: string;

async function createProject() {

const response = await projectsService.createProject(newProjectName);
createError = response.error ?? '';
if (createError) return;
newProjectName = '';
void refreshProjects();
await refreshProjects();
}


let importing = '';

async function importFwDataProject(name: string) {
Expand Down Expand Up @@ -59,12 +57,16 @@

let remoteProjects: { [server: string]: Project[] } = {};
let loadingRemoteProjects = false;
async function fetchRemoteProjects() {
async function fetchRemoteProjects(): Promise<void> {
loadingRemoteProjects = true;
remoteProjects = await projectsService.fetchRemoteProjects();
loadingRemoteProjects = false;
}
fetchRemoteProjects();

fetchRemoteProjects().catch((error) => {
console.error(`Failed to fetch remote projects`, error);
throw error;
});


let servers: ServerStatus[] = [];
Expand Down Expand Up @@ -97,7 +99,7 @@
: []),
] satisfies ColumnDef<Project>[];

function matchesProject(projects: Project[], project: Project) {
function matchesProject(projects: Project[], project: Project): Project | undefined {
let matches: Project | undefined = undefined;
if (project.id) {
matches = projects.find(p => p.id == project.id && p.serverAuthority == project.serverAuthority);
Expand All @@ -120,7 +122,7 @@
};
}
let authority = Object.entries(serversProjects)
.find(([server, projects]) => matchesProject(projects, project))?.[0];
.find(([_server, projects]) => matchesProject(projects, project))?.[0];
return authority ? servers.find(s => s.authority == authority) : undefined;
}
</script>
Expand Down Expand Up @@ -152,7 +154,7 @@
<Table {columns}
data={projects.filter((p) => $isDev || p.fwdata).sort((p1, p2) => p1.name.localeCompare(p2.name))}
classes={{ th: 'p-4' }}>
<tbody slot="data" let:columns let:data let:getCellValue let:getCellContent>
<tbody slot="data" let:columns let:data let:getCellContent>
{#each data ?? [] as project, rowIndex}
<tr class="tabular-nums">
{#each columns as column (column.name)}
Expand Down Expand Up @@ -262,7 +264,7 @@
</div>
</div>

<style>
<style lang="postcss">
.home {
min-height: 100%;
display: grid;
Expand Down
10 changes: 5 additions & 5 deletions frontend/viewer/src/ProjectView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
$: $entries = $_entries;
$: console.debug('Entries:', $_entries);

function fetchEntries(s: string, isConnected: boolean, exemplar: string | null) {
function fetchEntries(s: string, isConnected: boolean, exemplar: string | null): Promise<IEntry[] | undefined> {
if (!isConnected) return Promise.resolve(undefined);
return lexboxApi.SearchEntries(s ?? '', {
offset: 0,
Expand Down Expand Up @@ -232,7 +232,7 @@
};
});

async function openInFlex() {
function openInFlex() {
AppNotification.displayAction('The project is open in FieldWorks. Please close it to reopen.', 'warning', {
label: 'Open',
callback: () => window.location.reload()
Expand Down Expand Up @@ -265,7 +265,7 @@
</div>
</div>
{:else}
<div class="project-view !flex flex-col PortalTarget" style="{spaceForEditorStyle}">
<div class="project-view !flex flex-col PortalTarget" style={spaceForEditorStyle}>
<AppBar class="bg-secondary min-h-12 shadow-md">
<div slot="title" class="prose">
<h3>{projectName}</h3>
Expand Down Expand Up @@ -340,11 +340,11 @@
</div>
<Editor entry={$selectedEntry}
{readonly}
on:change={e => {
on:change={_ => {
$selectedEntry = $selectedEntry;
$entries = $entries;
}}
on:delete={e => {
on:delete={_ => {
$selectedEntry = undefined;
refreshEntries();
}} />
Expand Down
Loading
Loading