mirror of
https://github.com/trambarhq/relaks-wordpress-example.git
synced 2025-09-02 20:52:33 +02:00
Implemented image dialog box (issue #17).
This commit is contained in:
@@ -47,6 +47,7 @@ class FrontEnd extends PureComponent {
|
||||
<div className="page-container">
|
||||
<PageComponent route={route} wp={wp} key={key} />
|
||||
</div>
|
||||
<div id="overlay" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@@ -52,14 +52,15 @@ class PostPage extends AsyncComponent {
|
||||
}
|
||||
|
||||
// see how recently a category was visited
|
||||
let historyIndex = (c) => {
|
||||
|
||||
return _.findLastIndex(route.history, { params: { categorySlug: c.slug }});
|
||||
let historyIndex = (category) => {
|
||||
let predicate = { params: { categorySlug: category.slug }};
|
||||
return _.findLastIndex(route.history, predicate);
|
||||
};
|
||||
// see how deep a category is
|
||||
let depth = (c) => {
|
||||
if (c.parent) {
|
||||
let parent = _.find(allCategories, { id: c.parent });
|
||||
let depth = (category) => {
|
||||
if (category.parent) {
|
||||
let predicate = { id: category.parent };
|
||||
let parent = _.find(allCategories, predicate);
|
||||
if (parent) {
|
||||
return depth(parent) + 1;
|
||||
}
|
||||
@@ -97,7 +98,7 @@ class PostPageSync extends PureComponent {
|
||||
let { route, categories, post, author, tags, comments } = this.props;
|
||||
let trail = [ { label: 'Categories' } ];
|
||||
for (let category of categories) {
|
||||
let label = _.get(c, 'name', '');
|
||||
let label = _.get(category, 'name', '');
|
||||
let url = route.prefetchObjectURL(category);
|
||||
trail.push({ label, url });
|
||||
}
|
||||
|
@@ -190,6 +190,9 @@ class Route {
|
||||
node.attribs.target = '_blank';
|
||||
}
|
||||
}
|
||||
if (_.startsWith(node.attribs.href, '/wp-content/')) {
|
||||
node.attribs.href = siteURL + node.attribs.href;
|
||||
}
|
||||
if (_.startsWith(node.attribs.href, '/')) {
|
||||
// strip off page number
|
||||
node.attribs.href = node.attribs.href.replace(/\/\d+\/?$/, '');
|
||||
|
@@ -320,6 +320,65 @@ A {
|
||||
}
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.image-dialog {
|
||||
.background, .foreground {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.background {
|
||||
background-color: #ffffff;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.foreground {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
pointer-events: none;
|
||||
|
||||
.box {
|
||||
position: relative;
|
||||
pointer-events: auto;
|
||||
background: #66023c;
|
||||
border-color: 1px solid black;
|
||||
padding: 1em 1em 1em 1em;
|
||||
box-shadow: 2px 2px 10px #000000;
|
||||
max-width: 90%;
|
||||
color: #cccccc;
|
||||
|
||||
.image {
|
||||
display: block;
|
||||
border: 1px solid #000000;
|
||||
max-width: 100%;
|
||||
max-height: 80vh;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
position: absolute;
|
||||
font-size: 0.75em;
|
||||
padding: 0.25em 0.25em 0.25em 0.25em;
|
||||
margin: -0.25em -0.25em -0.25em -0.25em;
|
||||
right: 0.35em;
|
||||
top: 0.35em;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
.page-container {
|
||||
transition: margin-left 0.3s;
|
||||
|
57
src/widgets/image-dialog.jsx
Normal file
57
src/widgets/image-dialog.jsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import _ from 'lodash';
|
||||
import React, { PureComponent } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
class ImageDialog extends PureComponent {
|
||||
|
||||
render() {
|
||||
let { imageURL } = this.props;
|
||||
if (!imageURL) {
|
||||
return null;
|
||||
}
|
||||
let container = document.getElementById('overlay');
|
||||
let dialog = this.renderDialog();
|
||||
return ReactDOM.createPortal(dialog, container);
|
||||
}
|
||||
|
||||
renderDialog() {
|
||||
let { imageURL } = this.props;
|
||||
return (
|
||||
<div className="image-dialog">
|
||||
<div className="background" onClick={this.handleCloseClick}/>
|
||||
<div className="foreground">
|
||||
<div className="box">
|
||||
<div className="close-button" onClick={this.handleCloseClick}>
|
||||
<i className="fa fa-times" />
|
||||
</div>
|
||||
<img className="image" src={imageURL} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
handleCloseClick = (evt) => {
|
||||
let { onClose } = this.props;
|
||||
if (onClose) {
|
||||
onClose({
|
||||
type: 'close',
|
||||
target: this,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
const PropTypes = require('prop-types');
|
||||
|
||||
ImageDialog.propTypes = {
|
||||
imageURL: PropTypes.string,
|
||||
onClose: PropTypes.func,
|
||||
};
|
||||
}
|
||||
|
||||
export {
|
||||
ImageDialog as default,
|
||||
ImageDialog,
|
||||
};
|
@@ -3,10 +3,18 @@ import Moment from 'moment';
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
import HTML from 'widgets/html';
|
||||
import ImageDialog from 'widgets/image-dialog';
|
||||
|
||||
class PostView extends PureComponent {
|
||||
static displayName = 'PostView';
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
imageURL: null,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
let { post, author, transform } = this.props;
|
||||
let title = _.get(post, 'title.rendered', '');
|
||||
@@ -23,12 +31,41 @@ class PostView extends PureComponent {
|
||||
<div className="author">{name}</div>
|
||||
</div>
|
||||
<h1><HTML text={title} /></h1>
|
||||
<div className="content">
|
||||
<div className="content" onClick={this.handleClick}>
|
||||
<HTML text={content} transform={transform} />
|
||||
</div>
|
||||
{this.renderImageDialog()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderImageDialog() {
|
||||
let { imageURL } = this.state;
|
||||
return <ImageDialog imageURL={imageURL} onClose={this.handleDialogClose} />;
|
||||
}
|
||||
|
||||
handleClick = (evt) => {
|
||||
let target = evt.target;
|
||||
let container = evt.currentTarget;
|
||||
if (target.tagName === 'IMG') {
|
||||
let link;
|
||||
for (let p = target; p && p !== container; p = p.parentNode) {
|
||||
if (p.tagName === 'A') {
|
||||
link = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (link) {
|
||||
let imageURL = link.href;
|
||||
this.setState({ imageURL });
|
||||
evt.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleDialogClose = (evt) => {
|
||||
this.setState({ imageURL: null });
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
|
Reference in New Issue
Block a user