chore: Upgrade Prettier 1.8 -> 2.0 (#1436)
This commit is contained in:
@ -12,7 +12,7 @@ export const Action = styled(Flex)`
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
height: 24px;
|
height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ export const Separator = styled.div`
|
|||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
width: 1px;
|
width: 1px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
background: ${props => props.theme.divider};
|
background: ${(props) => props.theme.divider};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Actions = styled(Flex)`
|
const Actions = styled(Flex)`
|
||||||
@ -35,8 +35,8 @@ const Actions = styled(Flex)`
|
|||||||
right: 0;
|
right: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background: ${props => props.theme.background};
|
background: ${(props) => props.theme.background};
|
||||||
transition: ${props => props.theme.backgroundTransition};
|
transition: ${(props) => props.theme.backgroundTransition};
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
-webkit-backdrop-filter: blur(20px);
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ export default class Analytics extends React.Component<Props> {
|
|||||||
// standard Google Analytics script
|
// standard Google Analytics script
|
||||||
window.ga =
|
window.ga =
|
||||||
window.ga ||
|
window.ga ||
|
||||||
function() {
|
function () {
|
||||||
// $FlowIssue
|
// $FlowIssue
|
||||||
(ga.q = ga.q || []).push(arguments);
|
(ga.q = ga.q || []).push(arguments);
|
||||||
};
|
};
|
||||||
|
@ -48,8 +48,8 @@ const IconWrapper = styled.div`
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: -2px;
|
bottom: -2px;
|
||||||
right: -2px;
|
right: -2px;
|
||||||
background: ${props => props.theme.primary};
|
background: ${(props) => props.theme.primary};
|
||||||
border: 2px solid ${props => props.theme.background};
|
border: 2px solid ${(props) => props.theme.background};
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
@ -57,10 +57,10 @@ const IconWrapper = styled.div`
|
|||||||
|
|
||||||
const CircleImg = styled.img`
|
const CircleImg = styled.img`
|
||||||
display: block;
|
display: block;
|
||||||
width: ${props => props.size}px;
|
width: ${(props) => props.size}px;
|
||||||
height: ${props => props.size}px;
|
height: ${(props) => props.size}px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border: 2px solid ${props => props.theme.background};
|
border: 2px solid ${(props) => props.theme.background};
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -47,7 +47,9 @@ class AvatarWithPresence extends React.Component<Props> {
|
|||||||
<strong>{user.name}</strong> {isCurrentUser && "(You)"}
|
<strong>{user.name}</strong> {isCurrentUser && "(You)"}
|
||||||
<br />
|
<br />
|
||||||
{isPresent
|
{isPresent
|
||||||
? isEditing ? "currently editing" : "currently viewing"
|
? isEditing
|
||||||
|
? "currently editing"
|
||||||
|
: "currently viewing"
|
||||||
: `viewed ${distanceInWordsToNow(new Date(lastViewedAt))} ago`}
|
: `viewed ${distanceInWordsToNow(new Date(lastViewedAt))} ago`}
|
||||||
</Centered>
|
</Centered>
|
||||||
}
|
}
|
||||||
@ -77,7 +79,7 @@ const Centered = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const AvatarWrapper = styled.div`
|
const AvatarWrapper = styled.div`
|
||||||
opacity: ${props => (props.isPresent ? 1 : 0.5)};
|
opacity: ${(props) => (props.isPresent ? 1 : 0.5)};
|
||||||
transition: opacity 250ms ease-in-out;
|
transition: opacity 250ms ease-in-out;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -11,7 +11,8 @@ type Props = {
|
|||||||
function Branding({ href = env.URL }: Props) {
|
function Branding({ href = env.URL }: Props) {
|
||||||
return (
|
return (
|
||||||
<Link href={href}>
|
<Link href={href}>
|
||||||
<OutlineLogo size={16} /> Outline
|
<OutlineLogo size={16} />
|
||||||
|
Outline
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -25,17 +26,17 @@ const Link = styled.a`
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-top-right-radius: 2px;
|
border-top-right-radius: 2px;
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
fill: ${props => props.theme.text};
|
fill: ${(props) => props.theme.text};
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: ${props => props.theme.sidebarBackground};
|
background: ${(props) => props.theme.sidebarBackground};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ const Breadcrumb = observer(({ document, collections, onlyText }: Props) => {
|
|||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
{collection.name}
|
{collection.name}
|
||||||
{path.map(n => (
|
{path.map((n) => (
|
||||||
<React.Fragment key={n.id}>
|
<React.Fragment key={n.id}>
|
||||||
<SmallSlash />
|
<SmallSlash />
|
||||||
{n.title}
|
{n.title}
|
||||||
@ -61,7 +61,8 @@ const Breadcrumb = observer(({ document, collections, onlyText }: Props) => {
|
|||||||
{isTemplate && (
|
{isTemplate && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<CollectionName to="/templates">
|
<CollectionName to="/templates">
|
||||||
<ShapesIcon color="currentColor" />
|
<ShapesIcon color="currentColor" />
|
||||||
|
|
||||||
<span>Templates</span>
|
<span>Templates</span>
|
||||||
</CollectionName>
|
</CollectionName>
|
||||||
<Slash />
|
<Slash />
|
||||||
@ -70,14 +71,16 @@ const Breadcrumb = observer(({ document, collections, onlyText }: Props) => {
|
|||||||
{isDraft && (
|
{isDraft && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<CollectionName to="/drafts">
|
<CollectionName to="/drafts">
|
||||||
<EditIcon color="currentColor" />
|
<EditIcon color="currentColor" />
|
||||||
|
|
||||||
<span>Drafts</span>
|
<span>Drafts</span>
|
||||||
</CollectionName>
|
</CollectionName>
|
||||||
<Slash />
|
<Slash />
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
<CollectionName to={collectionUrl(collection.id)}>
|
<CollectionName to={collectionUrl(collection.id)}>
|
||||||
<CollectionIcon collection={collection} expanded />
|
<CollectionIcon collection={collection} expanded />
|
||||||
|
|
||||||
<span>{collection.name}</span>
|
<span>{collection.name}</span>
|
||||||
</CollectionName>
|
</CollectionName>
|
||||||
{isNestedDocument && (
|
{isNestedDocument && (
|
||||||
@ -119,7 +122,7 @@ const SmallSlash = styled(GoToIcon)`
|
|||||||
|
|
||||||
export const Slash = styled(GoToIcon)`
|
export const Slash = styled(GoToIcon)`
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
fill: ${props => props.theme.divider};
|
fill: ${(props) => props.theme.divider};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Overflow = styled(MoreIcon)`
|
const Overflow = styled(MoreIcon)`
|
||||||
@ -134,7 +137,7 @@ const Overflow = styled(MoreIcon)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Crumb = styled(Link)`
|
const Crumb = styled(Link)`
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@ -149,7 +152,7 @@ const Crumb = styled(Link)`
|
|||||||
const CollectionName = styled(Link)`
|
const CollectionName = styled(Link)`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
@ -14,7 +14,7 @@ export default class BreadcrumbMenu extends React.Component<Props> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu label={this.props.label} position="center">
|
<DropdownMenu label={this.props.label} position="center">
|
||||||
{path.map(item => (
|
{path.map((item) => (
|
||||||
<DropdownMenuItem as={Link} to={item.url} key={item.id}>
|
<DropdownMenuItem as={Link} to={item.url} key={item.id}>
|
||||||
{item.title}
|
{item.title}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
@ -5,13 +5,13 @@ import { darken, lighten } from "polished";
|
|||||||
import { ExpandedIcon } from "outline-icons";
|
import { ExpandedIcon } from "outline-icons";
|
||||||
|
|
||||||
const RealButton = styled.button`
|
const RealButton = styled.button`
|
||||||
display: ${props => (props.fullwidth ? "block" : "inline-block")};
|
display: ${(props) => (props.fullwidth ? "block" : "inline-block")};
|
||||||
width: ${props => (props.fullwidth ? "100%" : "auto")};
|
width: ${(props) => (props.fullwidth ? "100%" : "auto")};
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
background: ${props => props.theme.buttonBackground};
|
background: ${(props) => props.theme.buttonBackground};
|
||||||
color: ${props => props.theme.buttonText};
|
color: ${(props) => props.theme.buttonText};
|
||||||
box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 2px;
|
box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 2px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@ -24,7 +24,7 @@ const RealButton = styled.button`
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
fill: ${props => props.iconColor || props.theme.buttonText};
|
fill: ${(props) => props.iconColor || props.theme.buttonText};
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-moz-focus-inner {
|
&::-moz-focus-inner {
|
||||||
@ -33,12 +33,12 @@ const RealButton = styled.button`
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: ${props => darken(0.05, props.theme.buttonBackground)};
|
background: ${(props) => darken(0.05, props.theme.buttonBackground)};
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
transition-duration: 0.05s;
|
transition-duration: 0.05s;
|
||||||
box-shadow: ${props => lighten(0.4, props.theme.buttonBackground)} 0px 0px
|
box-shadow: ${(props) => lighten(0.4, props.theme.buttonBackground)} 0px 0px
|
||||||
0px 3px;
|
0px 3px;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
@ -46,10 +46,10 @@ const RealButton = styled.button`
|
|||||||
&:disabled {
|
&:disabled {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
color: ${props => props.theme.white50};
|
color: ${(props) => props.theme.white50};
|
||||||
}
|
}
|
||||||
|
|
||||||
${props =>
|
${(props) =>
|
||||||
props.neutral &&
|
props.neutral &&
|
||||||
`
|
`
|
||||||
background: ${props.theme.buttonNeutralBackground};
|
background: ${props.theme.buttonNeutralBackground};
|
||||||
@ -80,9 +80,9 @@ const RealButton = styled.button`
|
|||||||
&:disabled {
|
&:disabled {
|
||||||
color: ${props.theme.textTertiary};
|
color: ${props.theme.textTertiary};
|
||||||
}
|
}
|
||||||
`} ${props =>
|
`} ${(props) =>
|
||||||
props.danger &&
|
props.danger &&
|
||||||
`
|
`
|
||||||
background: ${props.theme.danger};
|
background: ${props.theme.danger};
|
||||||
color: ${props.theme.white};
|
color: ${props.theme.white};
|
||||||
|
|
||||||
@ -103,20 +103,20 @@ const Label = styled.span`
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
${props => props.hasIcon && "padding-left: 4px;"};
|
${(props) => props.hasIcon && "padding-left: 4px;"};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Inner = styled.span`
|
export const Inner = styled.span`
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
padding-right: ${props => (props.disclosure ? 2 : 8)}px;
|
padding-right: ${(props) => (props.disclosure ? 2 : 8)}px;
|
||||||
line-height: ${props => (props.hasIcon ? 24 : 32)}px;
|
line-height: ${(props) => (props.hasIcon ? 24 : 32)}px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
min-height: 30px;
|
min-height: 30px;
|
||||||
|
|
||||||
${props => props.hasIcon && props.hasText && "padding-left: 4px;"};
|
${(props) => props.hasIcon && props.hasText && "padding-left: 4px;"};
|
||||||
${props => props.hasIcon && !props.hasText && "padding: 0 4px;"};
|
${(props) => props.hasIcon && !props.hasText && "padding: 0 4px;"};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
|
@ -15,13 +15,13 @@ export type Props = {
|
|||||||
|
|
||||||
const LabelText = styled.span`
|
const LabelText = styled.span`
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-left: ${props => (props.small ? "6px" : "10px")};
|
margin-left: ${(props) => (props.small ? "6px" : "10px")};
|
||||||
${props => (props.small ? `color: ${props.theme.textSecondary}` : "")};
|
${(props) => (props.small ? `color: ${props.theme.textSecondary}` : "")};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
${props => (props.small ? "font-size: 14px" : "")};
|
${(props) => (props.small ? "font-size: 14px" : "")};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Label = styled.label`
|
const Label = styled.label`
|
||||||
|
@ -32,27 +32,27 @@ class Collaborators extends React.Component<Props> {
|
|||||||
|
|
||||||
const documentViews = views.inDocument(document.id);
|
const documentViews = views.inDocument(document.id);
|
||||||
|
|
||||||
const presentIds = documentPresence.map(p => p.userId);
|
const presentIds = documentPresence.map((p) => p.userId);
|
||||||
const editingIds = documentPresence
|
const editingIds = documentPresence
|
||||||
.filter(p => p.isEditing)
|
.filter((p) => p.isEditing)
|
||||||
.map(p => p.userId);
|
.map((p) => p.userId);
|
||||||
|
|
||||||
// ensure currently present via websocket are always ordered first
|
// ensure currently present via websocket are always ordered first
|
||||||
const mostRecentViewers = sortBy(
|
const mostRecentViewers = sortBy(
|
||||||
documentViews.slice(0, MAX_AVATAR_DISPLAY),
|
documentViews.slice(0, MAX_AVATAR_DISPLAY),
|
||||||
view => {
|
(view) => {
|
||||||
return presentIds.includes(view.user.id);
|
return presentIds.includes(view.user.id);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const viewersKeyedByUserId = keyBy(mostRecentViewers, v => v.user.id);
|
const viewersKeyedByUserId = keyBy(mostRecentViewers, (v) => v.user.id);
|
||||||
const overflow = documentViews.length - mostRecentViewers.length;
|
const overflow = documentViews.length - mostRecentViewers.length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Facepile
|
<Facepile
|
||||||
users={mostRecentViewers.map(v => v.user)}
|
users={mostRecentViewers.map((v) => v.user)}
|
||||||
overflow={overflow}
|
overflow={overflow}
|
||||||
renderAvatar={user => {
|
renderAvatar={(user) => {
|
||||||
const isPresent = presentIds.includes(user.id);
|
const isPresent = presentIds.includes(user.id);
|
||||||
const isEditing = editingIds.includes(user.id);
|
const isEditing = editingIds.includes(user.id);
|
||||||
const { lastViewedAt } = viewersKeyedByUserId[user.id];
|
const { lastViewedAt } = viewersKeyedByUserId[user.id];
|
||||||
|
@ -133,16 +133,16 @@ const Wrapper = styled(Flex)`
|
|||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
min-width: ${props => props.theme.sidebarWidth};
|
min-width: ${(props) => props.theme.sidebarWidth};
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overscroll-behavior: none;
|
overscroll-behavior: none;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Sidebar = styled(Flex)`
|
const Sidebar = styled(Flex)`
|
||||||
background: ${props => props.theme.background};
|
background: ${(props) => props.theme.background};
|
||||||
min-width: ${props => props.theme.sidebarWidth};
|
min-width: ${(props) => props.theme.sidebarWidth};
|
||||||
border-left: 1px solid ${props => props.theme.divider};
|
border-left: 1px solid ${(props) => props.theme.divider};
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ const StyledRevisionMenu = styled(RevisionMenu)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledNavLink = styled(NavLink)`
|
const StyledNavLink = styled(NavLink)`
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
display: block;
|
display: block;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
@ -17,7 +17,7 @@ export default function DocumentList({ limit, documents, ...rest }: Props) {
|
|||||||
mode={ArrowKeyNavigation.mode.VERTICAL}
|
mode={ArrowKeyNavigation.mode.VERTICAL}
|
||||||
defaultActiveChildIndex={0}
|
defaultActiveChildIndex={0}
|
||||||
>
|
>
|
||||||
{items.map(document => (
|
{items.map((document) => (
|
||||||
<DocumentPreview key={document.id} document={document} {...rest} />
|
<DocumentPreview key={document.id} document={document} {...rest} />
|
||||||
))}
|
))}
|
||||||
</ArrowKeyNavigation>
|
</ArrowKeyNavigation>
|
||||||
|
@ -48,7 +48,7 @@ class DocumentPreview extends React.Component<Props> {
|
|||||||
return tag.replace(/<b\b[^>]*>(.*?)<\/b>/gi, "$1");
|
return tag.replace(/<b\b[^>]*>(.*?)<\/b>/gi, "$1");
|
||||||
};
|
};
|
||||||
|
|
||||||
handleNewFromTemplate = event => {
|
handleNewFromTemplate = (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
@ -97,18 +97,14 @@ class DocumentPreview extends React.Component<Props> {
|
|||||||
)}
|
)}
|
||||||
</Actions>
|
</Actions>
|
||||||
)}
|
)}
|
||||||
{document.isDraft &&
|
{document.isDraft && showDraft && (
|
||||||
showDraft && (
|
<Tooltip tooltip="Only visible to you" delay={500} placement="top">
|
||||||
<Tooltip
|
<Badge>Draft</Badge>
|
||||||
tooltip="Only visible to you"
|
</Tooltip>
|
||||||
delay={500}
|
)}
|
||||||
placement="top"
|
{document.isTemplate && showTemplate && (
|
||||||
>
|
<Badge primary>Template</Badge>
|
||||||
<Badge>Draft</Badge>
|
)}
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
{document.isTemplate &&
|
|
||||||
showTemplate && <Badge primary>Template</Badge>}
|
|
||||||
<SecondaryActions>
|
<SecondaryActions>
|
||||||
{document.isTemplate &&
|
{document.isTemplate &&
|
||||||
!document.isArchived &&
|
!document.isArchived &&
|
||||||
@ -120,7 +116,8 @@ class DocumentPreview extends React.Component<Props> {
|
|||||||
>
|
>
|
||||||
New doc
|
New doc
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<DocumentMenu document={document} showPin={showPin} />
|
<DocumentMenu document={document} showPin={showPin} />
|
||||||
</SecondaryActions>
|
</SecondaryActions>
|
||||||
</Heading>
|
</Heading>
|
||||||
@ -146,7 +143,7 @@ const StyledStar = withTheme(styled(({ solid, theme, ...props }) => (
|
|||||||
<StarredIcon color={theme.text} {...props} />
|
<StarredIcon color={theme.text} {...props} />
|
||||||
))`
|
))`
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
opacity: ${props => (props.solid ? "1 !important" : 0)};
|
opacity: ${(props) => (props.solid ? "1 !important" : 0)};
|
||||||
transition: all 100ms ease-in-out;
|
transition: all 100ms ease-in-out;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@ -182,7 +179,7 @@ const DocumentLink = styled(Link)`
|
|||||||
&:hover,
|
&:hover,
|
||||||
&:active,
|
&:active,
|
||||||
&:focus {
|
&:focus {
|
||||||
background: ${props => props.theme.listItemHoverBackground};
|
background: ${(props) => props.theme.listItemHoverBackground};
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
${SecondaryActions} {
|
${SecondaryActions} {
|
||||||
@ -207,7 +204,7 @@ const Heading = styled.h3`
|
|||||||
margin-bottom: 0.25em;
|
margin-bottom: 0.25em;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
|
||||||
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
||||||
`;
|
`;
|
||||||
@ -225,7 +222,7 @@ const Title = styled(Highlight)`
|
|||||||
|
|
||||||
const ResultContext = styled(Highlight)`
|
const ResultContext = styled(Highlight)`
|
||||||
display: block;
|
display: block;
|
||||||
color: ${props => props.theme.textTertiary};
|
color: ${(props) => props.theme.textTertiary};
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-top: -0.25em;
|
margin-top: -0.25em;
|
||||||
margin-bottom: 0.25em;
|
margin-bottom: 0.25em;
|
||||||
|
@ -30,12 +30,12 @@ type Props = {
|
|||||||
export const GlobalStyles = createGlobalStyle`
|
export const GlobalStyles = createGlobalStyle`
|
||||||
.activeDropZone {
|
.activeDropZone {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: ${props => props.theme.slateDark};
|
background: ${(props) => props.theme.slateDark};
|
||||||
svg { fill: ${props => props.theme.white}; }
|
svg { fill: ${(props) => props.theme.white}; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.activeDropZone a {
|
.activeDropZone a {
|
||||||
color: ${props => props.theme.white} !important;
|
color: ${(props) => props.theme.white} !important;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ class DropdownMenu extends React.Component<Props> {
|
|||||||
onClick={
|
onClick={
|
||||||
typeof children === "function"
|
typeof children === "function"
|
||||||
? undefined
|
? undefined
|
||||||
: ev => {
|
: (ev) => {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
closePortal();
|
closePortal();
|
||||||
}
|
}
|
||||||
@ -245,24 +245,24 @@ const Position = styled.div`
|
|||||||
${({ bottom }) => (bottom !== undefined ? `bottom: ${bottom}px` : "")};
|
${({ bottom }) => (bottom !== undefined ? `bottom: ${bottom}px` : "")};
|
||||||
max-height: 75%;
|
max-height: 75%;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
transform: ${props =>
|
transform: ${(props) =>
|
||||||
props.position === "center" ? "translateX(-50%)" : "initial"};
|
props.position === "center" ? "translateX(-50%)" : "initial"};
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Menu = styled.div`
|
const Menu = styled.div`
|
||||||
animation: ${fadeAndScaleIn} 200ms ease;
|
animation: ${fadeAndScaleIn} 200ms ease;
|
||||||
transform-origin: ${props => (props.left !== undefined ? "25%" : "75%")} 0;
|
transform-origin: ${(props) => (props.left !== undefined ? "25%" : "75%")} 0;
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
background: ${props => rgba(props.theme.menuBackground, 0.8)};
|
background: ${(props) => rgba(props.theme.menuBackground, 0.8)};
|
||||||
border: ${props =>
|
border: ${(props) =>
|
||||||
props.theme.menuBorder ? `1px solid ${props.theme.menuBorder}` : "none"};
|
props.theme.menuBorder ? `1px solid ${props.theme.menuBorder}` : "none"};
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
padding: 0.5em 0;
|
padding: 0.5em 0;
|
||||||
min-width: 180px;
|
min-width: 180px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
box-shadow: ${props => props.theme.menuShadow};
|
box-shadow: ${(props) => props.theme.menuShadow};
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
@ -278,7 +278,7 @@ export const Header = styled.h3`
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: ${props => props.theme.sidebarText};
|
color: ${(props) => props.theme.sidebarText};
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
margin: 1em 12px 0.5em;
|
margin: 1em 12px 0.5em;
|
||||||
`;
|
`;
|
||||||
|
@ -29,7 +29,8 @@ const DropdownMenuItem = ({
|
|||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<CheckmarkIcon
|
<CheckmarkIcon
|
||||||
color={selected === false ? "transparent" : undefined}
|
color={selected === false ? "transparent" : undefined}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
{children}
|
{children}
|
||||||
@ -44,7 +45,7 @@ const MenuItem = styled.a`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 32px;
|
min-height: 32px;
|
||||||
|
|
||||||
color: ${props =>
|
color: ${(props) =>
|
||||||
props.disabled ? props.theme.textTertiary : props.theme.textSecondary};
|
props.disabled ? props.theme.textTertiary : props.theme.textSecondary};
|
||||||
justify-content: left;
|
justify-content: left;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -57,10 +58,10 @@ const MenuItem = styled.a`
|
|||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
opacity: ${props => (props.disabled ? ".5" : 1)};
|
opacity: ${(props) => (props.disabled ? ".5" : 1)};
|
||||||
}
|
}
|
||||||
|
|
||||||
${props =>
|
${(props) =>
|
||||||
props.disabled
|
props.disabled
|
||||||
? "pointer-events: none;"
|
? "pointer-events: none;"
|
||||||
: `
|
: `
|
||||||
|
@ -81,11 +81,11 @@ class Editor extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const StyledEditor = styled(RichMarkdownEditor)`
|
const StyledEditor = styled(RichMarkdownEditor)`
|
||||||
flex-grow: ${props => (props.grow ? 1 : 0)};
|
flex-grow: ${(props) => (props.grow ? 1 : 0)};
|
||||||
justify-content: start;
|
justify-content: start;
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
transition: ${props => props.theme.backgroundTransition};
|
transition: ${(props) => props.theme.backgroundTransition};
|
||||||
}
|
}
|
||||||
|
|
||||||
.notice-block.tip,
|
.notice-block.tip,
|
||||||
@ -95,13 +95,13 @@ const StyledEditor = styled(RichMarkdownEditor)`
|
|||||||
|
|
||||||
p {
|
p {
|
||||||
a {
|
a {
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
border-bottom: 1px solid ${props => lighten(0.5, props.theme.text)};
|
border-bottom: 1px solid ${(props) => lighten(0.5, props.theme.text)};
|
||||||
text-decoration: none !important;
|
text-decoration: none !important;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-bottom: 1px solid ${props => props.theme.text};
|
border-bottom: 1px solid ${(props) => props.theme.text};
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
const Empty = styled.p`
|
const Empty = styled.p`
|
||||||
color: ${props => props.theme.textTertiary};
|
color: ${(props) => props.theme.textTertiary};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default Empty;
|
export default Empty;
|
||||||
|
@ -48,9 +48,9 @@ class ErrorBoundary extends React.Component<Props> {
|
|||||||
<PageTitle title="Something Unexpected Happened" />
|
<PageTitle title="Something Unexpected Happened" />
|
||||||
<h1>Something Unexpected Happened</h1>
|
<h1>Something Unexpected Happened</h1>
|
||||||
<HelpText>
|
<HelpText>
|
||||||
Sorry, an unrecoverable error occurred{isReported &&
|
Sorry, an unrecoverable error occurred
|
||||||
" – our engineers have been notified"}. Please try reloading the
|
{isReported && " – our engineers have been notified"}. Please try
|
||||||
page, it may have been a temporary glitch.
|
reloading the page, it may have been a temporary glitch.
|
||||||
</HelpText>
|
</HelpText>
|
||||||
{this.showDetails && <Pre>{this.error.toString()}</Pre>}
|
{this.showDetails && <Pre>{this.error.toString()}</Pre>}
|
||||||
<p>
|
<p>
|
||||||
@ -73,7 +73,7 @@ class ErrorBoundary extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Pre = styled.pre`
|
const Pre = styled.pre`
|
||||||
background: ${props => props.theme.smoke};
|
background: ${(props) => props.theme.smoke};
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
@ -31,7 +31,7 @@ class Facepile extends React.Component<Props> {
|
|||||||
<span>+{overflow}</span>
|
<span>+{overflow}</span>
|
||||||
</More>
|
</More>
|
||||||
)}
|
)}
|
||||||
{users.map(user => (
|
{users.map((user) => (
|
||||||
<AvatarWrapper key={user.id}>{renderAvatar(user)}</AvatarWrapper>
|
<AvatarWrapper key={user.id}>{renderAvatar(user)}</AvatarWrapper>
|
||||||
))}
|
))}
|
||||||
</Avatars>
|
</Avatars>
|
||||||
@ -56,12 +56,12 @@ const More = styled.div`
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
min-width: ${props => props.size}px;
|
min-width: ${(props) => props.size}px;
|
||||||
height: ${props => props.size}px;
|
height: ${(props) => props.size}px;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
background: ${props => props.theme.slate};
|
background: ${(props) => props.theme.slate};
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
border: 2px solid ${props => props.theme.background};
|
border: 2px solid ${(props) => props.theme.background};
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
@ -3,7 +3,7 @@ import styled from "styled-components";
|
|||||||
import { fadeIn } from "shared/styles/animations";
|
import { fadeIn } from "shared/styles/animations";
|
||||||
|
|
||||||
const Fade = styled.span`
|
const Fade = styled.span`
|
||||||
animation: ${fadeIn} ${props => props.timing || "250ms"} ease-in-out;
|
animation: ${fadeIn} ${(props) => props.timing || "250ms"} ease-in-out;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default Fade;
|
export default Fade;
|
||||||
|
@ -41,7 +41,7 @@ class GroupListItem extends React.Component<Props> {
|
|||||||
const membershipsInGroup = groupMemberships.inGroup(group.id);
|
const membershipsInGroup = groupMemberships.inGroup(group.id);
|
||||||
const users = membershipsInGroup
|
const users = membershipsInGroup
|
||||||
.slice(0, MAX_AVATAR_DISPLAY)
|
.slice(0, MAX_AVATAR_DISPLAY)
|
||||||
.map(gm => gm.user);
|
.map((gm) => gm.user);
|
||||||
|
|
||||||
const overflow = memberCount - users.length;
|
const overflow = memberCount - users.length;
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@ import styled from "styled-components";
|
|||||||
|
|
||||||
const HelpText = styled.p`
|
const HelpText = styled.p`
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
color: ${props => props.theme.textSecondary};
|
color: ${(props) => props.theme.textSecondary};
|
||||||
font-size: ${props => (props.small ? "13px" : "inherit")};
|
font-size: ${(props) => (props.small ? "13px" : "inherit")};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default HelpText;
|
export default HelpText;
|
||||||
|
@ -38,7 +38,7 @@ function Highlight({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Mark = styled.mark`
|
const Mark = styled.mark`
|
||||||
background: ${props => props.theme.yellow};
|
background: ${(props) => props.theme.yellow};
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
padding: 0 4px;
|
padding: 0 4px;
|
||||||
`;
|
`;
|
||||||
|
@ -57,42 +57,39 @@ function HoverPreview({ node, documents, onClose, event }: Props) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
React.useEffect(
|
React.useEffect(() => {
|
||||||
() => {
|
if (slug) {
|
||||||
if (slug) {
|
documents.prefetchDocument(slug, {
|
||||||
documents.prefetchDocument(slug, {
|
prefetch: true,
|
||||||
prefetch: true,
|
});
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
|
||||||
startOpenTimer();
|
startOpenTimer();
|
||||||
|
|
||||||
|
if (cardRef.current) {
|
||||||
|
cardRef.current.addEventListener("mouseenter", stopCloseTimer);
|
||||||
|
cardRef.current.addEventListener("mouseleave", startCloseTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
node.addEventListener("mouseout", startCloseTimer);
|
||||||
|
node.addEventListener("mouseover", stopCloseTimer);
|
||||||
|
node.addEventListener("mouseover", startOpenTimer);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
node.removeEventListener("mouseout", startCloseTimer);
|
||||||
|
node.removeEventListener("mouseover", stopCloseTimer);
|
||||||
|
node.removeEventListener("mouseover", startOpenTimer);
|
||||||
|
|
||||||
if (cardRef.current) {
|
if (cardRef.current) {
|
||||||
cardRef.current.addEventListener("mouseenter", stopCloseTimer);
|
cardRef.current.removeEventListener("mouseenter", stopCloseTimer);
|
||||||
cardRef.current.addEventListener("mouseleave", startCloseTimer);
|
cardRef.current.removeEventListener("mouseleave", startCloseTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
node.addEventListener("mouseout", startCloseTimer);
|
if (timerClose.current) {
|
||||||
node.addEventListener("mouseover", stopCloseTimer);
|
clearTimeout(timerClose.current);
|
||||||
node.addEventListener("mouseover", startOpenTimer);
|
}
|
||||||
|
};
|
||||||
return () => {
|
}, [node]);
|
||||||
node.removeEventListener("mouseout", startCloseTimer);
|
|
||||||
node.removeEventListener("mouseover", stopCloseTimer);
|
|
||||||
node.removeEventListener("mouseover", startOpenTimer);
|
|
||||||
|
|
||||||
if (cardRef.current) {
|
|
||||||
cardRef.current.removeEventListener("mouseenter", stopCloseTimer);
|
|
||||||
cardRef.current.removeEventListener("mouseleave", startCloseTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timerClose.current) {
|
|
||||||
clearTimeout(timerClose.current);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
[node]
|
|
||||||
);
|
|
||||||
|
|
||||||
const anchorBounds = node.getBoundingClientRect();
|
const anchorBounds = node.getBoundingClientRect();
|
||||||
const cardBounds = cardRef.current
|
const cardBounds = cardRef.current
|
||||||
@ -112,7 +109,7 @@ function HoverPreview({ node, documents, onClose, event }: Props) {
|
|||||||
>
|
>
|
||||||
<div ref={cardRef}>
|
<div ref={cardRef}>
|
||||||
<HoverPreviewDocument url={node.href}>
|
<HoverPreviewDocument url={node.href}>
|
||||||
{content =>
|
{(content) =>
|
||||||
isVisible ? (
|
isVisible ? (
|
||||||
<Animate>
|
<Animate>
|
||||||
<Card>
|
<Card>
|
||||||
@ -156,8 +153,8 @@ const CardContent = styled.div`
|
|||||||
// &:after — gradient mask for overflow text
|
// &:after — gradient mask for overflow text
|
||||||
const Card = styled.div`
|
const Card = styled.div`
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
background: ${props => props.theme.background};
|
background: ${(props) => props.theme.background};
|
||||||
border: ${props =>
|
border: ${(props) =>
|
||||||
props.theme.menuBorder ? `1px solid ${props.theme.menuBorder}` : "none"};
|
props.theme.menuBorder ? `1px solid ${props.theme.menuBorder}` : "none"};
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
box-shadow: 0 30px 90px -20px rgba(0, 0, 0, 0.3),
|
box-shadow: 0 30px 90px -20px rgba(0, 0, 0, 0.3),
|
||||||
@ -179,15 +176,15 @@ const Card = styled.div`
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
90deg,
|
90deg,
|
||||||
${props => transparentize(1, props.theme.background)} 0%,
|
${(props) => transparentize(1, props.theme.background)} 0%,
|
||||||
${props => transparentize(1, props.theme.background)} 75%,
|
${(props) => transparentize(1, props.theme.background)} 75%,
|
||||||
${props => props.theme.background} 90%
|
${(props) => props.theme.background} 90%
|
||||||
);
|
);
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
height: 1.7em;
|
height: 1.7em;
|
||||||
border-bottom: 16px solid ${props => props.theme.background};
|
border-bottom: 16px solid ${(props) => props.theme.background};
|
||||||
border-bottom-left-radius: 4px;
|
border-bottom-left-radius: 4px;
|
||||||
border-bottom-right-radius: 4px;
|
border-bottom-right-radius: 4px;
|
||||||
}
|
}
|
||||||
@ -205,7 +202,7 @@ const Position = styled.div`
|
|||||||
|
|
||||||
const Pointer = styled.div`
|
const Pointer = styled.div`
|
||||||
top: -22px;
|
top: -22px;
|
||||||
left: ${props => props.offset}px;
|
left: ${(props) => props.offset}px;
|
||||||
width: 22px;
|
width: 22px;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -222,14 +219,14 @@ const Pointer = styled.div`
|
|||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
border: 8px solid transparent;
|
border: 8px solid transparent;
|
||||||
border-bottom-color: ${props =>
|
border-bottom-color: ${(props) =>
|
||||||
props.theme.menuBorder || "rgba(0, 0, 0, 0.1)"};
|
props.theme.menuBorder || "rgba(0, 0, 0, 0.1)"};
|
||||||
right: -1px;
|
right: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
border: 7px solid transparent;
|
border: 7px solid transparent;
|
||||||
border-bottom-color: ${props => props.theme.background};
|
border-bottom-color: ${(props) => props.theme.background};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import DocumentMeta from "components/DocumentMeta";
|
|||||||
type Props = {
|
type Props = {
|
||||||
url: string,
|
url: string,
|
||||||
documents: DocumentsStore,
|
documents: DocumentsStore,
|
||||||
children: React.Node => React.Node,
|
children: (React.Node) => React.Node,
|
||||||
};
|
};
|
||||||
|
|
||||||
function HoverPreviewDocument({ url, documents, children }: Props) {
|
function HoverPreviewDocument({ url, documents, children }: Props) {
|
||||||
@ -45,7 +45,7 @@ const Content = styled(Link)`
|
|||||||
|
|
||||||
const Heading = styled.h2`
|
const Heading = styled.h2`
|
||||||
margin: 0 0 0.75em;
|
margin: 0 0 0.75em;
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default inject("documents")(observer(HoverPreviewDocument));
|
export default inject("documents")(observer(HoverPreviewDocument));
|
||||||
|
@ -166,7 +166,7 @@ class IconPicker extends React.Component<Props> {
|
|||||||
const Component = icons[this.props.icon || "collection"].component;
|
const Component = icons[this.props.icon || "collection"].component;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper ref={ref => (this.node = ref)}>
|
<Wrapper ref={(ref) => (this.node = ref)}>
|
||||||
<label>
|
<label>
|
||||||
<LabelText>Icon</LabelText>
|
<LabelText>Icon</LabelText>
|
||||||
</label>
|
</label>
|
||||||
@ -179,7 +179,7 @@ class IconPicker extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Icons onClick={preventEventBubble}>
|
<Icons onClick={preventEventBubble}>
|
||||||
{Object.keys(icons).map(name => {
|
{Object.keys(icons).map((name) => {
|
||||||
const Component = icons[name].component;
|
const Component = icons[name].component;
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
@ -195,7 +195,7 @@ class IconPicker extends React.Component<Props> {
|
|||||||
<Flex onClick={preventEventBubble}>
|
<Flex onClick={preventEventBubble}>
|
||||||
<ColorPicker
|
<ColorPicker
|
||||||
color={this.props.color}
|
color={this.props.color}
|
||||||
onChange={color =>
|
onChange={(color) =>
|
||||||
this.props.onChange(color.hex, this.props.icon)
|
this.props.onChange(color.hex, this.props.icon)
|
||||||
}
|
}
|
||||||
colors={colors}
|
colors={colors}
|
||||||
@ -214,7 +214,7 @@ const Icons = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const LabelButton = styled(NudeButton)`
|
const LabelButton = styled(NudeButton)`
|
||||||
border: 1px solid ${props => props.theme.inputBorder};
|
border: 1px solid ${(props) => props.theme.inputBorder};
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
`;
|
`;
|
||||||
|
@ -9,29 +9,29 @@ import Flex from "components/Flex";
|
|||||||
const RealTextarea = styled.textarea`
|
const RealTextarea = styled.textarea`
|
||||||
border: 0;
|
border: 0;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 8px 12px 8px ${props => (props.hasIcon ? "8px" : "12px")};
|
padding: 8px 12px 8px ${(props) => (props.hasIcon ? "8px" : "12px")};
|
||||||
outline: none;
|
outline: none;
|
||||||
background: none;
|
background: none;
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
|
|
||||||
&:disabled,
|
&:disabled,
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
color: ${props => props.theme.placeholder};
|
color: ${(props) => props.theme.placeholder};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const RealInput = styled.input`
|
const RealInput = styled.input`
|
||||||
border: 0;
|
border: 0;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 8px 12px 8px ${props => (props.hasIcon ? "8px" : "12px")};
|
padding: 8px 12px 8px ${(props) => (props.hasIcon ? "8px" : "12px")};
|
||||||
outline: none;
|
outline: none;
|
||||||
background: none;
|
background: none;
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
height: 30px;
|
height: 30px;
|
||||||
|
|
||||||
&:disabled,
|
&:disabled,
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
color: ${props => props.theme.placeholder};
|
color: ${(props) => props.theme.placeholder};
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-search-cancel-button {
|
&::-webkit-search-cancel-button {
|
||||||
@ -40,8 +40,8 @@ const RealInput = styled.input`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
flex: ${props => (props.flex ? "1" : "0")};
|
flex: ${(props) => (props.flex ? "1" : "0")};
|
||||||
max-width: ${props => (props.short ? "350px" : "100%")};
|
max-width: ${(props) => (props.short ? "350px" : "100%")};
|
||||||
min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : "0")};
|
min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : "0")};
|
||||||
max-height: ${({ maxHeight }) => (maxHeight ? `${maxHeight}px` : "initial")};
|
max-height: ${({ maxHeight }) => (maxHeight ? `${maxHeight}px` : "initial")};
|
||||||
`;
|
`;
|
||||||
@ -56,16 +56,17 @@ const IconWrapper = styled.span`
|
|||||||
export const Outline = styled(Flex)`
|
export const Outline = styled(Flex)`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin: ${props => (props.margin !== undefined ? props.margin : "0 0 16px")};
|
margin: ${(props) =>
|
||||||
|
props.margin !== undefined ? props.margin : "0 0 16px"};
|
||||||
color: inherit;
|
color: inherit;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: ${props =>
|
border-color: ${(props) =>
|
||||||
props.hasError
|
props.hasError
|
||||||
? "red"
|
? "red"
|
||||||
: props.focused
|
: props.focused
|
||||||
? props.theme.inputBorderFocused
|
? props.theme.inputBorderFocused
|
||||||
: props.theme.inputBorder};
|
: props.theme.inputBorder};
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -147,7 +148,7 @@ class Input extends React.Component<Props> {
|
|||||||
<Outline focused={this.focused} margin={margin}>
|
<Outline focused={this.focused} margin={margin}>
|
||||||
{icon && <IconWrapper>{icon}</IconWrapper>}
|
{icon && <IconWrapper>{icon}</IconWrapper>}
|
||||||
<InputComponent
|
<InputComponent
|
||||||
ref={ref => (this.input = ref)}
|
ref={(ref) => (this.input = ref)}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
onFocus={this.handleFocus}
|
onFocus={this.handleFocus}
|
||||||
type={type === "textarea" ? undefined : type}
|
type={type === "textarea" ? undefined : type}
|
||||||
|
@ -30,7 +30,7 @@ class InputSearch extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSearchInput = ev => {
|
handleSearchInput = (ev) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
this.props.history.push(
|
this.props.history.push(
|
||||||
searchUrl(ev.target.value, this.props.collectionId)
|
searchUrl(ev.target.value, this.props.collectionId)
|
||||||
@ -50,7 +50,7 @@ class InputSearch extends React.Component<Props> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<InputMaxWidth
|
<InputMaxWidth
|
||||||
ref={ref => (this.input = ref)}
|
ref={(ref) => (this.input = ref)}
|
||||||
type="search"
|
type="search"
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
onInput={this.handleSearchInput}
|
onInput={this.handleSearchInput}
|
||||||
|
@ -12,11 +12,11 @@ const Select = styled.select`
|
|||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
outline: none;
|
outline: none;
|
||||||
background: none;
|
background: none;
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
|
|
||||||
&:disabled,
|
&:disabled,
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
color: ${props => props.theme.placeholder};
|
color: ${(props) => props.theme.placeholder};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ class InputSelect extends React.Component<Props> {
|
|||||||
))}
|
))}
|
||||||
<Outline focused={this.focused} className={className}>
|
<Outline focused={this.focused} className={className}>
|
||||||
<Select onBlur={this.handleBlur} onFocus={this.handleFocus} {...rest}>
|
<Select onBlur={this.handleBlur} onFocus={this.handleFocus} {...rest}>
|
||||||
{options.map(option => (
|
{options.map((option) => (
|
||||||
<option value={option.value} key={option.value}>
|
<option value={option.value} key={option.value}>
|
||||||
{option.label}
|
{option.label}
|
||||||
</option>
|
</option>
|
||||||
|
@ -7,13 +7,13 @@ const Key = styled.kbd`
|
|||||||
font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier,
|
font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier,
|
||||||
monospace;
|
monospace;
|
||||||
line-height: 10px;
|
line-height: 10px;
|
||||||
color: ${props => props.theme.almostBlack};
|
color: ${(props) => props.theme.almostBlack};
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
background-color: ${props => props.theme.smokeLight};
|
background-color: ${(props) => props.theme.smokeLight};
|
||||||
border: solid 1px ${props => props.theme.slateLight};
|
border: solid 1px ${(props) => props.theme.slateLight};
|
||||||
border-bottom-color: ${props => props.theme.slate};
|
border-bottom-color: ${(props) => props.theme.slate};
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
box-shadow: inset 0 -1px 0 ${props => props.theme.slate};
|
box-shadow: inset 0 -1px 0 ${(props) => props.theme.slate};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default Key;
|
export default Key;
|
||||||
|
@ -21,7 +21,7 @@ export const Label = styled(Flex)`
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: ${props => props.theme.textTertiary};
|
color: ${(props) => props.theme.textTertiary};
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -142,8 +142,8 @@ class Layout extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Container = styled(Flex)`
|
const Container = styled(Flex)`
|
||||||
background: ${props => props.theme.background};
|
background: ${(props) => props.theme.background};
|
||||||
transition: ${props => props.theme.backgroundTransition};
|
transition: ${(props) => props.theme.backgroundTransition};
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
@ -158,7 +158,7 @@ const Content = styled(Flex)`
|
|||||||
}
|
}
|
||||||
|
|
||||||
${breakpoint("tablet")`
|
${breakpoint("tablet")`
|
||||||
margin-left: ${props => (props.editMode ? 0 : props.theme.sidebarWidth)};
|
margin-left: ${(props) => (props.editMode ? 0 : props.theme.sidebarWidth)};
|
||||||
`};
|
`};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -27,9 +27,9 @@ const ListItem = ({ image, title, subtitle, actions }: Props) => {
|
|||||||
|
|
||||||
const Wrapper = styled.li`
|
const Wrapper = styled.li`
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: ${props => (props.compact ? "8px" : "12px")} 0;
|
padding: ${(props) => (props.compact ? "8px" : "12px")} 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border-bottom: 1px solid ${props => props.theme.divider};
|
border-bottom: 1px solid ${(props) => props.theme.divider};
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
@ -59,7 +59,7 @@ const Content = styled(Flex)`
|
|||||||
const Subtitle = styled.p`
|
const Subtitle = styled.p`
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: ${props => props.theme.slate};
|
color: ${(props) => props.theme.slate};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Actions = styled.div`
|
const Actions = styled.div`
|
||||||
|
@ -13,7 +13,7 @@ type Props = {
|
|||||||
const Placeholder = ({ count }: Props) => {
|
const Placeholder = ({ count }: Props) => {
|
||||||
return (
|
return (
|
||||||
<Fade>
|
<Fade>
|
||||||
{times(count || 2, index => (
|
{times(count || 2, (index) => (
|
||||||
<Item key={index} column auto>
|
<Item key={index} column auto>
|
||||||
<Mask />
|
<Mask />
|
||||||
</Item>
|
</Item>
|
||||||
|
@ -13,7 +13,7 @@ type Props = {
|
|||||||
const ListPlaceHolder = ({ count }: Props) => {
|
const ListPlaceHolder = ({ count }: Props) => {
|
||||||
return (
|
return (
|
||||||
<Fade>
|
<Fade>
|
||||||
{times(count || 2, index => (
|
{times(count || 2, (index) => (
|
||||||
<Item key={index} column auto>
|
<Item key={index} column auto>
|
||||||
<Mask header />
|
<Mask header />
|
||||||
<Mask />
|
<Mask />
|
||||||
|
@ -27,10 +27,11 @@ class Mask extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Redacted = styled(Flex)`
|
const Redacted = styled(Flex)`
|
||||||
width: ${props => (props.header ? props.width / 2 : props.width)}%;
|
width: ${(props) => (props.header ? props.width / 2 : props.width)}%;
|
||||||
height: ${props => (props.height ? props.height : props.header ? 24 : 18)}px;
|
height: ${(props) =>
|
||||||
|
props.height ? props.height : props.header ? 24 : 18}px;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
background-color: ${props => props.theme.divider};
|
background-color: ${(props) => props.theme.divider};
|
||||||
animation: ${pulsate} 1.3s infinite;
|
animation: ${pulsate} 1.3s infinite;
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
|
@ -21,7 +21,7 @@ type Props = {
|
|||||||
|
|
||||||
const GlobalStyles = createGlobalStyle`
|
const GlobalStyles = createGlobalStyle`
|
||||||
.ReactModal__Overlay {
|
.ReactModal__Overlay {
|
||||||
background-color: ${props =>
|
background-color: ${(props) =>
|
||||||
transparentize(0.25, props.theme.background)} !important;
|
transparentize(0.25, props.theme.background)} !important;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ const GlobalStyles = createGlobalStyle`
|
|||||||
.ReactModalPortal + .ReactModalPortal {
|
.ReactModalPortal + .ReactModalPortal {
|
||||||
.ReactModal__Overlay {
|
.ReactModal__Overlay {
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
box-shadow: 0 -2px 10px ${props => props.theme.shadow};
|
box-shadow: 0 -2px 10px ${(props) => props.theme.shadow};
|
||||||
border-radius: 8px 0 0 8px;
|
border-radius: 8px 0 0 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ const Modal = ({
|
|||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<Content onClick={ev => ev.stopPropagation()} column>
|
<Content onClick={(ev) => ev.stopPropagation()} column>
|
||||||
{title && <h1>{title}</h1>}
|
{title && <h1>{title}</h1>}
|
||||||
|
|
||||||
{children}
|
{children}
|
||||||
@ -109,8 +109,8 @@ const StyledModal = styled(ReactModal)`
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
background: ${props => props.theme.background};
|
background: ${(props) => props.theme.background};
|
||||||
transition: ${props => props.theme.backgroundTransition};
|
transition: ${(props) => props.theme.backgroundTransition};
|
||||||
padding: 8vh 2rem 2rem;
|
padding: 8vh 2rem 2rem;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ const Close = styled(NudeButton)`
|
|||||||
right: 0;
|
right: 0;
|
||||||
margin: 12px;
|
margin: 12px;
|
||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
|
||||||
@ -153,7 +153,7 @@ const Back = styled(NudeButton)`
|
|||||||
top: 2rem;
|
top: 2rem;
|
||||||
left: 2rem;
|
left: 2rem;
|
||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
const Notice = styled.p`
|
const Notice = styled.p`
|
||||||
background: ${props => props.theme.sidebarBackground};
|
background: ${(props) => props.theme.sidebarBackground};
|
||||||
color: ${props => props.theme.sidebarText};
|
color: ${(props) => props.theme.sidebarText};
|
||||||
padding: 10px 12px;
|
padding: 10px 12px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -14,7 +14,7 @@ const Button = styled.button`
|
|||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
transition-duration: 0.05s;
|
transition-duration: 0.05s;
|
||||||
box-shadow: ${props => lighten(0.4, props.theme.buttonBackground)} 0px 0px
|
box-shadow: ${(props) => lighten(0.4, props.theme.buttonBackground)} 0px 0px
|
||||||
0px 3px;
|
0px 3px;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ class PaginatedDocumentList extends React.Component<Props> {
|
|||||||
heading={heading}
|
heading={heading}
|
||||||
fetch={fetch}
|
fetch={fetch}
|
||||||
options={options}
|
options={options}
|
||||||
renderItem={item => (
|
renderItem={(item) => (
|
||||||
<DocumentPreview key={item.id} document={item} {...rest} />
|
<DocumentPreview key={item.id} document={item} {...rest} />
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
@ -14,7 +14,7 @@ type Props = {
|
|||||||
heading?: React.Node,
|
heading?: React.Node,
|
||||||
empty?: React.Node,
|
empty?: React.Node,
|
||||||
items: any[],
|
items: any[],
|
||||||
renderItem: any => React.Node,
|
renderItem: (any) => React.Node,
|
||||||
};
|
};
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
|
@ -44,7 +44,7 @@ class PathToDocument extends React.Component<Props> {
|
|||||||
<Component ref={ref} onClick={this.handleClick} href="" selectable>
|
<Component ref={ref} onClick={this.handleClick} href="" selectable>
|
||||||
{collection && <CollectionIcon collection={collection} />}
|
{collection && <CollectionIcon collection={collection} />}
|
||||||
{result.path
|
{result.path
|
||||||
.map(doc => <Title key={doc.id}>{doc.title}</Title>)
|
.map((doc) => <Title key={doc.id}>{doc.title}</Title>)
|
||||||
.reduce((prev, curr) => [prev, <StyledGoToIcon />, curr])}
|
.reduce((prev, curr) => [prev, <StyledGoToIcon />, curr])}
|
||||||
{document && (
|
{document && (
|
||||||
<Flex>
|
<Flex>
|
||||||
@ -73,7 +73,7 @@ const ResultWrapper = styled.div`
|
|||||||
margin-left: -4px;
|
margin-left: -4px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
cursor: default;
|
cursor: default;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ const ResultWrapperLink = styled(ResultWrapper.withComponent("a"))`
|
|||||||
&:hover,
|
&:hover,
|
||||||
&:active,
|
&:active,
|
||||||
&:focus {
|
&:focus {
|
||||||
background: ${props => props.theme.listItemHoverBackground};
|
background: ${(props) => props.theme.listItemHoverBackground};
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -10,16 +10,16 @@ import CollectionsStore from "stores/CollectionsStore";
|
|||||||
import AuthStore from "stores/AuthStore";
|
import AuthStore from "stores/AuthStore";
|
||||||
|
|
||||||
const Container = styled(Flex)`
|
const Container = styled(Flex)`
|
||||||
color: ${props => props.theme.textTertiary};
|
color: ${(props) => props.theme.textTertiary};
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Modified = styled.span`
|
const Modified = styled.span`
|
||||||
color: ${props =>
|
color: ${(props) =>
|
||||||
props.highlight ? props.theme.text : props.theme.textTertiary};
|
props.highlight ? props.theme.text : props.theme.textTertiary};
|
||||||
font-weight: ${props => (props.highlight ? "600" : "400")};
|
font-weight: ${(props) => (props.highlight ? "600" : "400")};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -104,15 +104,14 @@ function PublishingInfo({
|
|||||||
<Container align="center" {...rest}>
|
<Container align="center" {...rest}>
|
||||||
{updatedByMe ? "You" : updatedBy.name}
|
{updatedByMe ? "You" : updatedBy.name}
|
||||||
{content}
|
{content}
|
||||||
{showCollection &&
|
{showCollection && collection && (
|
||||||
collection && (
|
<span>
|
||||||
<span>
|
in
|
||||||
in
|
<strong>
|
||||||
<strong>
|
<Breadcrumb document={document} onlyText />
|
||||||
<Breadcrumb document={document} onlyText />
|
</strong>
|
||||||
</strong>
|
</span>
|
||||||
</span>
|
)}
|
||||||
)}
|
|
||||||
{children}
|
{children}
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
@ -31,7 +31,7 @@ const Wrapper = styled.div`
|
|||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overscroll-behavior: none;
|
overscroll-behavior: none;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
box-shadow: ${props =>
|
box-shadow: ${(props) =>
|
||||||
props.shadow ? "0 1px inset rgba(0,0,0,.1)" : "none"};
|
props.shadow ? "0 1px inset rgba(0,0,0,.1)" : "none"};
|
||||||
transition: all 250ms ease-in-out;
|
transition: all 250ms ease-in-out;
|
||||||
`;
|
`;
|
||||||
|
@ -119,7 +119,8 @@ class MainSidebar extends React.Component<Props> {
|
|||||||
icon={<EditIcon color="currentColor" />}
|
icon={<EditIcon color="currentColor" />}
|
||||||
label={
|
label={
|
||||||
<Drafts align="center">
|
<Drafts align="center">
|
||||||
Drafts{draftDocumentsCount > 0 && (
|
Drafts
|
||||||
|
{draftDocumentsCount > 0 && (
|
||||||
<Bubble count={draftDocumentsCount} />
|
<Bubble count={draftDocumentsCount} />
|
||||||
)}
|
)}
|
||||||
</Drafts>
|
</Drafts>
|
||||||
|
@ -146,13 +146,12 @@ class SettingsSidebar extends React.Component<Props> {
|
|||||||
/>
|
/>
|
||||||
</Section>
|
</Section>
|
||||||
)}
|
)}
|
||||||
{can.update &&
|
{can.update && env.DEPLOYMENT !== "hosted" && (
|
||||||
env.DEPLOYMENT !== "hosted" && (
|
<Section>
|
||||||
<Section>
|
<Header>Installation</Header>
|
||||||
<Header>Installation</Header>
|
<Version />
|
||||||
<Version />
|
</Section>
|
||||||
</Section>
|
)}
|
||||||
)}
|
|
||||||
</Scrollable>
|
</Scrollable>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
|
@ -67,9 +67,10 @@ const Container = styled(Flex)`
|
|||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: ${props => props.theme.sidebarBackground};
|
background: ${(props) => props.theme.sidebarBackground};
|
||||||
transition: left 100ms ease-out, ${props => props.theme.backgroundTransition};
|
transition: left 100ms ease-out,
|
||||||
margin-left: ${props => (props.mobileSidebarVisible ? 0 : "-100%")};
|
${(props) => props.theme.backgroundTransition};
|
||||||
|
margin-left: ${(props) => (props.mobileSidebarVisible ? 0 : "-100%")};
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
|
|
||||||
@media print {
|
@media print {
|
||||||
@ -80,7 +81,7 @@ const Container = styled(Flex)`
|
|||||||
&:before,
|
&:before,
|
||||||
&:after {
|
&:after {
|
||||||
content: "";
|
content: "";
|
||||||
background: ${props => props.theme.sidebarBackground};
|
background: ${(props) => props.theme.sidebarBackground};
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -50vh;
|
top: -50vh;
|
||||||
left: 0;
|
left: 0;
|
||||||
@ -94,8 +95,8 @@ const Container = styled(Flex)`
|
|||||||
}
|
}
|
||||||
|
|
||||||
${breakpoint("tablet")`
|
${breakpoint("tablet")`
|
||||||
left: ${props => (props.editMode ? `-${props.theme.sidebarWidth}` : 0)};
|
left: ${(props) => (props.editMode ? `-${props.theme.sidebarWidth}` : 0)};
|
||||||
width: ${props => props.theme.sidebarWidth};
|
width: ${(props) => props.theme.sidebarWidth};
|
||||||
margin: 0;
|
margin: 0;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
`};
|
`};
|
||||||
@ -106,8 +107,8 @@ const Toggle = styled.a`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: ${props => (props.mobileSidebarVisible ? "auto" : 0)};
|
left: ${(props) => (props.mobileSidebarVisible ? "auto" : 0)};
|
||||||
right: ${props => (props.mobileSidebarVisible ? 0 : "auto")};
|
right: ${(props) => (props.mobileSidebarVisible ? 0 : "auto")};
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
margin: 12px;
|
margin: 12px;
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@ const Bubble = ({ count }: Props) => {
|
|||||||
const Count = styled.div`
|
const Count = styled.div`
|
||||||
animation: ${bounceIn} 600ms;
|
animation: ${bounceIn} 600ms;
|
||||||
transform-origin: center center;
|
transform-origin: center center;
|
||||||
color: ${props => props.theme.white};
|
color: ${(props) => props.theme.white};
|
||||||
background: ${props => props.theme.slateDark};
|
background: ${(props) => props.theme.slateDark};
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-feature-settings: "tnum";
|
font-feature-settings: "tnum";
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
@ -61,7 +61,7 @@ class CollectionLink extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Flex column>
|
<Flex column>
|
||||||
{collection.documents.map(node => (
|
{collection.documents.map((node) => (
|
||||||
<DocumentLink
|
<DocumentLink
|
||||||
key={node.id}
|
key={node.id}
|
||||||
node={node}
|
node={node}
|
||||||
|
@ -57,7 +57,7 @@ class Collections extends React.Component<Props> {
|
|||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{collections.orderedData.map(collection => (
|
{collections.orderedData.map((collection) => (
|
||||||
<CollectionLink
|
<CollectionLink
|
||||||
key={collection.id}
|
key={collection.id}
|
||||||
documents={documents}
|
documents={documents}
|
||||||
@ -94,6 +94,9 @@ class Collections extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default inject("collections", "ui", "documents", "policies")(
|
export default inject(
|
||||||
withRouter(Collections)
|
"collections",
|
||||||
);
|
"ui",
|
||||||
|
"documents",
|
||||||
|
"policies"
|
||||||
|
)(withRouter(Collections));
|
||||||
|
@ -76,7 +76,7 @@ class DocumentLink extends React.Component<Props> {
|
|||||||
collection &&
|
collection &&
|
||||||
(collection
|
(collection
|
||||||
.pathToDocument(activeDocument)
|
.pathToDocument(activeDocument)
|
||||||
.map(entry => entry.id)
|
.map((entry) => entry.id)
|
||||||
.includes(node.id) ||
|
.includes(node.id) ||
|
||||||
this.isActiveDocument())
|
this.isActiveDocument())
|
||||||
);
|
);
|
||||||
@ -110,14 +110,12 @@ class DocumentLink extends React.Component<Props> {
|
|||||||
onClose={() => (this.menuOpen = false)}
|
onClose={() => (this.menuOpen = false)}
|
||||||
/>
|
/>
|
||||||
</Fade>
|
</Fade>
|
||||||
) : (
|
) : undefined
|
||||||
undefined
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{this.hasChildDocuments() && (
|
{this.hasChildDocuments() && (
|
||||||
<DocumentChildren column>
|
<DocumentChildren column>
|
||||||
{node.children.map(childNode => (
|
{node.children.map((childNode) => (
|
||||||
<DocumentLink
|
<DocumentLink
|
||||||
key={childNode.id}
|
key={childNode.id}
|
||||||
collection={collection}
|
collection={collection}
|
||||||
|
@ -6,7 +6,7 @@ const Header = styled(Flex)`
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: ${props => props.theme.sidebarText};
|
color: ${(props) => props.theme.sidebarText};
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
margin: 4px 16px;
|
margin: 4px 16px;
|
||||||
`;
|
`;
|
||||||
|
@ -46,7 +46,7 @@ const Subheading = styled.div`
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: ${props => props.theme.sidebarText};
|
color: ${(props) => props.theme.sidebarText};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const TeamName = styled.div`
|
const TeamName = styled.div`
|
||||||
@ -54,7 +54,7 @@ const TeamName = styled.div`
|
|||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 24px;
|
padding-right: 24px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
`;
|
`;
|
||||||
|
@ -108,11 +108,11 @@ const IconWrapper = styled.span`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Action = styled.span`
|
const Action = styled.span`
|
||||||
display: ${props => (props.menuOpen ? "inline" : "none")};
|
display: ${(props) => (props.menuOpen ? "inline" : "none")};
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 4px;
|
top: 4px;
|
||||||
right: 4px;
|
right: 4px;
|
||||||
color: ${props => props.theme.textTertiary};
|
color: ${(props) => props.theme.textTertiary};
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
@ -132,17 +132,17 @@ const StyledNavLink = styled(NavLink)`
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
padding: 4px 16px;
|
padding: 4px 16px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
color: ${props => props.theme.sidebarText};
|
color: ${(props) => props.theme.sidebarText};
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
background: ${props => props.theme.black05};
|
background: ${(props) => props.theme.black05};
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,13 +71,13 @@ class SocketProvider extends React.Component<Props> {
|
|||||||
this.socket.authenticated = true;
|
this.socket.authenticated = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on("unauthorized", err => {
|
this.socket.on("unauthorized", (err) => {
|
||||||
this.socket.authenticated = false;
|
this.socket.authenticated = false;
|
||||||
ui.showToast(err.message);
|
ui.showToast(err.message);
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on("entities", async event => {
|
this.socket.on("entities", async (event) => {
|
||||||
if (event.documentIds) {
|
if (event.documentIds) {
|
||||||
for (const documentDescriptor of event.documentIds) {
|
for (const documentDescriptor of event.documentIds) {
|
||||||
const documentId = documentDescriptor.id;
|
const documentId = documentDescriptor.id;
|
||||||
@ -182,23 +182,23 @@ class SocketProvider extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on("documents.star", event => {
|
this.socket.on("documents.star", (event) => {
|
||||||
documents.starredIds.set(event.documentId, true);
|
documents.starredIds.set(event.documentId, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on("documents.unstar", event => {
|
this.socket.on("documents.unstar", (event) => {
|
||||||
documents.starredIds.set(event.documentId, false);
|
documents.starredIds.set(event.documentId, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
// received when a user is given access to a collection
|
// received when a user is given access to a collection
|
||||||
// if the user is us then we go ahead and load the collection from API.
|
// if the user is us then we go ahead and load the collection from API.
|
||||||
this.socket.on("collections.add_user", event => {
|
this.socket.on("collections.add_user", (event) => {
|
||||||
if (auth.user && event.userId === auth.user.id) {
|
if (auth.user && event.userId === auth.user.id) {
|
||||||
collections.fetch(event.collectionId, { force: true });
|
collections.fetch(event.collectionId, { force: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Document policies might need updating as the permission changes
|
// Document policies might need updating as the permission changes
|
||||||
documents.inCollection(event.collectionId).forEach(document => {
|
documents.inCollection(event.collectionId).forEach((document) => {
|
||||||
policies.remove(document.id);
|
policies.remove(document.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -206,7 +206,7 @@ class SocketProvider extends React.Component<Props> {
|
|||||||
// received when a user is removed from having access to a collection
|
// received when a user is removed from having access to a collection
|
||||||
// to keep state in sync we must update our UI if the user is us,
|
// to keep state in sync we must update our UI if the user is us,
|
||||||
// or otherwise just remove any membership state we have for that user.
|
// or otherwise just remove any membership state we have for that user.
|
||||||
this.socket.on("collections.remove_user", event => {
|
this.socket.on("collections.remove_user", (event) => {
|
||||||
if (auth.user && event.userId === auth.user.id) {
|
if (auth.user && event.userId === auth.user.id) {
|
||||||
collections.remove(event.collectionId);
|
collections.remove(event.collectionId);
|
||||||
memberships.removeCollectionMemberships(event.collectionId);
|
memberships.removeCollectionMemberships(event.collectionId);
|
||||||
@ -218,32 +218,32 @@ class SocketProvider extends React.Component<Props> {
|
|||||||
|
|
||||||
// received a message from the API server that we should request
|
// received a message from the API server that we should request
|
||||||
// to join a specific room. Forward that to the ws server.
|
// to join a specific room. Forward that to the ws server.
|
||||||
this.socket.on("join", event => {
|
this.socket.on("join", (event) => {
|
||||||
this.socket.emit("join", event);
|
this.socket.emit("join", event);
|
||||||
});
|
});
|
||||||
|
|
||||||
// received a message from the API server that we should request
|
// received a message from the API server that we should request
|
||||||
// to leave a specific room. Forward that to the ws server.
|
// to leave a specific room. Forward that to the ws server.
|
||||||
this.socket.on("leave", event => {
|
this.socket.on("leave", (event) => {
|
||||||
this.socket.emit("leave", event);
|
this.socket.emit("leave", event);
|
||||||
});
|
});
|
||||||
|
|
||||||
// received whenever we join a document room, the payload includes
|
// received whenever we join a document room, the payload includes
|
||||||
// userIds that are present/viewing and those that are editing.
|
// userIds that are present/viewing and those that are editing.
|
||||||
this.socket.on("document.presence", event => {
|
this.socket.on("document.presence", (event) => {
|
||||||
presence.init(event.documentId, event.userIds, event.editingIds);
|
presence.init(event.documentId, event.userIds, event.editingIds);
|
||||||
});
|
});
|
||||||
|
|
||||||
// received whenever a new user joins a document room, aka they
|
// received whenever a new user joins a document room, aka they
|
||||||
// navigate to / start viewing a document
|
// navigate to / start viewing a document
|
||||||
this.socket.on("user.join", event => {
|
this.socket.on("user.join", (event) => {
|
||||||
presence.touch(event.documentId, event.userId, event.isEditing);
|
presence.touch(event.documentId, event.userId, event.isEditing);
|
||||||
views.touch(event.documentId, event.userId);
|
views.touch(event.documentId, event.userId);
|
||||||
});
|
});
|
||||||
|
|
||||||
// received whenever a new user leaves a document room, aka they
|
// received whenever a new user leaves a document room, aka they
|
||||||
// navigate away / stop viewing a document
|
// navigate away / stop viewing a document
|
||||||
this.socket.on("user.leave", event => {
|
this.socket.on("user.leave", (event) => {
|
||||||
presence.leave(event.documentId, event.userId);
|
presence.leave(event.documentId, event.userId);
|
||||||
views.touch(event.documentId, event.userId);
|
views.touch(event.documentId, event.userId);
|
||||||
});
|
});
|
||||||
@ -251,7 +251,7 @@ class SocketProvider extends React.Component<Props> {
|
|||||||
// received when another client in a document room wants to change
|
// received when another client in a document room wants to change
|
||||||
// or update it's presence. Currently the only property is whether
|
// or update it's presence. Currently the only property is whether
|
||||||
// the client is in editing state or not.
|
// the client is in editing state or not.
|
||||||
this.socket.on("user.presence", event => {
|
this.socket.on("user.presence", (event) => {
|
||||||
presence.touch(event.documentId, event.userId, event.isEditing);
|
presence.touch(event.documentId, event.userId, event.isEditing);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const H3 = styled.h3`
|
const H3 = styled.h3`
|
||||||
border-bottom: 1px solid ${props => props.theme.divider};
|
border-bottom: 1px solid ${(props) => props.theme.divider};
|
||||||
margin-top: 22px;
|
margin-top: 22px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
@ -21,8 +21,8 @@ const Underline = styled("span")`
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
color: ${props => props.theme.textSecondary};
|
color: ${(props) => props.theme.textSecondary};
|
||||||
border-bottom: 3px solid ${props => props.theme.textSecondary};
|
border-bottom: 3px solid ${(props) => props.theme.textSecondary};
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ const Label = styled.label`
|
|||||||
const Wrapper = styled.label`
|
const Wrapper = styled.label`
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: ${props => props.width}px;
|
width: ${(props) => props.width}px;
|
||||||
height: ${props => props.height}px;
|
height: ${(props) => props.height}px;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
`;
|
`;
|
||||||
@ -51,16 +51,16 @@ const Slider = styled.span`
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background-color: ${props => props.theme.slate};
|
background-color: ${(props) => props.theme.slate};
|
||||||
-webkit-transition: 0.4s;
|
-webkit-transition: 0.4s;
|
||||||
transition: 0.4s;
|
transition: 0.4s;
|
||||||
border-radius: ${props => props.height}px;
|
border-radius: ${(props) => props.height}px;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
content: "";
|
content: "";
|
||||||
height: ${props => props.height - 8}px;
|
height: ${(props) => props.height - 8}px;
|
||||||
width: ${props => props.height - 8}px;
|
width: ${(props) => props.height - 8}px;
|
||||||
left: 4px;
|
left: 4px;
|
||||||
bottom: 4px;
|
bottom: 4px;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
@ -77,15 +77,15 @@ const HiddenInput = styled.input`
|
|||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
|
|
||||||
&:checked + ${Slider} {
|
&:checked + ${Slider} {
|
||||||
background-color: ${props => props.theme.primary};
|
background-color: ${(props) => props.theme.primary};
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus + ${Slider} {
|
&:focus + ${Slider} {
|
||||||
box-shadow: 0 0 1px ${props => props.theme.primary};
|
box-shadow: 0 0 1px ${(props) => props.theme.primary};
|
||||||
}
|
}
|
||||||
|
|
||||||
&:checked + ${Slider}:before {
|
&:checked + ${Slider}:before {
|
||||||
transform: translateX(${props => props.width - props.height}px);
|
transform: translateX(${(props) => props.width - props.height}px);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -15,20 +15,20 @@ const StyledNavLink = styled(NavLink)`
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: ${props => props.theme.textTertiary};
|
color: ${(props) => props.theme.textTertiary};
|
||||||
margin-right: 24px;
|
margin-right: 24px;
|
||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: ${props => props.theme.textSecondary};
|
color: ${(props) => props.theme.textSecondary};
|
||||||
border-bottom: 3px solid ${props => props.theme.divider};
|
border-bottom: 3px solid ${(props) => props.theme.divider};
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-bottom: 3px solid
|
border-bottom: 3px solid
|
||||||
${props => lighten(0.4, props.theme.buttonBackground)};
|
${(props) => lighten(0.4, props.theme.buttonBackground)};
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -3,13 +3,13 @@ import styled from "styled-components";
|
|||||||
|
|
||||||
const Tabs = styled.nav`
|
const Tabs = styled.nav`
|
||||||
position: relative;
|
position: relative;
|
||||||
border-bottom: 1px solid ${props => props.theme.divider};
|
border-bottom: 1px solid ${(props) => props.theme.divider};
|
||||||
margin-top: 22px;
|
margin-top: 22px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Separator = styled.span`
|
export const Separator = styled.span`
|
||||||
border-left: 1px solid ${props => props.theme.divider};
|
border-left: 1px solid ${(props) => props.theme.divider};
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 2px;
|
top: 2px;
|
||||||
margin-right: 24px;
|
margin-right: 24px;
|
||||||
|
@ -5,8 +5,8 @@ const TeamLogo = styled.img`
|
|||||||
width: auto;
|
width: auto;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: ${props => props.theme.background};
|
background: ${(props) => props.theme.background};
|
||||||
border: 1px solid ${props => props.theme.divider};
|
border: 1px solid ${(props) => props.theme.divider};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default TeamLogo;
|
export default TeamLogo;
|
||||||
|
@ -9,14 +9,14 @@ let callbacks = [];
|
|||||||
// This is a shared timer that fires every minute, used for
|
// This is a shared timer that fires every minute, used for
|
||||||
// updating all Time components across the page all at once.
|
// updating all Time components across the page all at once.
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
callbacks.forEach(cb => cb());
|
callbacks.forEach((cb) => cb());
|
||||||
}, 1000 * 60);
|
}, 1000 * 60);
|
||||||
|
|
||||||
function eachMinute(fn) {
|
function eachMinute(fn) {
|
||||||
callbacks.push(fn);
|
callbacks.push(fn);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
callbacks = callbacks.filter(cb => cb !== fn);
|
callbacks = callbacks.filter((cb) => cb !== fn);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ class Toasts extends React.Component<Props> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<List>
|
<List>
|
||||||
{ui.orderedToasts.map(toast => (
|
{ui.orderedToasts.map((toast) => (
|
||||||
<Toast
|
<Toast
|
||||||
key={toast.id}
|
key={toast.id}
|
||||||
toast={toast}
|
toast={toast}
|
||||||
@ -29,8 +29,8 @@ class Toasts extends React.Component<Props> {
|
|||||||
|
|
||||||
const List = styled.ol`
|
const List = styled.ol`
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: ${props => props.theme.hpadding};
|
left: ${(props) => props.theme.hpadding};
|
||||||
bottom: ${props => props.theme.vpadding};
|
bottom: ${(props) => props.theme.vpadding};
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -61,13 +61,13 @@ const Action = styled.span`
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: ${props => props.theme.toastText};
|
color: ${(props) => props.theme.toastText};
|
||||||
background: ${props => darken(0.05, props.theme.toastBackground)};
|
background: ${(props) => darken(0.05, props.theme.toastBackground)};
|
||||||
border-top-right-radius: 5px;
|
border-top-right-radius: 5px;
|
||||||
border-bottom-right-radius: 5px;
|
border-bottom-right-radius: 5px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: ${props => darken(0.1, props.theme.toastBackground)};
|
background: ${(props) => darken(0.1, props.theme.toastBackground)};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -76,14 +76,14 @@ const Container = styled.div`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
animation: ${fadeAndScaleIn} 100ms ease;
|
animation: ${fadeAndScaleIn} 100ms ease;
|
||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
color: ${props => props.theme.toastText};
|
color: ${(props) => props.theme.toastText};
|
||||||
background: ${props => props.theme.toastBackground};
|
background: ${(props) => props.theme.toastBackground};
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: ${props => darken(0.05, props.theme.toastBackground)};
|
background: ${(props) => darken(0.05, props.theme.toastBackground)};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -54,19 +54,19 @@ const Shortcut = styled.kbd`
|
|||||||
font: 10px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier,
|
font: 10px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier,
|
||||||
monospace;
|
monospace;
|
||||||
line-height: 10px;
|
line-height: 10px;
|
||||||
color: ${props => props.theme.tooltipBackground};
|
color: ${(props) => props.theme.tooltipBackground};
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
background-color: ${props => props.theme.tooltipText};
|
background-color: ${(props) => props.theme.tooltipText};
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledTippy = styled(Tippy)`
|
const StyledTippy = styled(Tippy)`
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
background-color: ${props => props.theme.tooltipBackground};
|
background-color: ${(props) => props.theme.tooltipBackground};
|
||||||
color: ${props => props.theme.tooltipText};
|
color: ${(props) => props.theme.tooltipText};
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
fill: ${props => props.theme.tooltipBackground};
|
fill: ${(props) => props.theme.tooltipBackground};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -19,9 +19,7 @@ export default class Figma extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Frame
|
<Frame
|
||||||
src={`https://www.figma.com/embed?embed_host=outline&url=${
|
src={`https://www.figma.com/embed?embed_host=outline&url=${this.props.attrs.href}`}
|
||||||
this.props.attrs.href
|
|
||||||
}`}
|
|
||||||
title="Figma Embed"
|
title="Figma Embed"
|
||||||
border
|
border
|
||||||
/>
|
/>
|
||||||
|
@ -48,14 +48,10 @@ class Gist extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const gistLink = `https://gist.github.com/${id}.js`;
|
const gistLink = `https://gist.github.com/${id}.js`;
|
||||||
const gistScript = `<script type="text/javascript" src="${
|
const gistScript = `<script type="text/javascript" src="${gistLink}"></script>`;
|
||||||
gistLink
|
|
||||||
}"></script>`;
|
|
||||||
const styles =
|
const styles =
|
||||||
"<style>*{ font-size:12px; } body { margin: 0; } .gist .blob-wrapper.data { max-height:150px; overflow:auto; }</style>";
|
"<style>*{ font-size:12px; } body { margin: 0; } .gist .blob-wrapper.data { max-height:150px; overflow:auto; }</style>";
|
||||||
const iframeHtml = `<html><head><base target="_parent">${
|
const iframeHtml = `<html><head><base target="_parent">${styles}</head><body>${gistScript}</body></html>`;
|
||||||
styles
|
|
||||||
}</head><body>${gistScript}</body></html>`;
|
|
||||||
|
|
||||||
doc.open();
|
doc.open();
|
||||||
doc.writeln(iframeHtml);
|
doc.writeln(iframeHtml);
|
||||||
@ -67,7 +63,7 @@ class Gist extends React.Component<Props> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<iframe
|
<iframe
|
||||||
ref={ref => {
|
ref={(ref) => {
|
||||||
this.iframeNode = ref;
|
this.iframeNode = ref;
|
||||||
}}
|
}}
|
||||||
type="text/html"
|
type="text/html"
|
||||||
|
@ -65,17 +65,17 @@ class Frame extends React.Component<Props> {
|
|||||||
const Rounded = styled.div`
|
const Rounded = styled.div`
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: ${props => props.width};
|
width: ${(props) => props.width};
|
||||||
height: ${props => props.height};
|
height: ${(props) => props.height};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// This wrapper allows us to pass non-standard HTML attributes through to the DOM element
|
// This wrapper allows us to pass non-standard HTML attributes through to the DOM element
|
||||||
// https://www.styled-components.com/docs/basics#passed-props
|
// https://www.styled-components.com/docs/basics#passed-props
|
||||||
const Iframe = props => <iframe {...props} />;
|
const Iframe = (props) => <iframe {...props} />;
|
||||||
|
|
||||||
const StyledIframe = styled(Iframe)`
|
const StyledIframe = styled(Iframe)`
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
border-color: ${props => props.theme.embedBorder};
|
border-color: ${(props) => props.theme.embedBorder};
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -97,9 +97,9 @@ class CollectionMenu extends React.Component<Props> {
|
|||||||
<VisuallyHidden>
|
<VisuallyHidden>
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
ref={ref => (this.file = ref)}
|
ref={(ref) => (this.file = ref)}
|
||||||
onChange={this.onFilePicked}
|
onChange={this.onFilePicked}
|
||||||
onClick={ev => ev.stopPropagation()}
|
onClick={(ev) => ev.stopPropagation()}
|
||||||
accept="text/markdown, text/plain"
|
accept="text/markdown, text/plain"
|
||||||
/>
|
/>
|
||||||
</VisuallyHidden>
|
</VisuallyHidden>
|
||||||
@ -153,6 +153,8 @@ class CollectionMenu extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default inject("ui", "documents", "policies")(
|
export default inject(
|
||||||
withRouter(CollectionMenu)
|
"ui",
|
||||||
);
|
"documents",
|
||||||
|
"policies"
|
||||||
|
)(withRouter(CollectionMenu));
|
||||||
|
@ -219,12 +219,11 @@ class DocumentMenu extends React.Component<Props> {
|
|||||||
New nested document
|
New nested document
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
)}
|
)}
|
||||||
{can.update &&
|
{can.update && !document.isTemplate && (
|
||||||
!document.isTemplate && (
|
<DropdownMenuItem onClick={this.handleOpenTemplateModal}>
|
||||||
<DropdownMenuItem onClick={this.handleOpenTemplateModal}>
|
Create template…
|
||||||
Create template…
|
</DropdownMenuItem>
|
||||||
</DropdownMenuItem>
|
)}
|
||||||
)}
|
|
||||||
{can.update && (
|
{can.update && (
|
||||||
<DropdownMenuItem onClick={this.handleEdit}>Edit</DropdownMenuItem>
|
<DropdownMenuItem onClick={this.handleEdit}>Edit</DropdownMenuItem>
|
||||||
)}
|
)}
|
||||||
|
@ -63,7 +63,7 @@ class NewDocumentMenu extends React.Component<Props> {
|
|||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<Header>Choose a collection</Header>
|
<Header>Choose a collection</Header>
|
||||||
{collections.orderedData.map(collection => {
|
{collections.orderedData.map((collection) => {
|
||||||
const can = policies.abilities(collection.id);
|
const can = policies.abilities(collection.id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -72,7 +72,8 @@ class NewDocumentMenu extends React.Component<Props> {
|
|||||||
onClick={() => this.handleNewDocument(collection.id)}
|
onClick={() => this.handleNewDocument(collection.id)}
|
||||||
disabled={!can.update}
|
disabled={!can.update}
|
||||||
>
|
>
|
||||||
<CollectionIcon collection={collection} /> {collection.name}
|
<CollectionIcon collection={collection} />
|
||||||
|
{collection.name}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -53,7 +53,7 @@ class NewTemplateMenu extends React.Component<Props> {
|
|||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<Header>Choose a collection</Header>
|
<Header>Choose a collection</Header>
|
||||||
{collections.orderedData.map(collection => {
|
{collections.orderedData.map((collection) => {
|
||||||
const can = policies.abilities(collection.id);
|
const can = policies.abilities(collection.id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -62,7 +62,8 @@ class NewTemplateMenu extends React.Component<Props> {
|
|||||||
onClick={() => this.handleNewDocument(collection.id)}
|
onClick={() => this.handleNewDocument(collection.id)}
|
||||||
disabled={!can.update}
|
disabled={!can.update}
|
||||||
>
|
>
|
||||||
<CollectionIcon collection={collection} /> {collection.name}
|
<CollectionIcon collection={collection} />
|
||||||
|
{collection.name}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -33,7 +33,7 @@ class TemplatesMenu extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
{templates.map(template => (
|
{templates.map((template) => (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
key={template.id}
|
key={template.id}
|
||||||
onClick={() => document.updateFromTemplate(template)}
|
onClick={() => document.updateFromTemplate(template)}
|
||||||
|
@ -18,9 +18,7 @@ class UserMenu extends React.Component<Props> {
|
|||||||
const { user, users } = this.props;
|
const { user, users } = this.props;
|
||||||
if (
|
if (
|
||||||
!window.confirm(
|
!window.confirm(
|
||||||
`Are you want to make ${
|
`Are you want to make ${user.name} an admin? Admins can modify team and billing information.`
|
||||||
user.name
|
|
||||||
} an admin? Admins can modify team and billing information.`
|
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
@ -72,12 +70,11 @@ class UserMenu extends React.Component<Props> {
|
|||||||
Make {user.name} a member…
|
Make {user.name} a member…
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
)}
|
)}
|
||||||
{!user.isAdmin &&
|
{!user.isAdmin && !user.isSuspended && (
|
||||||
!user.isSuspended && (
|
<DropdownMenuItem onClick={this.handlePromote}>
|
||||||
<DropdownMenuItem onClick={this.handlePromote}>
|
Make {user.name} an admin…
|
||||||
Make {user.name} an admin…
|
</DropdownMenuItem>
|
||||||
</DropdownMenuItem>
|
)}
|
||||||
)}
|
|
||||||
{!user.lastActiveAt && (
|
{!user.lastActiveAt && (
|
||||||
<DropdownMenuItem onClick={this.handleRevoke}>
|
<DropdownMenuItem onClick={this.handleRevoke}>
|
||||||
Revoke invite…
|
Revoke invite…
|
||||||
|
@ -11,7 +11,7 @@ export default class BaseModel {
|
|||||||
this.store = store;
|
this.store = store;
|
||||||
}
|
}
|
||||||
|
|
||||||
save = async params => {
|
save = async (params) => {
|
||||||
this.isSaving = true;
|
this.isSaving = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -37,7 +37,7 @@ export default class Collection extends BaseModel {
|
|||||||
get documentIds(): string[] {
|
get documentIds(): string[] {
|
||||||
const results = [];
|
const results = [];
|
||||||
const travelDocuments = (documentList, path) =>
|
const travelDocuments = (documentList, path) =>
|
||||||
documentList.forEach(document => {
|
documentList.forEach((document) => {
|
||||||
results.push(document.id);
|
results.push(document.id);
|
||||||
travelDocuments(document.children);
|
travelDocuments(document.children);
|
||||||
});
|
});
|
||||||
@ -49,7 +49,7 @@ export default class Collection extends BaseModel {
|
|||||||
@action
|
@action
|
||||||
updateDocument(document: Document) {
|
updateDocument(document: Document) {
|
||||||
const travelDocuments = (documentList, path) =>
|
const travelDocuments = (documentList, path) =>
|
||||||
documentList.forEach(d => {
|
documentList.forEach((d) => {
|
||||||
if (d.id === document.id) {
|
if (d.id === document.id) {
|
||||||
d.title = document.title;
|
d.title = document.title;
|
||||||
d.url = document.url;
|
d.url = document.url;
|
||||||
@ -63,8 +63,8 @@ export default class Collection extends BaseModel {
|
|||||||
|
|
||||||
getDocumentChildren(documentId: string): NavigationNode[] {
|
getDocumentChildren(documentId: string): NavigationNode[] {
|
||||||
let result = [];
|
let result = [];
|
||||||
const traveler = nodes => {
|
const traveler = (nodes) => {
|
||||||
nodes.forEach(childNode => {
|
nodes.forEach((childNode) => {
|
||||||
if (childNode.id === documentId) {
|
if (childNode.id === documentId) {
|
||||||
result = childNode.children;
|
result = childNode.children;
|
||||||
return;
|
return;
|
||||||
@ -83,7 +83,7 @@ export default class Collection extends BaseModel {
|
|||||||
pathToDocument(document: Document) {
|
pathToDocument(document: Document) {
|
||||||
let path;
|
let path;
|
||||||
const traveler = (nodes, previousPath) => {
|
const traveler = (nodes, previousPath) => {
|
||||||
nodes.forEach(childNode => {
|
nodes.forEach((childNode) => {
|
||||||
const newPath = [...previousPath, childNode];
|
const newPath = [...previousPath, childNode];
|
||||||
if (childNode.id === document.id) {
|
if (childNode.id === document.id) {
|
||||||
path = newPath;
|
path = newPath;
|
||||||
|
@ -133,7 +133,7 @@ export default class Document extends BaseModel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@action
|
@action
|
||||||
updateFromJson = data => {
|
updateFromJson = (data) => {
|
||||||
set(this, data);
|
set(this, data);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -253,11 +253,7 @@ export default class Document extends BaseModel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getSummary = (paragraphs: number = 4) => {
|
getSummary = (paragraphs: number = 4) => {
|
||||||
const result = this.text
|
const result = this.text.trim().split("\n").slice(0, paragraphs).join("\n");
|
||||||
.trim()
|
|
||||||
.split("\n")
|
|
||||||
.slice(0, paragraphs)
|
|
||||||
.join("\n");
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
@ -171,14 +171,17 @@ class CollectionScene extends React.Component<Props> {
|
|||||||
<Centered column>
|
<Centered column>
|
||||||
<HelpText>
|
<HelpText>
|
||||||
<strong>{collection.name}</strong> doesn’t contain any
|
<strong>{collection.name}</strong> doesn’t contain any
|
||||||
documents yet.<br />Get started by creating a new one!
|
documents yet.
|
||||||
|
<br />
|
||||||
|
Get started by creating a new one!
|
||||||
</HelpText>
|
</HelpText>
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Link to={newDocumentUrl(collection.id)}>
|
<Link to={newDocumentUrl(collection.id)}>
|
||||||
<Button icon={<NewDocumentIcon color={theme.buttonText} />}>
|
<Button icon={<NewDocumentIcon color={theme.buttonText} />}>
|
||||||
Create a document
|
Create a document
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{collection.private && (
|
{collection.private && (
|
||||||
<Button onClick={this.onPermissions} neutral>
|
<Button onClick={this.onPermissions} neutral>
|
||||||
Manage members…
|
Manage members…
|
||||||
@ -329,6 +332,9 @@ const Wrapper = styled(Flex)`
|
|||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default inject("collections", "policies", "documents", "ui")(
|
export default inject(
|
||||||
withTheme(CollectionScene)
|
"collections",
|
||||||
);
|
"policies",
|
||||||
|
"documents",
|
||||||
|
"ui"
|
||||||
|
)(withTheme(CollectionScene));
|
||||||
|
@ -56,7 +56,7 @@ class CollectionEdit extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleDescriptionChange = getValue => {
|
handleDescriptionChange = (getValue) => {
|
||||||
this.description = getValue();
|
this.description = getValue();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ class AddGroupsToCollection extends React.Component<Props> {
|
|||||||
});
|
});
|
||||||
}, 250);
|
}, 250);
|
||||||
|
|
||||||
handleAddGroup = group => {
|
handleAddGroup = (group) => {
|
||||||
try {
|
try {
|
||||||
this.props.collectionGroupMemberships.create({
|
this.props.collectionGroupMemberships.create({
|
||||||
collectionId: this.props.collection.id,
|
collectionId: this.props.collection.id,
|
||||||
@ -77,7 +77,8 @@ class AddGroupsToCollection extends React.Component<Props> {
|
|||||||
Can’t find the group you’re looking for?{" "}
|
Can’t find the group you’re looking for?{" "}
|
||||||
<a role="button" onClick={this.handleNewGroupModalOpen}>
|
<a role="button" onClick={this.handleNewGroupModalOpen}>
|
||||||
Create a group
|
Create a group
|
||||||
</a>.
|
</a>
|
||||||
|
.
|
||||||
</HelpText>
|
</HelpText>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
@ -99,7 +100,7 @@ class AddGroupsToCollection extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
items={groups.notInCollection(collection.id, this.query)}
|
items={groups.notInCollection(collection.id, this.query)}
|
||||||
fetch={this.query ? undefined : groups.fetchPage}
|
fetch={this.query ? undefined : groups.fetchPage}
|
||||||
renderItem={item => (
|
renderItem={(item) => (
|
||||||
<GroupListItem
|
<GroupListItem
|
||||||
key={item.id}
|
key={item.id}
|
||||||
group={item}
|
group={item}
|
||||||
@ -130,6 +131,9 @@ const ButtonWrap = styled.div`
|
|||||||
margin-left: 6px;
|
margin-left: 6px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default inject("auth", "groups", "collectionGroupMemberships", "ui")(
|
export default inject(
|
||||||
AddGroupsToCollection
|
"auth",
|
||||||
);
|
"groups",
|
||||||
|
"collectionGroupMemberships",
|
||||||
|
"ui"
|
||||||
|
)(AddGroupsToCollection);
|
||||||
|
@ -50,7 +50,7 @@ class AddPeopleToCollection extends React.Component<Props> {
|
|||||||
});
|
});
|
||||||
}, 250);
|
}, 250);
|
||||||
|
|
||||||
handleAddUser = user => {
|
handleAddUser = (user) => {
|
||||||
try {
|
try {
|
||||||
this.props.memberships.create({
|
this.props.memberships.create({
|
||||||
collectionId: this.props.collection.id,
|
collectionId: this.props.collection.id,
|
||||||
@ -74,7 +74,8 @@ class AddPeopleToCollection extends React.Component<Props> {
|
|||||||
Need to add someone who’s not yet on the team yet?{" "}
|
Need to add someone who’s not yet on the team yet?{" "}
|
||||||
<a role="button" onClick={this.handleInviteModalOpen}>
|
<a role="button" onClick={this.handleInviteModalOpen}>
|
||||||
Invite people to {team.name}
|
Invite people to {team.name}
|
||||||
</a>.
|
</a>
|
||||||
|
.
|
||||||
</HelpText>
|
</HelpText>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
@ -97,7 +98,7 @@ class AddPeopleToCollection extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
items={users.notInCollection(collection.id, this.query)}
|
items={users.notInCollection(collection.id, this.query)}
|
||||||
fetch={this.query ? undefined : users.fetchPage}
|
fetch={this.query ? undefined : users.fetchPage}
|
||||||
renderItem={item => (
|
renderItem={(item) => (
|
||||||
<MemberListItem
|
<MemberListItem
|
||||||
key={item.id}
|
key={item.id}
|
||||||
user={item}
|
user={item}
|
||||||
@ -118,6 +119,9 @@ class AddPeopleToCollection extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default inject("auth", "users", "memberships", "ui")(
|
export default inject(
|
||||||
AddPeopleToCollection
|
"auth",
|
||||||
);
|
"users",
|
||||||
|
"memberships",
|
||||||
|
"ui"
|
||||||
|
)(AddPeopleToCollection);
|
||||||
|
@ -55,7 +55,7 @@ class CollectionMembers extends React.Component<Props> {
|
|||||||
this.addMemberModalOpen = false;
|
this.addMemberModalOpen = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
handleRemoveUser = user => {
|
handleRemoveUser = (user) => {
|
||||||
try {
|
try {
|
||||||
this.props.memberships.delete({
|
this.props.memberships.delete({
|
||||||
collectionId: this.props.collection.id,
|
collectionId: this.props.collection.id,
|
||||||
@ -80,7 +80,7 @@ class CollectionMembers extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleRemoveGroup = group => {
|
handleRemoveGroup = (group) => {
|
||||||
try {
|
try {
|
||||||
this.props.collectionGroupMemberships.delete({
|
this.props.collectionGroupMemberships.delete({
|
||||||
collectionId: this.props.collection.id,
|
collectionId: this.props.collection.id,
|
||||||
@ -118,7 +118,7 @@ class CollectionMembers extends React.Component<Props> {
|
|||||||
if (!user) return null;
|
if (!user) return null;
|
||||||
|
|
||||||
const key = memberships.orderedData
|
const key = memberships.orderedData
|
||||||
.map(m => m.permission)
|
.map((m) => m.permission)
|
||||||
.concat(collection.private)
|
.concat(collection.private)
|
||||||
.join("-");
|
.join("-");
|
||||||
|
|
||||||
@ -133,7 +133,8 @@ class CollectionMembers extends React.Component<Props> {
|
|||||||
team by{" "}
|
team by{" "}
|
||||||
<a role="button" onClick={this.props.onEdit}>
|
<a role="button" onClick={this.props.onEdit}>
|
||||||
changing its visibility
|
changing its visibility
|
||||||
</a>.
|
</a>
|
||||||
|
.
|
||||||
</HelpText>
|
</HelpText>
|
||||||
<span>
|
<span>
|
||||||
<Button
|
<Button
|
||||||
@ -153,7 +154,8 @@ class CollectionMembers extends React.Component<Props> {
|
|||||||
collection,{" "}
|
collection,{" "}
|
||||||
<a role="button" onClick={this.props.onEdit}>
|
<a role="button" onClick={this.props.onEdit}>
|
||||||
make it private
|
make it private
|
||||||
</a>.
|
</a>
|
||||||
|
.
|
||||||
</HelpText>
|
</HelpText>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -166,7 +168,7 @@ class CollectionMembers extends React.Component<Props> {
|
|||||||
fetch={collectionGroupMemberships.fetchPage}
|
fetch={collectionGroupMemberships.fetchPage}
|
||||||
options={collection.private ? { id: collection.id } : undefined}
|
options={collection.private ? { id: collection.id } : undefined}
|
||||||
empty={<Empty>This collection has no groups.</Empty>}
|
empty={<Empty>This collection has no groups.</Empty>}
|
||||||
renderItem={group => (
|
renderItem={(group) => (
|
||||||
<CollectionGroupMemberListItem
|
<CollectionGroupMemberListItem
|
||||||
key={group.id}
|
key={group.id}
|
||||||
group={group}
|
group={group}
|
||||||
@ -174,7 +176,7 @@ class CollectionMembers extends React.Component<Props> {
|
|||||||
`${group.id}-${collection.id}`
|
`${group.id}-${collection.id}`
|
||||||
)}
|
)}
|
||||||
onRemove={() => this.handleRemoveGroup(group)}
|
onRemove={() => this.handleRemoveGroup(group)}
|
||||||
onUpdate={permission =>
|
onUpdate={(permission) =>
|
||||||
this.handleUpdateGroup(group, permission)
|
this.handleUpdateGroup(group, permission)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@ -219,14 +221,14 @@ class CollectionMembers extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
fetch={collection.private ? memberships.fetchPage : users.fetchPage}
|
fetch={collection.private ? memberships.fetchPage : users.fetchPage}
|
||||||
options={collection.private ? { id: collection.id } : undefined}
|
options={collection.private ? { id: collection.id } : undefined}
|
||||||
renderItem={item => (
|
renderItem={(item) => (
|
||||||
<MemberListItem
|
<MemberListItem
|
||||||
key={item.id}
|
key={item.id}
|
||||||
user={item}
|
user={item}
|
||||||
membership={memberships.get(`${item.id}-${collection.id}`)}
|
membership={memberships.get(`${item.id}-${collection.id}`)}
|
||||||
canEdit={collection.private && item.id !== user.id}
|
canEdit={collection.private && item.id !== user.id}
|
||||||
onRemove={() => this.handleRemoveUser(item)}
|
onRemove={() => this.handleRemoveUser(item)}
|
||||||
onUpdate={permission => this.handleUpdateUser(item, permission)}
|
onUpdate={(permission) => this.handleUpdateUser(item, permission)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
@ -39,7 +39,7 @@ const MemberListItem = ({
|
|||||||
? collectionGroupMembership.permission
|
? collectionGroupMembership.permission
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
onChange={ev => onUpdate(ev.target.value)}
|
onChange={(ev) => onUpdate(ev.target.value)}
|
||||||
labelHidden
|
labelHidden
|
||||||
/>
|
/>
|
||||||
<ButtonWrap>
|
<ButtonWrap>
|
||||||
|
@ -52,29 +52,26 @@ const MemberListItem = ({
|
|||||||
image={<Avatar src={user.avatarUrl} size={40} />}
|
image={<Avatar src={user.avatarUrl} size={40} />}
|
||||||
actions={
|
actions={
|
||||||
<Flex align="center">
|
<Flex align="center">
|
||||||
{canEdit &&
|
{canEdit && onUpdate && (
|
||||||
onUpdate && (
|
<Select
|
||||||
<Select
|
label="Permissions"
|
||||||
label="Permissions"
|
options={PERMISSIONS}
|
||||||
options={PERMISSIONS}
|
value={membership ? membership.permission : undefined}
|
||||||
value={membership ? membership.permission : undefined}
|
onChange={(ev) => onUpdate(ev.target.value)}
|
||||||
onChange={ev => onUpdate(ev.target.value)}
|
labelHidden
|
||||||
labelHidden
|
/>
|
||||||
/>
|
)}
|
||||||
)}
|
|
||||||
|
|
||||||
{canEdit &&
|
{canEdit && onRemove && (
|
||||||
onRemove && (
|
<DropdownMenu>
|
||||||
<DropdownMenu>
|
<DropdownMenuItem onClick={onRemove}>Remove</DropdownMenuItem>
|
||||||
<DropdownMenuItem onClick={onRemove}>Remove</DropdownMenuItem>
|
</DropdownMenu>
|
||||||
</DropdownMenu>
|
)}
|
||||||
)}
|
{canEdit && onAdd && (
|
||||||
{canEdit &&
|
<Button onClick={onAdd} neutral>
|
||||||
onAdd && (
|
Add
|
||||||
<Button onClick={onAdd} neutral>
|
</Button>
|
||||||
Add
|
)}
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -37,9 +37,7 @@ const UserListItem = ({ user, onAdd, canEdit }: Props) => {
|
|||||||
<Button type="button" onClick={onAdd} icon={<PlusIcon />} neutral>
|
<Button type="button" onClick={onAdd} icon={<PlusIcon />} neutral>
|
||||||
Add
|
Add
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : undefined
|
||||||
undefined
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -85,7 +85,7 @@ class CollectionNew extends React.Component<Props> {
|
|||||||
this.hasOpenedIconPicker = true;
|
this.hasOpenedIconPicker = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
handleDescriptionChange = getValue => {
|
handleDescriptionChange = (getValue) => {
|
||||||
this.description = getValue();
|
this.description = getValue();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import Flex from "components/Flex";
|
|||||||
|
|
||||||
const Container = styled(Flex)`
|
const Container = styled(Flex)`
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top: ${props => (props.isShare ? "50px" : "0")};
|
margin-top: ${(props) => (props.isShare ? "50px" : "0")};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default Container;
|
export default Container;
|
||||||
|
@ -16,26 +16,23 @@ export default function Contents({ headings }: Props) {
|
|||||||
const [activeSlug, setActiveSlug] = React.useState();
|
const [activeSlug, setActiveSlug] = React.useState();
|
||||||
const position = useWindowScrollPosition({ throttle: 100 });
|
const position = useWindowScrollPosition({ throttle: 100 });
|
||||||
|
|
||||||
React.useEffect(
|
React.useEffect(() => {
|
||||||
() => {
|
for (let key = 0; key < headings.length; key++) {
|
||||||
for (let key = 0; key < headings.length; key++) {
|
const heading = headings[key];
|
||||||
const heading = headings[key];
|
const element = window.document.getElementById(
|
||||||
const element = window.document.getElementById(
|
decodeURIComponent(heading.id)
|
||||||
decodeURIComponent(heading.id)
|
);
|
||||||
);
|
|
||||||
|
|
||||||
if (element) {
|
if (element) {
|
||||||
const bounding = element.getBoundingClientRect();
|
const bounding = element.getBoundingClientRect();
|
||||||
if (bounding.top > HEADING_OFFSET) {
|
if (bounding.top > HEADING_OFFSET) {
|
||||||
const last = headings[Math.max(0, key - 1)];
|
const last = headings[Math.max(0, key - 1)];
|
||||||
setActiveSlug(last.id);
|
setActiveSlug(last.id);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
[position, headings]
|
}, [position, headings]);
|
||||||
);
|
|
||||||
|
|
||||||
// calculate the minimum heading level and adjust all the headings to make
|
// calculate the minimum heading level and adjust all the headings to make
|
||||||
// that the top-most. This prevents the contents from being weirdly indented
|
// that the top-most. This prevents the contents from being weirdly indented
|
||||||
@ -52,7 +49,7 @@ export default function Contents({ headings }: Props) {
|
|||||||
<Heading>Contents</Heading>
|
<Heading>Contents</Heading>
|
||||||
{headings.length ? (
|
{headings.length ? (
|
||||||
<List>
|
<List>
|
||||||
{headings.map(heading => (
|
{headings.map((heading) => (
|
||||||
<ListItem
|
<ListItem
|
||||||
key={heading.id}
|
key={heading.id}
|
||||||
level={heading.level - headingAdjustment}
|
level={heading.level - headingAdjustment}
|
||||||
@ -75,7 +72,7 @@ const Wrapper = styled("div")`
|
|||||||
position: sticky;
|
position: sticky;
|
||||||
top: 80px;
|
top: 80px;
|
||||||
|
|
||||||
box-shadow: 1px 0 0 ${props => darken(0.05, props.theme.sidebarBackground)};
|
box-shadow: 1px 0 0 ${(props) => darken(0.05, props.theme.sidebarBackground)};
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
margin-right: 2em;
|
margin-right: 2em;
|
||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
@ -93,7 +90,7 @@ const Heading = styled("h3")`
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: ${props => props.theme.sidebarText};
|
color: ${(props) => props.theme.sidebarText};
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -106,20 +103,20 @@ const Empty = styled(HelpText)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const ListItem = styled("li")`
|
const ListItem = styled("li")`
|
||||||
margin-left: ${props => (props.level - 1) * 10}px;
|
margin-left: ${(props) => (props.level - 1) * 10}px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
padding-right: 2em;
|
padding-right: 2em;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
border-right: 3px solid
|
border-right: 3px solid
|
||||||
${props => (props.active ? props.theme.textSecondary : "transparent")};
|
${(props) => (props.active ? props.theme.textSecondary : "transparent")};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Link = styled("a")`
|
const Link = styled("a")`
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: ${props => props.theme.primary};
|
color: ${(props) => props.theme.primary};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ class DataLoader extends React.Component<Props> {
|
|||||||
const results = await this.props.documents.search(term);
|
const results = await this.props.documents.search(term);
|
||||||
|
|
||||||
return results
|
return results
|
||||||
.filter(result => result.document.title)
|
.filter((result) => result.document.title)
|
||||||
.map((result, index) => ({
|
.map((result, index) => ({
|
||||||
title: result.document.title,
|
title: result.document.title,
|
||||||
url: result.document.url,
|
url: result.document.url,
|
||||||
@ -130,7 +130,7 @@ class DataLoader extends React.Component<Props> {
|
|||||||
return this.goToDocumentCanonical();
|
return this.goToDocumentCanonical();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.props.shares.fetch(document.id).catch(err => {
|
this.props.shares.fetch(document.id).catch((err) => {
|
||||||
if (!(err instanceof NotFoundError)) {
|
if (!(err instanceof NotFoundError)) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
@ -195,7 +195,12 @@ class DataLoader extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default withRouter(
|
export default withRouter(
|
||||||
inject("ui", "auth", "documents", "revisions", "policies", "shares")(
|
inject(
|
||||||
DataLoader
|
"ui",
|
||||||
)
|
"auth",
|
||||||
|
"documents",
|
||||||
|
"revisions",
|
||||||
|
"policies",
|
||||||
|
"shares"
|
||||||
|
)(DataLoader)
|
||||||
);
|
);
|
||||||
|
@ -298,7 +298,7 @@ class DocumentScene extends React.Component<Props> {
|
|||||||
this.isUploading = false;
|
this.isUploading = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
onChange = getEditorText => {
|
onChange = (getEditorText) => {
|
||||||
this.getEditorText = getEditorText;
|
this.getEditorText = getEditorText;
|
||||||
|
|
||||||
// document change while read only is presumed to be a checkbox edit,
|
// document change while read only is presumed to be a checkbox edit,
|
||||||
@ -312,7 +312,7 @@ class DocumentScene extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onChangeTitle = event => {
|
onChangeTitle = (event) => {
|
||||||
this.title = event.target.value;
|
this.title = event.target.value;
|
||||||
this.updateIsDirtyDebounced();
|
this.updateIsDirtyDebounced();
|
||||||
this.autosave();
|
this.autosave();
|
||||||
@ -409,22 +409,20 @@ class DocumentScene extends React.Component<Props> {
|
|||||||
column
|
column
|
||||||
auto
|
auto
|
||||||
>
|
>
|
||||||
{document.isTemplate &&
|
{document.isTemplate && !readOnly && (
|
||||||
!readOnly && (
|
<Notice muted>
|
||||||
<Notice muted>
|
You’re editing a template. Highlight some text and use the{" "}
|
||||||
You’re editing a template. Highlight some text and use the{" "}
|
<PlaceholderIcon color="currentColor" /> control to add
|
||||||
<PlaceholderIcon color="currentColor" /> control to add
|
placeholders that can be filled out when creating new
|
||||||
placeholders that can be filled out when creating new
|
documents from this template.
|
||||||
documents from this template.
|
</Notice>
|
||||||
</Notice>
|
)}
|
||||||
)}
|
{document.archivedAt && !document.deletedAt && (
|
||||||
{document.archivedAt &&
|
<Notice muted>
|
||||||
!document.deletedAt && (
|
Archived by {document.updatedBy.name}{" "}
|
||||||
<Notice muted>
|
<Time dateTime={document.archivedAt} /> ago
|
||||||
Archived by {document.updatedBy.name}{" "}
|
</Notice>
|
||||||
<Time dateTime={document.archivedAt} /> ago
|
)}
|
||||||
</Notice>
|
|
||||||
)}
|
|
||||||
{document.deletedAt && (
|
{document.deletedAt && (
|
||||||
<Notice muted>
|
<Notice muted>
|
||||||
Deleted by {document.updatedBy.name}{" "}
|
Deleted by {document.updatedBy.name}{" "}
|
||||||
@ -440,15 +438,14 @@ class DocumentScene extends React.Component<Props> {
|
|||||||
</Notice>
|
</Notice>
|
||||||
)}
|
)}
|
||||||
<Flex auto={!readOnly}>
|
<Flex auto={!readOnly}>
|
||||||
{ui.tocVisible &&
|
{ui.tocVisible && readOnly && (
|
||||||
readOnly && (
|
<Contents
|
||||||
<Contents
|
headings={this.editor ? this.editor.getHeadings() : []}
|
||||||
headings={this.editor ? this.editor.getHeadings() : []}
|
/>
|
||||||
/>
|
)}
|
||||||
)}
|
|
||||||
<Editor
|
<Editor
|
||||||
id={document.id}
|
id={document.id}
|
||||||
ref={ref => {
|
ref={(ref) => {
|
||||||
if (ref) {
|
if (ref) {
|
||||||
this.editor = ref;
|
this.editor = ref;
|
||||||
}
|
}
|
||||||
@ -476,16 +473,14 @@ class DocumentScene extends React.Component<Props> {
|
|||||||
ui={this.props.ui}
|
ui={this.props.ui}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
{readOnly &&
|
{readOnly && !isShare && !revision && (
|
||||||
!isShare &&
|
<React.Fragment>
|
||||||
!revision && (
|
<MarkAsViewed document={document} />
|
||||||
<React.Fragment>
|
<ReferencesWrapper isOnlyTitle={document.isOnlyTitle}>
|
||||||
<MarkAsViewed document={document} />
|
<References document={document} />
|
||||||
<ReferencesWrapper isOnlyTitle={document.isOnlyTitle}>
|
</ReferencesWrapper>
|
||||||
<References document={document} />
|
</React.Fragment>
|
||||||
</ReferencesWrapper>
|
)}
|
||||||
</React.Fragment>
|
|
||||||
)}
|
|
||||||
</MaxWidth>
|
</MaxWidth>
|
||||||
</Container>
|
</Container>
|
||||||
</Background>
|
</Background>
|
||||||
@ -501,12 +496,12 @@ const PlaceholderIcon = styled(InputIcon)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Background = styled(Container)`
|
const Background = styled(Container)`
|
||||||
background: ${props => props.theme.background};
|
background: ${(props) => props.theme.background};
|
||||||
transition: ${props => props.theme.backgroundTransition};
|
transition: ${(props) => props.theme.backgroundTransition};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ReferencesWrapper = styled("div")`
|
const ReferencesWrapper = styled("div")`
|
||||||
margin-top: ${props => (props.isOnlyTitle ? -45 : 16)}px;
|
margin-top: ${(props) => (props.isOnlyTitle ? -45 : 16)}px;
|
||||||
|
|
||||||
@media print {
|
@media print {
|
||||||
display: none;
|
display: none;
|
||||||
@ -514,7 +509,7 @@ const ReferencesWrapper = styled("div")`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const MaxWidth = styled(Flex)`
|
const MaxWidth = styled(Flex)`
|
||||||
${props =>
|
${(props) =>
|
||||||
props.archived && `* { color: ${props.theme.textSecondary} !important; } `};
|
props.archived && `* { color: ${props.theme.textSecondary} !important; } `};
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
@ -523,7 +518,7 @@ const MaxWidth = styled(Flex)`
|
|||||||
${breakpoint("tablet")`
|
${breakpoint("tablet")`
|
||||||
padding: 0 24px;
|
padding: 0 24px;
|
||||||
margin: 4px auto 12px;
|
margin: 4px auto 12px;
|
||||||
max-width: calc(48px + ${props => (props.tocVisible ? "64em" : "46em")});
|
max-width: calc(48px + ${(props) => (props.tocVisible ? "64em" : "46em")});
|
||||||
`};
|
`};
|
||||||
|
|
||||||
${breakpoint("desktopLarge")`
|
${breakpoint("desktopLarge")`
|
||||||
|
@ -44,7 +44,7 @@ class DocumentMove extends React.Component<Props> {
|
|||||||
|
|
||||||
// Build index
|
// Build index
|
||||||
const indexeableDocuments = [];
|
const indexeableDocuments = [];
|
||||||
paths.forEach(path => indexeableDocuments.push(path));
|
paths.forEach((path) => indexeableDocuments.push(path));
|
||||||
index.addDocuments(indexeableDocuments);
|
index.addDocuments(indexeableDocuments);
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
@ -65,20 +65,20 @@ class DocumentMove extends React.Component<Props> {
|
|||||||
|
|
||||||
// Exclude root from search results if document is already at the root
|
// Exclude root from search results if document is already at the root
|
||||||
if (!document.parentDocumentId) {
|
if (!document.parentDocumentId) {
|
||||||
results = results.filter(result => result.id !== document.collectionId);
|
results = results.filter((result) => result.id !== document.collectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exclude document if on the path to result, or the same result
|
// Exclude document if on the path to result, or the same result
|
||||||
results = results.filter(
|
results = results.filter(
|
||||||
result =>
|
(result) =>
|
||||||
!result.path.map(doc => doc.id).includes(document.id) &&
|
!result.path.map((doc) => doc.id).includes(document.id) &&
|
||||||
last(result.path.map(doc => doc.id)) !== document.parentDocumentId
|
last(result.path.map((doc) => doc.id)) !== document.parentDocumentId
|
||||||
);
|
);
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleKeyDown = ev => {
|
handleKeyDown = (ev) => {
|
||||||
// Down
|
// Down
|
||||||
if (ev.which === 40) {
|
if (ev.which === 40) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
@ -98,7 +98,7 @@ class DocumentMove extends React.Component<Props> {
|
|||||||
this.searchTerm = ev.target.value;
|
this.searchTerm = ev.target.value;
|
||||||
};
|
};
|
||||||
|
|
||||||
setFirstDocumentRef = ref => {
|
setFirstDocumentRef = (ref) => {
|
||||||
this.firstDocument = ref;
|
this.firstDocument = ref;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -121,50 +121,47 @@ class DocumentMove extends React.Component<Props> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen onRequestClose={onRequestClose} title="Move document">
|
<Modal isOpen onRequestClose={onRequestClose} title="Move document">
|
||||||
{document &&
|
{document && collections.isLoaded && (
|
||||||
collections.isLoaded && (
|
<Flex column>
|
||||||
<Flex column>
|
<Section>
|
||||||
<Section>
|
<Labeled label="Current location">
|
||||||
<Labeled label="Current location">
|
{this.renderPathToCurrentDocument()}
|
||||||
{this.renderPathToCurrentDocument()}
|
</Labeled>
|
||||||
</Labeled>
|
</Section>
|
||||||
</Section>
|
|
||||||
|
|
||||||
<Section column>
|
<Section column>
|
||||||
<Labeled label="Choose a new location">
|
<Labeled label="Choose a new location">
|
||||||
<Input
|
<Input
|
||||||
type="search"
|
type="search"
|
||||||
placeholder="Search collections & documents…"
|
placeholder="Search collections & documents…"
|
||||||
onKeyDown={this.handleKeyDown}
|
onKeyDown={this.handleKeyDown}
|
||||||
onChange={this.handleFilter}
|
onChange={this.handleFilter}
|
||||||
required
|
required
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
</Labeled>
|
</Labeled>
|
||||||
<Flex column>
|
<Flex column>
|
||||||
<StyledArrowKeyNavigation
|
<StyledArrowKeyNavigation
|
||||||
mode={ArrowKeyNavigation.mode.VERTICAL}
|
mode={ArrowKeyNavigation.mode.VERTICAL}
|
||||||
defaultActiveChildIndex={0}
|
defaultActiveChildIndex={0}
|
||||||
>
|
>
|
||||||
{this.results
|
{this.results.slice(0, MAX_RESULTS).map((result, index) => (
|
||||||
.slice(0, MAX_RESULTS)
|
<PathToDocument
|
||||||
.map((result, index) => (
|
key={result.id}
|
||||||
<PathToDocument
|
result={result}
|
||||||
key={result.id}
|
document={document}
|
||||||
result={result}
|
collection={collections.get(result.collectionId)}
|
||||||
document={document}
|
ref={(ref) =>
|
||||||
collection={collections.get(result.collectionId)}
|
index === 0 && this.setFirstDocumentRef(ref)
|
||||||
ref={ref =>
|
}
|
||||||
index === 0 && this.setFirstDocumentRef(ref)
|
onSuccess={this.handleSuccess}
|
||||||
}
|
/>
|
||||||
onSuccess={this.handleSuccess}
|
))}
|
||||||
/>
|
</StyledArrowKeyNavigation>
|
||||||
))}
|
</Flex>
|
||||||
</StyledArrowKeyNavigation>
|
</Section>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Section>
|
)}
|
||||||
</Flex>
|
|
||||||
)}
|
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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={(ref) => (this.editor = ref)}
|
||||||
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}
|
||||||
@ -98,15 +98,13 @@ class DocumentEditor extends React.Component<Props> {
|
|||||||
{...this.props}
|
{...this.props}
|
||||||
/>
|
/>
|
||||||
{!readOnly && <ClickablePadding onClick={this.focusAtEnd} grow />}
|
{!readOnly && <ClickablePadding onClick={this.focusAtEnd} grow />}
|
||||||
{this.activeLinkEvent &&
|
{this.activeLinkEvent && !isShare && readOnly && (
|
||||||
!isShare &&
|
<HoverPreview
|
||||||
readOnly && (
|
node={this.activeLinkEvent.target}
|
||||||
<HoverPreview
|
event={this.activeLinkEvent}
|
||||||
node={this.activeLinkEvent.target}
|
onClose={this.handleLinkInactive}
|
||||||
event={this.activeLinkEvent}
|
/>
|
||||||
onClose={this.handleLinkInactive}
|
)}
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -117,10 +115,10 @@ const Title = styled(Textarea)`
|
|||||||
line-height: 1.25;
|
line-height: 1.25;
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
text: ${props => props.theme.text};
|
text: ${(props) => props.theme.text};
|
||||||
background: ${props => props.theme.background};
|
background: ${(props) => props.theme.background};
|
||||||
transition: ${props => props.theme.backgroundTransition};
|
transition: ${(props) => props.theme.backgroundTransition};
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
font-size: 2.25em;
|
font-size: 2.25em;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
outline: none;
|
outline: none;
|
||||||
@ -129,7 +127,7 @@ const Title = styled(Textarea)`
|
|||||||
resize: none;
|
resize: none;
|
||||||
|
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
color: ${props => props.theme.placeholder};
|
color: ${(props) => props.theme.placeholder};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -194,12 +194,11 @@ class Header extends React.Component<Props> {
|
|||||||
</Title>
|
</Title>
|
||||||
)}
|
)}
|
||||||
<Wrapper align="center" justify="flex-end">
|
<Wrapper align="center" justify="flex-end">
|
||||||
{isSaving &&
|
{isSaving && !isPublishing && (
|
||||||
!isPublishing && (
|
<Action>
|
||||||
<Action>
|
<Status>Saving…</Status>
|
||||||
<Status>Saving…</Status>
|
</Action>
|
||||||
</Action>
|
)}
|
||||||
)}
|
|
||||||
|
|
||||||
<Fade>
|
<Fade>
|
||||||
<Collaborators
|
<Collaborators
|
||||||
@ -207,40 +206,38 @@ class Header extends React.Component<Props> {
|
|||||||
currentUserId={auth.user ? auth.user.id : undefined}
|
currentUserId={auth.user ? auth.user.id : undefined}
|
||||||
/>
|
/>
|
||||||
</Fade>
|
</Fade>
|
||||||
{isEditing &&
|
{isEditing && !isTemplate && isNew && (
|
||||||
!isTemplate &&
|
<Action>
|
||||||
isNew && (
|
<TemplatesMenu document={document} />
|
||||||
<Action>
|
</Action>
|
||||||
<TemplatesMenu document={document} />
|
)}
|
||||||
</Action>
|
{!isEditing && canShareDocuments && (
|
||||||
)}
|
<Action>
|
||||||
{!isEditing &&
|
<Tooltip
|
||||||
canShareDocuments && (
|
tooltip={
|
||||||
<Action>
|
isPubliclyShared ? (
|
||||||
<Tooltip
|
<React.Fragment>
|
||||||
tooltip={
|
Anyone with the link <br />
|
||||||
isPubliclyShared ? (
|
can view this document
|
||||||
<React.Fragment>
|
</React.Fragment>
|
||||||
Anyone with the link <br />can view this document
|
) : (
|
||||||
</React.Fragment>
|
""
|
||||||
) : (
|
)
|
||||||
""
|
}
|
||||||
)
|
delay={500}
|
||||||
}
|
placement="bottom"
|
||||||
delay={500}
|
>
|
||||||
placement="bottom"
|
<Button
|
||||||
|
icon={isPubliclyShared ? <GlobeIcon /> : undefined}
|
||||||
|
onClick={this.handleShareLink}
|
||||||
|
neutral
|
||||||
|
small
|
||||||
>
|
>
|
||||||
<Button
|
Share
|
||||||
icon={isPubliclyShared ? <GlobeIcon /> : undefined}
|
</Button>
|
||||||
onClick={this.handleShareLink}
|
</Tooltip>
|
||||||
neutral
|
</Action>
|
||||||
small
|
)}
|
||||||
>
|
|
||||||
Share
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Action>
|
|
||||||
)}
|
|
||||||
{isEditing && (
|
{isEditing && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Action>
|
<Action>
|
||||||
@ -282,62 +279,56 @@ class Header extends React.Component<Props> {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Action>
|
</Action>
|
||||||
)}
|
)}
|
||||||
{canEdit &&
|
{canEdit && can.createChildDocument && (
|
||||||
can.createChildDocument && (
|
<Action>
|
||||||
<Action>
|
<NewChildDocumentMenu
|
||||||
<NewChildDocumentMenu
|
document={document}
|
||||||
document={document}
|
label={
|
||||||
label={
|
<Tooltip
|
||||||
<Tooltip
|
tooltip="New document"
|
||||||
tooltip="New document"
|
shortcut="n"
|
||||||
shortcut="n"
|
delay={500}
|
||||||
delay={500}
|
placement="bottom"
|
||||||
placement="bottom"
|
>
|
||||||
>
|
<Button icon={<PlusIcon />} neutral>
|
||||||
<Button icon={<PlusIcon />} neutral>
|
New doc
|
||||||
New doc
|
</Button>
|
||||||
</Button>
|
</Tooltip>
|
||||||
</Tooltip>
|
}
|
||||||
}
|
/>
|
||||||
/>
|
</Action>
|
||||||
</Action>
|
)}
|
||||||
)}
|
{canEdit && isTemplate && !isDraft && !isRevision && (
|
||||||
{canEdit &&
|
<Action>
|
||||||
isTemplate &&
|
<Button
|
||||||
!isDraft &&
|
icon={<PlusIcon />}
|
||||||
!isRevision && (
|
onClick={this.handleNewFromTemplate}
|
||||||
<Action>
|
primary
|
||||||
|
small
|
||||||
|
>
|
||||||
|
New from template
|
||||||
|
</Button>
|
||||||
|
</Action>
|
||||||
|
)}
|
||||||
|
{can.update && isDraft && !isRevision && (
|
||||||
|
<Action>
|
||||||
|
<Tooltip
|
||||||
|
tooltip="Publish"
|
||||||
|
shortcut={`${meta}+shift+p`}
|
||||||
|
delay={500}
|
||||||
|
placement="bottom"
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
icon={<PlusIcon />}
|
onClick={this.handlePublish}
|
||||||
onClick={this.handleNewFromTemplate}
|
title="Publish document"
|
||||||
primary
|
disabled={publishingIsDisabled}
|
||||||
small
|
small
|
||||||
>
|
>
|
||||||
New from template
|
{isPublishing ? "Publishing…" : "Publish"}
|
||||||
</Button>
|
</Button>
|
||||||
</Action>
|
</Tooltip>
|
||||||
)}
|
</Action>
|
||||||
{can.update &&
|
)}
|
||||||
isDraft &&
|
|
||||||
!isRevision && (
|
|
||||||
<Action>
|
|
||||||
<Tooltip
|
|
||||||
tooltip="Publish"
|
|
||||||
shortcut={`${meta}+shift+p`}
|
|
||||||
delay={500}
|
|
||||||
placement="bottom"
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
onClick={this.handlePublish}
|
|
||||||
title="Publish document"
|
|
||||||
disabled={publishingIsDisabled}
|
|
||||||
small
|
|
||||||
>
|
|
||||||
{isPublishing ? "Publishing…" : "Publish"}
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
</Action>
|
|
||||||
)}
|
|
||||||
{!isEditing && (
|
{!isEditing && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Separator />
|
<Separator />
|
||||||
@ -358,7 +349,7 @@ class Header extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Status = styled.div`
|
const Status = styled.div`
|
||||||
color: ${props => props.theme.slate};
|
color: ${(props) => props.theme.slate};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const BreadcrumbAndContents = styled(Flex)`
|
const BreadcrumbAndContents = styled(Flex)`
|
||||||
@ -386,9 +377,9 @@ const Actions = styled(Flex)`
|
|||||||
right: 0;
|
right: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
background: ${props => transparentize(0.2, props.theme.background)};
|
background: ${(props) => transparentize(0.2, props.theme.background)};
|
||||||
box-shadow: 0 1px 0
|
box-shadow: 0 1px 0
|
||||||
${props =>
|
${(props) =>
|
||||||
props.isCompact
|
props.isCompact
|
||||||
? darken(0.05, props.theme.sidebarBackground)
|
? darken(0.05, props.theme.sidebarBackground)
|
||||||
: "transparent"};
|
: "transparent"};
|
||||||
@ -402,7 +393,7 @@ const Actions = styled(Flex)`
|
|||||||
}
|
}
|
||||||
|
|
||||||
${breakpoint("tablet")`
|
${breakpoint("tablet")`
|
||||||
padding: ${props => (props.isCompact ? "12px" : `24px 24px 0`)};
|
padding: ${(props) => (props.isCompact ? "12px" : `24px 24px 0`)};
|
||||||
`};
|
`};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ const DocumentLink = styled(Link)`
|
|||||||
&:hover,
|
&:hover,
|
||||||
&:active,
|
&:active,
|
||||||
&:focus {
|
&:focus {
|
||||||
background: ${props => props.theme.listItemHoverBackground};
|
background: ${(props) => props.theme.listItemHoverBackground};
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -39,7 +39,7 @@ const Title = styled.h3`
|
|||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 0.25em;
|
margin-bottom: 0.25em;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
color: ${props => props.theme.text};
|
color: ${(props) => props.theme.text};
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
|
||||||
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
||||||
`;
|
`;
|
||||||
|
@ -52,7 +52,7 @@ class References extends React.Component<Props> {
|
|||||||
)}
|
)}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
{isBacklinksTab
|
{isBacklinksTab
|
||||||
? backlinks.map(backlinkedDocument => (
|
? backlinks.map((backlinkedDocument) => (
|
||||||
<ReferenceListItem
|
<ReferenceListItem
|
||||||
anchor={document.urlId}
|
anchor={document.urlId}
|
||||||
key={backlinkedDocument.id}
|
key={backlinkedDocument.id}
|
||||||
@ -62,7 +62,7 @@ class References extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
: children.map(node => {
|
: children.map((node) => {
|
||||||
// If we have the document in the store already then use it to get the extra
|
// If we have the document in the store already then use it to get the extra
|
||||||
// contextual info, otherwise the collection node will do (only has title and id)
|
// contextual info, otherwise the collection node will do (only has title and id)
|
||||||
const document = documents.get(node.id);
|
const document = documents.get(node.id);
|
||||||
|
@ -51,17 +51,15 @@ class DocumentDelete extends React.Component<Props> {
|
|||||||
<HelpText>
|
<HelpText>
|
||||||
Are you sure about that? Deleting the{" "}
|
Are you sure about that? Deleting the{" "}
|
||||||
<strong>{document.titleWithDefault}</strong> {document.noun} will
|
<strong>{document.titleWithDefault}</strong> {document.noun} will
|
||||||
delete all of its history{document.isTemplate
|
delete all of its history
|
||||||
? ""
|
{document.isTemplate ? "" : ", and any nested documents"}.
|
||||||
: ", and any nested documents"}.
|
|
||||||
</HelpText>
|
</HelpText>
|
||||||
{!document.isDraft &&
|
{!document.isDraft && !document.isArchived && (
|
||||||
!document.isArchived && (
|
<HelpText>
|
||||||
<HelpText>
|
If you’d like the option of referencing or restoring this{" "}
|
||||||
If you’d like the option of referencing or restoring this{" "}
|
{document.noun} in the future, consider archiving it instead.
|
||||||
{document.noun} in the future, consider archiving it instead.
|
</HelpText>
|
||||||
</HelpText>
|
)}
|
||||||
)}
|
|
||||||
<Button type="submit" danger>
|
<Button type="submit" danger>
|
||||||
{this.isDeleting ? "Deleting…" : "I’m sure – Delete"}
|
{this.isDeleting ? "Deleting…" : "I’m sure – Delete"}
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -35,7 +35,7 @@ class DocumentShare extends React.Component<Props> {
|
|||||||
clearTimeout(this.timeout);
|
clearTimeout(this.timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePublishedChange = async event => {
|
handlePublishedChange = async (event) => {
|
||||||
const { document, shares } = this.props;
|
const { document, shares } = this.props;
|
||||||
const share = shares.getByDocumentId(document.id);
|
const share = shares.getByDocumentId(document.id);
|
||||||
invariant(share, "Share must exist");
|
invariant(share, "Share must exist");
|
||||||
@ -76,7 +76,8 @@ class DocumentShare extends React.Component<Props> {
|
|||||||
: "It is only viewable by those that already have access to the collection."}{" "}
|
: "It is only viewable by those that already have access to the collection."}{" "}
|
||||||
<Link to="/settings/shares" onClick={onSubmit}>
|
<Link to="/settings/shares" onClick={onSubmit}>
|
||||||
Manage all share links
|
Manage all share links
|
||||||
</Link>.
|
</Link>
|
||||||
|
.
|
||||||
</HelpText>
|
</HelpText>
|
||||||
{canPublish && (
|
{canPublish && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
@ -112,7 +113,9 @@ class DocumentShare extends React.Component<Props> {
|
|||||||
<Button type="submit" disabled={this.isCopied || !share} primary>
|
<Button type="submit" disabled={this.isCopied || !share} primary>
|
||||||
{this.isCopied ? "Copied!" : "Copy Link"}
|
{this.isCopied ? "Copied!" : "Copy Link"}
|
||||||
</Button>
|
</Button>
|
||||||
</CopyToClipboard> <a href={share.url} target="_blank">
|
</CopyToClipboard>
|
||||||
|
|
||||||
|
<a href={share.url} target="_blank">
|
||||||
Preview
|
Preview
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,9 +10,8 @@ const Error404 = () => {
|
|||||||
<PageTitle title="Not Found" />
|
<PageTitle title="Not Found" />
|
||||||
<h1>Not found</h1>
|
<h1>Not found</h1>
|
||||||
<Empty>
|
<Empty>
|
||||||
We were unable to find the page you’re looking for. Go to the <a href="/">
|
We were unable to find the page you’re looking for. Go to the
|
||||||
homepage
|
<a href="/">homepage</a>?
|
||||||
</a>?
|
|
||||||
</Empty>
|
</Empty>
|
||||||
</CenteredContent>
|
</CenteredContent>
|
||||||
);
|
);
|
||||||
|
@ -50,7 +50,7 @@ class AddPeopleToGroup extends React.Component<Props> {
|
|||||||
});
|
});
|
||||||
}, 250);
|
}, 250);
|
||||||
|
|
||||||
handleAddUser = async user => {
|
handleAddUser = async (user) => {
|
||||||
try {
|
try {
|
||||||
await this.props.groupMemberships.create({
|
await this.props.groupMemberships.create({
|
||||||
groupId: this.props.group.id,
|
groupId: this.props.group.id,
|
||||||
@ -74,7 +74,8 @@ class AddPeopleToGroup extends React.Component<Props> {
|
|||||||
someone who’s not yet on the team yet?{" "}
|
someone who’s not yet on the team yet?{" "}
|
||||||
<a role="button" onClick={this.handleInviteModalOpen}>
|
<a role="button" onClick={this.handleInviteModalOpen}>
|
||||||
Invite them to {team.name}
|
Invite them to {team.name}
|
||||||
</a>.
|
</a>
|
||||||
|
.
|
||||||
</HelpText>
|
</HelpText>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
@ -97,7 +98,7 @@ class AddPeopleToGroup extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
items={users.notInGroup(group.id, this.query)}
|
items={users.notInGroup(group.id, this.query)}
|
||||||
fetch={this.query ? undefined : users.fetchPage}
|
fetch={this.query ? undefined : users.fetchPage}
|
||||||
renderItem={item => (
|
renderItem={(item) => (
|
||||||
<GroupMemberListItem
|
<GroupMemberListItem
|
||||||
key={item.id}
|
key={item.id}
|
||||||
user={item}
|
user={item}
|
||||||
@ -118,6 +119,9 @@ class AddPeopleToGroup extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default inject("auth", "users", "groupMemberships", "ui")(
|
export default inject(
|
||||||
AddPeopleToGroup
|
"auth",
|
||||||
);
|
"users",
|
||||||
|
"groupMemberships",
|
||||||
|
"ui"
|
||||||
|
)(AddPeopleToGroup);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user