diff --git a/.eslintrc b/.eslintrc index b013cd5aa2..6f04225bd0 100644 --- a/.eslintrc +++ b/.eslintrc @@ -25,10 +25,16 @@ "rules": { "eqeqeq": 2, "curly": 2, + "arrow-body-style": ["error", "as-needed"], + "spaced-comment": "error", "object-shorthand": "error", "no-mixed-operators": "off", "no-useless-escape": "off", "es/no-regexp-lookbehind-assertions": "error", + "react/self-closing-comp": ["error", { + "component": true, + "html": true + }], "@typescript-eslint/no-unused-vars": [ "error", { diff --git a/app/actions/definitions/collections.tsx b/app/actions/definitions/collections.tsx index accc602c46..697364032e 100644 --- a/app/actions/definitions/collections.tsx +++ b/app/actions/definitions/collections.tsx @@ -17,9 +17,9 @@ import { createAction } from "~/actions"; import { CollectionSection } from "~/actions/sections"; import history from "~/utils/history"; -const ColorCollectionIcon = ({ collection }: { collection: Collection }) => { - return ; -}; +const ColorCollectionIcon = ({ collection }: { collection: Collection }) => ( + +); export const openCollection = createAction({ name: ({ t }) => t("Open collection"), diff --git a/app/actions/definitions/teams.tsx b/app/actions/definitions/teams.tsx index f5bb08a915..0d0cae66c9 100644 --- a/app/actions/definitions/teams.tsx +++ b/app/actions/definitions/teams.tsx @@ -9,32 +9,28 @@ import { createAction } from "~/actions"; import { ActionContext } from "~/types"; import { TeamSection } from "../sections"; -export const createTeamsList = ({ stores }: { stores: RootStore }) => { - return ( - stores.auth.availableTeams?.map((session) => ({ - id: `switch-${session.id}`, - name: session.name, - analyticsName: "Switch workspace", - section: TeamSection, - keywords: "change switch workspace organization team", - icon: () => ( - - ), - visible: ({ currentTeamId }: ActionContext) => - currentTeamId !== session.id, - perform: () => (window.location.href = session.url), - })) ?? [] - ); -}; +export const createTeamsList = ({ stores }: { stores: RootStore }) => + stores.auth.availableTeams?.map((session) => ({ + id: `switch-${session.id}`, + name: session.name, + analyticsName: "Switch workspace", + section: TeamSection, + keywords: "change switch workspace organization team", + icon: () => ( + + ), + visible: ({ currentTeamId }: ActionContext) => currentTeamId !== session.id, + perform: () => (window.location.href = session.url), + })) ?? []; export const switchTeam = createAction({ name: ({ t }) => t("Switch workspace"), @@ -53,9 +49,8 @@ export const createTeam = createAction({ keywords: "create change switch workspace organization team", section: TeamSection, icon: , - visible: ({ stores, currentTeamId }) => { - return stores.policies.abilities(currentTeamId ?? "").createTeam; - }, + visible: ({ stores, currentTeamId }) => + stores.policies.abilities(currentTeamId ?? "").createTeam, perform: ({ t, event, stores }) => { event?.preventDefault(); event?.stopPropagation(); diff --git a/app/components/CenteredContent.tsx b/app/components/CenteredContent.tsx index 6eb0d9d6f0..7cd5e24d90 100644 --- a/app/components/CenteredContent.tsx +++ b/app/components/CenteredContent.tsx @@ -26,12 +26,10 @@ const Content = styled.div` `}; `; -const CenteredContent: React.FC = ({ children, ...rest }) => { - return ( - - {children} - - ); -}; +const CenteredContent: React.FC = ({ children, ...rest }) => ( + + {children} + +); export default CenteredContent; diff --git a/app/components/CircularProgressBar.tsx b/app/components/CircularProgressBar.tsx index f8ec93d8ad..8c38a3f570 100644 --- a/app/components/CircularProgressBar.tsx +++ b/app/components/CircularProgressBar.tsx @@ -42,7 +42,7 @@ const Circle = ({ style={{ transition: "stroke-dashoffset 0.6s ease 0s", }} - > + /> ); }; diff --git a/app/components/ContextMenu/index.tsx b/app/components/ContextMenu/index.tsx index d0154b1a3d..387ac63b46 100644 --- a/app/components/ContextMenu/index.tsx +++ b/app/components/ContextMenu/index.tsx @@ -37,7 +37,7 @@ export type Placement = | "left-start"; type Props = MenuStateReturn & { - "aria-label": string; + "aria-label"?: string; /** The parent menu state if this is a submenu. */ parentMenuState?: MenuStateReturn; /** Called when the context menu is opened. */ diff --git a/app/components/DocumentBreadcrumb.tsx b/app/components/DocumentBreadcrumb.tsx index d0832f7fb0..89fc5e3a42 100644 --- a/app/components/DocumentBreadcrumb.tsx +++ b/app/components/DocumentBreadcrumb.tsx @@ -131,7 +131,7 @@ const SmallSlash = styled(GoToIcon)` vertical-align: middle; flex-shrink: 0; - fill: ${(props) => props.theme.slate}; + fill: ${(props) => props.theme.textTertiary}; opacity: 0.5; `; diff --git a/app/components/DocumentExplorer.tsx b/app/components/DocumentExplorer.tsx index 4cce1706f3..4a0ccdab7d 100644 --- a/app/components/DocumentExplorer.tsx +++ b/app/components/DocumentExplorer.tsx @@ -63,11 +63,13 @@ function DocumentExplorer({ onSubmit, onSelect, items }: Props) { const VERTICAL_PADDING = 6; const HORIZONTAL_PADDING = 24; - const searchIndex = React.useMemo(() => { - return new FuzzySearch(items, ["title"], { - caseSensitive: false, - }); - }, [items]); + const searchIndex = React.useMemo( + () => + new FuzzySearch(items, ["title"], { + caseSensitive: false, + }), + [items] + ); React.useEffect(() => { if (searchTerm) { @@ -119,9 +121,7 @@ function DocumentExplorer({ onSubmit, onSelect, items }: Props) { setSearchTerm(ev.target.value); }; - const isExpanded = (node: number) => { - return includes(expandedNodes, nodes[node].id); - }; + const isExpanded = (node: number) => includes(expandedNodes, nodes[node].id); const calculateInitialScrollOffset = (itemCount: number) => { if (listRef.current) { @@ -169,9 +169,7 @@ function DocumentExplorer({ onSubmit, onSelect, items }: Props) { return selectedNodeId === nodeId; }; - const hasChildren = (node: number) => { - return nodes[node].children.length > 0; - }; + const hasChildren = (node: number) => nodes[node].children.length > 0; const toggleCollapse = (node: number) => { if (!hasChildren(node)) { @@ -275,13 +273,9 @@ function DocumentExplorer({ onSubmit, onSelect, items }: Props) { inputSearchRef.current?.focus(); }; - const next = () => { - return Math.min(activeNode + 1, nodes.length - 1); - }; + const next = () => Math.min(activeNode + 1, nodes.length - 1); - const prev = () => { - return Math.max(activeNode - 1, 0); - }; + const prev = () => Math.max(activeNode - 1, 0); const handleKeyDown = (ev: React.KeyboardEvent) => { switch (ev.key) { diff --git a/app/components/Editor.tsx b/app/components/Editor.tsx index bd3072c5d3..af09176782 100644 --- a/app/components/Editor.tsx +++ b/app/components/Editor.tsx @@ -116,13 +116,11 @@ function Editor(props: Props, ref: React.RefObject | null) { const results = await documents.searchTitles(term); return sortBy( - results.map((document: Document) => { - return { - title: document.title, - subtitle: , - url: document.url, - }; - }), + results.map((document: Document) => ({ + title: document.title, + subtitle: , + url: document.url, + })), (document) => deburr(document.title) .toLowerCase() diff --git a/app/components/IconPicker.tsx b/app/components/IconPicker.tsx index 1625deb357..eb048ffa84 100644 --- a/app/components/IconPicker.tsx +++ b/app/components/IconPicker.tsx @@ -240,29 +240,27 @@ function IconPicker({ onOpen, onClose, icon, color, onChange }: Props) { aria-label={t("Choose icon")} > - {Object.keys(icons).map((name, index) => { - return ( - onChange(color, name)} - {...menu} - > - {(props) => ( - - - - )} - - ); - })} + {Object.keys(icons).map((name, index) => ( + onChange(color, name)} + {...menu} + > + {(props) => ( + + + + )} + + ))} void; }; -const getOptionFromValue = (options: Option[], value: string | null) => { - return options.find((option) => option.value === value); -}; +const getOptionFromValue = (options: Option[], value: string | null) => + options.find((option) => option.value === value); const InputSelect = (props: Props) => { const { diff --git a/app/components/List/Placeholder.tsx b/app/components/List/Placeholder.tsx index 98d352f931..9f7fe76af3 100644 --- a/app/components/List/Placeholder.tsx +++ b/app/components/List/Placeholder.tsx @@ -14,18 +14,16 @@ type Props = { body?: PlaceholderTextProps; }; -const Placeholder = ({ count, className, header, body }: Props) => { - return ( - - {times(count || 2, (index) => ( - - - - - ))} - - ); -}; +const Placeholder = ({ count, className, header, body }: Props) => ( + + {times(count || 2, (index) => ( + + + + + ))} + +); const Item = styled(Flex)` padding: 10px 0; diff --git a/app/components/LoadingIndicator/LoadingIndicatorBar.tsx b/app/components/LoadingIndicator/LoadingIndicatorBar.tsx index ab1bedce30..95d0a1e426 100644 --- a/app/components/LoadingIndicator/LoadingIndicatorBar.tsx +++ b/app/components/LoadingIndicator/LoadingIndicatorBar.tsx @@ -2,13 +2,11 @@ import * as React from "react"; import styled, { keyframes } from "styled-components"; import { depths, s } from "@shared/styles"; -const LoadingIndicatorBar = () => { - return ( - - - - ); -}; +const LoadingIndicatorBar = () => ( + + + +); const loadingFrame = keyframes` from { margin-left: -100%; } diff --git a/app/components/Notice.tsx b/app/components/Notice.tsx index 901bb88dde..347afc01bb 100644 --- a/app/components/Notice.tsx +++ b/app/components/Notice.tsx @@ -9,24 +9,22 @@ type Props = { description?: JSX.Element; }; -const Notice: React.FC = ({ children, icon, description }) => { - return ( - - - {icon} - - {children} - {description && ( - <> -
- {description} - - )} -
-
-
- ); -}; +const Notice: React.FC = ({ children, icon, description }) => ( + + + {icon} + + {children} + {description && ( + <> +
+ {description} + + )} +
+
+
+); const Title = styled.span` font-weight: 500; diff --git a/app/components/NoticeAlert.tsx b/app/components/NoticeAlert.tsx deleted file mode 100644 index 35d2b10338..0000000000 --- a/app/components/NoticeAlert.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import * as React from "react"; -import Notice from "~/components/Notice"; - -const NoticeAlert: React.FC = ({ children }) => { - return ( - - - - {" "} - {children} - - ); -}; - -export default NoticeAlert; diff --git a/app/components/Scene.tsx b/app/components/Scene.tsx index 9aa83b2ff4..90ade8202e 100644 --- a/app/components/Scene.tsx +++ b/app/components/Scene.tsx @@ -21,32 +21,30 @@ const Scene: React.FC = ({ left, children, centered, -}) => { - return ( - - -
- {icon} {title} - - ) : ( - title - ) - } - actions={actions} - left={left} - /> - {centered !== false ? ( - {children} - ) : ( - children - )} - - ); -}; +}) => ( + + +
+ {icon} {title} + + ) : ( + title + ) + } + actions={actions} + left={left} + /> + {centered !== false ? ( + {children} + ) : ( + children + )} + +); const FillWidth = styled.div` width: 100%; diff --git a/app/components/SearchPopover.tsx b/app/components/SearchPopover.tsx index 64ca889775..27f9c83456 100644 --- a/app/components/SearchPopover.tsx +++ b/app/components/SearchPopover.tsx @@ -158,21 +158,19 @@ function SearchPopover({ shareId }: Props) { return ( <> - {(props) => { + {(props) => ( // props assumes the disclosure is a button, but we want a type-ahead // so we take the aria props, and ref and ignore the event handlers - return ( - - ); - }} + + )} { - return item.id !== orderedCollections[0].id; - }, + canDrop: (item) => item.id !== orderedCollections[0].id, collect: (monitor) => ({ isCollectionDropping: monitor.isOver(), isDraggingAnyCollection: monitor.getItemType() === "collection", diff --git a/app/components/Sidebar/components/DocumentLink.tsx b/app/components/Sidebar/components/DocumentLink.tsx index b84fa81a03..2374d0dae1 100644 --- a/app/components/Sidebar/components/DocumentLink.tsx +++ b/app/components/Sidebar/components/DocumentLink.tsx @@ -76,18 +76,20 @@ function InnerDocumentLink( [collection, node] ); - const showChildren = React.useMemo(() => { - return !!( - hasChildDocuments && - activeDocument && - collection && - (collection - .pathToDocument(activeDocument.id) - .map((entry) => entry.id) - .includes(node.id) || - isActiveDocument) - ); - }, [hasChildDocuments, activeDocument, isActiveDocument, node, collection]); + const showChildren = React.useMemo( + () => + !!( + hasChildDocuments && + activeDocument && + collection && + (collection + .pathToDocument(activeDocument.id) + .map((entry) => entry.id) + .includes(node.id) || + isActiveDocument) + ), + [hasChildDocuments, activeDocument, isActiveDocument, node, collection] + ); const [expanded, setExpanded] = React.useState(showChildren); diff --git a/app/components/Sidebar/components/DraggableCollectionLink.tsx b/app/components/Sidebar/components/DraggableCollectionLink.tsx index 54d1eb9aac..ad85fcd487 100644 --- a/app/components/Sidebar/components/DraggableCollectionLink.tsx +++ b/app/components/Sidebar/components/DraggableCollectionLink.tsx @@ -56,12 +56,9 @@ function DraggableCollectionLink({ fractionalIndex(collection.index, belowCollectionIndex) ); }, - canDrop: (item) => { - return ( - collection.id !== item.id && - (!belowCollection || item.id !== belowCollection.id) - ); - }, + canDrop: (item) => + collection.id !== item.id && + (!belowCollection || item.id !== belowCollection.id), collect: (monitor: DropTargetMonitor) => ({ isCollectionDropping: monitor.isOver(), isDraggingAnyCollection: monitor.canDrop(), diff --git a/app/components/Sidebar/components/NavLink.tsx b/app/components/Sidebar/components/NavLink.tsx index 5b83122179..16b5cfcc41 100644 --- a/app/components/Sidebar/components/NavLink.tsx +++ b/app/components/Sidebar/components/NavLink.tsx @@ -21,15 +21,13 @@ const resolveToLocation = ( const normalizeToLocation = ( to: LocationDescriptor, currentLocation: Location -) => { - return typeof to === "string" +) => + typeof to === "string" ? createLocation(to, null, undefined, currentLocation) : to; -}; -const joinClassnames = (...classnames: (string | undefined)[]) => { - return classnames.filter((i) => i).join(" "); -}; +const joinClassnames = (...classnames: (string | undefined)[]) => + classnames.filter((i) => i).join(" "); export type Props = React.AnchorHTMLAttributes & { activeClassName?: string; @@ -103,16 +101,13 @@ const NavLink = ({ }, [linkRef, scrollIntoViewIfNeeded, isActive]); const shouldFastClick = React.useCallback( - (event: React.MouseEvent): boolean => { - return ( - event.button === 0 && // Only intercept left clicks - !event.defaultPrevented && - !rest.target && - !event.altKey && - !event.metaKey && - !event.ctrlKey - ); - }, + (event: React.MouseEvent): boolean => + event.button === 0 && // Only intercept left clicks + !event.defaultPrevented && + !rest.target && + !event.altKey && + !event.metaKey && + !event.ctrlKey, [rest.target] ); @@ -153,7 +148,7 @@ const NavLink = ({ { if (["Enter", " "].includes(event.key)) { navigateTo(); diff --git a/app/components/Sidebar/components/SharedDocumentLink.tsx b/app/components/Sidebar/components/SharedDocumentLink.tsx index 938fcb64be..311ea762cf 100644 --- a/app/components/Sidebar/components/SharedDocumentLink.tsx +++ b/app/components/Sidebar/components/SharedDocumentLink.tsx @@ -42,9 +42,9 @@ function DocumentLink( !!node.children.length || activeDocument?.parentDocumentId === node.id; const document = documents.get(node.id); - const showChildren = React.useMemo(() => { - return !!hasChildDocuments; - }, [hasChildDocuments]); + const showChildren = React.useMemo(() => !!hasChildDocuments, [ + hasChildDocuments, + ]); const [expanded, setExpanded] = React.useState(showChildren); @@ -111,9 +111,7 @@ function DocumentLink( scrollIntoViewIfNeeded={!document?.isStarred} isDraft={isDraft} ref={ref} - isActive={() => { - return !!isActiveDocument; - }} + isActive={() => !!isActiveDocument} /> {expanded && nodeChildren.map((childNode, index) => ( diff --git a/app/components/Sidebar/components/Starred.tsx b/app/components/Sidebar/components/Starred.tsx index da4d79d02d..3871a1732b 100644 --- a/app/components/Sidebar/components/Starred.tsx +++ b/app/components/Sidebar/components/Starred.tsx @@ -6,7 +6,6 @@ import { useTranslation } from "react-i18next"; import Star from "~/models/Star"; import Flex from "~/components/Flex"; import useStores from "~/hooks/useStores"; -import useToasts from "~/hooks/useToasts"; import DropCursor from "./DropCursor"; import Header from "./Header"; import PlaceholderCollections from "./PlaceholderCollections"; @@ -22,7 +21,6 @@ function Starred() { const [displayedStarsCount, setDisplayedStarsCount] = React.useState( STARRED_PAGINATION_LIMIT ); - const { showToast } = useToasts(); const { stars } = useStores(); const { t } = useTranslation(); @@ -34,13 +32,10 @@ function Starred() { offset, }); } catch (error) { - showToast(t("Starred documents could not be loaded"), { - type: "error", - }); setFetchError(error); } }, - [stars, showToast, t] + [stars] ); React.useEffect(() => { diff --git a/app/components/Spinner.tsx b/app/components/Spinner.tsx index ef59b2a7c9..b1c1c30660 100644 --- a/app/components/Spinner.tsx +++ b/app/components/Spinner.tsx @@ -22,7 +22,7 @@ export default function Spinner({ color, ...props }: Props) { cx="8" cy="8" r="6" - > + /> ); } diff --git a/app/components/Squircle.tsx b/app/components/Squircle.tsx index 880d36809c..c3fb26ca36 100644 --- a/app/components/Squircle.tsx +++ b/app/components/Squircle.tsx @@ -7,23 +7,21 @@ type Props = { color?: string; }; -const Squircle: React.FC = ({ color, size = 28, children }) => { - return ( - - - - - {children} - - ); -}; +const Squircle: React.FC = ({ color, size = 28, children }) => ( + + + + + {children} + +); const Wrapper = styled(Flex)` position: relative; diff --git a/app/components/Subheading.tsx b/app/components/Subheading.tsx index 4a402a2c83..686e6478a2 100644 --- a/app/components/Subheading.tsx +++ b/app/components/Subheading.tsx @@ -34,14 +34,12 @@ const Background = styled.div<{ sticky?: boolean }>` z-index: 1; `; -const Subheading: React.FC = ({ children, sticky, ...rest }) => { - return ( - -

- {children} -

-
- ); -}; +const Subheading: React.FC = ({ children, sticky, ...rest }) => ( + +

+ {children} +

+
+); export default Subheading; diff --git a/app/components/Tab.tsx b/app/components/Tab.tsx index b020f1e5cd..ff28aa1f8e 100644 --- a/app/components/Tab.tsx +++ b/app/components/Tab.tsx @@ -17,6 +17,7 @@ const TabLink = styled(NavLink)` font-size: 14px; cursor: var(--pointer); color: ${s("textTertiary")}; + user-select: none; margin-right: 24px; padding: 6px 0; diff --git a/app/components/Table.tsx b/app/components/Table.tsx index a8e9f36af6..e95ddd20f1 100644 --- a/app/components/Table.tsx +++ b/app/components/Table.tsx @@ -195,23 +195,21 @@ export const Placeholder = ({ }: { columns: number; rows?: number; -}) => { - return ( - - - {new Array(rows).fill(1).map((_, row) => ( - - {new Array(columns).fill(1).map((_, col) => ( - - - - ))} - - ))} - - - ); -}; +}) => ( + + + {new Array(rows).fill(1).map((_, row) => ( + + {new Array(columns).fill(1).map((_, col) => ( + + + + ))} + + ))} + + +); const Anchor = styled.div` top: -32px; diff --git a/app/components/Toast.tsx b/app/components/Toast.tsx index a2f9bb3390..6e6dfca4ef 100644 --- a/app/components/Toast.tsx +++ b/app/components/Toast.tsx @@ -61,8 +61,9 @@ function Toast({ closeAfterMs = 3000, onRequestClose, toast }: Props) { {type === "loading" && } {type === "info" && } {type === "success" && } - {type === "warning" || - (type === "error" && )} + {(type === "warning" || type === "error") && ( + + )} {toast.message} {action && {action.text}} diff --git a/app/editor/components/BlockMenu.tsx b/app/editor/components/BlockMenu.tsx index 7cca6e5f58..aca9af54d2 100644 --- a/app/editor/components/BlockMenu.tsx +++ b/app/editor/components/BlockMenu.tsx @@ -30,7 +30,7 @@ function BlockMenu(props: Props) { return ( ( { + boundary: (parent) => // Prevents body and other parent elements from being scrolled - return parent !== containerRef.current; - }, + parent !== containerRef.current, }); } }, diff --git a/app/editor/components/SuggestionsMenu.tsx b/app/editor/components/SuggestionsMenu.tsx index ff126b4b57..743f59e2b3 100644 --- a/app/editor/components/SuggestionsMenu.tsx +++ b/app/editor/components/SuggestionsMenu.tsx @@ -397,11 +397,9 @@ function SuggestionsMenu(props: Props) { }); return filterExcessSeparators( - filtered.sort((item) => { - return searchInput && item.title - ? commandScore(item.title, searchInput) - : 0; - }) + filtered.sort((item) => + searchInput && item.title ? commandScore(item.title, searchInput) : 0 + ) ); }, [commands, props]); diff --git a/app/editor/components/SuggestionsMenuItem.tsx b/app/editor/components/SuggestionsMenuItem.tsx index 426a9443bb..b45fab8844 100644 --- a/app/editor/components/SuggestionsMenuItem.tsx +++ b/app/editor/components/SuggestionsMenuItem.tsx @@ -28,12 +28,11 @@ function SuggestionsMenuItem({ scrollIntoView(node, { scrollMode: "if-needed", block: "nearest", - boundary: (parent) => { + boundary: (parent) => // All the parent elements of your target are checked until they // reach the portal context. Prevents body and other parent // elements from being scrolled - return parent !== portal; - }, + parent !== portal, }); } }, diff --git a/app/editor/index.tsx b/app/editor/index.tsx index 607fbc14e7..a15ed08d8a 100644 --- a/app/editor/index.tsx +++ b/app/editor/index.tsx @@ -355,8 +355,8 @@ export class Editor extends React.PureComponent< decorations: Decoration<{ [key: string]: any; }>[] - ) => { - return new ComponentView(extension.component, { + ) => + new ComponentView(extension.component, { editor: this, extension, node, @@ -364,7 +364,6 @@ export class Editor extends React.PureComponent< getPos, decorations, }); - }; return { ...nodeViews, @@ -449,13 +448,12 @@ export class Editor extends React.PureComponent< throw new Error("createView called before ref available"); } - const isEditingCheckbox = (tr: Transaction) => { - return tr.steps.some( + const isEditingCheckbox = (tr: Transaction) => + tr.steps.some( (step: any) => step.slice?.content?.firstChild?.type.name === this.schema.nodes.checkbox_item.name ); - }; const self = this; // eslint-disable-line const view = new EditorView(this.elementRef.current, { @@ -579,36 +577,28 @@ export class Editor extends React.PureComponent< * * @returns True if the editor is empty */ - public isEmpty = () => { - return ProsemirrorHelper.isEmpty(this.view.state.doc); - }; + public isEmpty = () => ProsemirrorHelper.isEmpty(this.view.state.doc); /** * Return the headings in the current editor. * * @returns A list of headings in the document */ - public getHeadings = () => { - return ProsemirrorHelper.getHeadings(this.view.state.doc); - }; + public getHeadings = () => ProsemirrorHelper.getHeadings(this.view.state.doc); /** * Return the tasks/checkmarks in the current editor. * * @returns A list of tasks in the document */ - public getTasks = () => { - return ProsemirrorHelper.getTasks(this.view.state.doc); - }; + public getTasks = () => ProsemirrorHelper.getTasks(this.view.state.doc); /** * Return the comments in the current editor. * * @returns A list of comments in the document */ - public getComments = () => { - return ProsemirrorHelper.getComments(this.view.state.doc); - }; + public getComments = () => ProsemirrorHelper.getComments(this.view.state.doc); /** * Remove a specific comment mark from the document. @@ -661,9 +651,9 @@ export class Editor extends React.PureComponent< return; } - this.props.onChange((asString = true, trim = false) => { - return this.view ? this.value(asString, trim) : undefined; - }); + this.props.onChange((asString = true, trim = false) => + this.view ? this.value(asString, trim) : undefined + ); }; private handleEditorBlur = () => { @@ -835,13 +825,11 @@ const EditorContainer = styled(Styles)<{ focusedCommentId?: string }>` `; const LazyLoadedEditor = React.forwardRef( - (props: Props, ref) => { - return ( - - {(theme) => } - - ); - } + (props: Props, ref) => ( + + {(theme) => } + + ) ); export default LazyLoadedEditor; diff --git a/app/hooks/useBuildTheme.ts b/app/hooks/useBuildTheme.ts index c629309fa4..7a2fc9b9a8 100644 --- a/app/hooks/useBuildTheme.ts +++ b/app/hooks/useBuildTheme.ts @@ -21,17 +21,19 @@ export default function useBuildTheme(customTheme: Partial = {}) { const isMobile = useMediaQuery(`(max-width: ${breakpoints.tablet}px)`); const isPrinting = useMediaQuery("print"); - const theme = React.useMemo(() => { - return isPrinting - ? buildLightTheme(customTheme) - : isMobile - ? ui.resolvedTheme === "dark" - ? buildPitchBlackTheme(customTheme) - : buildLightTheme(customTheme) - : ui.resolvedTheme === "dark" - ? buildDarkTheme(customTheme) - : buildLightTheme(customTheme); - }, [customTheme, isMobile, isPrinting, ui.resolvedTheme]); + const theme = React.useMemo( + () => + isPrinting + ? buildLightTheme(customTheme) + : isMobile + ? ui.resolvedTheme === "dark" + ? buildPitchBlackTheme(customTheme) + : buildLightTheme(customTheme) + : ui.resolvedTheme === "dark" + ? buildDarkTheme(customTheme) + : buildLightTheme(customTheme), + [customTheme, isMobile, isPrinting, ui.resolvedTheme] + ); return theme; } diff --git a/app/hooks/useDictionary.ts b/app/hooks/useDictionary.ts index 088d40e71a..737986091b 100644 --- a/app/hooks/useDictionary.ts +++ b/app/hooks/useDictionary.ts @@ -4,8 +4,8 @@ import { useTranslation } from "react-i18next"; export default function useDictionary() { const { t } = useTranslation(); - return React.useMemo(() => { - return { + return React.useMemo( + () => ({ addColumnAfter: t("Insert column after"), addColumnBefore: t("Insert column before"), addRowAfter: t("Insert row after"), @@ -79,8 +79,9 @@ export default function useDictionary() { insertDate: t("Current date"), insertTime: t("Current time"), insertDateTime: t("Current date and time"), - }; - }, [t]); + }), + [t] + ); } export type Dictionary = ReturnType; diff --git a/app/hooks/useSettingsActions.tsx b/app/hooks/useSettingsActions.tsx index dda958c171..2359cd3c73 100644 --- a/app/hooks/useSettingsActions.tsx +++ b/app/hooks/useSettingsActions.tsx @@ -7,18 +7,20 @@ import useSettingsConfig from "./useSettingsConfig"; const useSettingsActions = () => { const config = useSettingsConfig(); - const actions = React.useMemo(() => { - return config.map((item) => { - const Icon = item.icon; - return { - id: item.path, - name: item.name, - icon: , - section: NavigationSection, - perform: () => history.push(item.path), - }; - }); - }, [config]); + const actions = React.useMemo( + () => + config.map((item) => { + const Icon = item.icon; + return { + id: item.path, + name: item.name, + icon: , + section: NavigationSection, + perform: () => history.push(item.path), + }; + }), + [config] + ); const navigateToSettings = React.useMemo( () => diff --git a/app/hooks/useSettingsConfig.ts b/app/hooks/useSettingsConfig.ts index e8258a314a..6b63596ee9 100644 --- a/app/hooks/useSettingsConfig.ts +++ b/app/hooks/useSettingsConfig.ts @@ -160,16 +160,18 @@ const useSettingsConfig = () => { icon: ExportIcon, }, // Integrations - ...mapValues(PluginLoader.plugins, (plugin) => { - return { - name: plugin.config.name, - path: integrationSettingsPath(plugin.id), - group: t("Integrations"), - component: plugin.settings, - enabled: !!plugin.settings && can.update, - icon: plugin.icon, - } as ConfigItem; - }), + ...mapValues( + PluginLoader.plugins, + (plugin) => + ({ + name: plugin.config.name, + path: integrationSettingsPath(plugin.id), + group: t("Integrations"), + component: plugin.settings, + enabled: !!plugin.settings && can.update, + icon: plugin.icon, + } as ConfigItem) + ), SelfHosted: { name: t("Self Hosted"), path: integrationSettingsPath("self-hosted"), diff --git a/app/hooks/useUnmount.ts b/app/hooks/useUnmount.ts index 57fa64691b..5be355e00c 100644 --- a/app/hooks/useUnmount.ts +++ b/app/hooks/useUnmount.ts @@ -4,11 +4,12 @@ const useUnmount = (callback: (...args: Array) => any) => { const ref = React.useRef(callback); ref.current = callback; - React.useEffect(() => { - return () => { + React.useEffect( + () => () => { ref.current(); - }; - }, []); + }, + [] + ); }; export default useUnmount; diff --git a/app/menus/AccountMenu.tsx b/app/menus/AccountMenu.tsx index 88970b297e..9f1e4e20c6 100644 --- a/app/menus/AccountMenu.tsx +++ b/app/menus/AccountMenu.tsx @@ -36,8 +36,8 @@ const AccountMenu: React.FC = ({ children }) => { } }, [menu, theme, previousTheme]); - const actions = React.useMemo(() => { - return [ + const actions = React.useMemo( + () => [ openKeyboardShortcuts, downloadApp, openAPIDocumentation, @@ -50,8 +50,9 @@ const AccountMenu: React.FC = ({ children }) => { navigateToAccountPreferences, separator(), logout, - ]; - }, []); + ], + [] + ); return ( <> diff --git a/app/menus/ApiKeyMenu.tsx b/app/menus/ApiKeyMenu.tsx new file mode 100644 index 0000000000..1681138fd6 --- /dev/null +++ b/app/menus/ApiKeyMenu.tsx @@ -0,0 +1,52 @@ +import { observer } from "mobx-react"; +import * as React from "react"; +import { useTranslation } from "react-i18next"; +import { useMenuState } from "reakit/Menu"; +import ApiKey from "~/models/ApiKey"; +import TokenRevokeDialog from "~/scenes/Settings/components/TokenRevokeDialog"; +import ContextMenu from "~/components/ContextMenu"; +import MenuItem from "~/components/ContextMenu/MenuItem"; +import OverflowMenuButton from "~/components/ContextMenu/OverflowMenuButton"; +import useStores from "~/hooks/useStores"; + +type Props = { + /** The apiKey to associate with the menu */ + token: ApiKey; + /** CSS class name */ + className?: string; +}; + +function ApiKeyMenu({ token, className }: Props) { + const menu = useMenuState({ + modal: true, + }); + const { dialogs } = useStores(); + const { t } = useTranslation(); + + const handleRevoke = React.useCallback(() => { + dialogs.openModal({ + title: t("Revoke token"), + isCentered: true, + content: ( + + ), + }); + }, [t, dialogs, token]); + + return ( + <> + + + + {t("Revoke")} + + + + ); +} + +export default observer(ApiKeyMenu); diff --git a/app/menus/OrganizationMenu.tsx b/app/menus/OrganizationMenu.tsx index 06beb149f7..fa3fba8b71 100644 --- a/app/menus/OrganizationMenu.tsx +++ b/app/menus/OrganizationMenu.tsx @@ -31,15 +31,16 @@ const OrganizationMenu: React.FC = ({ children }) => { // NOTE: it's useful to memoize on the team id and session because the action // menu is not cached at all. - const actions = React.useMemo(() => { - return [ + const actions = React.useMemo( + () => [ ...createTeamsList(context), createTeam, separator(), navigateToSettings, logout, - ]; - }, [context]); + ], + [context] + ); return ( <> diff --git a/app/models/BaseModel.ts b/app/models/BaseModel.ts index 7176034da7..d423a728cf 100644 --- a/app/models/BaseModel.ts +++ b/app/models/BaseModel.ts @@ -59,20 +59,17 @@ export default abstract class BaseModel { }; updateFromJson = (data: any) => { - //const isNew = !data.id && !this.id && this.isNew; + // const isNew = !data.id && !this.id && this.isNew; set(this, { ...data, isNew: false }); this.persistedAttributes = this.toAPI(); }; - fetch = (options?: any) => { - return this.store.fetch(this.id, options); - }; + fetch = (options?: any) => this.store.fetch(this.id, options); - refresh = () => { - return this.fetch({ + refresh = () => + this.fetch({ force: true, }); - }; delete = async () => { this.isSaving = true; diff --git a/app/models/Collection.ts b/app/models/Collection.ts index 4c0461910f..932c9b2781 100644 --- a/app/models/Collection.ts +++ b/app/models/Collection.ts @@ -209,19 +209,14 @@ export default class Collection extends ParanoidModel { } @action - star = async () => { - return this.store.star(this); - }; + star = async () => this.store.star(this); @action - unstar = async () => { - return this.store.unstar(this); - }; + unstar = async () => this.store.unstar(this); - export = (format: FileOperationFormat) => { - return client.post("/collections.export", { + export = (format: FileOperationFormat) => + client.post("/collections.export", { id: this.id, format, }); - }; } diff --git a/app/models/Document.ts b/app/models/Document.ts index 28f68b2a62..d4b8c68c24 100644 --- a/app/models/Document.ts +++ b/app/models/Document.ts @@ -238,23 +238,17 @@ export default class Document extends ParanoidModel { } @action - share = async () => { - return this.store.rootStore.shares.create({ + share = async () => + this.store.rootStore.shares.create({ documentId: this.id, }); - }; - archive = () => { - return this.store.archive(this); - }; + archive = () => this.store.archive(this); - restore = (options?: { revisionId?: string; collectionId?: string }) => { - return this.store.restore(this, options); - }; + restore = (options?: { revisionId?: string; collectionId?: string }) => + this.store.restore(this, options); - unpublish = () => { - return this.store.unpublish(this); - }; + unpublish = () => this.store.unpublish(this); @action enableEmbeds = () => { @@ -267,12 +261,11 @@ export default class Document extends ParanoidModel { }; @action - pin = (collectionId?: string) => { - return this.store.rootStore.pins.create({ + pin = (collectionId?: string) => + this.store.rootStore.pins.create({ documentId: this.id, ...(collectionId ? { collectionId } : {}), }); - }; @action unpin = (collectionId?: string) => { @@ -287,14 +280,10 @@ export default class Document extends ParanoidModel { }; @action - star = () => { - return this.store.star(this); - }; + star = () => this.store.star(this); @action - unstar = () => { - return this.store.unstar(this); - }; + unstar = () => this.store.unstar(this); /** * Subscribes the current user to this document. @@ -302,9 +291,7 @@ export default class Document extends ParanoidModel { * @returns A promise that resolves when the subscription is created. */ @action - subscribe = () => { - return this.store.subscribe(this); - }; + subscribe = () => this.store.subscribe(this); /** * Unsubscribes the current user to this document. @@ -312,9 +299,7 @@ export default class Document extends ParanoidModel { * @returns A promise that resolves when the subscription is destroyed. */ @action - unsubscribe = (userId: string) => { - return this.store.unsubscribe(userId, this); - }; + unsubscribe = (userId: string) => this.store.unsubscribe(userId, this); @action view = () => { @@ -336,9 +321,7 @@ export default class Document extends ParanoidModel { }; @action - templatize = () => { - return this.store.templatize(this.id); - }; + templatize = () => this.store.templatize(this.id); @action save = async (options?: SaveOptions | undefined) => { @@ -359,13 +342,10 @@ export default class Document extends ParanoidModel { } }; - move = (collectionId: string, parentDocumentId?: string | undefined) => { - return this.store.move(this.id, collectionId, parentDocumentId); - }; + move = (collectionId: string, parentDocumentId?: string | undefined) => + this.store.move(this.id, collectionId, parentDocumentId); - duplicate = () => { - return this.store.duplicate(this); - }; + duplicate = () => this.store.duplicate(this); getSummary = (paragraphs = 4) => { const result = this.text.trim().split("\n").slice(0, paragraphs).join("\n"); @@ -405,8 +385,8 @@ export default class Document extends ParanoidModel { }; } - download = (contentType: ExportContentType) => { - return client.post( + download = (contentType: ExportContentType) => + client.post( `/documents.export`, { id: this.id, @@ -418,5 +398,4 @@ export default class Document extends ParanoidModel { }, } ); - }; } diff --git a/app/models/User.ts b/app/models/User.ts index be5268adbc..3abe065d4e 100644 --- a/app/models/User.ts +++ b/app/models/User.ts @@ -90,13 +90,8 @@ class User extends ParanoidModel { * @param type The type of notification event * @returns The current preference */ - public subscribedToEventType = (type: NotificationEventType) => { - return ( - this.notificationSettings[type] ?? - NotificationEventDefaults[type] ?? - false - ); - }; + public subscribedToEventType = (type: NotificationEventType) => + this.notificationSettings[type] ?? NotificationEventDefaults[type] ?? false; /** * Sets a preference for the users notification settings on the model and diff --git a/app/models/decorators/Field.ts b/app/models/decorators/Field.ts index 4dc12abc85..5dabf8b873 100644 --- a/app/models/decorators/Field.ts +++ b/app/models/decorators/Field.ts @@ -1,8 +1,7 @@ const fields = new Map(); -export const getFieldsForModel = (target: any) => { - return fields.get(target.constructor.name); -}; +export const getFieldsForModel = (target: any) => + fields.get(target.constructor.name); /** * A decorator that records this key as a serializable field on the model. diff --git a/app/scenes/Document/components/CommentEditor.tsx b/app/scenes/Document/components/CommentEditor.tsx index 737abfbac4..de9e8e70c9 100644 --- a/app/scenes/Document/components/CommentEditor.tsx +++ b/app/scenes/Document/components/CommentEditor.tsx @@ -8,8 +8,6 @@ const extensions = withComments(basicExtensions); const CommentEditor = ( props: EditorProps, ref: React.RefObject -) => { - return ; -}; +) => ; export default React.forwardRef(CommentEditor); diff --git a/app/scenes/Document/components/CommentThread.tsx b/app/scenes/Document/components/CommentThread.tsx index c8707e8c3c..21d7253715 100644 --- a/app/scenes/Document/components/CommentThread.tsx +++ b/app/scenes/Document/components/CommentThread.tsx @@ -114,10 +114,9 @@ function CommentThread({ scrollMode: "if-needed", behavior: "smooth", block: "start", - boundary: (parent) => { + boundary: (parent) => // Prevents body and other parent elements from being scrolled - return parent.id !== "comments"; - }, + parent.id !== "comments", }); }, isVisible ? 0 : sidebarAppearDuration diff --git a/app/scenes/Document/components/MultiplayerEditor.tsx b/app/scenes/Document/components/MultiplayerEditor.tsx index 7ff74a7025..dc3992f5d6 100644 --- a/app/scenes/Document/components/MultiplayerEditor.tsx +++ b/app/scenes/Document/components/MultiplayerEditor.tsx @@ -185,13 +185,14 @@ function MultiplayerEditor({ onSynced, ...props }: Props, ref: any) { isMounted, ]); - const user = React.useMemo(() => { - return { + const user = React.useMemo( + () => ({ id: currentUser.id, name: currentUser.name, color: currentUser.color, - }; - }, [currentUser.id, currentUser.color, currentUser.name]); + }), + [currentUser.id, currentUser.color, currentUser.name] + ); const extensions = React.useMemo(() => { if (!remoteProvider) { diff --git a/app/scenes/Document/components/PublicBreadcrumb.tsx b/app/scenes/Document/components/PublicBreadcrumb.tsx index 639c624a87..e25d4a24fb 100644 --- a/app/scenes/Document/components/PublicBreadcrumb.tsx +++ b/app/scenes/Document/components/PublicBreadcrumb.tsx @@ -49,13 +49,11 @@ const PublicBreadcrumb: React.FC = ({ () => pathToDocument(sharedTree, documentId) .slice(0, -1) - .map((item) => { - return { - ...item, - type: "route", - to: sharedDocumentPath(shareId, item.url), - }; - }), + .map((item) => ({ + ...item, + type: "route", + to: sharedDocumentPath(shareId, item.url), + })), [sharedTree, shareId, documentId] ); diff --git a/app/scenes/Document/index.tsx b/app/scenes/Document/index.tsx index 211431cce6..6f42bddea5 100644 --- a/app/scenes/Document/index.tsx +++ b/app/scenes/Document/index.tsx @@ -30,9 +30,7 @@ export default function DocumentScene(props: Props) { setLastVisitedPath(currentPath); }, [currentPath, setLastVisitedPath]); - React.useEffect(() => { - return () => ui.clearActiveDocument(); - }, [ui]); + React.useEffect(() => () => ui.clearActiveDocument(), [ui]); // the urlId portion of the url does not include the slugified title // we only want to force a re-mount of the document component when the diff --git a/app/scenes/Login/Notices.tsx b/app/scenes/Login/Notices.tsx index d25166e0a9..3d5aaee1f1 100644 --- a/app/scenes/Login/Notices.tsx +++ b/app/scenes/Login/Notices.tsx @@ -1,6 +1,7 @@ +import { WarningIcon } from "outline-icons"; import * as React from "react"; import { Trans } from "react-i18next"; -import NoticeAlert from "~/components/NoticeAlert"; +import Notice from "~/components/Notice"; import useQuery from "~/hooks/useQuery"; export default function Notices() { @@ -13,7 +14,7 @@ export default function Notices() { } return ( - + }> {notice === "domain-required" && ( Unable to sign-in. Please navigate to your team's custom URL, then try @@ -103,6 +104,6 @@ export default function Notices() { team domain. )} - + ); } diff --git a/app/scenes/Settings/Groups.tsx b/app/scenes/Settings/Groups.tsx index 14b83aacce..e77cc7f0d9 100644 --- a/app/scenes/Settings/Groups.tsx +++ b/app/scenes/Settings/Groups.tsx @@ -12,7 +12,6 @@ import Heading from "~/components/Heading"; import Modal from "~/components/Modal"; import PaginatedList from "~/components/PaginatedList"; import Scene from "~/components/Scene"; -import Subheading from "~/components/Subheading"; import Text from "~/components/Text"; import useBoolean from "~/hooks/useBoolean"; import useCurrentTeam from "~/hooks/useCurrentTeam"; @@ -57,11 +56,15 @@ function Groups() { Groups can be used to organize and manage the people on your team. - {t("All groups")} {t("No groups have been created yet")}} fetch={groups.fetchPage} + heading={ +

+ All +

+ } renderItem={(item: Group) => ( , title: t("Document published"), description: t( "Receive a notification whenever a new document is published" @@ -31,6 +43,7 @@ function Notifications() { }, { event: NotificationEventType.UpdateDocument, + icon: , title: t("Document updated"), description: t( "Receive a notification when a document you are subscribed to is edited" @@ -38,6 +51,7 @@ function Notifications() { }, { event: NotificationEventType.CreateComment, + icon: , title: t("Comment posted"), description: t( "Receive a notification when a document you are subscribed to or a thread you participated in receives a comment" @@ -45,6 +59,7 @@ function Notifications() { }, { event: NotificationEventType.Mentioned, + icon: , title: t("Mentioned"), description: t( "Receive a notification when someone mentions you in a document or comment" @@ -52,6 +67,7 @@ function Notifications() { }, { event: NotificationEventType.CreateCollection, + icon: , title: t("Collection created"), description: t( "Receive a notification whenever a new collection is created" @@ -59,6 +75,7 @@ function Notifications() { }, { event: NotificationEventType.InviteAccepted, + icon: , title: t("Invite accepted"), description: t( "Receive a notification when someone you invited creates an account" @@ -66,6 +83,7 @@ function Notifications() { }, { event: NotificationEventType.ExportCompleted, + icon: , title: t("Export completed"), description: t( "Receive a notification when an export you requested has been completed" @@ -73,12 +91,14 @@ function Notifications() { }, { visible: isCloudHosted, + icon: , event: NotificationEventType.Onboarding, title: t("Getting started"), description: t("Tips on getting started with features and functionality"), }, { visible: isCloudHosted, + icon: , event: NotificationEventType.Features, title: t("New features"), description: t("Receive an email when new features of note are added"), @@ -138,7 +158,11 @@ function Notifications() { return ( + {option.icon} {option.title} + + } name={option.event} description={option.description} > diff --git a/app/scenes/Settings/Tokens.tsx b/app/scenes/Settings/Tokens.tsx index d2a4878e53..8d9195e567 100644 --- a/app/scenes/Settings/Tokens.tsx +++ b/app/scenes/Settings/Tokens.tsx @@ -10,7 +10,6 @@ import Heading from "~/components/Heading"; import Modal from "~/components/Modal"; import PaginatedList from "~/components/PaginatedList"; import Scene from "~/components/Scene"; -import Subheading from "~/components/Subheading"; import Text from "~/components/Text"; import useBoolean from "~/hooks/useBoolean"; import useCurrentTeam from "~/hooks/useCurrentTeam"; @@ -59,7 +58,7 @@ function Tokens() { {t("Tokens")}} + heading={

{t("Active")}

} renderItem={(token: ApiKey) => ( )} diff --git a/app/scenes/Settings/Zapier.tsx b/app/scenes/Settings/Zapier.tsx index 43ffcb5ae0..e633cf9770 100644 --- a/app/scenes/Settings/Zapier.tsx +++ b/app/scenes/Settings/Zapier.tsx @@ -21,7 +21,7 @@ function Zapier() { type="module" src="https://cdn.zapier.com/packages/partner-sdk/v0/zapier-elements/zapier-elements.esm.js" key="zapier-js" - > + /> { const { t } = useTranslation(); const { showToast } = useToasts(); - const { dialogs } = useStores(); const [linkCopied, setLinkCopied] = React.useState(false); React.useEffect(() => { @@ -34,32 +33,20 @@ const TokenListItem = ({ token }: Props) => { }); }, [showToast, t]); - const showRevokeConfirmation = React.useCallback(() => { - dialogs.openModal({ - title: t("Revoke token"), - isCentered: true, - content: ( - - ), - }); - }, [t, dialogs, token]); - return ( {token.secret}} + subtitle={{token.secret.slice(0, 15)}…} actions={ - <> + - - + + } /> ); diff --git a/app/scenes/UserProfile.tsx b/app/scenes/UserProfile.tsx deleted file mode 100644 index 2e95ed360e..0000000000 --- a/app/scenes/UserProfile.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import { formatDistanceToNow } from "date-fns"; -import { observer } from "mobx-react"; -import { EditIcon } from "outline-icons"; -import * as React from "react"; -import { useTranslation } from "react-i18next"; -import { useHistory } from "react-router-dom"; -import styled from "styled-components"; -import User from "~/models/User"; -import Avatar from "~/components/Avatar"; -import Badge from "~/components/Badge"; -import Button from "~/components/Button"; -import Flex from "~/components/Flex"; -import Modal from "~/components/Modal"; -import PaginatedDocumentList from "~/components/PaginatedDocumentList"; -import Subheading from "~/components/Subheading"; -import Text from "~/components/Text"; -import useCurrentUser from "~/hooks/useCurrentUser"; -import useStores from "~/hooks/useStores"; -import { settingsPath } from "~/utils/routeHelpers"; - -type Props = { - user: User; - onRequestClose: () => void; - isOpen: boolean; -}; - -function UserProfile(props: Props) { - const { t } = useTranslation(); - const { documents } = useStores(); - const currentUser = useCurrentUser(); - const history = useHistory(); - const { user, ...rest } = props; - if (!user) { - return null; - } - const isCurrentUser = currentUser.id === user.id; - - return ( - - -  {user.name} - - } - {...rest} - > - - - {isCurrentUser - ? t("You joined") - : user.lastActiveAt - ? t("Joined") - : t("Invited")}{" "} - {t("{{ time }} ago.", { - time: formatDistanceToNow(Date.parse(user.createdAt)), - })} - {user.isAdmin && ( - {t("Admin")} - )} - {user.isSuspended && {t("Suspended")}} - {isCurrentUser && ( - - - - )} - - {t("Recently updated")}} - empty={ - - {t("{{ userName }} hasn’t updated any documents yet.", { - userName: user.name, - })} - - } - showCollection - /> - - - ); -} - -const Edit = styled.span` - position: absolute; - top: 46px; - right: 0; -`; - -const StyledBadge = styled(Badge)` - position: relative; - top: -2px; -`; - -const Meta = styled(Text)` - margin-top: -12px; -`; - -export default observer(UserProfile); diff --git a/app/stores/AuthStore.ts b/app/stores/AuthStore.ts index a075281683..0182e4faeb 100644 --- a/app/stores/AuthStore.ts +++ b/app/stores/AuthStore.ts @@ -223,9 +223,7 @@ export default class AuthStore { }; @action - requestDelete = () => { - return client.post(`/users.requestDelete`); - }; + requestDelete = () => client.post(`/users.requestDelete`); @action deleteUser = async (data: { code: string }) => { @@ -350,5 +348,6 @@ export default class AuthStore { // Tell the host application we logged out, if any – allows window cleanup. Desktop.bridge?.onLogout?.(); + this.rootStore.logout(); }; } diff --git a/app/stores/CollectionsStore.ts b/app/stores/CollectionsStore.ts index 31c1aab30e..e135c0dcbf 100644 --- a/app/stores/CollectionsStore.ts +++ b/app/stores/CollectionsStore.ts @@ -218,9 +218,8 @@ export default class CollectionsStore extends BaseStore { this.rootStore.documents.fetchRecentlyViewed(); }; - export = (format: FileOperationFormat) => { - return client.post("/collections.export_all", { + export = (format: FileOperationFormat) => + client.post("/collections.export_all", { format, }); - }; } diff --git a/app/stores/DocumentsStore.ts b/app/stores/DocumentsStore.ts index ef208aa6da..c6b68fa2a5 100644 --- a/app/stores/DocumentsStore.ts +++ b/app/stores/DocumentsStore.ts @@ -303,81 +303,66 @@ export default class DocumentsStore extends BaseStore { }; @action - fetchArchived = async (options?: PaginationParams): Promise => { - return this.fetchNamedPage("archived", options); - }; + fetchArchived = async (options?: PaginationParams): Promise => + this.fetchNamedPage("archived", options); @action - fetchDeleted = async (options?: PaginationParams): Promise => { - return this.fetchNamedPage("deleted", options); - }; + fetchDeleted = async (options?: PaginationParams): Promise => + this.fetchNamedPage("deleted", options); @action fetchRecentlyUpdated = async ( options?: PaginationParams - ): Promise => { - return this.fetchNamedPage("list", options); - }; + ): Promise => this.fetchNamedPage("list", options); @action - fetchTemplates = async (options?: PaginationParams): Promise => { - return this.fetchNamedPage("list", { ...options, template: true }); - }; + fetchTemplates = async (options?: PaginationParams): Promise => + this.fetchNamedPage("list", { ...options, template: true }); @action - fetchAlphabetical = async ( - options?: PaginationParams - ): Promise => { - return this.fetchNamedPage("list", { + fetchAlphabetical = async (options?: PaginationParams): Promise => + this.fetchNamedPage("list", { sort: "title", direction: "ASC", ...options, }); - }; @action fetchLeastRecentlyUpdated = async ( options?: PaginationParams - ): Promise => { - return this.fetchNamedPage("list", { + ): Promise => + this.fetchNamedPage("list", { sort: "updatedAt", direction: "ASC", ...options, }); - }; @action fetchRecentlyPublished = async ( options?: PaginationParams - ): Promise => { - return this.fetchNamedPage("list", { + ): Promise => + this.fetchNamedPage("list", { sort: "publishedAt", direction: "DESC", ...options, }); - }; @action fetchRecentlyViewed = async ( options?: PaginationParams - ): Promise => { - return this.fetchNamedPage("viewed", options); - }; + ): Promise => this.fetchNamedPage("viewed", options); @action - fetchStarred = (options?: PaginationParams): Promise => { - return this.fetchNamedPage("starred", options); - }; + fetchStarred = (options?: PaginationParams): Promise => + this.fetchNamedPage("starred", options); @action - fetchDrafts = (options?: PaginationParams): Promise => { - return this.fetchNamedPage("drafts", options); - }; + fetchDrafts = (options?: PaginationParams): Promise => + this.fetchNamedPage("drafts", options); @action - fetchOwned = (options?: PaginationParams): Promise => { - return this.fetchNamedPage("list", options); - }; + fetchOwned = (options?: PaginationParams): Promise => + this.fetchNamedPage("list", options); @action searchTitles = async (query: string, options?: SearchParams) => { @@ -778,11 +763,10 @@ export default class DocumentsStore extends BaseStore { }); }; - star = (document: Document) => { - return this.rootStore.stars.create({ + star = (document: Document) => + this.rootStore.stars.create({ documentId: document.id, }); - }; unstar = (document: Document) => { const star = this.rootStore.stars.orderedData.find( @@ -791,12 +775,11 @@ export default class DocumentsStore extends BaseStore { return star?.delete(); }; - subscribe = (document: Document) => { - return this.rootStore.subscriptions.create({ + subscribe = (document: Document) => + this.rootStore.subscriptions.create({ documentId: document.id, event: "documents.update", }); - }; unsubscribe = (userId: string, document: Document) => { const subscription = this.rootStore.subscriptions.orderedData.find( @@ -808,9 +791,8 @@ export default class DocumentsStore extends BaseStore { return subscription?.delete(); }; - getByUrl = (url = ""): Document | undefined => { - return find(this.orderedData, (doc) => url.endsWith(doc.urlId)); - }; + getByUrl = (url = ""): Document | undefined => + find(this.orderedData, (doc) => url.endsWith(doc.urlId)); getCollectionForDocument(document: Document) { return this.rootStore.collections.data.get(document.collectionId); diff --git a/app/stores/GroupMembershipsStore.ts b/app/stores/GroupMembershipsStore.ts index 259429e48f..8681ac907a 100644 --- a/app/stores/GroupMembershipsStore.ts +++ b/app/stores/GroupMembershipsStore.ts @@ -73,7 +73,6 @@ export default class GroupMembershipsStore extends BaseStore { }); }; - inGroup = (groupId: string) => { - return filter(this.orderedData, (member) => member.groupId === groupId); - }; + inGroup = (groupId: string) => + filter(this.orderedData, (member) => member.groupId === groupId); } diff --git a/app/stores/PinsStore.ts b/app/stores/PinsStore.ts index 09c32256a0..956e705ba4 100644 --- a/app/stores/PinsStore.ts +++ b/app/stores/PinsStore.ts @@ -35,11 +35,10 @@ export default class PinsStore extends BaseStore { } }; - inCollection = (collectionId: string) => { - return computed(() => this.orderedData) + inCollection = (collectionId: string) => + computed(() => this.orderedData) .get() .filter((pin) => pin.collectionId === collectionId); - }; @computed get home() { diff --git a/app/stores/RootStore.ts b/app/stores/RootStore.ts index dcd1ee734f..ffea4bbb1d 100644 --- a/app/stores/RootStore.ts +++ b/app/stores/RootStore.ts @@ -87,30 +87,10 @@ export default class RootStore { } logout() { - this.apiKeys.clear(); - this.authenticationProviders.clear(); - // this.auth omitted for reasons... - this.collections.clear(); - this.collectionGroupMemberships.clear(); - this.comments.clear(); - this.documents.clear(); - this.events.clear(); - this.groups.clear(); - this.groupMemberships.clear(); - this.integrations.clear(); - this.memberships.clear(); - this.presence.clear(); - this.pins.clear(); - this.policies.clear(); - this.revisions.clear(); - this.searches.clear(); - this.shares.clear(); - this.stars.clear(); - this.subscriptions.clear(); - this.fileOperations.clear(); - // this.ui omitted to keep ui settings between sessions - this.users.clear(); - this.views.clear(); - this.webhookSubscriptions.clear(); + Object.getOwnPropertyNames(this) + .filter((key) => ["auth", "ui"].includes(key) === false) + .forEach((key) => { + this[key]?.clear?.(); + }); } } diff --git a/app/stores/SharesStore.ts b/app/stores/SharesStore.ts index ccc1cf72e7..cf09314c6c 100644 --- a/app/stores/SharesStore.ts +++ b/app/stores/SharesStore.ts @@ -99,7 +99,6 @@ export default class SharesStore extends BaseStore { return undefined; }; - getByDocumentId = (documentId: string): Share | null | undefined => { - return find(this.orderedData, (share) => share.documentId === documentId); - }; + getByDocumentId = (documentId: string): Share | null | undefined => + find(this.orderedData, (share) => share.documentId === documentId); } diff --git a/app/stores/UsersStore.ts b/app/stores/UsersStore.ts index 8efb9b5e24..911b9078f6 100644 --- a/app/stores/UsersStore.ts +++ b/app/stores/UsersStore.ts @@ -143,11 +143,10 @@ export default class UsersStore extends BaseStore { }; @action - resendInvite = async (user: User) => { - return client.post(`/users.resendInvite`, { + resendInvite = async (user: User) => + client.post(`/users.resendInvite`, { id: user.id, }); - }; @action fetchCounts = async (teamId: string): Promise => { diff --git a/app/stores/WebhookSubscriptionStore.ts b/app/stores/WebhookSubscriptionStore.ts index e2c5cce495..e228273dc5 100644 --- a/app/stores/WebhookSubscriptionStore.ts +++ b/app/stores/WebhookSubscriptionStore.ts @@ -1,3 +1,4 @@ +import { computed } from "mobx"; import WebhookSubscription from "~/models/WebhookSubscription"; import BaseStore, { RPCAction } from "./BaseStore"; import RootStore from "./RootStore"; @@ -15,4 +16,14 @@ export default class WebhookSubscriptionsStore extends BaseStore< constructor(rootStore: RootStore) { super(rootStore, WebhookSubscription); } + + @computed + get enabled() { + return this.orderedData.filter((subscription) => subscription.enabled); + } + + @computed + get disabled() { + return this.orderedData.filter((subscription) => !subscription.enabled); + } } diff --git a/app/utils/ApiClient.ts b/app/utils/ApiClient.ts index f9474dc9ed..5ba70c26a0 100644 --- a/app/utils/ApiClient.ts +++ b/app/utils/ApiClient.ts @@ -219,17 +219,13 @@ class ApiClient { path: string, data: Record | undefined, options?: FetchOptions - ) => { - return this.fetch(path, "GET", data, options); - }; + ) => this.fetch(path, "GET", data, options); post = ( path: string, data?: Record | undefined, options?: FetchOptions - ) => { - return this.fetch(path, "POST", data, options); - }; + ) => this.fetch(path, "POST", data, options); } export const client = new ApiClient(); diff --git a/app/utils/compressImage.ts b/app/utils/compressImage.ts index 27a6e518ba..7a7c5db38f 100644 --- a/app/utils/compressImage.ts +++ b/app/utils/compressImage.ts @@ -8,8 +8,7 @@ type Options = { export const compressImage = async ( file: File | Blob, options?: Options -): Promise => { - return new Promise((resolve, reject) => { +): Promise => + new Promise((resolve, reject) => { new Compressor(file, { ...options, success: resolve, error: reject }); }); -}; diff --git a/app/utils/download.ts b/app/utils/download.ts index 89ba73c568..0c8cc91bd9 100644 --- a/app/utils/download.ts +++ b/app/utils/download.ts @@ -43,7 +43,7 @@ export default function download( return saver(x); // everyone else can save dataURLs un-processed } - //end if dataURL passed? + // end if dataURL passed? try { blob = x instanceof B @@ -81,7 +81,7 @@ export default function download( return true; } - //do iframe dataURL download (old ch+FF): + // do iframe dataURL download (old ch+FF): const f = D.createElement("iframe"); D.body && D.body.appendChild(f); diff --git a/plugins/slack/client/Settings.tsx b/plugins/slack/client/Settings.tsx index 2305a92eb9..36580e5400 100644 --- a/plugins/slack/client/Settings.tsx +++ b/plugins/slack/client/Settings.tsx @@ -101,8 +101,8 @@ function Slack() { "links:read", "links:write", // TODO: Wait forever for Slack to approve these scopes. - //"users:read", - //"users:read.email", + // "users:read", + // "users:read.email", ]} redirectUri={`${env.URL}/auth/slack.commands`} state={team.id} diff --git a/plugins/webhooks/client/Settings.tsx b/plugins/webhooks/client/Settings.tsx index 37df39f255..ce93d6adc7 100644 --- a/plugins/webhooks/client/Settings.tsx +++ b/plugins/webhooks/client/Settings.tsx @@ -9,7 +9,6 @@ import Heading from "~/components/Heading"; import Modal from "~/components/Modal"; import PaginatedList from "~/components/PaginatedList"; import Scene from "~/components/Scene"; -import Subheading from "~/components/Subheading"; import Text from "~/components/Text"; import env from "~/env"; import useBoolean from "~/hooks/useBoolean"; @@ -55,8 +54,15 @@ function Webhooks() { {t("Webhooks")}} + items={webhookSubscriptions.enabled} + heading={

{t("Active")}

} + renderItem={(webhook: WebhookSubscription) => ( + + )} + /> + {t("Inactive")}} renderItem={(webhook: WebhookSubscription) => ( )} diff --git a/plugins/webhooks/client/components/WebhookSubscriptionListItem.tsx b/plugins/webhooks/client/components/WebhookSubscriptionListItem.tsx index 7a05dac32f..b564570b3c 100644 --- a/plugins/webhooks/client/components/WebhookSubscriptionListItem.tsx +++ b/plugins/webhooks/client/components/WebhookSubscriptionListItem.tsx @@ -45,7 +45,7 @@ const WebhookSubscriptionListItem = ({ webhook }: Props) => { <> {webhook.name} {!webhook.enabled && ( - {t("Disabled")} + {t("Disabled")} )} } diff --git a/plugins/webhooks/server/api/webhookSubscriptions.ts b/plugins/webhooks/server/api/webhookSubscriptions.ts index e53360132b..58dc2c86f0 100644 --- a/plugins/webhooks/server/api/webhookSubscriptions.ts +++ b/plugins/webhooks/server/api/webhookSubscriptions.ts @@ -106,6 +106,10 @@ router.post( ip: ctx.request.ip, }; await Event.create(event); + + ctx.body = { + success: true, + }; } ); diff --git a/server/commands/teamProvisioner.ts b/server/commands/teamProvisioner.ts index 38907a12e1..adbf4f6b0d 100644 --- a/server/commands/teamProvisioner.ts +++ b/server/commands/teamProvisioner.ts @@ -106,8 +106,8 @@ async function teamProvisioner({ } // We cannot find an existing team, so we create a new one - const team = await sequelize.transaction((transaction) => { - return teamCreator({ + const team = await sequelize.transaction((transaction) => + teamCreator({ name, domain, subdomain, @@ -115,8 +115,8 @@ async function teamProvisioner({ authenticationProviders: [authenticationProvider], ip, transaction, - }); - }); + }) + ); return { team, diff --git a/server/commands/teamUpdater.ts b/server/commands/teamUpdater.ts index 0485f1b7be..20a4059c3b 100644 --- a/server/commands/teamUpdater.ts +++ b/server/commands/teamUpdater.ts @@ -115,9 +115,10 @@ const teamUpdater = async ({ params, user, team, ip }: TeamUpdaterProps) => { transaction, }); if (changes) { - const data = changes.reduce((acc, curr) => { - return { ...acc, [curr]: team[curr] }; - }, {}); + const data = changes.reduce( + (acc, curr) => ({ ...acc, [curr]: team[curr] }), + {} + ); await Event.create( { diff --git a/server/emails/templates/components/Header.tsx b/server/emails/templates/components/Header.tsx index bd3032c7d3..d89db5b420 100644 --- a/server/emails/templates/components/Header.tsx +++ b/server/emails/templates/components/Header.tsx @@ -5,26 +5,24 @@ import EmptySpace from "./EmptySpace"; const url = env.CDN_URL ?? env.URL; -export default () => { - return ( - - - - - - -
- - {env.APP_NAME} -
- ); -}; +export default () => ( + + + + + + +
+ + {env.APP_NAME} +
+); diff --git a/server/index.ts b/server/index.ts index 594de2d77a..2ebf6a87e3 100644 --- a/server/index.ts +++ b/server/index.ts @@ -139,22 +139,25 @@ async function start(id: number, disconnect: () => void) { server.listen(normalizedPortFlag || env.PORT || "3000"); server.setTimeout(env.REQUEST_TIMEOUT); - ShutdownHelper.add("server", ShutdownOrder.last, () => { - return new Promise((resolve, reject) => { - // Calling stop prevents new connections from being accepted and waits for - // existing connections to close for the grace period before forcefully - // closing them. - server.stop((err, gracefully) => { - disconnect(); + ShutdownHelper.add( + "server", + ShutdownOrder.last, + () => + new Promise((resolve, reject) => { + // Calling stop prevents new connections from being accepted and waits for + // existing connections to close for the grace period before forcefully + // closing them. + server.stop((err, gracefully) => { + disconnect(); - if (err) { - reject(err); - } else { - resolve(gracefully); - } - }); - }); - }); + if (err) { + reject(err); + } else { + resolve(gracefully); + } + }); + }) + ); // Handle shutdown signals process.once("SIGTERM", () => ShutdownHelper.execute()); diff --git a/server/logging/Logger.ts b/server/logging/Logger.ts index 10a8627394..5d0527b6bc 100644 --- a/server/logging/Logger.ts +++ b/server/logging/Logger.ts @@ -126,9 +126,9 @@ class Logger { } if (request) { - scope.addEventProcessor((event) => { - return Sentry.Handlers.parseRequest(event, request); - }); + scope.addEventProcessor((event) => + Sentry.Handlers.parseRequest(event, request) + ); } Sentry.captureException(error); diff --git a/server/models/AuthenticationProvider.ts b/server/models/AuthenticationProvider.ts index 89e1443548..c2981f996d 100644 --- a/server/models/AuthenticationProvider.ts +++ b/server/models/AuthenticationProvider.ts @@ -123,14 +123,13 @@ class AuthenticationProvider extends Model { } }; - enable = (options?: SaveOptions) => { - return this.update( + enable = (options?: SaveOptions) => + this.update( { enabled: true, }, options ); - }; } export default AuthenticationProvider; diff --git a/server/models/Collection.ts b/server/models/Collection.ts index 3c867b21fa..d44c9ed51e 100644 --- a/server/models/Collection.ts +++ b/server/models/Collection.ts @@ -477,12 +477,10 @@ class Collection extends ParanoidModel { id: string ) => { children = await Promise.all( - children.map(async (childDocument) => { - return { - ...childDocument, - children: await removeFromChildren(childDocument.children, id), - }; - }) + children.map(async (childDocument) => ({ + ...childDocument, + children: await removeFromChildren(childDocument.children, id), + })) ); const match = find(children, { id, @@ -562,8 +560,8 @@ class Collection extends ParanoidModel { const { id } = updatedDocument; - const updateChildren = (documents: NavigationNode[]) => { - return Promise.all( + const updateChildren = (documents: NavigationNode[]) => + Promise.all( documents.map(async (document) => { if (document.id === id) { document = { @@ -577,7 +575,6 @@ class Collection extends ParanoidModel { return document; }) ); - }; this.documentStructure = await updateChildren(this.documentStructure); // Sequelize doesn't seem to set the value with splice on JSONB field @@ -619,8 +616,8 @@ class Collection extends ParanoidModel { ); } else { // Recursively place document - const placeDocument = (documentList: NavigationNode[]) => { - return documentList.map((childDocument) => { + const placeDocument = (documentList: NavigationNode[]) => + documentList.map((childDocument) => { if (document.parentDocumentId === childDocument.id) { childDocument.children.splice( index !== undefined ? index : childDocument.children.length, @@ -633,7 +630,6 @@ class Collection extends ParanoidModel { return childDocument; }); - }; this.documentStructure = placeDocument(this.documentStructure); } diff --git a/server/models/Document.ts b/server/models/Document.ts index d2ae43a793..20695496f4 100644 --- a/server/models/Document.ts +++ b/server/models/Document.ts @@ -668,8 +668,8 @@ class Document extends ParanoidModel { }; // Delete a document, archived or otherwise. - delete = (userId: string) => { - return this.sequelize.transaction(async (transaction: Transaction) => { + delete = (userId: string) => + this.sequelize.transaction(async (transaction: Transaction) => { if (!this.archivedAt && !this.template && this.collectionId) { // delete any children and remove from the document structure const collection = await Collection.findByPk(this.collectionId, { @@ -699,11 +699,8 @@ class Document extends ParanoidModel { ); return this; }); - }; - getTimestamp = () => { - return Math.round(new Date(this.updatedAt).getTime() / 1000); - }; + getTimestamp = () => Math.round(new Date(this.updatedAt).getTime() / 1000); getSummary = () => { const plainText = DocumentHelper.toPlainText(this); diff --git a/server/models/Share.ts b/server/models/Share.ts index b53637a6f4..797b3e75c6 100644 --- a/server/models/Share.ts +++ b/server/models/Share.ts @@ -34,39 +34,31 @@ import Fix from "./decorators/Fix"; ], })) @Scopes(() => ({ - withCollectionPermissions: (userId: string) => { - return { - include: [ - { - model: Document.scope("withDrafts"), - paranoid: true, - as: "document", - include: [ - { - attributes: [ - "id", - "permission", - "sharing", - "teamId", - "deletedAt", - ], - model: Collection.scope({ - method: ["withMembership", userId], - }), - as: "collection", - }, - ], - }, - { - association: "user", - paranoid: false, - }, - { - association: "team", - }, - ], - }; - }, + withCollectionPermissions: (userId: string) => ({ + include: [ + { + model: Document.scope("withDrafts"), + paranoid: true, + as: "document", + include: [ + { + attributes: ["id", "permission", "sharing", "teamId", "deletedAt"], + model: Collection.scope({ + method: ["withMembership", userId], + }), + as: "collection", + }, + ], + }, + { + association: "user", + paranoid: false, + }, + { + association: "team", + }, + ], + }), })) @Table({ tableName: "shares", modelName: "share" }) @Fix diff --git a/server/models/Team.ts b/server/models/Team.ts index 13726e1b93..bb7b3c575e 100644 --- a/server/models/Team.ts +++ b/server/models/Team.ts @@ -202,9 +202,8 @@ class Team extends ParanoidModel { * @param fallback An optional fallback value, defaults to false. * @returns The preference value if set, else undefined */ - public getPreference = (preference: TeamPreference, fallback = false) => { - return this.preferences?.[preference] ?? fallback; - }; + public getPreference = (preference: TeamPreference, fallback = false) => + this.preferences?.[preference] ?? fallback; provisionFirstCollection = async (userId: string) => { await this.sequelize!.transaction(async (transaction) => { diff --git a/server/models/User.ts b/server/models/User.ts index 80a5e25be5..d85ede94d4 100644 --- a/server/models/User.ts +++ b/server/models/User.ts @@ -286,13 +286,8 @@ class User extends ParanoidModel { * @param type The type of notification event * @returns The current preference */ - public subscribedToEventType = (type: NotificationEventType) => { - return ( - this.notificationSettings[type] ?? - NotificationEventDefaults[type] ?? - false - ); - }; + public subscribedToEventType = (type: NotificationEventType) => + this.notificationSettings[type] ?? NotificationEventDefaults[type] ?? false; /** * User flags are for storing information on a user record that is not visible @@ -321,9 +316,7 @@ class User extends ParanoidModel { * @param flag The flag to retrieve * @returns The flag value */ - public getFlag = (flag: UserFlag) => { - return this.flags?.[flag] ?? 0; - }; + public getFlag = (flag: UserFlag) => this.flags?.[flag] ?? 0; /** * User flags are for storing information on a user record that is not visible @@ -367,9 +360,8 @@ class User extends ParanoidModel { * @param fallback An optional fallback value, defaults to false. * @returns The preference value if set, else undefined */ - public getPreference = (preference: UserPreference, fallback = false) => { - return this.preferences?.[preference] ?? fallback; - }; + public getPreference = (preference: UserPreference, fallback = false) => + this.preferences?.[preference] ?? fallback; collectionIds = async (options = {}) => { const collectionStubs = await Collection.scope({ @@ -448,8 +440,8 @@ class User extends ParanoidModel { * @param expiresAt The time the token will expire at * @returns The session token */ - getJwtToken = (expiresAt?: Date) => { - return JWT.sign( + getJwtToken = (expiresAt?: Date) => + JWT.sign( { id: this.id, expiresAt: expiresAt ? expiresAt.toISOString() : undefined, @@ -457,7 +449,6 @@ class User extends ParanoidModel { }, this.jwtSecret ); - }; /** * Returns a temporary token that is only used for transferring a session @@ -466,8 +457,8 @@ class User extends ParanoidModel { * * @returns The transfer token */ - getTransferToken = () => { - return JWT.sign( + getTransferToken = () => + JWT.sign( { id: this.id, createdAt: new Date().toISOString(), @@ -476,7 +467,6 @@ class User extends ParanoidModel { }, this.jwtSecret ); - }; /** * Returns a temporary token that is only used for logging in from an email @@ -484,8 +474,8 @@ class User extends ParanoidModel { * * @returns The email signin token */ - getEmailSigninToken = () => { - return JWT.sign( + getEmailSigninToken = () => + JWT.sign( { id: this.id, createdAt: new Date().toISOString(), @@ -493,15 +483,14 @@ class User extends ParanoidModel { }, this.jwtSecret ); - }; /** * Returns a list of teams that have a user matching this user's email. * * @returns A promise resolving to a list of teams */ - availableTeams = async () => { - return Team.findAll({ + availableTeams = async () => + Team.findAll({ include: [ { model: this.constructor as typeof User, @@ -510,7 +499,6 @@ class User extends ParanoidModel { }, ], }); - }; demote = async (to: UserRole, options?: SaveOptions) => { const res = await (this.constructor as typeof User).findAndCountAll({ @@ -560,12 +548,11 @@ class User extends ParanoidModel { } }; - promote = () => { - return this.update({ + promote = () => + this.update({ isAdmin: true, isViewer: false, }); - }; // hooks diff --git a/server/models/helpers/DocumentHelper.tsx b/server/models/helpers/DocumentHelper.tsx index 0377165a5a..00237921c3 100644 --- a/server/models/helpers/DocumentHelper.tsx +++ b/server/models/helpers/DocumentHelper.tsx @@ -192,9 +192,8 @@ export default class DocumentHelper { const dom = new JSDOM(html); const doc = dom.window.document; - const containsDiffElement = (node: Element | null) => { - return node && node.innerHTML.includes("data-operation-index"); - }; + const containsDiffElement = (node: Element | null) => + node && node.innerHTML.includes("data-operation-index"); // We use querySelectorAll to get a static NodeList as we'll be modifying // it as we iterate, rather than getting content.childNodes. diff --git a/server/models/helpers/ProsemirrorHelper.tsx b/server/models/helpers/ProsemirrorHelper.tsx index 82adb82be4..a31e5d9616 100644 --- a/server/models/helpers/ProsemirrorHelper.tsx +++ b/server/models/helpers/ProsemirrorHelper.tsx @@ -90,7 +90,7 @@ export default class ProsemirrorHelper { : "article"; const rtl = isRTL(node.textContent); - const content =
; + const content =
; const children = ( <> {options?.title &&

{options.title}

} diff --git a/server/queues/processors/BacklinksProcessor.ts b/server/queues/processors/BacklinksProcessor.ts index 57e182b622..c457253053 100644 --- a/server/queues/processors/BacklinksProcessor.ts +++ b/server/queues/processors/BacklinksProcessor.ts @@ -8,7 +8,6 @@ export default class BacklinksProcessor extends BaseProcessor { static applicableEvents: Event["name"][] = [ "documents.publish", "documents.update", - //"documents.title_change", "documents.delete", ]; @@ -90,17 +89,6 @@ export default class BacklinksProcessor extends BaseProcessor { break; } - case "documents.title_change": { - // might as well check - const { title, previousTitle } = event.data; - if (!previousTitle || title === previousTitle) { - break; - } - - // TODO: Handle re-writing of titles into CRDT - break; - } - case "documents.delete": { await Backlink.destroy({ where: { diff --git a/server/routes/api/auth.test.ts b/server/routes/api/auth.test.ts index 0a25ec8c00..8475e691be 100644 --- a/server/routes/api/auth.test.ts +++ b/server/routes/api/auth.test.ts @@ -5,13 +5,11 @@ import { getTestServer } from "@server/test/support"; const mockTeamInSessionId = "1e023d05-951c-41c6-9012-c9fa0402e1c3"; -jest.mock("@server/utils/authentication", () => { - return { - getSessionsInCookie() { - return { [mockTeamInSessionId]: {} }; - }, - }; -}); +jest.mock("@server/utils/authentication", () => ({ + getSessionsInCookie() { + return { [mockTeamInSessionId]: {} }; + }, +})); const server = getTestServer(); diff --git a/server/routes/api/collections.ts b/server/routes/api/collections.ts index 428553e705..7c23ed7967 100644 --- a/server/routes/api/collections.ts +++ b/server/routes/api/collections.ts @@ -567,16 +567,16 @@ router.post( }).findByPk(id); authorize(user, "read", collection); - const fileOperation = await sequelize.transaction(async (transaction) => { - return collectionExporter({ + const fileOperation = await sequelize.transaction(async (transaction) => + collectionExporter({ collection, user, team, format, ip: ctx.request.ip, transaction, - }); - }); + }) + ); ctx.body = { success: true, @@ -599,15 +599,15 @@ router.post( assertIn(format, Object.values(FileOperationFormat), "Invalid format"); - const fileOperation = await sequelize.transaction(async (transaction) => { - return collectionExporter({ + const fileOperation = await sequelize.transaction(async (transaction) => + collectionExporter({ user, team, format, ip: ctx.request.ip, transaction, - }); - }); + }) + ); ctx.body = { success: true, diff --git a/server/routes/api/documents/documents.ts b/server/routes/api/documents/documents.ts index 9746578f03..90b7378577 100644 --- a/server/routes/api/documents/documents.ts +++ b/server/routes/api/documents/documents.ts @@ -1300,8 +1300,8 @@ router.post( authorize(user, "read", templateDocument); } - const document = await sequelize.transaction(async (transaction) => { - return documentCreator({ + const document = await sequelize.transaction(async (transaction) => + documentCreator({ title, text, publish, @@ -1313,8 +1313,8 @@ router.post( editorVersion, ip: ctx.request.ip, transaction, - }); - }); + }) + ); document.collection = collection; diff --git a/server/routes/api/teams/teams.ts b/server/routes/api/teams/teams.ts index 2952ef322d..667ca5f734 100644 --- a/server/routes/api/teams/teams.ts +++ b/server/routes/api/teams/teams.ts @@ -58,12 +58,10 @@ router.post( authorize(user, "createTeam", existingTeam); const authenticationProviders = existingTeam.authenticationProviders.map( - (provider) => { - return { - name: provider.name, - providerId: provider.providerId, - }; - } + (provider) => ({ + name: provider.name, + providerId: provider.providerId, + }) ); invariant( diff --git a/server/test/support.ts b/server/test/support.ts index bcff67785e..b813be3cc7 100644 --- a/server/test/support.ts +++ b/server/test/support.ts @@ -6,8 +6,8 @@ import { User, Document, Collection, Team } from "@server/models"; import onerror from "@server/onerror"; import webService from "@server/services/web"; -export const seed = async () => { - return sequelize.transaction(async (transaction) => { +export const seed = async () => + sequelize.transaction(async (transaction) => { const team = await Team.create( { name: "Team", @@ -97,7 +97,6 @@ export const seed = async () => { team, }; }); -}; export function getTestServer() { const app = webService(); diff --git a/server/utils/i18n.ts b/server/utils/i18n.ts index 0e43db3af7..3cb03a86ef 100644 --- a/server/utils/i18n.ts +++ b/server/utils/i18n.ts @@ -30,8 +30,8 @@ export function initI18n() { i18n.use(backend).init({ compatibilityJSON: "v3", backend: { - loadPath: (language: string) => { - return path.resolve( + loadPath: (language: string) => + path.resolve( path.join( __dirname, "..", @@ -42,8 +42,7 @@ export function initI18n() { unicodeBCP47toCLDR(language), "translation.json" ) - ); - }, + ), }, preload: languages.map(unicodeCLDRtoBCP47), interpolation: { diff --git a/server/utils/opensearch.ts b/server/utils/opensearch.ts index 371567e19d..5c5666b890 100644 --- a/server/utils/opensearch.ts +++ b/server/utils/opensearch.ts @@ -1,5 +1,4 @@ -export const opensearchResponse = (baseUrl: string): string => { - return ` +export const opensearchResponse = (baseUrl: string): string => ` Outline Search Outline @@ -9,4 +8,3 @@ export const opensearchResponse = (baseUrl: string): string => { ${baseUrl}/search `; -}; diff --git a/server/utils/prefetchTags.tsx b/server/utils/prefetchTags.tsx index 495679d72b..cd21aadb57 100644 --- a/server/utils/prefetchTags.tsx +++ b/server/utils/prefetchTags.tsx @@ -23,14 +23,12 @@ if (isProduction) { const returnFileAndImportsFromManifest = ( manifest: ManifestStructure, file: string - ): string[] => { - return [ - manifest[file]["file"], - ...manifest[file]["imports"].map((entry: string) => { - return manifest[entry]["file"]; - }), - ]; - }; + ): string[] => [ + manifest[file]["file"], + ...manifest[file]["imports"].map( + (entry: string) => manifest[entry]["file"] + ), + ]; Array.from([ ...returnFileAndImportsFromManifest(manifest, "app/index.tsx"), diff --git a/server/utils/s3.ts b/server/utils/s3.ts index 4454ffdfe5..b8cac6296a 100644 --- a/server/utils/s3.ts +++ b/server/utils/s3.ts @@ -150,14 +150,13 @@ export const uploadToS3FromUrl = async ( } }; -export const deleteFromS3 = (key: string) => { - return s3 +export const deleteFromS3 = (key: string) => + s3 .deleteObject({ Bucket: AWS_S3_UPLOAD_BUCKET_NAME, Key: key, }) .promise(); -}; export const getSignedUrl = async (key: string, expiresInMs = 60) => { const isDocker = AWS_S3_UPLOAD_BUCKET_URL.match(/http:\/\/s3:/); diff --git a/shared/editor/components/ImageZoom/utils.ts b/shared/editor/components/ImageZoom/utils.ts index dd213501bb..c350aaaa9b 100644 --- a/shared/editor/components/ImageZoom/utils.ts +++ b/shared/editor/components/ImageZoom/utils.ts @@ -20,16 +20,11 @@ export interface GetScaleToWindow { (data: { width: number; height: number; offset: number }): number; } -export const getScaleToWindow: GetScaleToWindow = ({ - height, - offset, - width, -}) => { - return Math.min( +export const getScaleToWindow: GetScaleToWindow = ({ height, offset, width }) => + Math.min( (window.innerWidth - offset * 2) / width, // scale X-axis (window.innerHeight - offset * 2) / height // scale Y-axis ); -}; export interface GetScaleToWindowMax { (data: { @@ -80,8 +75,8 @@ export const getScale: GetScale = ({ offset, targetHeight, targetWidth, -}) => { - return !hasScalableSrc && targetHeight && targetWidth +}) => + !hasScalableSrc && targetHeight && targetWidth ? getScaleToWindowMax({ containerHeight, containerWidth, @@ -94,7 +89,6 @@ export const getScale: GetScale = ({ offset, width: containerWidth, }); -}; const URL_REGEX = /url(?:\(['"]?)(.*?)(?:['"]?\))/; diff --git a/shared/editor/lib/chainTransactions.ts b/shared/editor/lib/chainTransactions.ts index c328174ade..e62c211f47 100644 --- a/shared/editor/lib/chainTransactions.ts +++ b/shared/editor/lib/chainTransactions.ts @@ -10,9 +10,10 @@ export default function chainTransactions( dispatch?.(tr); }; const last = commands.pop(); - const reduced = commands.reduce((result, command) => { - return result || command(state, dispatcher); - }, false); + const reduced = commands.reduce( + (result, command) => result || command(state, dispatcher), + false + ); return reduced && last !== undefined && last(state, dispatch); }; } diff --git a/shared/editor/marks/Link.tsx b/shared/editor/marks/Link.tsx index 1bd60a606b..af1dee35c3 100644 --- a/shared/editor/marks/Link.tsx +++ b/shared/editor/marks/Link.tsx @@ -198,12 +198,9 @@ export default class Link extends Mark { const plugin: Plugin = new Plugin({ state: { - init: (config, state) => { - return getLinkDecorations(state); - }, - apply: (tr, decorationSet, _oldState, newState) => { - return tr.docChanged ? getLinkDecorations(newState) : decorationSet; - }, + init: (config, state) => getLinkDecorations(state), + apply: (tr, decorationSet, _oldState, newState) => + tr.docChanged ? getLinkDecorations(newState) : decorationSet, }, props: { decorations: (state: EditorState) => plugin.getState(state), diff --git a/shared/editor/nodes/Attachment.tsx b/shared/editor/nodes/Attachment.tsx index 1c526e65c3..f0cc1a2a8b 100644 --- a/shared/editor/nodes/Attachment.tsx +++ b/shared/editor/nodes/Attachment.tsx @@ -43,29 +43,25 @@ export default class Attachment extends Node { { priority: 100, tag: "a.attachment", - getAttrs: (dom: HTMLAnchorElement) => { - return { - id: dom.id, - title: dom.innerText, - href: dom.getAttribute("href"), - size: parseInt(dom.dataset.size || "0", 10), - }; - }, + getAttrs: (dom: HTMLAnchorElement) => ({ + id: dom.id, + title: dom.innerText, + href: dom.getAttribute("href"), + size: parseInt(dom.dataset.size || "0", 10), + }), }, ], - toDOM: (node) => { - return [ - "a", - { - class: `attachment`, - id: node.attrs.id, - href: sanitizeUrl(node.attrs.href), - download: node.attrs.title, - "data-size": node.attrs.size, - }, - node.attrs.title, - ]; - }, + toDOM: (node) => [ + "a", + { + class: `attachment`, + id: node.attrs.id, + href: sanitizeUrl(node.attrs.href), + download: node.attrs.title, + "data-size": node.attrs.size, + }, + node.attrs.title, + ], toPlainText: (node) => node.attrs.title, }; } diff --git a/shared/editor/nodes/CodeFence.ts b/shared/editor/nodes/CodeFence.ts index 4cea6ed1a1..c06b6330f5 100644 --- a/shared/editor/nodes/CodeFence.ts +++ b/shared/editor/nodes/CodeFence.ts @@ -148,11 +148,9 @@ export default class CodeFence extends Node { tag: ".code-block", preserveWhitespace: "full", contentElement: "code", - getAttrs: (dom: HTMLDivElement) => { - return { - language: dom.dataset.language, - }; - }, + getAttrs: (dom: HTMLDivElement) => ({ + language: dom.dataset.language, + }), }, ], toDOM: (node) => { diff --git a/shared/editor/nodes/Emoji.tsx b/shared/editor/nodes/Emoji.tsx index 6ea84894fa..792332fc24 100644 --- a/shared/editor/nodes/Emoji.tsx +++ b/shared/editor/nodes/Emoji.tsx @@ -101,10 +101,10 @@ export default class Emoji extends Node { ) { const { pos } = view.state.selection.$from; - return run(view, pos, pos, OPEN_REGEX, (state, match) => { + return run(view, pos, pos, OPEN_REGEX, (state, match) => // just tell Prosemirror we handled it and not to do anything - return match ? true : null; - }); + match ? true : null + ); } return false; @@ -189,9 +189,7 @@ export default class Emoji extends Node { parseMarkdown() { return { node: "emoji", - getAttrs: (tok: Token) => { - return { "data-name": tok.markup.trim() }; - }, + getAttrs: (tok: Token) => ({ "data-name": tok.markup.trim() }), }; } } diff --git a/shared/editor/nodes/Heading.ts b/shared/editor/nodes/Heading.ts index 4b50b9cadf..76fc07a327 100644 --- a/shared/editor/nodes/Heading.ts +++ b/shared/editor/nodes/Heading.ts @@ -114,9 +114,8 @@ export default class Heading extends Node { } commands({ type, schema }: { type: NodeType; schema: Schema }) { - return (attrs: Record) => { - return toggleBlockType(type, schema.nodes.paragraph, attrs); - }; + return (attrs: Record) => + toggleBlockType(type, schema.nodes.paragraph, attrs); } handleFoldContent = (event: MouseEvent) => { @@ -256,12 +255,9 @@ export default class Heading extends Node { const plugin: Plugin = new Plugin({ state: { - init: (config, state) => { - return getAnchors(state.doc); - }, - apply: (tr, oldState) => { - return tr.docChanged ? getAnchors(tr.doc) : oldState; - }, + init: (config, state) => getAnchors(state.doc), + apply: (tr, oldState) => + tr.docChanged ? getAnchors(tr.doc) : oldState, }, props: { decorations: (state) => plugin.getState(state), diff --git a/shared/editor/nodes/HorizontalRule.ts b/shared/editor/nodes/HorizontalRule.ts index 9bcba3dcd9..f23989bb8e 100644 --- a/shared/editor/nodes/HorizontalRule.ts +++ b/shared/editor/nodes/HorizontalRule.ts @@ -20,12 +20,10 @@ export default class HorizontalRule extends Node { }, group: "block", parseDOM: [{ tag: "hr" }], - toDOM: (node) => { - return [ - "hr", - { class: node.attrs.markup === "***" ? "page-break" : "" }, - ]; - }, + toDOM: (node) => [ + "hr", + { class: node.attrs.markup === "***" ? "page-break" : "" }, + ], }; } diff --git a/shared/editor/nodes/Image.tsx b/shared/editor/nodes/Image.tsx index 5c6a0b399f..82a252abae 100644 --- a/shared/editor/nodes/Image.tsx +++ b/shared/editor/nodes/Image.tsx @@ -219,30 +219,28 @@ export default class Image extends SimpleImage { downloadImageNode(node); }; - component = (props: ComponentProps) => { - return ( - ( + + - - {props.node.attrs.alt} - - - ); - }; + {props.node.attrs.alt} + + + ); toMarkdown(state: MarkdownSerializerState, node: ProsemirrorNode) { let markdown = @@ -275,17 +273,13 @@ export default class Image extends SimpleImage { parseMarkdown() { return { node: "image", - getAttrs: (token: Token) => { - return { - src: token.attrGet("src"), - alt: - (token?.children && - token.children[0] && - token.children[0].content) || - null, - ...parseTitleAttribute(token?.attrGet("title") || ""), - }; - }, + getAttrs: (token: Token) => ({ + src: token.attrGet("src"), + alt: + (token?.children && token.children[0] && token.children[0].content) || + null, + ...parseTitleAttribute(token?.attrGet("title") || ""), + }), }; } diff --git a/shared/editor/nodes/Mention.ts b/shared/editor/nodes/Mention.ts index 0fdf9eaa2f..05590a320d 100644 --- a/shared/editor/nodes/Mention.ts +++ b/shared/editor/nodes/Mention.ts @@ -47,19 +47,17 @@ export default class Mention extends Node { }), }, ], - toDOM: (node) => { - return [ - "span", - { - class: `${node.type.name}`, - id: node.attrs.id, - "data-type": node.attrs.type, - "data-id": node.attrs.modelId, - "data-actorId": node.attrs.actorId, - }, - node.attrs.label, - ]; - }, + toDOM: (node) => [ + "span", + { + class: `${node.type.name}`, + id: node.attrs.id, + "data-type": node.attrs.type, + "data-id": node.attrs.modelId, + "data-actorId": node.attrs.actorId, + }, + node.attrs.label, + ], toPlainText: (node) => `@${node.attrs.label}`, }; } @@ -109,10 +107,10 @@ export default class Mention extends Node { ) { const { pos } = view.state.selection.$from; - return run(view, pos, pos, OPEN_REGEX, (state, match) => { + return run(view, pos, pos, OPEN_REGEX, (state, match) => // just tell Prosemirror we handled it and not to do anything - return match ? true : null; - }); + match ? true : null + ); } return false; diff --git a/shared/editor/nodes/SimpleImage.tsx b/shared/editor/nodes/SimpleImage.tsx index e8168f9c9c..4f956700d8 100644 --- a/shared/editor/nodes/SimpleImage.tsx +++ b/shared/editor/nodes/SimpleImage.tsx @@ -51,31 +51,27 @@ export default class SimpleImage extends Node { }, { tag: "img", - getAttrs: (dom: HTMLImageElement) => { - return { - src: dom.getAttribute("src"), - alt: dom.getAttribute("alt"), - title: dom.getAttribute("title"), - }; - }, + getAttrs: (dom: HTMLImageElement) => ({ + src: dom.getAttribute("src"), + alt: dom.getAttribute("alt"), + title: dom.getAttribute("title"), + }), }, ], - toDOM: (node) => { - return [ - "div", + toDOM: (node) => [ + "div", + { + class: "image", + }, + [ + "img", { - class: "image", + ...node.attrs, + src: sanitizeUrl(node.attrs.src), + contentEditable: "false", }, - [ - "img", - { - ...node.attrs, - src: sanitizeUrl(node.attrs.src), - contentEditable: "false", - }, - ], - ]; - }, + ], + ], }; } @@ -155,9 +151,9 @@ export default class SimpleImage extends Node { } }; - component = (props: ComponentProps) => { - return ; - }; + component = (props: ComponentProps) => ( + + ); toMarkdown(state: MarkdownSerializerState, node: ProsemirrorNode) { state.write( @@ -172,16 +168,12 @@ export default class SimpleImage extends Node { parseMarkdown() { return { node: "image", - getAttrs: (token: Token) => { - return { - src: token.attrGet("src"), - alt: - (token?.children && - token.children[0] && - token.children[0].content) || - null, - }; - }, + getAttrs: (token: Token) => ({ + src: token.attrGet("src"), + alt: + (token?.children && token.children[0] && token.children[0].content) || + null, + }), }; } diff --git a/shared/editor/plugins/BlockMenuTrigger.tsx b/shared/editor/plugins/BlockMenuTrigger.tsx index 3908c0faf0..36926821d7 100644 --- a/shared/editor/plugins/BlockMenuTrigger.tsx +++ b/shared/editor/plugins/BlockMenuTrigger.tsx @@ -99,10 +99,10 @@ export default class BlockMenuTrigger extends Extension { ) { const { pos } = view.state.selection.$from; - return run(view, pos, pos, OPEN_REGEX, (state, match) => { + return run(view, pos, pos, OPEN_REGEX, (state, match) => // just tell Prosemirror we handled it and not to do anything - return match ? true : null; - }); + match ? true : null + ); } return false; diff --git a/shared/editor/plugins/Prism.ts b/shared/editor/plugins/Prism.ts index 0f56107207..b34fea897a 100644 --- a/shared/editor/plugins/Prism.ts +++ b/shared/editor/plugins/Prism.ts @@ -178,9 +178,7 @@ export default function Prism({ return new Plugin({ key: new PluginKey("prism"), state: { - init: (_: Plugin, { doc }) => { - return DecorationSet.create(doc, []); - }, + init: (_: Plugin, { doc }) => DecorationSet.create(doc, []), apply: (transaction: Transaction, decorationSet, oldState, state) => { const nodeName = state.selection.$head.parent.type.name; const previousNodeName = oldState.selection.$head.parent.type.name; diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json index 6153d59c7d..58e554fe0f 100644 --- a/shared/i18n/locales/en_US/translation.json +++ b/shared/i18n/locales/en_US/translation.json @@ -212,7 +212,6 @@ "Empty": "Empty", "Go back": "Go back", "Go forward": "Go forward", - "Starred documents could not be loaded": "Starred documents could not be loaded", "Starred": "Starred", "Show more": "Show more", "Toggle sidebar": "Toggle sidebar", @@ -314,6 +313,8 @@ "Integrations": "Integrations", "Self Hosted": "Self Hosted", "Google Analytics": "Google Analytics", + "Revoke token": "Revoke token", + "Revoke": "Revoke", "Show path to document": "Show path to document", "Path to document": "Path to document", "Group member options": "Group member options", @@ -688,9 +689,7 @@ "Date shared": "Date shared", "Shared nested": "Shared nested", "API token copied to clipboard": "API token copied to clipboard", - "Revoke token": "Revoke token", "Copied": "Copied", - "Revoke": "Revoke", "Revoking": "Revoking", "Are you sure you want to revoke the {{ tokenName }} token?": "Are you sure you want to revoke the {{ tokenName }} token?", "Active": "Active", @@ -729,8 +728,8 @@ "Create a \"Web\" stream in your Google Analytics admin dashboard and copy the measurement ID from the generated code snippet to install.": "Create a \"Web\" stream in your Google Analytics admin dashboard and copy the measurement ID from the generated code snippet to install.", "New group": "New group", "Groups can be used to organize and manage the people on your team.": "Groups can be used to organize and manage the people on your team.", - "All groups": "All groups", "No groups have been created yet": "No groups have been created yet", + "All": "All", "Quickly transfer your existing documents, pages, and files from other tools and services into {{appName}}. You can also drag and drop any HTML, Markdown, and text documents directly into Collections in the app.": "Quickly transfer your existing documents, pages, and files from other tools and services into {{appName}}. You can also drag and drop any HTML, Markdown, and text documents directly into Collections in the app.", "Import a zip file of Markdown documents (exported from version 0.67.0 or earlier)": "Import a zip file of Markdown documents (exported from version 0.67.0 or earlier)", "Import data": "Import data", @@ -811,7 +810,6 @@ "Documents that have been shared are listed below. Anyone that has the public link can access a read-only version of the document until the link has been revoked.": "Documents that have been shared are listed below. Anyone that has the public link can access a read-only version of the document until the link has been revoked.", "New token": "New token", "You can create an unlimited amount of personal tokens to authenticate\n with the API. Tokens have the same permissions as your user account.\n For more details see the developer documentation.": "You can create an unlimited amount of personal tokens to authenticate\n with the API. Tokens have the same permissions as your user account.\n For more details see the developer documentation.", - "Tokens": "Tokens", "Create a token": "Create a token", "Zapier is a platform that allows {{appName}} to easily integrate with thousands of other business tools. Automate your workflows, sync data, and more.": "Zapier is a platform that allows {{appName}} to easily integrate with thousands of other business tools. Automate your workflows, sync data, and more.", "Your are creating a new workspace using your current account — {{email}}": "Your are creating a new workspace using your current account — {{email}}", @@ -825,11 +823,6 @@ "Note: Signing back in will cause a new account to be automatically reprovisioned.": "Note: Signing back in will cause a new account to be automatically reprovisioned.", "Are you sure? Deleting your account will destroy identifying data associated with your user and cannot be undone. You will be immediately logged out of {{appName}} and all your API tokens will be revoked.": "Are you sure? Deleting your account will destroy identifying data associated with your user and cannot be undone. You will be immediately logged out of {{appName}} and all your API tokens will be revoked.", "Delete My Account": "Delete My Account", - "You joined": "You joined", - "Joined": "Joined", - "{{ time }} ago.": "{{ time }} ago.", - "Edit Profile": "Edit Profile", - "{{ userName }} hasn’t updated any documents yet.": "{{ userName }} hasn’t updated any documents yet.", "Today": "Today", "Yesterday": "Yesterday", "Last week": "Last week", @@ -872,6 +865,7 @@ "Webhooks": "Webhooks", "New webhook": "New webhook", "Webhooks can be used to notify your application when events happen in {{appName}}. Events are sent as a https request with a JSON payload in near real-time.": "Webhooks can be used to notify your application when events happen in {{appName}}. Events are sent as a https request with a JSON payload in near real-time.", + "Inactive": "Inactive", "Create a webhook": "Create a webhook", "Uploading": "Uploading" } diff --git a/shared/random.ts b/shared/random.ts index d0a7c50168..4f18a6aac2 100644 --- a/shared/random.ts +++ b/shared/random.ts @@ -1,9 +1,6 @@ -const randomInteger = (min: number, max: number) => { - return Math.floor(Math.random() * (max - min + 1) + min); -}; +const randomInteger = (min: number, max: number) => + Math.floor(Math.random() * (max - min + 1) + min); -const randomElement = (arr: T[]): T => { - return arr[randomInteger(0, arr.length - 1)]; -}; +const randomElement = (arr: T[]): T => arr[randomInteger(0, arr.length - 1)]; export { randomInteger, randomElement }; diff --git a/shared/styles/index.ts b/shared/styles/index.ts index d11fa8ad91..495595e085 100644 --- a/shared/styles/index.ts +++ b/shared/styles/index.ts @@ -22,9 +22,7 @@ export const ellipsis = () => ` */ export const s = (key: keyof DefaultTheme) => (props: { theme: DefaultTheme; -}) => { - return String(props.theme[key]); -}; +}) => String(props.theme[key]); /** * Mixin to hide scrollbars. diff --git a/shared/utils/color.ts b/shared/utils/color.ts index a09b35af3f..af094445cd 100644 --- a/shared/utils/color.ts +++ b/shared/utils/color.ts @@ -19,9 +19,8 @@ export const palette = [ darken(0.2, theme.brand.yellow), ]; -export const validateColorHex = (color: string) => { - return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(color); -}; +export const validateColorHex = (color: string) => + /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(color); export const stringToColor = (input: string) => { const inputAsNumber = parseInt(md5(input).toString(), 16); diff --git a/shared/utils/unescape.ts b/shared/utils/unescape.ts index 6f40f3ccd5..5de2587f4a 100644 --- a/shared/utils/unescape.ts +++ b/shared/utils/unescape.ts @@ -1,7 +1,4 @@ -const unescape = (text: string) => { - return text - .replace(/\\([\\`*{}[\]()#+\-.!_>])/g, "$1") - .replace(/\n\\\n/g, "\n\n"); -}; +const unescape = (text: string) => + text.replace(/\\([\\`*{}[\]()#+\-.!_>])/g, "$1").replace(/\n\\\n/g, "\n\n"); export default unescape;