-
-
Notifications
You must be signed in to change notification settings - Fork 411
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(NewCollectivePage): About section
- Loading branch information
Showing
8 changed files
with
224 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import styled from 'styled-components'; | ||
|
||
/** | ||
* React-Quill usually saves something like `<p><br/></p` when saving with an empty | ||
* editor. This function tries to detect this and returns true if there's no real | ||
* text, image or iframe contents. | ||
*/ | ||
export const isEmptyValue = value => { | ||
if (!value) { | ||
return true; | ||
} else if (value.length > 50) { | ||
// Running the regex on long strings can be costly, and there's very few chances | ||
// to have a blank content with tons of empty markup. | ||
return false; | ||
} else if (/(<img)|(<iframe)|(<video)/.test(value)) { | ||
// If the content has no text but has an image or an iframe (video) then it's not blank | ||
return false; | ||
} else { | ||
// Strip all tags and check if there's something left | ||
const cleanStr = value.replace(/(<([^>]+)>)/gi, ''); | ||
return cleanStr.length === 0; | ||
} | ||
}; | ||
|
||
/** | ||
* `HTMLEditor`'s associate, this component will display raw HTML with some CSS | ||
* resets to ensure we don't mess with the styles. | ||
* | ||
* ⚠️ Be careful! This component will pass content to `dangerouslySetInnerHTML` so | ||
* always ensure `content` is properly sanitized! | ||
*/ | ||
const HTMLContent = styled(({ content, ...props }) => { | ||
return <div dangerouslySetInnerHTML={{ __html: content }} {...props} />; | ||
})` | ||
/** Override global styles to match what we have in the editor */ | ||
h1, | ||
h2, | ||
h3 { | ||
margin: 0; | ||
} | ||
img { | ||
max-width: 100%; | ||
} | ||
.ql-align-center { | ||
text-align: center; | ||
} | ||
.ql-align-right { | ||
text-align: right; | ||
} | ||
.ql-align-left { | ||
text-align: left; | ||
} | ||
ul li { | ||
list-style: none; | ||
position: relative; | ||
padding: 0 0 0 2em; | ||
margin-bottom: 0.5em; | ||
&::before { | ||
content: ''; | ||
position: absolute; | ||
left: 0; | ||
top: 0.4em; | ||
width: 0.625em; | ||
height: 0.625em; | ||
border-radius: 50%; | ||
border: 0.1em solid #1f87ff; | ||
} | ||
} | ||
`; | ||
|
||
HTMLContent.propTypes = { | ||
/** The HTML string. Makes sure this is sanitized properly! */ | ||
content: PropTypes.string, | ||
}; | ||
|
||
export default HTMLContent; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { FormattedMessage } from 'react-intl'; | ||
import { Flex, Box } from '@rebass/grid'; | ||
|
||
import { H3, Span } from '../Text'; | ||
import HTMLEditor from '../HTMLEditor'; | ||
import HTMLContent, { isEmptyValue } from '../HTMLContent'; | ||
import InlineEditField from '../InlineEditField'; | ||
import Container from '../Container'; | ||
import StyledButton from '../StyledButton'; | ||
|
||
/** | ||
* Display the inline editable description section for the collective | ||
*/ | ||
const SectionAbout = ({ collective, canEdit, editMutation }) => { | ||
const isEmptyDescription = isEmptyValue(collective.longDescription); | ||
|
||
return ( | ||
<Flex flexDirection="column" alignItems="center" px={2} py={5}> | ||
<H3 fontSize="H2" fontWeight="normal" mb={5}> | ||
<FormattedMessage id="SectionAbout.Title" defaultMessage="Why we do what we do" /> | ||
</H3> | ||
|
||
<Container width="100%" maxWidth={700} margin="0 auto"> | ||
<InlineEditField | ||
mutation={editMutation} | ||
values={collective} | ||
field="longDescription" | ||
canEdit={canEdit} | ||
showEditIcon={!isEmptyDescription} | ||
> | ||
{({ isEditing, value, setValue, enableEditor }) => { | ||
if (isEditing) { | ||
return ( | ||
<HTMLEditor defaultValue={value} onChange={setValue} allowedHeaders={[false, 2, 3]} /** Disable H1 */ /> | ||
); | ||
} else if (isEmptyDescription) { | ||
return ( | ||
<Flex justifyContent="center"> | ||
{canEdit ? ( | ||
<Box margin="0 auto"> | ||
<StyledButton buttonSize="large" onClick={enableEditor}> | ||
<FormattedMessage id="CollectivePage.AddLongDescription" defaultMessage="Add your mission" /> | ||
</StyledButton> | ||
</Box> | ||
) : ( | ||
<Span color="black.500" fontStyle="italic"> | ||
<FormattedMessage | ||
id="SectionAbout.MissingDescription" | ||
defaultMessage="{collectiveName} didn't write a presentation yet" | ||
values={{ collectiveName: collective.name }} | ||
/> | ||
</Span> | ||
)} | ||
</Flex> | ||
); | ||
} else { | ||
return <HTMLContent content={collective.longDescription} data-cy="longDescription" />; | ||
} | ||
}} | ||
</InlineEditField> | ||
</Container> | ||
</Flex> | ||
); | ||
}; | ||
|
||
SectionAbout.propTypes = { | ||
/** The collective to display description for */ | ||
collective: PropTypes.shape({ | ||
id: PropTypes.number.isRequired, | ||
longDescription: PropTypes.string, | ||
name: PropTypes.string, | ||
}).isRequired, | ||
/** A mutation used to update the description */ | ||
editMutation: PropTypes.object, | ||
/** Can user edit the description? */ | ||
canEdit: PropTypes.bool, | ||
}; | ||
|
||
export default SectionAbout; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters