show photo in an overlay

This commit is contained in:
2020-10-16 15:47:27 +00:00
committed by Stepan Usatiuk
parent c878d08613
commit 537587b052
6 changed files with 96 additions and 26 deletions

View File

@@ -24,6 +24,7 @@ import { toggleDarkMode } from "~redux/localSettings/actions";
import { IAppState } from "~redux/reducers";
import { logoutUser } from "~redux/user/actions";
import { Photo } from "~Photos/Photo";
import { PhotoRoute } from "~Photos/PhotoRoute";
export interface IHomeProps extends RouteComponentProps {
user: IUserJSON | null;
@@ -103,7 +104,7 @@ export class HomeComponent extends React.PureComponent<IHomeProps> {
/>
<Route
path="/photos/:id"
component={Photo}
component={PhotoRoute}
/>
<Route path="/" component={Overview} />
</Switch>

View File

@@ -1,5 +1,32 @@
@import "~@blueprintjs/core/lib/scss/variables";
#photoOverlayContainer {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
transition: 0.3s;
}
.bp3-overlay-enter {
opacity: 0;
}
.bp3-overlay-enter-active {
opacity: 1;
}
.bp3-overlay-exit {
opacity: 1;
}
.bp3-overlay-exit-active {
opacity: 0;
}
#overview {
display: flex;
flex-direction: column;

View File

@@ -7,8 +7,9 @@ import { photosLoadStart } from "~redux/photos/actions";
import { IPhotoReqJSON } from "~../../src/entity/Photo";
import { LoadingStub } from "~LoadingStub";
import { PhotoCard } from "./PhotoCard";
import { Button } from "@blueprintjs/core";
import { Button, Classes, Overlay } from "@blueprintjs/core";
import { UploadButton } from "./UploadButton";
import { Photo } from "./Photo";
export interface IOverviewComponentProps {
photos: IPhotoReqJSON[] | null;
@@ -23,6 +24,9 @@ export interface IOverviewComponentProps {
export const OverviewComponent: React.FunctionComponent<IOverviewComponentProps> = (
props,
) => {
const [selectedPhoto, setSelectedPhoto] = React.useState<number>(0);
const [isOverlayOpened, setOverlayOpen] = React.useState<boolean>(false);
if (!props.overviewLoaded && !props.overviewFetching) {
props.fetchPhotos();
}
@@ -30,17 +34,44 @@ export const OverviewComponent: React.FunctionComponent<IOverviewComponentProps>
return <LoadingStub spinner={props.overviewFetchingSpinner} />;
}
const onCardClick = (id: number) => {
setSelectedPhoto(id);
setOverlayOpen(true);
};
const photos = props.photos
.sort((a, b) => b.shotAt - a.shotAt)
.map((photo) => <PhotoCard key={photo.id} photo={photo} />);
.map((photo) => (
<PhotoCard
key={photo.id}
photo={photo}
onClick={() => onCardClick(photo.id)}
/>
));
return (
<div id="overview">
<div id="actionbar">
<UploadButton />
<>
<Overlay
autoFocus
enforceFocus
usePortal
isOpen={isOverlayOpened}
onClose={() => {
setOverlayOpen(false);
}}
lazy
>
<div id="photoOverlayContainer">
<Photo id={selectedPhoto} />
</div>
</Overlay>
<div id="overview">
<div id="actionbar">
<UploadButton />
</div>
<div className="list">{photos}</div>
</div>
<div className="list">{photos}</div>
</div>
</>
);
};

View File

@@ -1,7 +1,6 @@
import "./Photo.scss";
import * as React from "react";
import { connect } from "react-redux";
import { RouteComponentProps, withRouter } from "react-router";
import { Dispatch } from "redux";
import { IPhotoReqJSON } from "~../../src/entity/Photo";
import { LoadingStub } from "~LoadingStub";
@@ -10,25 +9,19 @@ import { photoLoadStart } from "~redux/photos/actions";
import { IPhotoState } from "~redux/photos/reducer";
import { IAppState } from "~redux/reducers";
export interface IPhotoComponentProps extends RouteComponentProps {
export interface IPhotoComponentProps {
id: number;
photo: IPhotoReqJSON | undefined;
photoState: IPhotoState | undefined;
fetchPhoto: (id: number) => void;
}
function getId(props: RouteComponentProps) {
return parseInt((props.match?.params as { id: string }).id);
}
export const PhotoComponent: React.FunctionComponent<IPhotoComponentProps> = (
props,
) => {
const id = getId(props);
if (!props.photo && !props.photoState?.fetching) {
console.log(props);
props.fetchPhoto(id);
props.fetchPhoto(props.id);
}
if (!props.photo) {
return <LoadingStub spinner={false} />;
@@ -53,8 +46,8 @@ export const PhotoComponent: React.FunctionComponent<IPhotoComponentProps> = (
);
};
function mapStateToProps(state: IAppState, props: RouteComponentProps) {
const id = getId(props);
function mapStateToProps(state: IAppState, props: IPhotoComponentProps) {
const { id } = props;
let photo = undefined;
let photoState = undefined;
@@ -74,6 +67,8 @@ function mapDispatchToProps(dispatch: Dispatch) {
return { fetchPhoto: (id: number) => dispatch(photoLoadStart(id)) };
}
export const Photo = withRouter(
connect(mapStateToProps, mapDispatchToProps)(PhotoComponent),
);
// Because https://github.com/DefinitelyTyped/DefinitelyTyped/issues/16990
export const Photo = connect(
mapStateToProps,
mapDispatchToProps,
)(PhotoComponent) as any;

View File

@@ -20,6 +20,7 @@ export interface IPhotoCardComponentProps extends RouteComponentProps {
deletePhoto: (photo: IPhotoReqJSON) => void;
cancelDelete: (photo: IPhotoReqJSON) => void;
onClick: () => void;
}
@ContextMenuTarget
@@ -48,9 +49,7 @@ export class PhotoCardComponent extends React.PureComponent<
<Card
className="photoCard"
interactive={true}
onClick={() =>
this.props.history.push(`/photos/${this.props.photo.id}`)
}
onClick={() => this.props.onClick()}
>
{fileExists ? (
<img

View File

@@ -0,0 +1,17 @@
import * as React from "react";
import { RouteComponentProps, withRouter } from "react-router";
import { Photo } from "./Photo";
function getId(props: RouteComponentProps) {
return parseInt((props.match?.params as { id: string }).id);
}
export const PhotoRouteComponent: React.FunctionComponent<RouteComponentProps> = (
props: RouteComponentProps,
) => {
const id = getId(props);
return <Photo id={id} />;
};
export const PhotoRoute = withRouter(PhotoRouteComponent);