chore: Update syntax, improve more typing (#1439)

* chore: <React.Fragment> to <>

* flow types
This commit is contained in:
Tom Moor
2020-08-09 09:48:04 -07:00
committed by GitHub
parent ead55442e0
commit e2bd03494d
55 changed files with 239 additions and 221 deletions

View File

@ -40,7 +40,7 @@ class AvatarWithPresence extends React.Component<Props> {
} = this.props; } = this.props;
return ( return (
<React.Fragment> <>
<Tooltip <Tooltip
tooltip={ tooltip={
<Centered> <Centered>
@ -69,7 +69,7 @@ class AvatarWithPresence extends React.Component<Props> {
isOpen={this.isOpen} isOpen={this.isOpen}
onRequestClose={this.handleCloseProfile} onRequestClose={this.handleCloseProfile}
/> />
</React.Fragment> </>
); );
} }
} }

View File

@ -33,11 +33,11 @@ const Breadcrumb = observer(({ document, collections, onlyText }: Props) => {
if (onlyText === true) { if (onlyText === true) {
return ( return (
<React.Fragment> <>
{collection.private && ( {collection.private && (
<React.Fragment> <>
<SmallPadlockIcon color="currentColor" size={16} />{" "} <SmallPadlockIcon color="currentColor" size={16} />{" "}
</React.Fragment> </>
)} )}
{collection.name} {collection.name}
{path.map((n) => ( {path.map((n) => (
@ -46,7 +46,7 @@ const Breadcrumb = observer(({ document, collections, onlyText }: Props) => {
{n.title} {n.title}
</React.Fragment> </React.Fragment>
))} ))}
</React.Fragment> </>
); );
} }
@ -59,24 +59,24 @@ const Breadcrumb = observer(({ document, collections, onlyText }: Props) => {
return ( return (
<Wrapper justify="flex-start" align="center"> <Wrapper justify="flex-start" align="center">
{isTemplate && ( {isTemplate && (
<React.Fragment> <>
<CollectionName to="/templates"> <CollectionName to="/templates">
<ShapesIcon color="currentColor" /> <ShapesIcon color="currentColor" />
&nbsp; &nbsp;
<span>Templates</span> <span>Templates</span>
</CollectionName> </CollectionName>
<Slash /> <Slash />
</React.Fragment> </>
)} )}
{isDraft && ( {isDraft && (
<React.Fragment> <>
<CollectionName to="/drafts"> <CollectionName to="/drafts">
<EditIcon color="currentColor" /> <EditIcon color="currentColor" />
&nbsp; &nbsp;
<span>Drafts</span> <span>Drafts</span>
</CollectionName> </CollectionName>
<Slash /> <Slash />
</React.Fragment> </>
)} )}
<CollectionName to={collectionUrl(collection.id)}> <CollectionName to={collectionUrl(collection.id)}>
<CollectionIcon collection={collection} expanded /> <CollectionIcon collection={collection} expanded />
@ -84,17 +84,17 @@ const Breadcrumb = observer(({ document, collections, onlyText }: Props) => {
<span>{collection.name}</span> <span>{collection.name}</span>
</CollectionName> </CollectionName>
{isNestedDocument && ( {isNestedDocument && (
<React.Fragment> <>
<Slash /> <BreadcrumbMenu label={<Overflow />} path={menuPath} /> <Slash /> <BreadcrumbMenu label={<Overflow />} path={menuPath} />
</React.Fragment> </>
)} )}
{lastPath && ( {lastPath && (
<React.Fragment> <>
<Slash />{" "} <Slash />{" "}
<Crumb to={lastPath.url} title={lastPath.title}> <Crumb to={lastPath.url} title={lastPath.title}>
{lastPath.title} {lastPath.title}
</Crumb> </Crumb>
</React.Fragment> </>
)} )}
</Wrapper> </Wrapper>
); );

View File

@ -155,6 +155,6 @@ function Button({
); );
} }
export default React.forwardRef((props, ref) => ( export default React.forwardRef<Props, typeof Button>((props, ref) => (
<Button {...props} innerRef={ref} /> <Button {...props} innerRef={ref} />
)); ));

View File

@ -10,6 +10,7 @@ export type Props = {
labelHidden?: boolean, labelHidden?: boolean,
className?: string, className?: string,
note?: string, note?: string,
short?: boolean,
small?: boolean, small?: boolean,
}; };
@ -42,7 +43,7 @@ export default function Checkbox({
const wrappedLabel = <LabelText small={small}>{label}</LabelText>; const wrappedLabel = <LabelText small={small}>{label}</LabelText>;
return ( return (
<React.Fragment> <>
<Wrapper small={small}> <Wrapper small={small}>
<Label> <Label>
<input type="checkbox" {...rest} /> <input type="checkbox" {...rest} />
@ -55,6 +56,6 @@ export default function Checkbox({
</Label> </Label>
{note && <HelpText small>{note}</HelpText>} {note && <HelpText small>{note}</HelpText>}
</Wrapper> </Wrapper>
</React.Fragment> </>
); );
} }

View File

@ -18,10 +18,10 @@ function DocumentMeta({ views, isDraft, document }: Props) {
return ( return (
<Meta document={document}> <Meta document={document}>
{totalViews && !isDraft ? ( {totalViews && !isDraft ? (
<React.Fragment> <>
&nbsp;&middot; Viewed{" "} &nbsp;&middot; Viewed{" "}
{totalViews === 1 ? "once" : `${totalViews} times`} {totalViews === 1 ? "once" : `${totalViews} times`}
</React.Fragment> </>
) : null} ) : null}
</Meta> </Meta>
); );

View File

@ -161,7 +161,7 @@ class DropdownMenu extends React.Component<Props> {
closeOnEsc closeOnEsc
> >
{({ closePortal, openPortal, isOpen, portal }) => ( {({ closePortal, openPortal, isOpen, portal }) => (
<React.Fragment> <>
<Label <Label
onMouseMove={hover ? this.clearCloseTimeout : undefined} onMouseMove={hover ? this.clearCloseTimeout : undefined}
onMouseOut={ onMouseOut={
@ -220,7 +220,7 @@ class DropdownMenu extends React.Component<Props> {
</Menu> </Menu>
</Position> </Position>
)} )}
</React.Fragment> </>
)} )}
</PortalWithState> </PortalWithState>
</div> </div>

View File

@ -26,12 +26,12 @@ const DropdownMenuItem = ({
{...rest} {...rest}
> >
{selected !== undefined && ( {selected !== undefined && (
<React.Fragment> <>
<CheckmarkIcon <CheckmarkIcon
color={selected === false ? "transparent" : undefined} color={selected === false ? "transparent" : undefined}
/> />
&nbsp; &nbsp;
</React.Fragment> </>
)} )}
{children} {children}
</MenuItem> </MenuItem>

View File

@ -15,18 +15,21 @@ import { uploadFile } from "utils/uploadFile";
const EMPTY_ARRAY = []; const EMPTY_ARRAY = [];
type Props = { type Props = {
id: string, id?: string,
defaultValue?: string, defaultValue?: string,
readOnly?: boolean, readOnly?: boolean,
grow?: boolean, grow?: boolean,
disableEmbeds?: boolean, disableEmbeds?: boolean,
history: RouterHistory, ui?: UiStore,
};
type PropsWithRef = Props & {
forwardedRef: React.Ref<RichMarkdownEditor>, forwardedRef: React.Ref<RichMarkdownEditor>,
ui: UiStore, history: RouterHistory,
}; };
@observer @observer
class Editor extends React.Component<Props> { class Editor extends React.Component<PropsWithRef> {
@observable redirectTo: ?string; @observable redirectTo: ?string;
onUploadImage = async (file: File) => { onUploadImage = async (file: File) => {
@ -62,7 +65,9 @@ class Editor extends React.Component<Props> {
}; };
onShowToast = (message: string) => { onShowToast = (message: string) => {
this.props.ui.showToast(message); if (this.props.ui) {
this.props.ui.showToast(message);
}
}; };
render() { render() {
@ -120,6 +125,6 @@ const Span = styled.span`
const EditorWithRouterAndTheme = withRouter(withTheme(Editor)); const EditorWithRouterAndTheme = withRouter(withTheme(Editor));
export default React.forwardRef((props, ref) => ( export default React.forwardRef<Props, typeof Editor>((props, ref) => (
<EditorWithRouterAndTheme {...props} forwardedRef={ref} /> <EditorWithRouterAndTheme {...props} forwardedRef={ref} />
)); ));

View File

@ -46,15 +46,15 @@ class GroupListItem extends React.Component<Props> {
const overflow = memberCount - users.length; const overflow = memberCount - users.length;
return ( return (
<React.Fragment> <>
<ListItem <ListItem
title={ title={
<Title onClick={this.handleMembersModalOpen}>{group.name}</Title> <Title onClick={this.handleMembersModalOpen}>{group.name}</Title>
} }
subtitle={ subtitle={
<React.Fragment> <>
{memberCount} member{memberCount === 1 ? "" : "s"} {memberCount} member{memberCount === 1 ? "" : "s"}
</React.Fragment> </>
} }
actions={ actions={
<Flex align="center"> <Flex align="center">
@ -79,7 +79,7 @@ class GroupListItem extends React.Component<Props> {
> >
<GroupMembers group={group} onSubmit={this.handleMembersModalClose} /> <GroupMembers group={group} onSubmit={this.handleMembersModalClose} />
</Modal> </Modal>
</React.Fragment> </>
); );
} }
} }

View File

@ -31,7 +31,7 @@ function HoverPreview({ node, documents, onClose, event }: Props) {
const [isVisible, setVisible] = React.useState(false); const [isVisible, setVisible] = React.useState(false);
const timerClose = React.useRef(); const timerClose = React.useRef();
const timerOpen = React.useRef(); const timerOpen = React.useRef();
const cardRef = React.useRef(); const cardRef = React.useRef<?HTMLDivElement>();
const startCloseTimer = () => { const startCloseTimer = () => {
stopOpenTimer(); stopOpenTimer();
@ -68,6 +68,8 @@ function HoverPreview({ node, documents, onClose, event }: Props) {
if (cardRef.current) { if (cardRef.current) {
cardRef.current.addEventListener("mouseenter", stopCloseTimer); cardRef.current.addEventListener("mouseenter", stopCloseTimer);
}
if (cardRef.current) {
cardRef.current.addEventListener("mouseleave", startCloseTimer); cardRef.current.addEventListener("mouseleave", startCloseTimer);
} }
@ -82,6 +84,8 @@ function HoverPreview({ node, documents, onClose, event }: Props) {
if (cardRef.current) { if (cardRef.current) {
cardRef.current.removeEventListener("mouseenter", stopCloseTimer); cardRef.current.removeEventListener("mouseenter", stopCloseTimer);
}
if (cardRef.current) {
cardRef.current.removeEventListener("mouseleave", startCloseTimer); cardRef.current.removeEventListener("mouseleave", startCloseTimer);
} }

View File

@ -48,7 +48,7 @@ class InputRich extends React.Component<Props> {
const Editor = this.editorComponent; const Editor = this.editorComponent;
return ( return (
<React.Fragment> <>
<LabelText>{label}</LabelText> <LabelText>{label}</LabelText>
<StyledOutline <StyledOutline
@ -67,7 +67,7 @@ class InputRich extends React.Component<Props> {
"Loading…" "Loading…"
)} )}
</StyledOutline> </StyledOutline>
</React.Fragment> </>
); );
} }
} }

View File

@ -64,7 +64,7 @@ const Modal = ({
if (!isOpen) return null; if (!isOpen) return null;
return ( return (
<React.Fragment> <>
<GlobalStyles /> <GlobalStyles />
<StyledModal <StyledModal
contentLabel={title} contentLabel={title}
@ -85,7 +85,7 @@ const Modal = ({
<CloseIcon size={32} color="currentColor" /> <CloseIcon size={32} color="currentColor" />
</Close> </Close>
</StyledModal> </StyledModal>
</React.Fragment> </>
); );
}; };

View File

@ -20,6 +20,6 @@ const Button = styled.button`
} }
`; `;
export default React.forwardRef((props, ref) => ( export default React.forwardRef<any, typeof Button>((props, ref) => (
<Button {...props} ref={ref} /> <Button {...props} ref={ref} />
)); ));

View File

@ -106,10 +106,10 @@ class PaginatedList extends React.Component<Props> {
(this.isLoaded || this.isInitiallyLoaded) && !showLoading && !showEmpty; (this.isLoaded || this.isInitiallyLoaded) && !showLoading && !showEmpty;
return ( return (
<React.Fragment> <>
{showEmpty && empty} {showEmpty && empty}
{showList && ( {showList && (
<React.Fragment> <>
{heading} {heading}
<ArrowKeyNavigation <ArrowKeyNavigation
mode={ArrowKeyNavigation.mode.VERTICAL} mode={ArrowKeyNavigation.mode.VERTICAL}
@ -120,10 +120,10 @@ class PaginatedList extends React.Component<Props> {
{this.allowLoadMore && ( {this.allowLoadMore && (
<Waypoint key={this.renderCount} onEnter={this.loadMoreResults} /> <Waypoint key={this.renderCount} onEnter={this.loadMoreResults} />
)} )}
</React.Fragment> </>
)} )}
{showLoading && <ListPlaceholder count={5} />} {showLoading && <ListPlaceholder count={5} />}
</React.Fragment> </>
); );
} }
} }

View File

@ -55,7 +55,7 @@ class Collections extends React.Component<Props> {
const { collections, ui, documents } = this.props; const { collections, ui, documents } = this.props;
const content = ( const content = (
<React.Fragment> <>
{collections.orderedData.map((collection) => ( {collections.orderedData.map((collection) => (
<CollectionLink <CollectionLink
key={collection.id} key={collection.id}
@ -73,7 +73,7 @@ class Collections extends React.Component<Props> {
label="New collection…" label="New collection…"
exact exact
/> />
</React.Fragment> </>
); );
return ( return (

View File

@ -30,7 +30,7 @@ export default function Version() {
<SidebarLink <SidebarLink
href="https://github.com/outline/outline/releases" href="https://github.com/outline/outline/releases"
label={ label={
<React.Fragment> <>
v{version} v{version}
<br /> <br />
<LilBadge> <LilBadge>
@ -40,7 +40,7 @@ export default function Version() {
releasesBehind === 1 ? "" : "s" releasesBehind === 1 ? "" : "s"
} behind`} } behind`}
</LilBadge> </LilBadge>
</React.Fragment> </>
} }
/> />
); );

View File

@ -14,10 +14,10 @@ type Props = {
function Theme({ children, ui }: Props) { function Theme({ children, ui }: Props) {
return ( return (
<ThemeProvider theme={ui.resolvedTheme === "dark" ? dark : light}> <ThemeProvider theme={ui.resolvedTheme === "dark" ? dark : light}>
<React.Fragment> <>
<GlobalStyles /> <GlobalStyles />
{children} {children}
</React.Fragment> </>
</ThemeProvider> </ThemeProvider>
); );
} }

View File

@ -24,9 +24,9 @@ class Tooltip extends React.Component<Props> {
if (shortcut) { if (shortcut) {
content = ( content = (
<React.Fragment> <>
{tooltip} &middot; <Shortcut>{shortcut}</Shortcut> {tooltip} &middot; <Shortcut>{shortcut}</Shortcut>
</React.Fragment> </>
); );
} }

View File

@ -7,13 +7,16 @@ import styled from "styled-components";
type Props = { type Props = {
src?: string, src?: string,
border?: boolean, border?: boolean,
forwardedRef: *,
width?: string, width?: string,
height?: string, height?: string,
}; };
type PropsWithRef = Props & {
forwardedRef: React.Ref<typeof StyledIframe>,
};
@observer @observer
class Frame extends React.Component<Props> { class Frame extends React.Component<PropsWithRef> {
mounted: boolean; mounted: boolean;
@observable isLoaded: boolean = false; @observable isLoaded: boolean = false;
@ -79,6 +82,6 @@ const StyledIframe = styled(Iframe)`
border-radius: 3px; border-radius: 3px;
`; `;
export default React.forwardRef((props, ref) => ( export default React.forwardRef<Props, typeof Frame>((props, ref) => (
<Frame {...props} forwardedRef={ref} /> <Frame {...props} forwardedRef={ref} />
)); ));

View File

@ -21,23 +21,23 @@ const element = document.getElementById("root");
if (element) { if (element) {
render( render(
<React.Fragment> <>
<ErrorBoundary> <ErrorBoundary>
<Provider {...stores}> <Provider {...stores}>
<Theme> <Theme>
<Router> <Router>
<React.Fragment> <>
<ScrollToTop> <ScrollToTop>
<Routes /> <Routes />
</ScrollToTop> </ScrollToTop>
<Toasts /> <Toasts />
</React.Fragment> </>
</Router> </Router>
</Theme> </Theme>
</Provider> </Provider>
</ErrorBoundary> </ErrorBoundary>
{DevTools && <DevTools position={{ bottom: 0, right: 0 }} />} {DevTools && <DevTools position={{ bottom: 0, right: 0 }} />}
</React.Fragment>, </>,
element element
); );
} }

View File

@ -45,7 +45,7 @@ class AccountMenu extends React.Component<Props> {
const { ui } = this.props; const { ui } = this.props;
return ( return (
<React.Fragment> <>
<Modal <Modal
isOpen={this.keyboardShortcutsOpen} isOpen={this.keyboardShortcutsOpen}
onRequestClose={this.handleCloseKeyboardShortcuts} onRequestClose={this.handleCloseKeyboardShortcuts}
@ -118,7 +118,7 @@ class AccountMenu extends React.Component<Props> {
Log out Log out
</DropdownMenuItem> </DropdownMenuItem>
</DropdownMenu> </DropdownMenu>
</React.Fragment> </>
); );
} }
} }

View File

@ -93,7 +93,7 @@ class CollectionMenu extends React.Component<Props> {
const can = policies.abilities(collection.id); const can = policies.abilities(collection.id);
return ( return (
<React.Fragment> <>
<VisuallyHidden> <VisuallyHidden>
<input <input
type="file" type="file"
@ -117,7 +117,7 @@ class CollectionMenu extends React.Component<Props> {
</Modal> </Modal>
<DropdownMenu onOpen={onOpen} onClose={onClose} position={position}> <DropdownMenu onOpen={onOpen} onClose={onClose} position={position}>
{collection && ( {collection && (
<React.Fragment> <>
{can.update && ( {can.update && (
<DropdownMenuItem onClick={this.onNewDocument}> <DropdownMenuItem onClick={this.onNewDocument}>
New document New document
@ -142,13 +142,13 @@ class CollectionMenu extends React.Component<Props> {
Export Export
</DropdownMenuItem> </DropdownMenuItem>
)} )}
</React.Fragment> </>
)} )}
{can.delete && ( {can.delete && (
<DropdownMenuItem onClick={this.onDelete}>Delete</DropdownMenuItem> <DropdownMenuItem onClick={this.onDelete}>Delete</DropdownMenuItem>
)} )}
</DropdownMenu> </DropdownMenu>
</React.Fragment> </>
); );
} }
} }

View File

@ -153,7 +153,7 @@ class DocumentMenu extends React.Component<Props> {
const canViewHistory = can.read && !can.restore; const canViewHistory = can.read && !can.restore;
return ( return (
<React.Fragment> <>
<DropdownMenu <DropdownMenu
className={className} className={className}
position={position} position={position}
@ -197,7 +197,7 @@ class DocumentMenu extends React.Component<Props> {
</DropdownMenuItem> </DropdownMenuItem>
)} )}
{showToggleEmbeds && ( {showToggleEmbeds && (
<React.Fragment> <>
{document.embedsDisabled ? ( {document.embedsDisabled ? (
<DropdownMenuItem onClick={document.enableEmbeds}> <DropdownMenuItem onClick={document.enableEmbeds}>
Enable embeds Enable embeds
@ -207,7 +207,7 @@ class DocumentMenu extends React.Component<Props> {
Disable embeds Disable embeds
</DropdownMenuItem> </DropdownMenuItem>
)} )}
</React.Fragment> </>
)} )}
{!can.restore && <hr />} {!can.restore && <hr />}
@ -247,11 +247,11 @@ class DocumentMenu extends React.Component<Props> {
)} )}
<hr /> <hr />
{canViewHistory && ( {canViewHistory && (
<React.Fragment> <>
<DropdownMenuItem onClick={this.handleDocumentHistory}> <DropdownMenuItem onClick={this.handleDocumentHistory}>
History History
</DropdownMenuItem> </DropdownMenuItem>
</React.Fragment> </>
)} )}
{can.download && ( {can.download && (
<DropdownMenuItem onClick={this.handleExport}> <DropdownMenuItem onClick={this.handleExport}>
@ -282,7 +282,7 @@ class DocumentMenu extends React.Component<Props> {
onSubmit={this.handleCloseTemplateModal} onSubmit={this.handleCloseTemplateModal}
/> />
</Modal> </Modal>
</React.Fragment> </>
); );
} }
} }

View File

@ -50,7 +50,7 @@ class GroupMenu extends React.Component<Props> {
const can = policies.abilities(group.id); const can = policies.abilities(group.id);
return ( return (
<React.Fragment> <>
<Modal <Modal
title="Edit group" title="Edit group"
onRequestClose={this.handleEditModalClose} onRequestClose={this.handleEditModalClose}
@ -75,7 +75,7 @@ class GroupMenu extends React.Component<Props> {
<DropdownMenu onOpen={onOpen} onClose={onClose}> <DropdownMenu onOpen={onOpen} onClose={onClose}>
{group && ( {group && (
<React.Fragment> <>
<DropdownMenuItem onClick={this.props.onMembers}> <DropdownMenuItem onClick={this.props.onMembers}>
Members Members
</DropdownMenuItem> </DropdownMenuItem>
@ -91,10 +91,10 @@ class GroupMenu extends React.Component<Props> {
Delete Delete
</DropdownMenuItem> </DropdownMenuItem>
)} )}
</React.Fragment> </>
)} )}
</DropdownMenu> </DropdownMenu>
</React.Fragment> </>
); );
} }
} }

View File

@ -11,7 +11,7 @@ export default class BaseModel {
this.store = store; this.store = store;
} }
save = async (params) => { save = async (params: ?Object) => {
this.isSaving = true; this.isSaving = true;
try { try {
@ -27,7 +27,7 @@ export default class BaseModel {
} }
}; };
fetch = (options: *) => { fetch = (options?: any) => {
return this.store.fetch(this.id, options); return this.store.fetch(this.id, options);
}; };
@ -44,7 +44,7 @@ export default class BaseModel {
} }
}; };
toJS = () => { toJS = (): Object => {
return { ...this }; return { ...this };
}; };
} }

View File

@ -121,7 +121,7 @@ class CollectionScene extends React.Component<Props> {
return ( return (
<Actions align="center" justify="flex-end"> <Actions align="center" justify="flex-end">
{can.update && ( {can.update && (
<React.Fragment> <>
<Action> <Action>
<InputSearch <InputSearch
placeholder="Search in collection…" placeholder="Search in collection…"
@ -141,7 +141,7 @@ class CollectionScene extends React.Component<Props> {
</Tooltip> </Tooltip>
</Action> </Action>
<Separator /> <Separator />
</React.Fragment> </>
)} )}
<Action> <Action>
<CollectionMenu collection={this.collection} /> <CollectionMenu collection={this.collection} />
@ -165,7 +165,7 @@ class CollectionScene extends React.Component<Props> {
return ( return (
<CenteredContent> <CenteredContent>
{collection ? ( {collection ? (
<React.Fragment> <>
<PageTitle title={collection.name} /> <PageTitle title={collection.name} />
{collection.isEmpty ? ( {collection.isEmpty ? (
<Centered column> <Centered column>
@ -211,7 +211,7 @@ class CollectionScene extends React.Component<Props> {
</Modal> </Modal>
</Centered> </Centered>
) : ( ) : (
<React.Fragment> <>
<Heading> <Heading>
<CollectionIcon collection={collection} size={40} expanded />{" "} <CollectionIcon collection={collection} size={40} expanded />{" "}
{collection.name} {collection.name}
@ -228,12 +228,12 @@ class CollectionScene extends React.Component<Props> {
)} )}
{hasPinnedDocuments && ( {hasPinnedDocuments && (
<React.Fragment> <>
<Subheading> <Subheading>
<TinyPinIcon size={18} /> Pinned <TinyPinIcon size={18} /> Pinned
</Subheading> </Subheading>
<DocumentList documents={pinnedDocuments} showPin /> <DocumentList documents={pinnedDocuments} showPin />
</React.Fragment> </>
)} )}
<Tabs> <Tabs>
@ -296,18 +296,18 @@ class CollectionScene extends React.Component<Props> {
/> />
</Route> </Route>
</Switch> </Switch>
</React.Fragment> </>
)} )}
{this.renderActions()} {this.renderActions()}
</React.Fragment> </>
) : ( ) : (
<React.Fragment> <>
<Heading> <Heading>
<Mask height={35} /> <Mask height={35} />
</Heading> </Heading>
<ListPlaceholder count={5} /> <ListPlaceholder count={5} />
</React.Fragment> </>
)} )}
</CenteredContent> </CenteredContent>
); );

View File

@ -125,7 +125,7 @@ class CollectionMembers extends React.Component<Props> {
return ( return (
<Flex column> <Flex column>
{collection.private ? ( {collection.private ? (
<React.Fragment> <>
<HelpText> <HelpText>
Choose which groups and team members have access to view and edit Choose which groups and team members have access to view and edit
documents in the private <strong>{collection.name}</strong>{" "} documents in the private <strong>{collection.name}</strong>{" "}
@ -146,7 +146,7 @@ class CollectionMembers extends React.Component<Props> {
Add groups Add groups
</Button> </Button>
</span> </span>
</React.Fragment> </>
) : ( ) : (
<HelpText> <HelpText>
The <strong>{collection.name}</strong> collection is accessible by The <strong>{collection.name}</strong> collection is accessible by
@ -195,7 +195,7 @@ class CollectionMembers extends React.Component<Props> {
</GroupsWrap> </GroupsWrap>
)} )}
{collection.private ? ( {collection.private ? (
<React.Fragment> <>
<span> <span>
<Button <Button
type="button" type="button"
@ -208,7 +208,7 @@ class CollectionMembers extends React.Component<Props> {
</span> </span>
<Subheading>Individual Members</Subheading> <Subheading>Individual Members</Subheading>
</React.Fragment> </>
) : ( ) : (
<Subheading>Members</Subheading> <Subheading>Members</Subheading>
)} )}

View File

@ -30,7 +30,7 @@ const MemberListItem = ({
onRemove={onRemove} onRemove={onRemove}
onUpdate={onUpdate} onUpdate={onUpdate}
renderActions={({ openMembersModal }) => ( renderActions={({ openMembersModal }) => (
<React.Fragment> <>
<Select <Select
label="Permissions" label="Permissions"
options={PERMISSIONS} options={PERMISSIONS}
@ -51,7 +51,7 @@ const MemberListItem = ({
<DropdownMenuItem onClick={onRemove}>Remove</DropdownMenuItem> <DropdownMenuItem onClick={onRemove}>Remove</DropdownMenuItem>
</DropdownMenu> </DropdownMenu>
</ButtonWrap> </ButtonWrap>
</React.Fragment> </>
)} )}
/> />
); );

View File

@ -37,17 +37,17 @@ const MemberListItem = ({
<ListItem <ListItem
title={user.name} title={user.name}
subtitle={ subtitle={
<React.Fragment> <>
{user.lastActiveAt ? ( {user.lastActiveAt ? (
<React.Fragment> <>
Active <Time dateTime={user.lastActiveAt} /> ago Active <Time dateTime={user.lastActiveAt} /> ago
</React.Fragment> </>
) : ( ) : (
"Never signed in" "Never signed in"
)} )}
{!user.lastActiveAt && <Badge>Invited</Badge>} {!user.lastActiveAt && <Badge>Invited</Badge>}
{user.isAdmin && <Badge primary={user.isAdmin}>Admin</Badge>} {user.isAdmin && <Badge primary={user.isAdmin}>Admin</Badge>}
</React.Fragment> </>
} }
image={<Avatar src={user.avatarUrl} size={40} />} image={<Avatar src={user.avatarUrl} size={40} />}
actions={ actions={

View File

@ -20,17 +20,17 @@ const UserListItem = ({ user, onAdd, canEdit }: Props) => {
title={user.name} title={user.name}
image={<Avatar src={user.avatarUrl} size={40} />} image={<Avatar src={user.avatarUrl} size={40} />}
subtitle={ subtitle={
<React.Fragment> <>
{user.lastActiveAt ? ( {user.lastActiveAt ? (
<React.Fragment> <>
Active <Time dateTime={user.lastActiveAt} /> ago Active <Time dateTime={user.lastActiveAt} /> ago
</React.Fragment> </>
) : ( ) : (
"Never signed in" "Never signed in"
)} )}
{!user.lastActiveAt && <Badge>Invited</Badge>} {!user.lastActiveAt && <Badge>Invited</Badge>}
{user.isAdmin && <Badge primary={user.isAdmin}>Admin</Badge>} {user.isAdmin && <Badge primary={user.isAdmin}>Admin</Badge>}
</React.Fragment> </>
} }
actions={ actions={
canEdit ? ( canEdit ? (

View File

@ -3,7 +3,7 @@ import invariant from "invariant";
import { observable } from "mobx"; import { observable } from "mobx";
import { observer, inject } from "mobx-react"; import { observer, inject } from "mobx-react";
import * as React from "react"; import * as React from "react";
import type { Location, RouterHistory, Match } from "react-router-dom"; import type { RouterHistory, Match } from "react-router-dom";
import { withRouter } from "react-router-dom"; import { withRouter } from "react-router-dom";
import DocumentsStore from "stores/DocumentsStore"; import DocumentsStore from "stores/DocumentsStore";
import PoliciesStore from "stores/PoliciesStore"; import PoliciesStore from "stores/PoliciesStore";
@ -18,12 +18,13 @@ import DocumentComponent from "./Document";
import HideSidebar from "./HideSidebar"; import HideSidebar from "./HideSidebar";
import Loading from "./Loading"; import Loading from "./Loading";
import SocketPresence from "./SocketPresence"; import SocketPresence from "./SocketPresence";
import { type LocationWithState } from "types";
import { NotFoundError, OfflineError } from "utils/errors"; import { NotFoundError, OfflineError } from "utils/errors";
import { matchDocumentEdit, updateDocumentUrl } from "utils/routeHelpers"; import { matchDocumentEdit, updateDocumentUrl } from "utils/routeHelpers";
type Props = {| type Props = {|
match: Match, match: Match,
location: Location, location: LocationWithState,
shares: SharesStore, shares: SharesStore,
documents: DocumentsStore, documents: DocumentsStore,
policies: PoliciesStore, policies: PoliciesStore,
@ -166,10 +167,10 @@ class DataLoader extends React.Component<Props> {
if (!document) { if (!document) {
return ( return (
<React.Fragment> <>
<Loading location={location} /> <Loading location={location} />
{this.isEditing && <HideSidebar ui={ui} />} {this.isEditing && <HideSidebar ui={ui} />}
</React.Fragment> </>
); );
} }

View File

@ -375,7 +375,7 @@ class DocumentScene extends React.Component<Props> {
<Container justify="center" column auto> <Container justify="center" column auto>
{!readOnly && ( {!readOnly && (
<React.Fragment> <>
<Prompt <Prompt
when={this.isDirty && !this.isUploading} when={this.isDirty && !this.isUploading}
message={DISCARD_CHANGES} message={DISCARD_CHANGES}
@ -384,7 +384,7 @@ class DocumentScene extends React.Component<Props> {
when={this.isUploading && !this.isDirty} when={this.isUploading && !this.isDirty}
message={UPLOADING_WARNING} message={UPLOADING_WARNING}
/> />
</React.Fragment> </>
)} )}
{!isShare && ( {!isShare && (
<Header <Header
@ -427,12 +427,12 @@ class DocumentScene extends React.Component<Props> {
Deleted by {document.updatedBy.name}{" "} Deleted by {document.updatedBy.name}{" "}
<Time dateTime={document.deletedAt} /> ago <Time dateTime={document.deletedAt} /> ago
{document.permanentlyDeletedAt && ( {document.permanentlyDeletedAt && (
<React.Fragment> <>
<br /> <br />
This {document.noun} will be permanently deleted in{" "} This {document.noun} will be permanently deleted in{" "}
<Time dateTime={document.permanentlyDeletedAt} /> unless <Time dateTime={document.permanentlyDeletedAt} /> unless
restored. restored.
</React.Fragment> </>
)} )}
</Notice> </Notice>
)} )}
@ -473,12 +473,12 @@ class DocumentScene extends React.Component<Props> {
/> />
</Flex> </Flex>
{readOnly && !isShare && !revision && ( {readOnly && !isShare && !revision && (
<React.Fragment> <>
<MarkAsViewed document={document} /> <MarkAsViewed document={document} />
<ReferencesWrapper isOnlyTitle={document.isOnlyTitle}> <ReferencesWrapper isOnlyTitle={document.isOnlyTitle}>
<References document={document} /> <References document={document} />
</ReferencesWrapper> </ReferencesWrapper>
</React.Fragment> </>
)} )}
</MaxWidth> </MaxWidth>
</Container> </Container>

View File

@ -25,23 +25,23 @@ type Props = {
@observer @observer
class DocumentEditor extends React.Component<Props> { class DocumentEditor extends React.Component<Props> {
@observable activeLinkEvent: ?MouseEvent; @observable activeLinkEvent: ?MouseEvent;
editor: ?Editor; editor = React.createRef<typeof Editor>();
focusAtStart = () => { focusAtStart = () => {
if (this.editor) { if (this.editor.current) {
this.editor.focusAtStart(); this.editor.current.focusAtStart();
} }
}; };
focusAtEnd = () => { focusAtEnd = () => {
if (this.editor) { if (this.editor.current) {
this.editor.focusAtEnd(); this.editor.current.focusAtEnd();
} }
}; };
getHeadings = () => { getHeadings = () => {
if (this.editor) { if (this.editor.current) {
return this.editor.getHeadings(); return this.editor.current.getHeadings();
} }
return []; return [];
@ -89,7 +89,7 @@ class DocumentEditor extends React.Component<Props> {
/> />
<DocumentMeta isDraft={isDraft} document={document} /> <DocumentMeta isDraft={isDraft} document={document} />
<Editor <Editor
ref={(ref) => (this.editor = ref)} ref={this.editor}
autoFocus={title && !this.props.defaultValue} autoFocus={title && !this.props.defaultValue}
placeholder="…the rest is up to you" placeholder="…the rest is up to you"
onHoverLink={this.handleLinkActive} onHoverLink={this.handleLinkActive}

View File

@ -162,7 +162,7 @@ class Header extends React.Component<Props> {
<BreadcrumbAndContents align="center" justify="flex-start"> <BreadcrumbAndContents align="center" justify="flex-start">
<Breadcrumb document={document} /> <Breadcrumb document={document} />
{!isEditing && ( {!isEditing && (
<React.Fragment> <>
<Slash /> <Slash />
<Tooltip <Tooltip
tooltip={ui.tocVisible ? "Hide contents" : "Show contents"} tooltip={ui.tocVisible ? "Hide contents" : "Show contents"}
@ -183,7 +183,7 @@ class Header extends React.Component<Props> {
small small
/> />
</Tooltip> </Tooltip>
</React.Fragment> </>
)} )}
</BreadcrumbAndContents> </BreadcrumbAndContents>
{this.isScrolled && ( {this.isScrolled && (
@ -216,10 +216,10 @@ class Header extends React.Component<Props> {
<Tooltip <Tooltip
tooltip={ tooltip={
isPubliclyShared ? ( isPubliclyShared ? (
<React.Fragment> <>
Anyone with the link <br /> Anyone with the link <br />
can view this document can view this document
</React.Fragment> </>
) : ( ) : (
"" ""
) )
@ -239,7 +239,7 @@ class Header extends React.Component<Props> {
</Action> </Action>
)} )}
{isEditing && ( {isEditing && (
<React.Fragment> <>
<Action> <Action>
<Tooltip <Tooltip
tooltip="Save" tooltip="Save"
@ -258,7 +258,7 @@ class Header extends React.Component<Props> {
</Button> </Button>
</Tooltip> </Tooltip>
</Action> </Action>
</React.Fragment> </>
)} )}
{canEdit && ( {canEdit && (
<Action> <Action>
@ -330,7 +330,7 @@ class Header extends React.Component<Props> {
</Action> </Action>
)} )}
{!isEditing && ( {!isEditing && (
<React.Fragment> <>
<Separator /> <Separator />
<Action> <Action>
<DocumentMenu <DocumentMenu
@ -340,7 +340,7 @@ class Header extends React.Component<Props> {
showPrint showPrint
/> />
</Action> </Action>
</React.Fragment> </>
)} )}
</Wrapper> </Wrapper>
</Actions> </Actions>

View File

@ -26,7 +26,7 @@ class KeyboardShortcutsButton extends React.Component<Props> {
render() { render() {
return ( return (
<React.Fragment> <>
<Modal <Modal
isOpen={this.keyboardShortcutsOpen} isOpen={this.keyboardShortcutsOpen}
onRequestClose={this.handleCloseKeyboardShortcuts} onRequestClose={this.handleCloseKeyboardShortcuts}
@ -44,7 +44,7 @@ class KeyboardShortcutsButton extends React.Component<Props> {
<KeyboardIcon /> <KeyboardIcon />
</Button> </Button>
</Tooltip> </Tooltip>
</React.Fragment> </>
); );
} }
} }

View File

@ -1,13 +1,13 @@
// @flow // @flow
import * as React from "react"; import * as React from "react";
import type { Location } from "react-router-dom";
import CenteredContent from "components/CenteredContent"; import CenteredContent from "components/CenteredContent";
import LoadingPlaceholder from "components/LoadingPlaceholder"; import LoadingPlaceholder from "components/LoadingPlaceholder";
import PageTitle from "components/PageTitle"; import PageTitle from "components/PageTitle";
import Container from "./Container"; import Container from "./Container";
import type { LocationWithState } from "types";
type Props = {| type Props = {|
location: Location, location: LocationWithState,
|}; |};
export default function Loading({ location }: Props) { export default function Loading({ location }: Props) {

View File

@ -80,7 +80,7 @@ class DocumentShare extends React.Component<Props> {
. .
</HelpText> </HelpText>
{canPublish && ( {canPublish && (
<React.Fragment> <>
<Switch <Switch
id="published" id="published"
label="Publish to internet" label="Publish to internet"
@ -96,7 +96,7 @@ class DocumentShare extends React.Component<Props> {
: "Only team members with access can view this document"} : "Only team members with access can view this document"}
</PrivacyText> </PrivacyText>
</Privacy> </Privacy>
</React.Fragment> </>
)} )}
<br /> <br />
<Input <Input

View File

@ -62,7 +62,7 @@ class GroupMembers extends React.Component<Props> {
return ( return (
<Flex column> <Flex column>
{can.update ? ( {can.update ? (
<React.Fragment> <>
<HelpText> <HelpText>
Add and remove team members in the <strong>{group.name}</strong>{" "} Add and remove team members in the <strong>{group.name}</strong>{" "}
group. Adding people to the group will give them access to any group. Adding people to the group will give them access to any
@ -78,7 +78,7 @@ class GroupMembers extends React.Component<Props> {
Add people Add people
</Button> </Button>
</span> </span>
</React.Fragment> </>
) : ( ) : (
<HelpText> <HelpText>
Listing team members in the <strong>{group.name}</strong> group. Listing team members in the <strong>{group.name}</strong> group.

View File

@ -27,17 +27,17 @@ const GroupMemberListItem = ({
<ListItem <ListItem
title={user.name} title={user.name}
subtitle={ subtitle={
<React.Fragment> <>
{user.lastActiveAt ? ( {user.lastActiveAt ? (
<React.Fragment> <>
Active <Time dateTime={user.lastActiveAt} /> ago Active <Time dateTime={user.lastActiveAt} /> ago
</React.Fragment> </>
) : ( ) : (
"Never signed in" "Never signed in"
)} )}
{!user.lastActiveAt && <Badge>Invited</Badge>} {!user.lastActiveAt && <Badge>Invited</Badge>}
{user.isAdmin && <Badge primary={user.isAdmin}>Admin</Badge>} {user.isAdmin && <Badge primary={user.isAdmin}>Admin</Badge>}
</React.Fragment> </>
} }
image={<Avatar src={user.avatarUrl} size={40} />} image={<Avatar src={user.avatarUrl} size={40} />}
actions={ actions={

View File

@ -20,17 +20,17 @@ const UserListItem = ({ user, onAdd, canEdit }: Props) => {
title={user.name} title={user.name}
image={<Avatar src={user.avatarUrl} size={32} />} image={<Avatar src={user.avatarUrl} size={32} />}
subtitle={ subtitle={
<React.Fragment> <>
{user.lastActiveAt ? ( {user.lastActiveAt ? (
<React.Fragment> <>
Active <Time dateTime={user.lastActiveAt} /> ago Active <Time dateTime={user.lastActiveAt} /> ago
</React.Fragment> </>
) : ( ) : (
"Never signed in" "Never signed in"
)} )}
{!user.lastActiveAt && <Badge>Invited</Badge>} {!user.lastActiveAt && <Badge>Invited</Badge>}
{user.isAdmin && <Badge primary={user.isAdmin}>Admin</Badge>} {user.isAdmin && <Badge primary={user.isAdmin}>Admin</Badge>}
</React.Fragment> </>
} }
actions={ actions={
canEdit ? ( canEdit ? (

View File

@ -51,7 +51,7 @@ class GroupNew extends React.Component<Props> {
render() { render() {
return ( return (
<React.Fragment> <>
<form onSubmit={this.handleSubmit}> <form onSubmit={this.handleSubmit}>
<HelpText> <HelpText>
Groups are for organizing your team. They work best when centered Groups are for organizing your team. They work best when centered
@ -82,7 +82,7 @@ class GroupNew extends React.Component<Props> {
> >
<GroupMembers group={this.group} /> <GroupMembers group={this.group} />
</Modal> </Modal>
</React.Fragment> </>
); );
} }
} }

View File

@ -111,10 +111,10 @@ class Invite extends React.Component<Props> {
Invite team members to join your knowledge base. They will need to Invite team members to join your knowledge base. They will need to
sign in with {team.signinMethods}.{" "} sign in with {team.signinMethods}.{" "}
{can.update && ( {can.update && (
<React.Fragment> <>
As an admin you can also{" "} As an admin you can also{" "}
<Link to="/settings/security">enable email sign-in</Link>. <Link to="/settings/security">enable email sign-in</Link>.
</React.Fragment> </>
)} )}
</HelpText> </HelpText>
)} )}

View File

@ -8,7 +8,7 @@ type Props = {
export default function Notices({ notice }: Props) { export default function Notices({ notice }: Props) {
return ( return (
<React.Fragment> <>
{notice === "google-hd" && ( {notice === "google-hd" && (
<NoticeAlert> <NoticeAlert>
Sorry, Google sign in cannot be used with a personal email. Please try Sorry, Google sign in cannot be used with a personal email. Please try
@ -51,6 +51,6 @@ export default function Notices({ notice }: Props) {
please contact a team admin. please contact a team admin.
</NoticeAlert> </NoticeAlert>
)} )}
</React.Fragment> </>
); );
} }

View File

@ -72,7 +72,7 @@ class Service extends React.Component<Props, State> {
onSubmit={this.handleSubmitEmail} onSubmit={this.handleSubmitEmail}
> >
{this.state.showEmailSignin ? ( {this.state.showEmailSignin ? (
<React.Fragment> <>
<InputLarge <InputLarge
type="email" type="email"
name="email" name="email"
@ -87,7 +87,7 @@ class Service extends React.Component<Props, State> {
<ButtonLarge type="submit" disabled={this.state.isSubmitting}> <ButtonLarge type="submit" disabled={this.state.isSubmitting}>
Sign In Sign In
</ButtonLarge> </ButtonLarge>
</React.Fragment> </>
) : ( ) : (
<ButtonLarge type="submit" icon={<EmailIcon />} fullwidth> <ButtonLarge type="submit" icon={<EmailIcon />} fullwidth>
Continue with Email Continue with Email

View File

@ -125,12 +125,12 @@ class Login extends React.Component<Props, State> {
{...defaultService} {...defaultService}
/> />
{hasMultipleServices && ( {hasMultipleServices && (
<React.Fragment> <>
<Note> <Note>
You signed in with {defaultService.name} last time. You signed in with {defaultService.name} last time.
</Note> </Note>
<Or /> <Or />
</React.Fragment> </>
)} )}
</React.Fragment> </React.Fragment>
)} )}

View File

@ -46,7 +46,7 @@ type Props = {
@observer @observer
class Search extends React.Component<Props> { class Search extends React.Component<Props> {
firstDocument: ?DocumentPreview; firstDocument: ?typeof DocumentPreview;
@observable @observable
query: string = decodeURIComponent(this.props.match.params.term || ""); query: string = decodeURIComponent(this.props.match.params.term || "");

View File

@ -117,7 +117,7 @@ class Details extends React.Component<Props> {
short short
/> />
{env.SUBDOMAINS_ENABLED && ( {env.SUBDOMAINS_ENABLED && (
<React.Fragment> <>
<Input <Input
label="Subdomain" label="Subdomain"
name="subdomain" name="subdomain"
@ -134,7 +134,7 @@ class Details extends React.Component<Props> {
<strong>{this.subdomain}.getoutline.com</strong> <strong>{this.subdomain}.getoutline.com</strong>
</HelpText> </HelpText>
)} )}
</React.Fragment> </>
)} )}
<Button type="submit" disabled={isSaving || !this.isValid}> <Button type="submit" disabled={isSaving || !this.isValid}>
{isSaving ? "Saving…" : "Save"} {isSaving ? "Saving…" : "Save"}

View File

@ -84,14 +84,14 @@ class Events extends React.Component<Props> {
{showLoading ? ( {showLoading ? (
<ListPlaceholder count={5} /> <ListPlaceholder count={5} />
) : ( ) : (
<React.Fragment> <>
{events.orderedData.map((event) => ( {events.orderedData.map((event) => (
<EventListItem event={event} /> <EventListItem event={event} />
))} ))}
{this.allowLoadMore && ( {this.allowLoadMore && (
<Waypoint key={this.offset} onEnter={this.loadMoreResults} /> <Waypoint key={this.offset} onEnter={this.loadMoreResults} />
)} )}
</React.Fragment> </>
)} )}
</List> </List>
</CenteredContent> </CenteredContent>

View File

@ -104,12 +104,12 @@ class People extends React.Component<Props> {
</Tab> </Tab>
{can.invite && ( {can.invite && (
<React.Fragment> <>
<Separator /> <Separator />
<Tab to="/settings/people/invited" exact> <Tab to="/settings/people/invited" exact>
Invited Invited
</Tab> </Tab>
</React.Fragment> </>
)} )}
</Tabs> </Tabs>
<PaginatedList <PaginatedList

View File

@ -16,121 +16,119 @@ const description = (event) => {
switch (event.name) { switch (event.name) {
case "api_keys.create": case "api_keys.create":
return ( return (
<React.Fragment> <>
Created the API token <strong>{event.data.name}</strong> Created the API token <strong>{event.data.name}</strong>
</React.Fragment> </>
); );
case "api_keys.delete": case "api_keys.delete":
return ( return (
<React.Fragment> <>
Revoked the API token <strong>{event.data.name}</strong> Revoked the API token <strong>{event.data.name}</strong>
</React.Fragment> </>
); );
case "teams.create": case "teams.create":
return "Created the team"; return "Created the team";
case "shares.create": case "shares.create":
case "shares.revoke": case "shares.revoke":
return ( return (
<React.Fragment> <>
{capitalize(event.verbPastTense)} a{" "} {capitalize(event.verbPastTense)} a{" "}
<Link to={`/share/${event.modelId || ""}`}>share link</Link> to the{" "} <Link to={`/share/${event.modelId || ""}`}>share link</Link> to the{" "}
<Link to={`/doc/${event.documentId}`}>{event.data.name}</Link>{" "} <Link to={`/doc/${event.documentId}`}>{event.data.name}</Link>{" "}
document document
</React.Fragment> </>
); );
case "shares.update": case "shares.update":
return ( return (
<React.Fragment> <>
{event.data.published ? ( {event.data.published ? (
<React.Fragment> <>
Published a document{" "} Published a document{" "}
<Link to={`/share/${event.modelId || ""}`}>share link</Link> <Link to={`/share/${event.modelId || ""}`}>share link</Link>
</React.Fragment> </>
) : ( ) : (
<React.Fragment> <>
Unpublished a document{" "} Unpublished a document{" "}
<Link to={`/share/${event.modelId || ""}`}>share link</Link> <Link to={`/share/${event.modelId || ""}`}>share link</Link>
</React.Fragment> </>
)} )}
</React.Fragment> </>
); );
case "users.create": case "users.create":
return ( return <>{event.data.name} created an account</>;
<React.Fragment>{event.data.name} created an account</React.Fragment>
);
case "users.invite": case "users.invite":
return ( return (
<React.Fragment> <>
{capitalize(event.verbPastTense)} {event.data.name} ( {capitalize(event.verbPastTense)} {event.data.name} (
<a href={`mailto:${event.data.email || ""}`}> <a href={`mailto:${event.data.email || ""}`}>
{event.data.email || ""} {event.data.email || ""}
</a> </a>
) )
</React.Fragment> </>
); );
case "users.suspend": case "users.suspend":
return ( return (
<React.Fragment> <>
Suspended <strong>{event.data.name}s</strong> account Suspended <strong>{event.data.name}s</strong> account
</React.Fragment> </>
); );
case "users.activate": case "users.activate":
return ( return (
<React.Fragment> <>
Unsuspended <strong>{event.data.name}s</strong> account Unsuspended <strong>{event.data.name}s</strong> account
</React.Fragment> </>
); );
case "users.promote": case "users.promote":
return ( return (
<React.Fragment> <>
Made <strong>{event.data.name}</strong> an admin Made <strong>{event.data.name}</strong> an admin
</React.Fragment> </>
); );
case "users.demote": case "users.demote":
return ( return (
<React.Fragment> <>
Made <strong>{event.data.name}</strong> a member Made <strong>{event.data.name}</strong> a member
</React.Fragment> </>
); );
case "users.delete": case "users.delete":
return "Deleted their account"; return "Deleted their account";
case "groups.create": case "groups.create":
return ( return (
<React.Fragment> <>
Created the group <strong>{event.data.name}</strong> Created the group <strong>{event.data.name}</strong>
</React.Fragment> </>
); );
case "groups.update": case "groups.update":
return ( return (
<React.Fragment> <>
Update the group <strong>{event.data.name}</strong> Update the group <strong>{event.data.name}</strong>
</React.Fragment> </>
); );
case "groups.delete": case "groups.delete":
return ( return (
<React.Fragment> <>
Deleted the group <strong>{event.data.name}</strong> Deleted the group <strong>{event.data.name}</strong>
</React.Fragment> </>
); );
case "collections.add_user": case "collections.add_user":
case "collections.add_group": case "collections.add_group":
return ( return (
<React.Fragment> <>
Granted <strong>{event.data.name}</strong> access to a{" "} Granted <strong>{event.data.name}</strong> access to a{" "}
<Link to={`/collections/${event.collectionId || ""}`}> <Link to={`/collections/${event.collectionId || ""}`}>
collection collection
</Link> </Link>
</React.Fragment> </>
); );
case "collections.remove_user": case "collections.remove_user":
case "collections.remove_group": case "collections.remove_group":
return ( return (
<React.Fragment> <>
Revoked <strong>{event.data.name}</strong> access to a{" "} Revoked <strong>{event.data.name}</strong> access to a{" "}
<Link to={`/collections/${event.collectionId || ""}`}> <Link to={`/collections/${event.collectionId || ""}`}>
collection collection
</Link> </Link>
</React.Fragment> </>
); );
default: default:
} }
@ -138,60 +136,60 @@ const description = (event) => {
if (event.documentId) { if (event.documentId) {
if (event.name === "documents.delete") { if (event.name === "documents.delete") {
return ( return (
<React.Fragment> <>
Deleted the <strong>{event.data.title}</strong> document Deleted the <strong>{event.data.title}</strong> document
</React.Fragment> </>
); );
} }
if (event.name === "documents.create") { if (event.name === "documents.create") {
return ( return (
<React.Fragment> <>
{capitalize(event.verbPastTense)} the{" "} {capitalize(event.verbPastTense)} the{" "}
<Link to={`/doc/${event.documentId}`}> <Link to={`/doc/${event.documentId}`}>
{event.data.title || "Untitled"} {event.data.title || "Untitled"}
</Link>{" "} </Link>{" "}
document{" "} document{" "}
{event.data.templateId && ( {event.data.templateId && (
<React.Fragment> <>
from a <Link to={`/doc/${event.data.templateId}`}>template</Link> from a <Link to={`/doc/${event.data.templateId}`}>template</Link>
</React.Fragment> </>
)} )}
</React.Fragment> </>
); );
} }
return ( return (
<React.Fragment> <>
{capitalize(event.verbPastTense)} the{" "} {capitalize(event.verbPastTense)} the{" "}
<Link to={`/doc/${event.documentId}`}> <Link to={`/doc/${event.documentId}`}>
{event.data.title || "Untitled"} {event.data.title || "Untitled"}
</Link>{" "} </Link>{" "}
document document
</React.Fragment> </>
); );
} }
if (event.collectionId) { if (event.collectionId) {
if (event.name === "collections.delete") { if (event.name === "collections.delete") {
return ( return (
<React.Fragment> <>
Deleted the <strong>{event.data.name}</strong> collection Deleted the <strong>{event.data.name}</strong> collection
</React.Fragment> </>
); );
} }
return ( return (
<React.Fragment> <>
{capitalize(event.verbPastTense)} the{" "} {capitalize(event.verbPastTense)} the{" "}
<Link to={`/collections/${event.collectionId || ""}`}> <Link to={`/collections/${event.collectionId || ""}`}>
{event.data.name} {event.data.name}
</Link>{" "} </Link>{" "}
collection collection
</React.Fragment> </>
); );
} }
if (event.userId) { if (event.userId) {
return ( return (
<React.Fragment> <>
{capitalize(event.verbPastTense)} the user {event.data.name} {capitalize(event.verbPastTense)} the user {event.data.name}
</React.Fragment> </>
); );
} }
return ""; return "";
@ -204,10 +202,10 @@ const EventListItem = ({ event }: Props) => {
title={event.actor.name} title={event.actor.name}
image={<Avatar src={event.actor.avatarUrl} size={32} />} image={<Avatar src={event.actor.avatarUrl} size={32} />}
subtitle={ subtitle={
<React.Fragment> <>
{description(event)} <Time dateTime={event.createdAt} /> ago &middot;{" "} {description(event)} <Time dateTime={event.createdAt} /> ago &middot;{" "}
<strong>{event.name}</strong> <strong>{event.name}</strong>
</React.Fragment> </>
} }
actions={ actions={
event.actorIpAddress ? ( event.actorIpAddress ? (

View File

@ -16,7 +16,6 @@ const NotificationListItem = ({
setting, setting,
title, title,
event, event,
enabled,
onChange, onChange,
disabled, disabled,
description, description,

View File

@ -15,10 +15,10 @@ const ShareListItem = ({ share }: Props) => {
key={share.id} key={share.id}
title={share.documentTitle} title={share.documentTitle}
subtitle={ subtitle={
<React.Fragment> <>
Shared <Time dateTime={share.createdAt} /> ago by{" "} Shared <Time dateTime={share.createdAt} /> ago by{" "}
{share.createdBy.name} {share.createdBy.name}
</React.Fragment> </>
} }
actions={<ShareMenu share={share} />} actions={<ShareMenu share={share} />}
/> />

View File

@ -6,7 +6,7 @@ import ListItem from "components/List/Item";
type Props = { type Props = {
token: ApiKey, token: ApiKey,
onDelete: (tokenId: string) => void, onDelete: (tokenId: string) => Promise<void>,
}; };
const TokenListItem = ({ token, onDelete }: Props) => { const TokenListItem = ({ token, onDelete }: Props) => {

View File

@ -35,7 +35,7 @@ class UserListItem extends React.Component<Props> {
<ListItem <ListItem
title={<Title onClick={this.handleOpenProfile}>{user.name}</Title>} title={<Title onClick={this.handleOpenProfile}>{user.name}</Title>}
image={ image={
<React.Fragment> <>
<Avatar <Avatar
src={user.avatarUrl} src={user.avatarUrl}
size={40} size={40}
@ -46,21 +46,21 @@ class UserListItem extends React.Component<Props> {
isOpen={this.profileOpen} isOpen={this.profileOpen}
onRequestClose={this.handleCloseProfile} onRequestClose={this.handleCloseProfile}
/> />
</React.Fragment> </>
} }
subtitle={ subtitle={
<React.Fragment> <>
{user.email ? `${user.email} · ` : undefined} {user.email ? `${user.email} · ` : undefined}
{user.lastActiveAt ? ( {user.lastActiveAt ? (
<React.Fragment> <>
Active <Time dateTime={user.lastActiveAt} /> ago Active <Time dateTime={user.lastActiveAt} /> ago
</React.Fragment> </>
) : ( ) : (
"Invited" "Invited"
)} )}
{user.isAdmin && <Badge primary={user.isAdmin}>Admin</Badge>} {user.isAdmin && <Badge primary={user.isAdmin}>Admin</Badge>}
{user.isSuspended && <Badge>Suspended</Badge>} {user.isSuspended && <Badge>Suspended</Badge>}
</React.Fragment> </>
} }
actions={showMenu ? <UserMenu user={user} /> : undefined} actions={showMenu ? <UserMenu user={user} /> : undefined}
/> />

View File

@ -1,6 +1,13 @@
// @flow // @flow
import { type Location } from "react-router-dom";
import Document from "models/Document"; import Document from "models/Document";
export type LocationWithState = Location & {
state: {
[key: string]: string,
},
};
export type Toast = { export type Toast = {
id: string, id: string,
createdAt: string, createdAt: string,