diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 11756c97f..5617197c3 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -39,3 +39,31 @@ jobs: run: yarn install --frozen-lockfile --prefer-offline - name: Lint code run: yarn lint + format: + runs-on: ubuntu-latest + name: Checks codestyle of all .ts and .tsx files + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "::set-output name=dir::$(yarn cache dir)" + + - name: Cache node_modules + uses: actions/cache@v2 + id: yarn-cache + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-16-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Set up NodeJS + uses: actions/setup-node@v2 + with: + node-version: 16 + - name: Install dependencies + run: yarn install --frozen-lockfile --prefer-offline + - name: Lint code + run: yarn format diff --git a/.gitignore b/.gitignore index 6f2267d65..997e9fe3a 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ .idea !.idea/dictionaries/hedgedoc.xml !.idea/copyright +!.idea/prettier.xml # misc .DS_Store .env.local diff --git a/.idea/prettier.xml b/.idea/prettier.xml new file mode 100644 index 000000000..8004cebd9 --- /dev/null +++ b/.idea/prettier.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..c2658d7d1 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +node_modules/ diff --git a/.prettierignore.license b/.prettierignore.license new file mode 100644 index 000000000..25cc6904b --- /dev/null +++ b/.prettierignore.license @@ -0,0 +1,4 @@ +SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + +SPDX-License-Identifier: CC0-1.0 + diff --git a/package.json b/package.json index 221a3d086..4bbc3fe2e 100644 --- a/package.json +++ b/package.json @@ -118,6 +118,9 @@ "analyze": "cross-env ANALYZE=true yarn build:mock", "test": "craco test", "lint": "eslint --max-warnings=0 --ext .ts,.tsx src", + "lint:fix": "eslint --fix --ext .ts,.tsx src", + "format": "prettier -c \"src/**/*.{ts,tsx,js}\"", + "format:fix": "prettier -w \"src/**/*.{ts,tsx,js}\"", "eject": "react-scripts eject", "cy:open": "cypress open", "cy:run:chrome": "cypress run --browser chrome", @@ -145,9 +148,21 @@ "plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended-requiring-type-checking", "plugin:import/recommended", - "plugin:import/typescript" + "plugin:import/typescript", + "prettier" ] }, + "prettier": { + "parser": "typescript", + "singleQuote": true, + "jsxSingleQuote": true, + "semi": false, + "tabWidth": 2, + "trailingComma": "none", + "bracketSpacing": true, + "jsxBracketSameLine": true, + "arrowParens": "always" + }, "browserslist": { "production": [ ">0.2%", @@ -169,9 +184,11 @@ "cypress": "7.4.0", "cypress-commands": "1.1.0", "cypress-file-upload": "5.0.7", + "eslint-config-prettier": "8.3.0", "eslint-plugin-chai-friendly": "0.7.1", "eslint-plugin-cypress": "2.11.3", "http-server": "0.12.3", + "prettier": "2.3.0", "redux-devtools": "3.7.0", "redux-devtools-extension": "2.13.9", "ts-loader": "9.2.2", diff --git a/src/api/config/index.ts b/src/api/config/index.ts index a64c34258..dbe020700 100644 --- a/src/api/config/index.ts +++ b/src/api/config/index.ts @@ -12,5 +12,5 @@ export const getConfig = async (): Promise => { ...defaultFetchConfig }) expectResponseCode(response) - return await response.json() as Promise + return (await response.json()) as Promise } diff --git a/src/api/config/types.d.ts b/src/api/config/types.d.ts index bac4afc4f..73ae42f66 100644 --- a/src/api/config/types.d.ts +++ b/src/api/config/types.d.ts @@ -5,27 +5,27 @@ */ export interface Config { - allowAnonymous: boolean, - allowRegister: boolean, - authProviders: AuthProvidersState, - branding: BrandingConfig, - customAuthNames: CustomAuthNames, - useImageProxy: boolean, - specialUrls: SpecialUrls, - version: BackendVersion, - plantumlServer: string | null, - maxDocumentLength: number, + allowAnonymous: boolean + allowRegister: boolean + authProviders: AuthProvidersState + branding: BrandingConfig + customAuthNames: CustomAuthNames + useImageProxy: boolean + specialUrls: SpecialUrls + version: BackendVersion + plantumlServer: string | null + maxDocumentLength: number iframeCommunication: iframeCommunicationConfig } export interface iframeCommunicationConfig { - editorOrigin: string, + editorOrigin: string rendererOrigin: string } export interface BrandingConfig { - name: string, - logo: string, + name: string + logo: string } export interface BackendVersion { @@ -37,27 +37,27 @@ export interface BackendVersion { } export interface AuthProvidersState { - facebook: boolean, - github: boolean, - twitter: boolean, - gitlab: boolean, - dropbox: boolean, - ldap: boolean, - google: boolean, - saml: boolean, - oauth2: boolean, - internal: boolean, - openid: boolean, + facebook: boolean + github: boolean + twitter: boolean + gitlab: boolean + dropbox: boolean + ldap: boolean + google: boolean + saml: boolean + oauth2: boolean + internal: boolean + openid: boolean } export interface CustomAuthNames { - ldap: string; - oauth2: string; - saml: string; + ldap: string + oauth2: string + saml: string } export interface SpecialUrls { - privacy?: string, - termsOfUse?: string, - imprint?: string, + privacy?: string + termsOfUse?: string + imprint?: string } diff --git a/src/api/history/index.ts b/src/api/history/index.ts index a3372f10e..7f6e58a7e 100644 --- a/src/api/history/index.ts +++ b/src/api/history/index.ts @@ -10,7 +10,7 @@ import { HistoryEntryDto, HistoryEntryPutDto, HistoryEntryUpdateDto } from './ty export const getHistory = async (): Promise => { const response = await fetch(getApiUrl() + 'me/history') expectResponseCode(response) - return await response.json() as Promise + return (await response.json()) as Promise } export const postHistory = async (entries: HistoryEntryPutDto[]): Promise => { diff --git a/src/api/me/index.ts b/src/api/me/index.ts index a9109d97a..7085f5b9e 100644 --- a/src/api/me/index.ts +++ b/src/api/me/index.ts @@ -9,7 +9,7 @@ import { defaultFetchConfig, expectResponseCode, getApiUrl } from '../utils' import { isMockMode } from '../../utils/test-modes' export const getMe = async (): Promise => { - const response = await fetch(getApiUrl() + `me${ isMockMode() ? '-get' : '' }`, { + const response = await fetch(getApiUrl() + `me${isMockMode() ? '-get' : ''}`, { ...defaultFetchConfig }) expectResponseCode(response) diff --git a/src/api/media/index.ts b/src/api/media/index.ts index 107ff37a7..1b8e29306 100644 --- a/src/api/media/index.ts +++ b/src/api/media/index.ts @@ -16,7 +16,7 @@ export const getProxiedUrl = async (imageUrl: string): Promise + return (await response.json()) as Promise } export interface UploadedMedia { @@ -34,5 +34,5 @@ export const uploadFile = async (noteId: string, contentType: string, media: Blo body: media }) expectResponseCode(response, 201) - return await response.json() as Promise + return (await response.json()) as Promise } diff --git a/src/api/notes/index.ts b/src/api/notes/index.ts index d42523ed7..a348f393e 100644 --- a/src/api/notes/index.ts +++ b/src/api/notes/index.ts @@ -11,15 +11,15 @@ import { isMockMode } from '../../utils/test-modes' export const getNote = async (noteId: string): Promise => { // The "-get" suffix is necessary, because in our mock api (filesystem) the note id might already be a folder. // TODO: [mrdrogdrog] replace -get with actual api route as soon as api backend is ready. - const response = await fetch(getApiUrl() + `notes/${ noteId }${ isMockMode() ? '-get' : '' }`, { + const response = await fetch(getApiUrl() + `notes/${noteId}${isMockMode() ? '-get' : ''}`, { ...defaultFetchConfig }) expectResponseCode(response) - return await response.json() as Promise + return (await response.json()) as Promise } export const deleteNote = async (noteId: string): Promise => { - const response = await fetch(getApiUrl() + `notes/${ noteId }`, { + const response = await fetch(getApiUrl() + `notes/${noteId}`, { ...defaultFetchConfig, method: 'DELETE' }) diff --git a/src/api/revisions/index.ts b/src/api/revisions/index.ts index 964845ca7..82d423d8c 100644 --- a/src/api/revisions/index.ts +++ b/src/api/revisions/index.ts @@ -11,24 +11,24 @@ import { Revision, RevisionListEntry } from './types' const revisionCache = new Cache(3600) export const getRevision = async (noteId: string, timestamp: number): Promise => { - const cacheKey = `${ noteId }:${ timestamp }` + const cacheKey = `${noteId}:${timestamp}` if (revisionCache.has(cacheKey)) { return revisionCache.get(cacheKey) } - const response = await fetch(getApiUrl() + `notes/${ noteId }/revisions/${ timestamp }`, { + const response = await fetch(getApiUrl() + `notes/${noteId}/revisions/${timestamp}`, { ...defaultFetchConfig }) expectResponseCode(response) - const revisionData = await response.json() as Revision + const revisionData = (await response.json()) as Revision revisionCache.put(cacheKey, revisionData) return revisionData } export const getAllRevisions = async (noteId: string): Promise => { // TODO Change 'revisions-list' to 'revisions' as soon as the backend is ready to serve some data! - const response = await fetch(getApiUrl() + `notes/${ noteId }/revisions-list`, { + const response = await fetch(getApiUrl() + `notes/${noteId}/revisions-list`, { ...defaultFetchConfig }) expectResponseCode(response) - return await response.json() as Promise + return (await response.json()) as Promise } diff --git a/src/api/tokens/index.ts b/src/api/tokens/index.ts index f0ce8b632..7e54a205d 100644 --- a/src/api/tokens/index.ts +++ b/src/api/tokens/index.ts @@ -8,25 +8,25 @@ import { defaultFetchConfig, expectResponseCode, getApiUrl } from '../utils' import { AccessToken, AccessTokenSecret } from './types' export const getAccessTokenList = async (): Promise => { - const response = await fetch(`${ getApiUrl() }tokens`, { + const response = await fetch(`${getApiUrl()}tokens`, { ...defaultFetchConfig }) expectResponseCode(response) - return await response.json() as AccessToken[] + return (await response.json()) as AccessToken[] } export const postNewAccessToken = async (label: string): Promise => { - const response = await fetch(`${ getApiUrl() }tokens`, { + const response = await fetch(`${getApiUrl()}tokens`, { ...defaultFetchConfig, method: 'POST', body: label }) expectResponseCode(response) - return await response.json() as (AccessToken & AccessTokenSecret) + return (await response.json()) as AccessToken & AccessTokenSecret } export const deleteAccessToken = async (timestamp: number): Promise => { - const response = await fetch(`${ getApiUrl() }tokens/${ timestamp }`, { + const response = await fetch(`${getApiUrl()}tokens/${timestamp}`, { ...defaultFetchConfig, method: 'DELETE' }) diff --git a/src/api/users/index.ts b/src/api/users/index.ts index 8dfcd03ce..69316ec67 100644 --- a/src/api/users/index.ts +++ b/src/api/users/index.ts @@ -14,7 +14,7 @@ export const getUserById = async (userid: string): Promise => { if (cache.has(userid)) { return cache.get(userid) } - const response = await fetch(`${ getApiUrl() }/users/${ userid }`, { + const response = await fetch(`${getApiUrl()}/users/${userid}`, { ...defaultFetchConfig }) expectResponseCode(response) diff --git a/src/api/utils.ts b/src/api/utils.ts index 12a591ae5..e79492c97 100644 --- a/src/api/utils.ts +++ b/src/api/utils.ts @@ -24,6 +24,6 @@ export const getApiUrl = (): string => { export const expectResponseCode = (response: Response, code = 200): void => { if (response.status !== code) { - throw new Error(`response code is not ${ code }`) + throw new Error(`response code is not ${code}`) } } diff --git a/src/components/application-loader/application-loader.tsx b/src/components/application-loader/application-loader.tsx index e31e1b1ea..1a4d5ed1f 100644 --- a/src/components/application-loader/application-loader.tsx +++ b/src/components/application-loader/application-loader.tsx @@ -17,8 +17,10 @@ export const ApplicationLoader: React.FC = ({ children }) => { const backendBaseUrl = useBackendBaseUrl() const customizeAssetsUrl = useCustomizeAssetsUrl() - const setUpTasks = useCallback(() => createSetUpTaskList(frontendAssetsUrl, customizeAssetsUrl, backendBaseUrl), - [backendBaseUrl, customizeAssetsUrl, frontendAssetsUrl]) + const setUpTasks = useCallback( + () => createSetUpTaskList(frontendAssetsUrl, customizeAssetsUrl, backendBaseUrl), + [backendBaseUrl, customizeAssetsUrl, frontendAssetsUrl] + ) const [failedTitle, setFailedTitle] = useState('') const [doneTasks, setDoneTasks] = useState(0) @@ -26,28 +28,25 @@ export const ApplicationLoader: React.FC = ({ children }) => { const runTask = useCallback(async (task: Promise): Promise => { await task - setDoneTasks(prevDoneTasks => { + setDoneTasks((prevDoneTasks) => { return prevDoneTasks + 1 }) }, []) useEffect(() => { for (const task of initTasks) { - runTask(task.task) - .catch((reason: Error) => { - console.error(reason) - setFailedTitle(task.name) - }) + runTask(task.task).catch((reason: Error) => { + console.error(reason) + setFailedTitle(task.name) + }) } }, [initTasks, runTask]) const tasksAreRunning = doneTasks < initTasks.length || initTasks.length === 0 if (tasksAreRunning) { - return + return } else { - return ) }> - { children } - + return }>{children} } } diff --git a/src/components/application-loader/initializers/fetch-and-set-banner.ts b/src/components/application-loader/initializers/fetch-and-set-banner.ts index 54b8ea358..c037c5059 100644 --- a/src/components/application-loader/initializers/fetch-and-set-banner.ts +++ b/src/components/application-loader/initializers/fetch-and-set-banner.ts @@ -11,7 +11,7 @@ export const BANNER_LOCAL_STORAGE_KEY = 'banner.lastModified' export const fetchAndSetBanner = async (customizeAssetsUrl: string): Promise => { const cachedLastModified = window.localStorage.getItem(BANNER_LOCAL_STORAGE_KEY) - const bannerUrl = `${ customizeAssetsUrl }banner.txt` + const bannerUrl = `${customizeAssetsUrl}banner.txt` if (cachedLastModified) { const response = await fetch(bannerUrl, { diff --git a/src/components/application-loader/initializers/i18n.ts b/src/components/application-loader/initializers/i18n.ts index e043ce762..f845d5251 100644 --- a/src/components/application-loader/initializers/i18n.ts +++ b/src/components/application-loader/initializers/i18n.ts @@ -19,7 +19,7 @@ export const setUpI18n = async (frontendAssetsUrl: string): Promise => { fallbackLng: 'en', debug: process.env.NODE_ENV !== 'production', backend: { - loadPath: `${ frontendAssetsUrl }locales/{{lng}}.json` + loadPath: `${frontendAssetsUrl}locales/{{lng}}.json` }, interpolation: { diff --git a/src/components/application-loader/initializers/index.ts b/src/components/application-loader/initializers/index.ts index 958b63373..0cd2bd016 100644 --- a/src/components/application-loader/initializers/index.ts +++ b/src/components/application-loader/initializers/index.ts @@ -13,7 +13,7 @@ import { fetchFrontendConfig } from './fetch-frontend-config' const customDelay: () => Promise = async () => { if (window.localStorage.getItem('customDelay')) { - return new Promise(resolve => setTimeout(resolve, 5000)) + return new Promise((resolve) => setTimeout(resolve, 5000)) } else { return Promise.resolve() } @@ -24,28 +24,39 @@ export interface InitTask { task: Promise } -export const createSetUpTaskList = (frontendAssetsUrl: string, customizeAssetsUrl: string, backendBaseUrl: string): InitTask[] => { +export const createSetUpTaskList = ( + frontendAssetsUrl: string, + customizeAssetsUrl: string, + backendBaseUrl: string +): InitTask[] => { setApiUrl({ - apiUrl: `${ backendBaseUrl }api/private/` + apiUrl: `${backendBaseUrl}api/private/` }) - return [{ - name: 'Load Translations', - task: setUpI18n(frontendAssetsUrl) - }, { - name: 'Load config', - task: fetchFrontendConfig() - }, { - name: 'Fetch user information', - task: fetchAndSetUser() - }, { - name: 'Banner', - task: fetchAndSetBanner(customizeAssetsUrl) - }, { - name: 'Load history state', - task: refreshHistoryState() - }, { - name: 'Add Delay', - task: customDelay() - }] + return [ + { + name: 'Load Translations', + task: setUpI18n(frontendAssetsUrl) + }, + { + name: 'Load config', + task: fetchFrontendConfig() + }, + { + name: 'Fetch user information', + task: fetchAndSetUser() + }, + { + name: 'Banner', + task: fetchAndSetBanner(customizeAssetsUrl) + }, + { + name: 'Load history state', + task: refreshHistoryState() + }, + { + name: 'Add Delay', + task: customDelay() + } + ] } diff --git a/src/components/application-loader/loading-screen.tsx b/src/components/application-loader/loading-screen.tsx index 9910c89d6..4ee623aaf 100644 --- a/src/components/application-loader/loading-screen.tsx +++ b/src/components/application-loader/loading-screen.tsx @@ -15,15 +15,16 @@ export interface LoadingScreenProps { export const LoadingScreen: React.FC = ({ failedTitle }) => { return ( -
-
- - +
+
+ +
- - - The task '{ failedTitle }' failed.
+ + + The task '{failedTitle}' failed. +
For further information look into the browser console.
diff --git a/src/components/common/branding/branding.tsx b/src/components/common/branding/branding.tsx index 7b72afa54..bda523b27 100644 --- a/src/components/common/branding/branding.tsx +++ b/src/components/common/branding/branding.tsx @@ -21,20 +21,20 @@ export const Branding: React.FC = ({ inline = false, delimiter = const showBranding = !!branding.name || !!branding.logo return ( - - - @ + + + @ - { - branding.logo - ? { - : branding.name - } + {branding.logo ? ( + {branding.name} + ) : ( + branding.name + )} ) } diff --git a/src/components/common/cache/cache.test.ts b/src/components/common/cache/cache.test.ts index 9723248be..b2c7fa005 100644 --- a/src/components/common/cache/cache.test.ts +++ b/src/components/common/cache/cache.test.ts @@ -16,88 +16,68 @@ describe('Test caching functionality', () => { it('initialize with right lifetime, no entry limit', () => { const lifetime = 1000 const lifetimedCache = new Cache(lifetime) - expect(lifetimedCache.entryLifetime) - .toEqual(lifetime) - expect(lifetimedCache.maxEntries) - .toEqual(0) + expect(lifetimedCache.entryLifetime).toEqual(lifetime) + expect(lifetimedCache.maxEntries).toEqual(0) }) it('initialize with right lifetime, given entry limit', () => { const lifetime = 1000 const maxEntries = 10 const limitedCache = new Cache(lifetime, maxEntries) - expect(limitedCache.entryLifetime) - .toEqual(lifetime) - expect(limitedCache.maxEntries) - .toEqual(maxEntries) + expect(limitedCache.entryLifetime).toEqual(lifetime) + expect(limitedCache.maxEntries).toEqual(maxEntries) }) it('entry exists after inserting', () => { testCache.put('test', 123) - expect(testCache.has('test')) - .toBe(true) + expect(testCache.has('test')).toBe(true) }) it('entry does not exist prior inserting', () => { - expect(testCache.has('test')) - .toBe(false) + expect(testCache.has('test')).toBe(false) }) it('entry does expire', () => { const shortLivingCache = new Cache(2) shortLivingCache.put('test', 123) - expect(shortLivingCache.has('test')) - .toBe(true) + expect(shortLivingCache.has('test')).toBe(true) setTimeout(() => { - expect(shortLivingCache.has('test')) - .toBe(false) + expect(shortLivingCache.has('test')).toBe(false) }, 2000) }) it('entry value does not change', () => { const testValue = Date.now() testCache.put('test', testValue) - expect(testCache.get('test')) - .toEqual(testValue) + expect(testCache.get('test')).toEqual(testValue) }) it('error is thrown on non-existent entry', () => { const accessNonExistentEntry = () => { testCache.get('test') } - expect(accessNonExistentEntry) - .toThrow(Error) + expect(accessNonExistentEntry).toThrow(Error) }) it('newer item replaces older item', () => { testCache.put('test', 123) testCache.put('test', 456) - expect(testCache.get('test')) - .toEqual(456) + expect(testCache.get('test')).toEqual(456) }) it('entry limit is respected', () => { const limitedCache = new Cache(1000, 2) limitedCache.put('first', 1) - expect(limitedCache.has('first')) - .toBe(true) - expect(limitedCache.has('second')) - .toBe(false) - expect(limitedCache.has('third')) - .toBe(false) + expect(limitedCache.has('first')).toBe(true) + expect(limitedCache.has('second')).toBe(false) + expect(limitedCache.has('third')).toBe(false) limitedCache.put('second', 2) - expect(limitedCache.has('first')) - .toBe(true) - expect(limitedCache.has('second')) - .toBe(true) - expect(limitedCache.has('third')) - .toBe(false) + expect(limitedCache.has('first')).toBe(true) + expect(limitedCache.has('second')).toBe(true) + expect(limitedCache.has('third')).toBe(false) limitedCache.put('third', 3) - expect(limitedCache.has('first')) - .toBe(false) - expect(limitedCache.has('second')) - .toBe(true) - expect(limitedCache.has('third')) - .toBe(true) + expect(limitedCache.has('first')).toBe(false) + expect(limitedCache.has('second')).toBe(true) + expect(limitedCache.has('third')).toBe(true) }) }) diff --git a/src/components/common/cache/cache.ts b/src/components/common/cache/cache.ts index 68486c943..8268f918b 100644 --- a/src/components/common/cache/cache.ts +++ b/src/components/common/cache/cache.ts @@ -27,7 +27,7 @@ export class Cache { return false } const entry = this.store.get(key) - return (!!entry && entry.entryCreated >= (Date.now() - this.entryLifetime * 1000)) + return !!entry && entry.entryCreated >= Date.now() - this.entryLifetime * 1000 } get(key: K): V { @@ -40,8 +40,7 @@ export class Cache { put(key: K, value: V): void { if (this.maxEntries > 0 && this.store.size === this.maxEntries) { - this.store.delete(this.store.keys() - .next().value) + this.store.delete(this.store.keys().next().value) } this.store.set(key, { entryCreated: Date.now(), diff --git a/src/components/common/copyable/copy-overlay.tsx b/src/components/common/copyable/copy-overlay.tsx index 569be1ebb..e725be17a 100644 --- a/src/components/common/copyable/copy-overlay.tsx +++ b/src/components/common/copyable/copy-overlay.tsx @@ -22,20 +22,21 @@ export const CopyOverlay: React.FC = ({ content, clickComponen const [tooltipId] = useState(() => uuid()) const copyToClipboard = useCallback((content: string) => { - navigator.clipboard.writeText(content) - .then(() => { - setError(false) - }) - .catch(() => { - setError(true) - console.error('couldn\'t copy') - }) - .finally(() => { - setShowCopiedTooltip(true) - setTimeout(() => { - setShowCopiedTooltip(false) - }, 2000) - }) + navigator.clipboard + .writeText(content) + .then(() => { + setError(false) + }) + .catch(() => { + setError(true) + console.error("couldn't copy") + }) + .finally(() => { + setShowCopiedTooltip(true) + setTimeout(() => { + setShowCopiedTooltip(false) + }, 2000) + }) }, []) useEffect(() => { @@ -51,17 +52,17 @@ export const CopyOverlay: React.FC = ({ content, clickComponen }, [clickComponent, copyToClipboard, content]) return ( - - { (props) => ( - - - + + {(props) => ( + + + - - + + - ) } + )} ) } diff --git a/src/components/common/copyable/copy-to-clipboard-button/copy-to-clipboard-button.tsx b/src/components/common/copyable/copy-to-clipboard-button/copy-to-clipboard-button.tsx index 6bfc27cf8..bc912b76d 100644 --- a/src/components/common/copyable/copy-to-clipboard-button/copy-to-clipboard-button.tsx +++ b/src/components/common/copyable/copy-to-clipboard-button/copy-to-clipboard-button.tsx @@ -29,11 +29,15 @@ export const CopyToClipboardButton: React.FC = ({ return ( - - + ) } diff --git a/src/components/common/copyable/copyable-field/copyable-field.tsx b/src/components/common/copyable/copyable-field/copyable-field.tsx index 74bc3dd96..38bd23fc1 100644 --- a/src/components/common/copyable/copyable-field/copyable-field.tsx +++ b/src/components/common/copyable/copyable-field/copyable-field.tsx @@ -22,35 +22,36 @@ export const CopyableField: React.FC = ({ content, nativeSha const copyButton = useRef(null) const doShareAction = useCallback(() => { - navigator.share({ - text: content, - url: url - }) - .catch(err => { - console.error('Native sharing failed: ', err) - }) + navigator + .share({ + text: content, + url: url + }) + .catch((err) => { + console.error('Native sharing failed: ', err) + }) }, [content, url]) const sharingSupported = typeof navigator.share === 'function' return ( - - + + - - + - - + ) } diff --git a/src/components/common/fork-awesome/fork-awesome-icon.tsx b/src/components/common/fork-awesome/fork-awesome-icon.tsx index 4b7c5ab7d..d336d0f31 100644 --- a/src/components/common/fork-awesome/fork-awesome-icon.tsx +++ b/src/components/common/fork-awesome/fork-awesome-icon.tsx @@ -15,12 +15,16 @@ export interface ForkAwesomeIconProps { stacked?: boolean } -export const ForkAwesomeIcon: React.FC = ({ icon, fixedWidth = false, size, className, stacked = false }) => { +export const ForkAwesomeIcon: React.FC = ({ + icon, + fixedWidth = false, + size, + className, + stacked = false +}) => { const fixedWithClass = fixedWidth ? 'fa-fw' : '' - const sizeClass = size ? `-${ size }` : (stacked ? '-1x' : '') + const sizeClass = size ? `-${size}` : stacked ? '-1x' : '' const stackClass = stacked ? '-stack' : '' - const extraClasses = `${ className ?? '' } ${ sizeClass || stackClass ? `fa${ stackClass }${ sizeClass }` : '' }` - return ( - - ) + const extraClasses = `${className ?? ''} ${sizeClass || stackClass ? `fa${stackClass}${sizeClass}` : ''}` + return } diff --git a/src/components/common/fork-awesome/fork-awesome-stack.tsx b/src/components/common/fork-awesome/fork-awesome-stack.tsx index f19408ef2..563c614d8 100644 --- a/src/components/common/fork-awesome/fork-awesome-stack.tsx +++ b/src/components/common/fork-awesome/fork-awesome-stack.tsx @@ -15,15 +15,13 @@ export interface ForkAwesomeStackProps { export const ForkAwesomeStack: React.FC = ({ size, children }) => { return ( - - { - React.Children.map(children, (child) => { - if (!React.isValidElement(child)) { - return null - } - return - }) - } + + {React.Children.map(children, (child) => { + if (!React.isValidElement(child)) { + return null + } + return + })} ) } diff --git a/src/components/common/hedge-doc-logo/hedge-doc-logo-with-text.tsx b/src/components/common/hedge-doc-logo/hedge-doc-logo-with-text.tsx index b254e6175..b3f017464 100644 --- a/src/components/common/hedge-doc-logo/hedge-doc-logo-with-text.tsx +++ b/src/components/common/hedge-doc-logo/hedge-doc-logo-with-text.tsx @@ -16,7 +16,7 @@ export enum HedgeDocLogoSize { } export interface HedgeDocLogoProps { - size?: HedgeDocLogoSize | number, + size?: HedgeDocLogoSize | number logoType: HedgeDocLogoType } @@ -29,11 +29,11 @@ export enum HedgeDocLogoType { export const HedgeDocLogoWithText: React.FC = ({ size = HedgeDocLogoSize.MEDIUM, logoType }) => { switch (logoType) { case HedgeDocLogoType.COLOR_VERTICAL: - return + return case HedgeDocLogoType.BW_HORIZONTAL: - return + return case HedgeDocLogoType.WB_HORIZONTAL: - return + return default: return null } diff --git a/src/components/common/hedge-doc-logo/hedge-doc-logo.tsx b/src/components/common/hedge-doc-logo/hedge-doc-logo.tsx index b5456f517..8d7350fe8 100644 --- a/src/components/common/hedge-doc-logo/hedge-doc-logo.tsx +++ b/src/components/common/hedge-doc-logo/hedge-doc-logo.tsx @@ -18,5 +18,5 @@ export interface HedgeDocLogoProps { } export const HedgeDocLogo: React.FC = ({ size = HedgeDocLogoSize.MEDIUM }) => { - return + return } diff --git a/src/components/common/icon-button/icon-button.tsx b/src/components/common/icon-button/icon-button.tsx index 0facb1a89..4e8631b1c 100644 --- a/src/components/common/icon-button/icon-button.tsx +++ b/src/components/common/icon-button/icon-button.tsx @@ -18,17 +18,23 @@ export interface IconButtonProps extends ButtonProps { iconFixedWidth?: boolean } -export const IconButton: React.FC = ({ icon, children, iconFixedWidth = false, border = false, className, ...props }) => { +export const IconButton: React.FC = ({ + icon, + children, + iconFixedWidth = false, + border = false, + className, + ...props +}) => { return ( - ) diff --git a/src/components/common/icon-button/translated-icon-button.tsx b/src/components/common/icon-button/translated-icon-button.tsx index 14972e28a..41675a0f7 100644 --- a/src/components/common/icon-button/translated-icon-button.tsx +++ b/src/components/common/icon-button/translated-icon-button.tsx @@ -14,8 +14,8 @@ export interface TranslatedIconButtonProps extends IconButtonProps { export const TranslatedIconButton: React.FC = ({ i18nKey, ...props }) => { return ( - - + + ) } diff --git a/src/components/common/links/external-link.tsx b/src/components/common/links/external-link.tsx index 1ac879fd3..9c078af59 100644 --- a/src/components/common/links/external-link.tsx +++ b/src/components/common/links/external-link.tsx @@ -10,20 +10,21 @@ import { IconName } from '../fork-awesome/types' import { ShowIf } from '../show-if/show-if' import { LinkWithTextProps } from './types' -export const ExternalLink: React.FC = ({ href, text, icon, id, className = 'text-light', title }) => { +export const ExternalLink: React.FC = ({ + href, + text, + icon, + id, + className = 'text-light', + title +}) => { return ( - - -   + + + +   - { text } + {text} ) } diff --git a/src/components/common/links/internal-link.tsx b/src/components/common/links/internal-link.tsx index 4127b7106..d0cb16b55 100644 --- a/src/components/common/links/internal-link.tsx +++ b/src/components/common/links/internal-link.tsx @@ -11,17 +11,21 @@ import { IconName } from '../fork-awesome/types' import { ShowIf } from '../show-if/show-if' import { LinkWithTextProps } from './types' -export const InternalLink: React.FC = ({ href, text, icon, id, className = 'text-light', title }) => { +export const InternalLink: React.FC = ({ + href, + text, + icon, + id, + className = 'text-light', + title +}) => { return ( - - -   + + + +   - { text } + {text} ) } diff --git a/src/components/common/links/translated-external-link.tsx b/src/components/common/links/translated-external-link.tsx index 3923ce9d6..7f2910962 100644 --- a/src/components/common/links/translated-external-link.tsx +++ b/src/components/common/links/translated-external-link.tsx @@ -11,7 +11,5 @@ import { TranslatedLinkProps } from './types' export const TranslatedExternalLink: React.FC = ({ i18nKey, i18nOption, ...props }) => { const { t } = useTranslation() - return ( - - ) + return } diff --git a/src/components/common/links/translated-internal-link.tsx b/src/components/common/links/translated-internal-link.tsx index 5d7819cf2..b79e6fbd8 100644 --- a/src/components/common/links/translated-internal-link.tsx +++ b/src/components/common/links/translated-internal-link.tsx @@ -11,7 +11,5 @@ import { TranslatedLinkProps } from './types' export const TranslatedInternalLink: React.FC = ({ i18nKey, i18nOption, ...props }) => { const { t } = useTranslation() - return ( - - ) + return } diff --git a/src/components/common/lock-button/lock-button.tsx b/src/components/common/lock-button/lock-button.tsx index 8fc942f01..2b2098f3e 100644 --- a/src/components/common/lock-button/lock-button.tsx +++ b/src/components/common/lock-button/lock-button.tsx @@ -9,18 +9,15 @@ import { Button } from 'react-bootstrap' import { ForkAwesomeIcon } from '../fork-awesome/fork-awesome-icon' export interface LockButtonProps { - locked: boolean, + locked: boolean onLockedChanged: (newState: boolean) => void title: string } export const LockButton: React.FC = ({ locked, onLockedChanged, title }) => { return ( - ) } diff --git a/src/components/common/modals/common-modal.tsx b/src/components/common/modals/common-modal.tsx index 5ec4ad07e..c7fb4d471 100644 --- a/src/components/common/modals/common-modal.tsx +++ b/src/components/common/modals/common-modal.tsx @@ -23,24 +23,38 @@ export interface CommonModalProps { 'data-cy'?: string } -export const CommonModal: React.FC = ({ show, onHide, titleI18nKey, title, closeButton, icon, additionalClasses, size, children, ...props }) => { +export const CommonModal: React.FC = ({ + show, + onHide, + titleI18nKey, + title, + closeButton, + icon, + additionalClasses, + size, + children, + ...props +}) => { useTranslation() return ( - - + + - -   + + +   - { titleI18nKey - ? - : { title } - } + {titleI18nKey ? : {title}} - { children } + {children} ) } diff --git a/src/components/common/modals/deletion-modal.tsx b/src/components/common/modals/deletion-modal.tsx index cf9cde4c9..1a68441f8 100644 --- a/src/components/common/modals/deletion-modal.tsx +++ b/src/components/common/modals/deletion-modal.tsx @@ -14,17 +14,23 @@ export interface DeletionModalProps extends CommonModalProps { deletionButtonI18nKey: string } -export const DeletionModal: React.FC = ({ show, onHide, titleI18nKey, onConfirm, deletionButtonI18nKey, icon, children }) => { +export const DeletionModal: React.FC = ({ + show, + onHide, + titleI18nKey, + onConfirm, + deletionButtonI18nKey, + icon, + children +}) => { useTranslation() return ( - - - { children } - + + {children} - diff --git a/src/components/common/modals/error-modal.tsx b/src/components/common/modals/error-modal.tsx index 93ab40383..e1b9bb924 100644 --- a/src/components/common/modals/error-modal.tsx +++ b/src/components/common/modals/error-modal.tsx @@ -10,10 +10,8 @@ import { CommonModal, CommonModalProps } from './common-modal' export const ErrorModal: React.FC = ({ show, onHide, titleI18nKey, icon, children }) => { return ( - - - { children } - + + {children} ) } diff --git a/src/components/common/motd-banner/motd-banner.tsx b/src/components/common/motd-banner/motd-banner.tsx index 88dc66be0..b2c592da7 100644 --- a/src/components/common/motd-banner/motd-banner.tsx +++ b/src/components/common/motd-banner/motd-banner.tsx @@ -31,22 +31,18 @@ export const MotdBanner: React.FC = () => { } if (!bannerState.text) { - return + return } return ( - - - { bannerState.text } - - ) diff --git a/src/components/common/number-range/number-range.ts b/src/components/common/number-range/number-range.ts index 1d7e10907..495fcf880 100644 --- a/src/components/common/number-range/number-range.ts +++ b/src/components/common/number-range/number-range.ts @@ -5,6 +5,5 @@ */ export const createNumberRangeArray = (length: number): number[] => { - return Array.from(Array(length) - .keys()) + return Array.from(Array(length).keys()) } diff --git a/src/components/common/pagination/pager-item.tsx b/src/components/common/pagination/pager-item.tsx index 80d5eebb3..4f41d45ee 100644 --- a/src/components/common/pagination/pager-item.tsx +++ b/src/components/common/pagination/pager-item.tsx @@ -13,9 +13,9 @@ export interface PageItemProps { export const PagerItem: React.FC = ({ index, onClick }) => { return ( -
  • - onClick(index) }> - { index + 1 } +
  • + onClick(index)}> + {index + 1}
  • ) diff --git a/src/components/common/pagination/pager-pagination.tsx b/src/components/common/pagination/pager-pagination.tsx index f1a88bf91..ea62db504 100644 --- a/src/components/common/pagination/pager-pagination.tsx +++ b/src/components/common/pagination/pager-pagination.tsx @@ -15,7 +15,11 @@ export interface PaginationProps { lastPageIndex: number } -export const PagerPagination: React.FC = ({ numberOfPageButtonsToShowAfterAndBeforeCurrent, onPageChange, lastPageIndex }) => { +export const PagerPagination: React.FC = ({ + numberOfPageButtonsToShowAfterAndBeforeCurrent, + onPageChange, + lastPageIndex +}) => { if (numberOfPageButtonsToShowAfterAndBeforeCurrent % 2 !== 0) { throw new Error('number of pages to show must be even!') } @@ -29,55 +33,38 @@ export const PagerPagination: React.FC = ({ numberOfPageButtons onPageChange(pageIndex) }, [onPageChange, pageIndex]) - const correctedLowerPageIndex = - Math.min( - Math.max( - Math.min( - wantedLowerPageIndex, - wantedLowerPageIndex + lastPageIndex - wantedUpperPageIndex - ), - 0 - ), - lastPageIndex - ) + const correctedLowerPageIndex = Math.min( + Math.max(Math.min(wantedLowerPageIndex, wantedLowerPageIndex + lastPageIndex - wantedUpperPageIndex), 0), + lastPageIndex + ) - const correctedUpperPageIndex = - Math.max( - Math.min( - Math.max( - wantedUpperPageIndex, - wantedUpperPageIndex - wantedLowerPageIndex - ), - lastPageIndex - ), - 0 - ) + const correctedUpperPageIndex = Math.max( + Math.min(Math.max(wantedUpperPageIndex, wantedUpperPageIndex - wantedLowerPageIndex), lastPageIndex), + 0 + ) - const paginationItemsBefore = Array.from(new Array(correctedPageIndex - correctedLowerPageIndex)) - .map((k, index) => { - const itemIndex = correctedLowerPageIndex + index - return - }) + const paginationItemsBefore = Array.from(new Array(correctedPageIndex - correctedLowerPageIndex)).map((k, index) => { + const itemIndex = correctedLowerPageIndex + index + return + }) - const paginationItemsAfter = Array.from(new Array(correctedUpperPageIndex - correctedPageIndex)) - .map((k, index) => { - const itemIndex = correctedPageIndex + index + 1 - return - }) + const paginationItemsAfter = Array.from(new Array(correctedUpperPageIndex - correctedPageIndex)).map((k, index) => { + const itemIndex = correctedPageIndex + index + 1 + return + }) return ( - 0 }> - - + 0}> + + - { paginationItemsBefore } - { correctedPageIndex + 1 } - { paginationItemsAfter } - - - + {paginationItemsBefore} + {correctedPageIndex + 1} + {paginationItemsAfter} + + + ) diff --git a/src/components/common/pagination/pager.tsx b/src/components/common/pagination/pager.tsx index bc5ff8e29..3c2bb778f 100644 --- a/src/components/common/pagination/pager.tsx +++ b/src/components/common/pagination/pager.tsx @@ -12,7 +12,12 @@ export interface PagerPageProps { onLastPageIndexChange: (lastPageIndex: number) => void } -export const Pager: React.FC = ({ children, numberOfElementsPerPage, pageIndex, onLastPageIndexChange }) => { +export const Pager: React.FC = ({ + children, + numberOfElementsPerPage, + pageIndex, + onLastPageIndexChange +}) => { const maxPageIndex = Math.ceil(React.Children.count(children) / numberOfElementsPerPage) - 1 const correctedPageIndex = Math.min(maxPageIndex, Math.max(0, pageIndex)) @@ -20,13 +25,12 @@ export const Pager: React.FC = ({ children, numberOfElementsPerP onLastPageIndexChange(maxPageIndex) }, [children, maxPageIndex, numberOfElementsPerPage, onLastPageIndexChange]) - return - { - React.Children.toArray(children) - .filter((value, index) => { - const pageOfElement = Math.floor((index) / numberOfElementsPerPage) - return (pageOfElement === correctedPageIndex) - }) - } - + return ( + + {React.Children.toArray(children).filter((value, index) => { + const pageOfElement = Math.floor(index / numberOfElementsPerPage) + return pageOfElement === correctedPageIndex + })} + + ) } diff --git a/src/components/common/routing/not-found-error-screen.tsx b/src/components/common/routing/not-found-error-screen.tsx index 9b7078940..3cf7ad4e9 100644 --- a/src/components/common/routing/not-found-error-screen.tsx +++ b/src/components/common/routing/not-found-error-screen.tsx @@ -11,7 +11,9 @@ export const NotFoundErrorScreen: React.FC = () => { return (
    -

    404 Not Found oops.

    +

    + 404 Not Found oops. +

    ) diff --git a/src/components/common/routing/redirector.tsx b/src/components/common/routing/redirector.tsx index 8977fd77d..3dc1dc2a3 100644 --- a/src/components/common/routing/redirector.tsx +++ b/src/components/common/routing/redirector.tsx @@ -26,10 +26,10 @@ export const Redirector: React.FC = () => { }, [id]) if (error) { - return () + return } else if (!error && error != null) { - return () + return } else { - return (Loading) + return Loading } } diff --git a/src/components/common/show-if/show-if.tsx b/src/components/common/show-if/show-if.tsx index 9a2ecd184..770780571 100644 --- a/src/components/common/show-if/show-if.tsx +++ b/src/components/common/show-if/show-if.tsx @@ -11,5 +11,5 @@ export interface ShowIfProps { } export const ShowIf: React.FC = ({ children, condition }) => { - return condition ? { children } : null + return condition ? {children} : null } diff --git a/src/components/common/user-avatar/user-avatar.tsx b/src/components/common/user-avatar/user-avatar.tsx index 100d50928..06dc7c2e4 100644 --- a/src/components/common/user-avatar/user-avatar.tsx +++ b/src/components/common/user-avatar/user-avatar.tsx @@ -11,9 +11,9 @@ import './user-avatar.scss' export interface UserAvatarProps { size?: 'sm' | 'lg' - name: string; - photo: string; - additionalClasses?: string; + name: string + photo: string + additionalClasses?: string showName?: boolean } @@ -21,15 +21,15 @@ const UserAvatar: React.FC = ({ name, photo, size, additionalCl const { t } = useTranslation() return ( - + { - - { name } + + {name} ) diff --git a/src/components/common/wait-spinner/wait-spinner.tsx b/src/components/common/wait-spinner/wait-spinner.tsx index e1f0f4ced..28ef5cd59 100644 --- a/src/components/common/wait-spinner/wait-spinner.tsx +++ b/src/components/common/wait-spinner/wait-spinner.tsx @@ -9,8 +9,8 @@ import { ForkAwesomeIcon } from '../fork-awesome/fork-awesome-icon' export const WaitSpinner: React.FC = () => { return ( -
    - +
    +
    ) } diff --git a/src/components/document-read-only-page/ErrorWhileLoadingNoteAlert.tsx b/src/components/document-read-only-page/ErrorWhileLoadingNoteAlert.tsx index 8e6f59cbc..4c581cd43 100644 --- a/src/components/document-read-only-page/ErrorWhileLoadingNoteAlert.tsx +++ b/src/components/document-read-only-page/ErrorWhileLoadingNoteAlert.tsx @@ -14,11 +14,13 @@ export const ErrorWhileLoadingNoteAlert: React.FC = ({ show }) useTranslation() return ( - - - -
    - + + + + + +
    +
    ) diff --git a/src/components/document-read-only-page/LoadingNoteAlert.tsx b/src/components/document-read-only-page/LoadingNoteAlert.tsx index a11c476fd..1baed95ff 100644 --- a/src/components/document-read-only-page/LoadingNoteAlert.tsx +++ b/src/components/document-read-only-page/LoadingNoteAlert.tsx @@ -12,9 +12,9 @@ import { SimpleAlertProps } from '../common/simple-alert/simple-alert-props' export const LoadingNoteAlert: React.FC = ({ show }) => { return ( - - - + + + ) diff --git a/src/components/document-read-only-page/document-infobar.tsx b/src/components/document-read-only-page/document-infobar.tsx index ce19da133..0d7bb7e9b 100644 --- a/src/components/document-read-only-page/document-infobar.tsx +++ b/src/components/document-read-only-page/document-infobar.tsx @@ -39,32 +39,38 @@ export const DocumentInfobar: React.FC = ({ const assetsBaseUrl = useCustomizeAssetsUrl() return ( -
    -
     
    -
    -
    +
    +
     
    +
    +
    + mode={DocumentInfoLineWithTimeMode.CREATED} + time={createdTime} + userName={createdAuthor} + profileImageSrc={`${assetsBaseUrl}/img/avatar.png`} + /> -
    + mode={DocumentInfoLineWithTimeMode.EDITED} + time={changedTime} + userName={changedAuthor} + profileImageSrc={`${assetsBaseUrl}/img/avatar.png`} + /> +
    - - { viewCount } - - + + {viewCount} + +
    -
     
    +
     
    ) } diff --git a/src/components/document-read-only-page/document-read-only-page.tsx b/src/components/document-read-only-page/document-read-only-page.tsx index 2aa813ccf..273094cce 100644 --- a/src/components/document-read-only-page/document-read-only-page.tsx +++ b/src/components/document-read-only-page/document-read-only-page.tsx @@ -25,7 +25,6 @@ import { LoadingNoteAlert } from './LoadingNoteAlert' import { RendererType } from '../render-page/rendering-message' export const DocumentReadOnlyPage: React.FC = () => { - useTranslation() const { id } = useParams() @@ -39,28 +38,30 @@ export const DocumentReadOnlyPage: React.FC = () => { const noteDetails = useSelector((state: ApplicationState) => state.noteDetails) return ( -
    - - -
    - - +
    + + +
    + +
    - + + -
    ) diff --git a/src/components/editor-page/app-bar/app-bar.tsx b/src/components/editor-page/app-bar/app-bar.tsx index 5f0fd11d5..b050f2bed 100644 --- a/src/components/editor-page/app-bar/app-bar.tsx +++ b/src/components/editor-page/app-bar/app-bar.tsx @@ -36,31 +36,31 @@ export const AppBar: React.FC = ({ mode }) => { const noteFrontmatter = useSelector((state: ApplicationState) => state.noteDetails.frontmatter, equal) return ( - -