Skip to content

Commit

Permalink
Clean up viewer: add eslint, fix linting errors, remove unused imports
Browse files Browse the repository at this point in the history
  • Loading branch information
myieye committed Oct 17, 2024
1 parent 6fd56de commit 6500e0d
Show file tree
Hide file tree
Showing 58 changed files with 477 additions and 225 deletions.
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
142 changes: 142 additions & 0 deletions frontend/viewer/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
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': [
'warn',
{
'allowExpressions': true,
'allowedNames': ['load'],
},
],
'@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',
}
},
},
];
3 changes: 2 additions & 1 deletion 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 Down
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
28 changes: 15 additions & 13 deletions frontend/viewer/src/HomeView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,17 @@
let createError: string;
async function createProject() {
async function createProject(): Promise<void> {
const response = await projectsService.createProject(newProjectName);
createError = response.error ?? '';
if (createError) return;
newProjectName = '';
void refreshProjects();
await refreshProjects();
}
let importing = '';
async function importFwDataProject(name: string) {
async function importFwDataProject(name: string): Promise<void> {
importing = name;
await projectsService.importFwDataProject(name);
await refreshProjects();
Expand All @@ -41,7 +39,7 @@
let downloading = '';
async function downloadCrdtProject(project: Project) {
async function downloadCrdtProject(project: Project): Promise<void> {
downloading = project.name;
await projectsService.downloadCrdtProject(project);
await refreshProjects();
Expand All @@ -51,20 +49,24 @@
let projectsPromise = projectsService.fetchProjects().then(p => projects = p);
let projects: Project[] = [];
async function refreshProjects() {
async function refreshProjects(): Promise<void> {
let promise = projectsService.fetchProjects();
projects = await promise;//avoids clearing out the list until the new list is fetched
projectsPromise = promise;
}
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
18 changes: 9 additions & 9 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 All @@ -150,7 +150,7 @@
// and we need the extra call to updateEntryIdSearchParam in refreshSelection
const unsubSelectedEntry = selectedEntry.subscribe(updateEntryIdSearchParam);
$: { pickedEntry; updateEntryIdSearchParam(); }
function updateEntryIdSearchParam() {
function updateEntryIdSearchParam(): void {
updateSearchParam(ViewerSearchParam.EntryId, navigateToEntryId ?? (pickedEntry ? $selectedEntry?.id : undefined), true);
}
Expand All @@ -160,7 +160,7 @@
}
//selection handling, make sure the selected entry is always in the list of entries
function refreshSelection() {
function refreshSelection(): void {
if (!$entries) return;
if (navigateToEntryId) {
Expand Down Expand Up @@ -189,14 +189,14 @@
$: _loading = !$entries || !$writingSystems || loading;
function onEntryCreated(entry: IEntry, options?: NewEntryDialogOptions) {
function onEntryCreated(entry: IEntry, options?: NewEntryDialogOptions): void {
$entries?.push(entry);//need to add it before refresh, otherwise it won't get selected because it's not in the list
if (!options?.dontNavigate) {
navigateToEntry(entry, headword(entry));
}
}
function navigateToEntry(entry: IEntry, searchText?: string) {
function navigateToEntry(entry: IEntry, searchText?: string): void {
// this is to ensure that the selected entry is in the list of entries, otherwise it won't be selected
$search = searchText ?? '';
$selectedIndexExemplar = null;
Expand Down Expand Up @@ -232,7 +232,7 @@
};
});
async function openInFlex() {
function openInFlex(): void {
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

0 comments on commit 6500e0d

Please sign in to comment.