Fixing all eslint's reported error

This commit is contained in:
Jarosław Sadziński 2022-12-27 19:35:03 +01:00
parent dcefd4a81b
commit fd02a00a0e
29 changed files with 80 additions and 51 deletions

View File

@ -4,8 +4,8 @@
!/test
!/plugins
!/buildtools
!/stubs
!/.eslintrc.js
# And exclude some things within those (generated files)
/_build
/plugins/**/dist

View File

@ -134,7 +134,7 @@ export class AccessRules extends Disposable {
// there were only removals, then length will be reduced.
getChangedStatus(tableRules.length < this._ruleCollection.getAllTableIds().length),
getChangedStatus(userAttr.length < this._ruleCollection.getUserAttributeRules().size),
...tableRules.map(t => use(t.ruleStatus)),
...tableRules.map(tr => use(tr.ruleStatus)),
...userAttr.map(u => use(u.ruleStatus)),
specialRules ? use(specialRules.ruleStatus) : RuleStatus.Unchanged,
);
@ -239,7 +239,7 @@ export class AccessRules extends Disposable {
const newResources: MetaRowRecord<'_grist_ACLResources'>[] = flatten(
[{tableId: '*', colIds: '*'}],
this._specialRules.get()?.getResources() || [],
...this._tableRules.get().map(t => t.getResources()))
...this._tableRules.get().map(tr => tr.getResources()))
.map(r => ({id: -1, ...r}));
// Prepare userActions and a mapping of serializedResource to rowIds.
@ -350,7 +350,7 @@ export class AccessRules extends Disposable {
// synchronously, which prevents the menu from closing on click.
menuItemAsync(() => this._addTableRules(tableId),
this.getTableTitle(tableId),
dom.cls('disabled', (use) => use(this._tableRules).some(t => t.tableId === tableId)),
dom.cls('disabled', (use) => use(this._tableRules).some(tr => tr.tableId === tableId)),
)
),
),
@ -442,7 +442,7 @@ export class AccessRules extends Disposable {
*/
public getRules(): RuleRec[] {
return flatten(
...this._tableRules.get().map(t => t.getRules()),
...this._tableRules.get().map(tr => tr.getRules()),
this._specialRules.get()?.getRules() || [],
this._docDefaultRuleSet.get()?.getRules('*') || []
);
@ -484,7 +484,7 @@ export class AccessRules extends Disposable {
}
private _addTableRules(tableId: string) {
if (this._tableRules.get().some(t => t.tableId === tableId)) {
if (this._tableRules.get().some(tr => tr.tableId === tableId)) {
throw new Error(`Trying to add TableRules for existing table ${tableId}`);
}
const defRuleSet: RuleSet = {tableId, colIds: '*', body: []};

View File

@ -239,7 +239,7 @@ export function buildUpgradeMessage(
) {
if (!canUpgrade) { return t("Contact the site owner to upgrade the plan to raise limits."); }
const upgradeLinkText = t("start your 30-day free trial of the Pro plan.")
const upgradeLinkText = t("start your 30-day free trial of the Pro plan.");
// TODO i18next
return [
variant === 'short' ? null : t("For higher limits, "),

View File

@ -986,7 +986,7 @@ export class GristDoc extends DisposableWithEvents {
* Renames table. Method exposed primarily for tests.
*/
public async renameTable(tableId: string, newTableName: string) {
const tableRec = this.docModel.visibleTables.all().find(t => t.tableId.peek() === tableId);
const tableRec = this.docModel.visibleTables.all().find(tb => tb.tableId.peek() === tableId);
if (!tableRec) {
throw new UserError(`No table with id ${tableId}`);
}

View File

@ -380,7 +380,7 @@ export class Importer extends DisposableWithEvents {
}
private _getHiddenTableIds(): string[] {
return this._sourceInfoArray.get().map((t: SourceInfo) => t.hiddenTableId);
return this._sourceInfoArray.get().map((si: SourceInfo) => si.hiddenTableId);
}
private async _reImport(upload: UploadResult) {

View File

@ -1,11 +1,12 @@
import {computed, Computed, dom, DomElementArg, IDisposableOwner, Observable, styled} from "grainjs";
import {cssModalBody, cssModalButtons, cssModalTitle, IModalControl, modal, cssAnimatedModal} from 'app/client/ui2018/modals';
import {cssAnimatedModal, cssModalBody, cssModalButtons, cssModalTitle,
IModalControl, modal} from 'app/client/ui2018/modals';
import {bigBasicButton, bigPrimaryButton} from 'app/client/ui2018/buttons';
import {mediaXSmall, testId, theme, vars} from 'app/client/ui2018/cssVars';
import {UserManagerModel, IOrgMemberSelectOption} from 'app/client/models/UserManagerModel';
import {IOrgMemberSelectOption, UserManagerModel} from 'app/client/models/UserManagerModel';
import {icon} from 'app/client/ui2018/icons';
import {textarea} from "app/client/ui/inputs";
import {BasicRole, VIEWER, NonGuestRole, isBasicRole} from "app/common/roles";
import {BasicRole, isBasicRole, NonGuestRole, VIEWER} from "app/common/roles";
import {menu, menuItem} from 'app/client/ui2018/menus';
function parseEmailList(emailListRaw: string): Array<string> {
@ -29,7 +30,9 @@ export function buildMultiUserManagerModal(
const rolesObs = Observable.create<BasicRole>(owner, VIEWER);
const isValidObs = Observable.create(owner, true);
const enableAdd: Computed<boolean> = computed((use) => Boolean(use(emailListObs) && use(rolesObs) && use(isValidObs)));
const enableAdd: Computed<boolean> = computed(
(use) => Boolean(use(emailListObs) && use(rolesObs) && use(isValidObs))
);
const save = (ctl: IModalControl) => {
const emailList = parseEmailList(emailListObs.get());
@ -40,7 +43,7 @@ export function buildMultiUserManagerModal(
emailList.forEach(email => onAdd(email, role));
ctl.close();
}
}
};
return modal(ctl => [
{ style: 'padding: 0;' },
@ -63,7 +66,7 @@ export function buildMultiUserManagerModal(
{ style: 'margin: 32px 64px; display: flex;' },
bigPrimaryButton('Confirm',
dom.boolAttr('disabled', (use) => !use(enableAdd)),
dom.on('click', () => {save(ctl)}),
dom.on('click', () => { save(ctl); }),
testId('um-confirm')
),
bigBasicButton(

View File

@ -101,7 +101,7 @@ function domT(key: string, args: any, tImpl: typeof i18next.t) {
// If there are any DomElements in args, handle it with missingInterpolationHandler.
const domElements = !args ? [] : Object.entries(args).filter(([_, value]) => isLikeDomContents(value));
if (!args || !domElements.length) {
return tImpl(key, args || undefined) as any;
return tImpl(key, args || undefined);
} else {
// Make a copy of the arguments, and remove any dom elements from it. It will instruct
// i18next library to use `missingInterpolationHandler` handler.
@ -171,5 +171,5 @@ export function makeT(scope: string, instance?: typeof i18next) {
reportError(error);
}
return domT(key, args, scopedResolver!);
}
};
}

View File

@ -73,7 +73,9 @@ class ColumnPicker extends Disposable {
properValue,
options,
{
defaultLabel: this._column.typeDesc != "any" ? t("Pick a {{columnType}} column", {"columnType": this._column.typeDesc}) : t("Pick a column")
defaultLabel: this._column.typeDesc != "any"
? t("Pick a {{columnType}} column", {"columnType": this._column.typeDesc})
: t("Pick a column")
}
),
testId('mapping-for-' + this._column.name),
@ -117,7 +119,11 @@ class ColumnListPicker extends Disposable {
col.label.peek(),
)),
wrongTypeCount > 0 ? menuText(
t("{{wrongTypeCount}} non-{{columnType}} columns are not shown", {wrongTypeCount, columnType: this._column.type.toLowerCase(), count: wrongTypeCount}),
t("{{wrongTypeCount}} non-{{columnType}} columns are not shown", {
wrongTypeCount,
columnType: this._column.type.toLowerCase(),
count: wrongTypeCount
}),
testId('map-message-' + this._column.name)
) : null
];
@ -371,8 +377,12 @@ export class CustomSectionConfig extends Disposable {
}
switch(level) {
case AccessLevel.none: return cssConfirmLine(t("Widget does not require any permissions."));
case AccessLevel.read_table: return cssConfirmLine(t("Widget needs to {{read}} the current table.", {read: dom("b", "read")})); // TODO i18next
case AccessLevel.full: return cssConfirmLine(t("Widget needs {{fullAccess}} to this document.", {fullAccess: dom("b", "full access")})); // TODO i18next
case AccessLevel.read_table:
return cssConfirmLine(t("Widget needs to {{read}} the current table.", {read: dom("b", "read")}));
case AccessLevel.full:
return cssConfirmLine(t("Widget needs {{fullAccess}} to this document.", {
fullAccess: dom("b", "full access")
}));
default: throw new Error(`Unsupported ${level} access level`);
}
}

View File

@ -1,4 +1,4 @@
import {makeT} from 'app/client/lib/localization'
import {makeT} from 'app/client/lib/localization';
const t = makeT('ExampleInfo');

View File

@ -268,8 +268,8 @@ export class PageWidgetSelect extends Disposable {
}) :
null;
private _isNewTableDisabled = Computed.create(this, this._value.type, (use, t) => !isValidSelection(
'New Table', t, this._options.isNewPage));
private _isNewTableDisabled = Computed.create(this, this._value.type, (use, type) => !isValidSelection(
'New Table', type, this._options.isNewPage));
constructor(
private _value: IWidgetValueObs,
@ -399,8 +399,8 @@ export class PageWidgetSelect extends Disposable {
this._value.summarize.set(true);
}
private _selectType(t: IWidgetType) {
this._value.type.set(t);
private _selectType(type: IWidgetType) {
this._value.type.set(type);
}
private _selectTable(tid: TableId) {

View File

@ -100,11 +100,11 @@ function removeView(activeDoc: GristDoc, viewId: number, pageName: string) {
const removePage = () => [['RemoveRecord', '_grist_Views', viewId]];
const removeAll = () => [
...removePage(),
...notVisibleTables.map(t => ['RemoveTable', t.tableId.peek()])
...notVisibleTables.map(tb => ['RemoveTable', tb.tableId.peek()])
];
if (notVisibleTables.length) {
const tableNames = notVisibleTables.map(t => t.tableNameDef.peek());
const tableNames = notVisibleTables.map(tb => tb.tableNameDef.peek());
buildPrompt(tableNames, async (option) => {
// Errors are handled in the dialog.
if (option === 'data') {
@ -174,7 +174,7 @@ function buildOption(value: Observable<RemoveOption>, id: RemoveOption, content:
function buildWarning(tables: string[]) {
return cssWarning(
dom.forEach(tables, (t) => cssTableName(t, testId('table')))
dom.forEach(tables, (tb) => cssTableName(tb, testId('table')))
);
}

View File

@ -39,8 +39,8 @@ import {icon} from 'app/client/ui2018/icons';
import {cssLink} from 'app/client/ui2018/links';
import {loadingSpinner} from 'app/client/ui2018/loaders';
import {menu, menuItem, menuText} from 'app/client/ui2018/menus';
import {confirmModal, cssModalBody, cssModalButtons, cssModalTitle, IModalControl,
modal, cssAnimatedModal} from 'app/client/ui2018/modals';
import {confirmModal, cssAnimatedModal, cssModalBody, cssModalButtons, cssModalTitle,
IModalControl, modal} from 'app/client/ui2018/modals';
export interface IUserManagerOptions {
permissionData: Promise<PermissionData>;

View File

@ -73,7 +73,10 @@ export function createNotFoundPage(appModel: AppModel, message?: string) {
document.title = t("Page not found{{suffix}}", {suffix: getPageTitleSuffix(getGristConfig())});
return pagePanelsError(appModel, t("Page not found{{suffix}}", {suffix: ''}), [
cssErrorText(message || t("The requested page could not be found.{{separator}}Please check the URL and try again.", {separator: dom('br')})), // TODO: i18next
cssErrorText(message ||
t("The requested page could not be found.{{separator}}Please check the URL and try again.", {
separator: dom('br')
})),
cssButtonWrap(bigPrimaryButtonLink(t("Go to main page"), testId('error-primary-btn'),
urlState().setLinkUrl({}))),
cssButtonWrap(bigBasicButtonLink(t("Contact support"), {href: 'https://getgrist.com/contact'})),

View File

@ -1,5 +1,5 @@
import {theme, vars} from 'app/client/ui2018/cssVars';
import {dom, IDomArgs, DomElementArg, IInputOptions, Observable, styled, subscribe} from 'grainjs';
import {dom, DomElementArg, IDomArgs, IInputOptions, Observable, styled, subscribe} from 'grainjs';
export const cssInput = styled('input', `
font-size: ${vars.mediumFontSize};

View File

@ -1,4 +1,4 @@
import { ACResults, buildHighlightedDom, normalizeText, HighlightFunc } from 'app/client/lib/ACIndex';
import { ACResults, buildHighlightedDom, HighlightFunc, normalizeText } from 'app/client/lib/ACIndex';
import { Autocomplete } from 'app/client/lib/autocomplete';
import { ICellItem } from 'app/client/models/ColumnACIndexes';
import { reportError } from 'app/client/models/errors';

View File

@ -1,5 +1,5 @@
import { createGroup } from 'app/client/components/commands';
import { ACItem, ACResults, normalizeText, HighlightFunc } from 'app/client/lib/ACIndex';
import { ACItem, ACResults, HighlightFunc, normalizeText } from 'app/client/lib/ACIndex';
import { IAutocompleteOptions } from 'app/client/lib/autocomplete';
import { IToken, TokenField, tokenFieldStyles } from 'app/client/lib/TokenField';
import { reportError } from 'app/client/models/errors';

View File

@ -9,5 +9,5 @@ export default function getCurrentTime(): moment.Moment {
if (typeof window === 'undefined' || !window) { return getDefault(); }
const searchParams = new URLSearchParams(window.location.search);
return searchParams.has('currentTime') ? moment(searchParams.get('currentTime')!) : getDefault();
return searchParams.has('currentTime') ? moment(searchParams.get('currentTime')) : getDefault();
}

View File

@ -18,7 +18,7 @@ import {makeId} from 'app/server/lib/idUtils';
import log from 'app/server/lib/log';
import {IPermitStore, Permit} from 'app/server/lib/Permit';
import {AccessTokenInfo} from 'app/server/lib/AccessTokens';
import {allowHost, isEnvironmentAllowedHost, getOriginUrl, optStringParam} from 'app/server/lib/requestUtils';
import {allowHost, getOriginUrl, isEnvironmentAllowedHost, optStringParam} from 'app/server/lib/requestUtils';
import * as cookie from 'cookie';
import {NextFunction, Request, RequestHandler, Response} from 'express';
import {IncomingMessage} from 'http';

View File

@ -955,8 +955,8 @@ export class DocWorkerApi {
const options: DownloadOptions = {
...params,
filename: name + (params.tableId === name ? '' : '-' + params.tableId),
}
return options
};
return options;
}
private _getActiveDoc(req: RequestWithLogin): Promise<ActiveDoc> {

View File

@ -1,7 +1,7 @@
import {ApiError} from 'app/common/ApiError';
import {createFormatter} from 'app/common/ValueFormatter';
import {ActiveDoc} from 'app/server/lib/ActiveDoc';
import {ExportData, exportSection, exportTable, Filter, DownloadOptions} from 'app/server/lib/Export';
import {DownloadOptions, ExportData, exportSection, exportTable, Filter} from 'app/server/lib/Export';
import log from 'app/server/lib/log';
import * as bluebird from 'bluebird';
import contentDisposition from 'content-disposition';

View File

@ -1,6 +1,6 @@
import {ActiveDoc} from 'app/server/lib/ActiveDoc';
import {createExcelFormatter} from 'app/server/lib/ExcelFormatter';
import {ExportData, exportDoc, DownloadOptions, exportSection, exportTable, Filter} from 'app/server/lib/Export';
import {DownloadOptions, ExportData, exportDoc, exportSection, exportTable, Filter} from 'app/server/lib/Export';
import {Alignment, Border, Fill, Workbook} from 'exceljs';
import * as express from 'express';
import log from 'app/server/lib/log';

View File

@ -923,7 +923,7 @@ export async function backupSqliteDatabase(src: string, dest: string,
} finally {
if (testProgress) { testProgress({action: 'close', phase: 'before'}); }
try {
if (db) { await fromCallback(cb => db!.close(cb)); }
if (db) { await fromCallback(cb => db.close(cb)); }
} catch (err) {
_log.debug(null, `problem stopping copy of ${src} (${label}): ${err}`);
}

View File

@ -376,7 +376,7 @@ export class DocTriggers {
private async _pushToRedisQueue(events: WebHookEvent[]) {
const strings = events.map(e => JSON.stringify(e));
await this._redisClient!.rpushAsync(this._redisQueueKey, ...strings);
await this._redisClient?.rpushAsync(this._redisQueueKey, ...strings);
}
private async _getRedisQueue(redisClient: RedisClient) {

View File

@ -108,7 +108,9 @@ export function allowHost(req: Request, allowedHost: string|URL) {
// For requests to a native subdomains, only the base domain needs to match.
const allowedDomain = parseSubdomain(allowedUrl.hostname);
const actualDomain = parseSubdomain(actualUrl.hostname);
return (!_.isEmpty(actualDomain) ? actualDomain.base === allowedDomain.base : allowedUrl.hostname === actualUrl.hostname);
return (!_.isEmpty(actualDomain) ?
actualDomain.base === allowedDomain.base :
allowedUrl.hostname === actualUrl.hostname);
}
}

View File

@ -21,8 +21,8 @@
"test:docker": "./test/test_under_docker.sh",
"test:python": "sandbox_venv3/bin/python sandbox/grist/runtests.py ${GREP_TESTS:+discover -p \"test*${GREP_TESTS}*.py\"}",
"cli": "NODE_PATH=_build:_build/stubs:_build/ext node _build/app/server/companion.js",
"lint": "eslint .",
"lint:fix": "eslint --fix .",
"lint": "eslint --cache --cache-strategy content .",
"lint:fix": "eslint --cache --cache-strategy content --fix .",
"generate:translation": "NODE_PATH=_build:_build/stubs:_build/ext node buildtools/generate_translation_keys.js"
},
"keywords": [

5
test/.eslintrc.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
rules: {
'@typescript-eslint/no-shadow': 'off',
},
}

View File

@ -2,14 +2,14 @@ import {makeT, t} from 'app/client/lib/localization';
import {assert} from 'chai';
import i18next, {i18n} from 'i18next';
import {Disposable, dom, DomContents, observable} from "grainjs";
import {popGlobals, pushGlobals, G} from 'grainjs/dist/cjs/lib/browserGlobals';
import {G, popGlobals, pushGlobals} from 'grainjs/dist/cjs/lib/browserGlobals';
import {JSDOM} from 'jsdom';
describe('localization', function() {
let instance: i18n;
before(() => {
instance = i18next.createInstance();
instance.init({
void instance.init({
lng: 'en',
resources: {
en: {

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-shadow */
import {ActionSummary} from 'app/common/ActionSummary';
import {BulkColValues, UserAction} from 'app/common/DocActions';
import {arrayRepeat} from 'app/common/gutil';
@ -2103,7 +2104,10 @@ function testDocApi() {
});
it("GET /docs/{did}/download/xlsx returns 404 if tableId is invalid", async function() {
const resp = await axios.get(`${serverUrl}/api/docs/${docIds.TestDoc}/download/xlsx?tableId=MissingTableId`, chimpy);
const resp = await axios.get(
`${serverUrl}/api/docs/${docIds.TestDoc}/download/xlsx?tableId=MissingTableId`,
chimpy
);
assert.equal(resp.status, 404);
assert.deepEqual(resp.data, { error: 'Table MissingTableId not found.' });
});

View File

@ -3,6 +3,8 @@
"include": [
"app/**/*.js",
"app/**/*.ts",
"stubs/**/*.ts",
"stubs/**/*.ts",
"test/**/*.js",
"test/**/*.ts",
"plugins/**/*.js",