Skip to content

Commit

Permalink
feat: display pdf files
Browse files Browse the repository at this point in the history
  • Loading branch information
pyphilia committed Jan 19, 2021
1 parent 0d9ad78 commit b919c27
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 1 deletion.
29 changes: 28 additions & 1 deletion src/components/phase/PhaseItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,46 @@ import {
APPLICATION,
IFRAME,
DEFAULT_PROTOCOL,
PDF,
} from '../../config/constants';
import PhaseText from './PhaseText';
import PhaseImage from './PhaseImage';
import PhaseVideo from './PhaseVideo';
import PhaseApp from './PhaseApp';
import PhasePdf from './PhasePdf';

// prop types gets confused when dealing with helper renderers
// eslint-disable-next-line react/prop-types
const renderResource = ({ id, mimeType, content, asset, url, name }) => {
const renderResource = ({
id,
mimeType,
content,
asset,
url,
name,
spaceId,
phaseId,
appInstance,
}) => {
if (mimeType === TEXT) {
return <PhaseText key={id} id={id} content={content} />;
}

if (mimeType === PDF) {
return (
<PhasePdf
key={id}
id={id}
url={url}
asset={asset}
name={name}
spaceId={spaceId}
phaseId={phaseId}
appInstance={appInstance}
/>
);
}

if (IMAGE.test(mimeType)) {
return <PhaseImage key={id} id={id} url={url} asset={asset} name={name} />;
}
Expand Down
163 changes: 163 additions & 0 deletions src/components/phase/PhasePdf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Resizable } from 're-resizable';
import SwapVerticalCircleIcon from '@material-ui/icons/SwapVerticalCircle';
import PlayCircleFilledIcon from '@material-ui/icons/PlayCircleFilled';
import './PhaseApp.css';
import { getHeight, setHeight } from '../../actions/layout';
import {
DEFAULT_APP_HEIGHT,
MAX_APP_HEIGHT,
MIN_APP_HEIGHT,
} from '../../config/layout';
import { buildPhaseAppName } from '../../config/selectors';

const style = {
marginTop: '2rem',
marginBottom: '2rem',
};

const iconStyle = { background: 'white', borderRadius: '12px' };

class PhasePdf extends Component {
static propTypes = {
url: PropTypes.string,
asset: PropTypes.string,
name: PropTypes.string,
folder: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
};

static defaultProps = {
url: null,
asset: null,
name: 'Pdf',
};

state = {
height: DEFAULT_APP_HEIGHT,
};

constructor(props) {
super(props);
const { id } = props;
this.state.height = getHeight(id) || DEFAULT_APP_HEIGHT;
}

componentDidMount() {
window.addEventListener('message', this.handleReceiveMessage);
}

componentWillUnmount() {
window.removeEventListener('message', this.handleReceiveMessage);
}

renderHandleIcon = () => {
const { height } = this.state;
if (height >= MAX_APP_HEIGHT) {
return (
<PlayCircleFilledIcon
color="primary"
style={{
...iconStyle,
transform: 'rotate(-90deg)',
}}
/>
);
}
if (height <= MIN_APP_HEIGHT) {
return (
<PlayCircleFilledIcon
color="primary"
style={{
...iconStyle,
transform: 'rotate(90deg)',
}}
/>
);
}
return <SwapVerticalCircleIcon color="primary" style={iconStyle} />;
};

render() {
const { url, asset, name, id, folder } = this.props;

// replace 'download' by 'raw' to display the resource
// when the space is not saved
let uri = url.replace('download', 'raw');
if (asset) {
// assets with absolute paths are usually for testing
if (asset.startsWith('/')) {
uri = `file://${asset}`;
} else {
uri = `file://${folder}/${asset}`;
}
}

// get style
const { height } = this.state;
return (
<Resizable
style={style}
defaultSize={{
height,
width: 'auto',
}}
minHeight={MIN_APP_HEIGHT}
maxHeight={MAX_APP_HEIGHT}
enable={{
top: false,
right: false,
bottom: true,
left: false,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
}}
onResizeStop={(e, direction, ref, d) => {
const { height: oldHeight } = this.state;
const newHeight = oldHeight + d.height;
this.setState({
height: newHeight,
});
setHeight(id, newHeight);
}}
handleComponent={{
bottom: (
<div
style={{
width: '100%',
textAlign: 'center',
marginTop: '-8px',
}}
>
{this.renderHandleIcon()}
</div>
),
}}
>
<div style={{ height: '100%', overflowY: 'hidden' }}>
<iframe
title={name}
className="Pdf"
name={buildPhaseAppName(id)}
src={uri}
ref={(c) => {
this.iframe = c;
}}
/>
</div>
</Resizable>
);
}
}

const mapStateToProps = ({ authentication }) => ({
folder: authentication.getIn(['current', 'folder']),
});

const ConnectedComponent = connect(mapStateToProps)(PhasePdf);

export default ConnectedComponent;
1 change: 1 addition & 0 deletions src/config/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export const PRODUCT_NAME = 'Graasp';

// phase item types
export const TEXT = 'text/html';
export const PDF = 'application/pdf';
export const VIDEO = new RegExp('video/*');
export const IMAGE = new RegExp('image/*');
export const RESOURCE = 'Resource';
Expand Down

0 comments on commit b919c27

Please sign in to comment.