mirror of
https://github.com/usatiuk/photos.git
synced 2025-10-28 15:27:49 +01:00
show photo in an overlay
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
17
frontend/src/Photos/PhotoRoute.tsx
Normal file
17
frontend/src/Photos/PhotoRoute.tsx
Normal 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);
|
||||
Reference in New Issue
Block a user