diff --git a/.eslintrc b/.eslintrc index b013cd5aa..6f04225bd 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 accc602c4..697364032 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 f5bb08a91..0d0cae66c 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 6eb0d9d6f..7cd5e24d9 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 f8ec93d8a..8c38a3f57 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 d0154b1a3..387ac63b4 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 d0832f7fb..89fc5e3a4 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 4cce1706f..4a0ccdab7 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 bd3072c5d..af0917678 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 1625deb35..eb048ffa8 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 98d352f93..9f7fe76af 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 ab1bedce3..95d0a1e42 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 901bb88dd..347afc01b 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 35d2b1033..000000000 --- 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 9aa83b2ff..90ade8202 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 64ca88977..27f9c8345 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 b84fa81a0..2374d0dae 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 54d1eb9aa..ad85fcd48 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 5b8312217..16b5cfcc4 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 938fcb64b..311ea762c 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 da4d79d02..3871a1732 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 ef59b2a7c..b1c1c3066 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 880d36809..c3fb26ca3 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 4a402a2c8..686e6478a 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 b020f1e5c..ff28aa1f8 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 a8e9f36af..e95ddd20f 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 a2f9bb339..6e6dfca4e 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 7cca6e5f5..aca9af54d 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 ff126b4b5..743f59e2b 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 426a9443b..b45fab884 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 607fbc14e..a15ed08d8 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 c629309fa..7a2fc9b9a 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 088d40e71..737986091 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 dda958c17..2359cd3c7 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 e8258a314..6b63596ee 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 57fa64691..5be355e00 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 88970b297..9f1e4e20c 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 000000000..1681138fd --- /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 06beb149f..fa3fba8b7 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 7176034da..d423a728c 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 4c0461910..932c9b278 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 28f68b2a6..d4b8c68c2 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 be5268adb..3abe065d4 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 4dc12abc8..5dabf8b87 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 737abfbac..de9e8e70c 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 c8707e8c3..21d725371 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 7ff74a702..dc3992f5d 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 639c624a8..e25d4a24f 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 211431cce..6f42bddea 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 d25166e0a..3d5aaee1f 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 14b83aacc..e77cc7f0d 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 d2a4878e5..8d9195e56 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 43ffcb5ae..e633cf977 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 2e95ed360..000000000 --- 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 a07528168..0182e4fae 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 31c1aab30..e135c0dcb 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 ef208aa6d..c6b68fa2a 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 259429e48..8681ac907 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 09c32256a..956e705ba 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 dcd1ee734..ffea4bbb1 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 ccc1cf72e..cf09314c6 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 8efb9b5e2..911b9078f 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 e2c5cce49..e228273dc 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 f9474dc9e..5ba70c26a 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 27a6e518b..7a7c5db38 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 89ba73c56..0c8cc91bd 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 2305a92eb..36580e540 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 37df39f25..ce93d6adc 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 7a05dac32..b564570b3 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 e53360132..58dc2c86f 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 38907a12e..adbf4f6b0 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 0485f1b7b..20a4059c3 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 bd3032c7d..d89db5b42 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 594de2d77..2ebf6a87e 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 10a862739..5d0527b6b 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 89e144354..c2981f996 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 3c867b21f..d44c9ed51 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 d2ae43a79..20695496f 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 b53637a6f..797b3e75c 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 13726e1b9..bb7b3c575 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 80a5e25be..d85ede94d 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 0377165a5..00237921c 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 82adb82be..a31e5d961 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 57e182b62..c45725305 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 0a25ec8c0..8475e691b 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 428553e70..7c23ed796 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 9746578f0..90b737857 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 2952ef322..667ca5f73 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 bcff67785..b813be3cc 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 0e43db3af..3cb03a86e 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 371567e19..5c5666b89 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 495679d72..cd21aadb5 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 4454ffdfe..b8cac6296 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 dd213501b..c350aaaa9 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 c328174ad..e62c211f4 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 1bd60a606..af1dee35c 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 1c526e65c..f0cc1a2a8 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 4cea6ed1a..c06b6330f 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 6ea84894f..792332fc2 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 4b50b9cad..76fc07a32 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 9bcba3dcd..f23989bb8 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 5c6a0b399..82a252aba 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 0fdf9eaa2..05590a320 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 e8168f9c9..4f956700d 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 3908c0faf..36926821d 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 0f5610720..b34fea897 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 6153d59c7..58e554fe0 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 d0a7c5016..4f18a6aac 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 d11fa8ad9..495595e08 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 a09b35af3..af094445c 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 6f40f3ccd..5de2587f4 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;