diff --git a/ui/src/App.js b/ui/src/App.js
index f6d5891c..1bdfeb2d 100644
--- a/ui/src/App.js
+++ b/ui/src/App.js
@@ -1,22 +1,23 @@
import React, { Component } from 'react'
-import { Redirect } from 'react-router-dom'
+import { createGlobalStyle } from 'styled-components'
+
+const GlobalStyle = createGlobalStyle`
+ #root, body {
+ height: 100%;
+ margin: 0;
+ }
+`
import Routes from './Routes'
class App extends Component {
render() {
- const token = localStorage.getItem('token')
-
- if (!token) {
- return (
- <>
-
-
- >
- )
- }
-
- return
+ return (
+ <>
+
+
+ >
+ )
}
}
diff --git a/ui/src/Layout.js b/ui/src/Layout.js
new file mode 100644
index 00000000..d3b8dba2
--- /dev/null
+++ b/ui/src/Layout.js
@@ -0,0 +1,46 @@
+import React, { Component } from 'react'
+import styled from 'styled-components'
+
+const Container = styled.div`
+ height: 100%;
+ /* display: grid;
+ grid-template-columns: 80px 1fr 500px; */
+`
+
+const LeftSidebar = styled.div`
+ height: 100%;
+ width: 80px;
+ position: fixed;
+ top: 0;
+ left: 0;
+ background-color: #eee;
+`
+
+const RightSidebar = styled.div`
+ height: 100%;
+ width: 500px;
+ position: fixed;
+ right: 0;
+ top: 0;
+ background-color: #eee;
+`
+
+const Content = styled.div`
+ margin-left: 80px;
+ margin-right: 500px;
+ padding: 0 8px;
+`
+
+class Layout extends Component {
+ render() {
+ return (
+
+ Left
+ {this.props.children}
+ Right
+
+ )
+ }
+}
+
+export default Layout
diff --git a/ui/src/Pages/AlbumPage.js b/ui/src/Pages/AlbumPage.js
deleted file mode 100644
index bc6d719e..00000000
--- a/ui/src/Pages/AlbumPage.js
+++ /dev/null
@@ -1,230 +0,0 @@
-import React, { Component } from 'react'
-import gql from 'graphql-tag'
-import { Query } from 'react-apollo'
-import styled from 'styled-components'
-import { useSpring, animated } from 'react-spring'
-
-const albumQuery = gql`
- query albumQuery($id: ID) {
- album(id: $id) {
- title
- photos {
- id
- thumbnail {
- path
- width
- height
- }
- }
- }
- }
-`
-
-const Gallery = styled.div`
- display: flex;
- flex-wrap: wrap;
- align-items: center;
-`
-
-const Photo = styled.img`
- margin: 4px;
- background-color: #eee;
- display: inline-block;
- height: 200px;
- flex-grow: 1;
- object-fit: cover;
-
- &:nth-last-child(6) ~ img {
- flex-grow: 0;
- }
-
- ${props =>
- props.active &&
- `
- will-change: transform;
- position: relative;
- z-index: 999;
- `}
-`
-
-const Dimmer = ({ onClick, active }) => {
- const [props, set, stop] = useSpring(() => ({ opacity: 0 }))
-
- set({
- opacity: active ? 1 : 0,
- })
-
- const AnimatedDimmer = styled(animated.div)`
- position: fixed;
- width: 100%;
- height: 100%;
- background-color: black;
- margin: 0;
- z-index: 10;
- `
-
- return (
-
- )
-}
-
-class AlbumPage extends Component {
- constructor(props) {
- super(props)
-
- this.state = {
- activeImage: -1,
- }
-
- this.setActiveImage = this.setActiveImage.bind(this)
- this.animateImage = this.animateImage.bind(this)
-
- this.photoAmount = 1
- this.previousActive = false
-
- this.scrollEvent = () => {
- if (this.state.activeImage != -1) {
- this.dismissPopup()
- }
- }
-
- this.keyUpEvent = e => {
- const activeImage = this.state.activeImage
- if (activeImage != -1) {
- if (e.key == 'ArrowRight') {
- this.setActiveImage((activeImage + 1) % this.photoAmount)
- }
-
- if (e.key == 'ArrowLeft') {
- if (activeImage <= 0) {
- this.setActiveImage(this.photoAmount - 1)
- } else {
- this.setActiveImage(activeImage - 1)
- }
- }
- }
- }
- }
-
- componentDidMount() {
- document.addEventListener('scroll', this.scrollEvent)
- document.addEventListener('keyup', this.keyUpEvent)
- }
-
- componentWillUnmount() {
- document.removeEventListener('scroll', this.scrollEvent)
- document.removeEventListener('keyup', this.keyUpEvent)
- }
-
- setActiveImage(index) {
- this.previousActive = this.state.activeImage != -1
- this.setState({
- activeImage: index,
- })
- }
-
- dismissPopup() {
- this.previousActive = true
- this.setState({
- activeImage: -1,
- })
- }
-
- animateImage(target) {
- const margin = 32
-
- const windowWidth = window.innerWidth
- const windowHeight = window.innerHeight
-
- const viewportWidth = windowWidth - margin * 2
- const viewportHeight = windowHeight - margin * 2
-
- const { naturalWidth, naturalHeight } = target
- const { width, height, top, left } = target.getBoundingClientRect()
-
- const scaleX = Math.min(naturalWidth, viewportWidth) / width
- const scaleY = Math.min(naturalHeight, viewportHeight) / height
- const scale = Math.min(scaleX, scaleY)
-
- const translateX = (-left + (windowWidth - width) / 2) / scale
- const translateY = (-top + (windowHeight - height) / 2) / scale
-
- if (!this.previousActive) target.style.transition = `transform 0.4s`
-
- requestAnimationFrame(() => {
- target.style.transform = `scale(${scale})
- translate3d(${translateX}px, ${translateY}px, 0)`
- })
- }
-
- render() {
- const albumId = this.props.match.params.id
-
- // let dimmer = this.state.activeImage != -1 && (
- // this.setActiveImage(-1)} />
- // )
-
- return (
-
-
this.setActiveImage(-1)}
- active={this.state.activeImage != -1}
- />
-
- {({ loading, error, data }) => {
- if (error) return Error
- if (loading) return Loading
-
- this.photoAmount = data.album.photos.length
-
- const { activeImage } = this.state
-
- const photos = data.album.photos.map((photo, index) => {
- const active = index == activeImage
- let ref = null
- let style = {}
-
- if (active) {
- ref = target => {
- if (target == null) return
- this.animateImage(target)
- }
- } else {
- style.transform = null
- }
-
- return (
- {
- requestAnimationFrame(() => {
- if (activeImage != index) {
- this.setActiveImage(index)
- } else {
- this.dismissPopup()
- }
- })
- }}
- style={style}
- src={photo.thumbnail.path}
- >
- )
- })
-
- return {photos}
- }}
-
-
- )
- }
-}
-
-export default AlbumPage
diff --git a/ui/src/Pages/AlbumPage/AlbumPage.js b/ui/src/Pages/AlbumPage/AlbumPage.js
new file mode 100644
index 00000000..f54a7848
--- /dev/null
+++ b/ui/src/Pages/AlbumPage/AlbumPage.js
@@ -0,0 +1,106 @@
+import React, { Component } from 'react'
+import gql from 'graphql-tag'
+import { Query } from 'react-apollo'
+import { Gallery, Photo, PhotoFiller } from './styledElements'
+import Layout from '../../Layout'
+
+const albumQuery = gql`
+ query albumQuery($id: ID) {
+ album(id: $id) {
+ title
+ photos {
+ id
+ thumbnail {
+ path
+ width
+ height
+ }
+ }
+ }
+ }
+`
+
+class AlbumPage extends Component {
+ constructor(props) {
+ super(props)
+
+ this.state = {
+ activeImage: -1,
+ }
+
+ this.setActiveImage = this.setActiveImage.bind(this)
+
+ this.photoAmount = 1
+ this.previousActive = false
+
+ this.keyUpEvent = e => {
+ const activeImage = this.state.activeImage
+ if (activeImage != -1) {
+ if (e.key == 'ArrowRight') {
+ this.setActiveImage((activeImage + 1) % this.photoAmount)
+ }
+
+ if (e.key == 'ArrowLeft') {
+ if (activeImage <= 0) {
+ this.setActiveImage(this.photoAmount - 1)
+ } else {
+ this.setActiveImage(activeImage - 1)
+ }
+ }
+ }
+ }
+ }
+
+ componentDidMount() {
+ document.addEventListener('keyup', this.keyUpEvent)
+ }
+
+ componentWillUnmount() {
+ document.removeEventListener('keyup', this.keyUpEvent)
+ }
+
+ setActiveImage(index) {
+ this.previousActive = this.state.activeImage != -1
+ this.setState({
+ activeImage: index,
+ })
+ }
+
+ dismissPopup() {
+ this.setState({
+ activeImage: -1,
+ })
+ }
+
+ render() {
+ const albumId = this.props.match.params.id
+
+ return (
+
+
+ {({ loading, error, data }) => {
+ if (error) return Error
+ if (loading) return Loading
+
+ this.photoAmount = data.album.photos.length
+
+ const { activeImage } = this.state
+
+ const photos = data.album.photos.map((photo, index) => {
+ return
+ })
+
+ return (
+
+ {photos}
+
+
+ )
+ }}
+
+
+ )
+ }
+}
+
+export default AlbumPage
diff --git a/ui/src/Pages/AlbumPage/Dimmer.js b/ui/src/Pages/AlbumPage/Dimmer.js
new file mode 100644
index 00000000..96f863ac
--- /dev/null
+++ b/ui/src/Pages/AlbumPage/Dimmer.js
@@ -0,0 +1,31 @@
+import React from 'react'
+import { useSpring, animated } from 'react-spring'
+
+const Dimmer = ({ onClick, active }) => {
+ const [props, set, stop] = useSpring(() => ({ opacity: 0 }))
+
+ set({
+ opacity: active ? 1 : 0,
+ })
+
+ const AnimatedDimmer = styled(animated.div)`
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ background-color: black;
+ margin: 0;
+ z-index: 10;
+ `
+
+ return (
+
+ )
+}
+
+export default Dimmer
diff --git a/ui/src/Pages/AlbumPage/styledElements.js b/ui/src/Pages/AlbumPage/styledElements.js
new file mode 100644
index 00000000..e729bcc8
--- /dev/null
+++ b/ui/src/Pages/AlbumPage/styledElements.js
@@ -0,0 +1,28 @@
+import styled from 'styled-components'
+
+export const Gallery = styled.div`
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+`
+
+export const Photo = styled.img`
+ margin: 4px;
+ background-color: #eee;
+ height: 200px;
+ flex-grow: 1;
+ object-fit: cover;
+
+ ${props =>
+ props.active &&
+ `
+ will-change: transform;
+ position: relative;
+ z-index: 999;
+ `}
+`
+
+export const PhotoFiller = styled.div`
+ height: 200px;
+ flex-grow: 999999;
+`
diff --git a/ui/src/Albums.js b/ui/src/Pages/HomePage/Albums.js
similarity index 100%
rename from ui/src/Albums.js
rename to ui/src/Pages/HomePage/Albums.js
diff --git a/ui/src/Pages/HomePage.js b/ui/src/Pages/HomePage/HomePage.js
similarity index 65%
rename from ui/src/Pages/HomePage.js
rename to ui/src/Pages/HomePage/HomePage.js
index 817e78c0..33b3ff30 100644
--- a/ui/src/Pages/HomePage.js
+++ b/ui/src/Pages/HomePage/HomePage.js
@@ -1,13 +1,14 @@
import React, { Component } from 'react'
-import Albums from '../Albums'
+import Albums from './Albums'
+import Layout from '../../Layout'
class HomePage extends Component {
render() {
return (
-
+
)
}
}
diff --git a/ui/src/Routes.js b/ui/src/Routes.js
index 5937b832..78cb17e2 100644
--- a/ui/src/Routes.js
+++ b/ui/src/Routes.js
@@ -2,13 +2,21 @@ import React, { Component } from 'react'
import { Route, Switch } from 'react-router-dom'
import LoginPage from './Pages/LoginPage'
-import HomePage from './Pages/HomePage'
-import AlbumPage from './Pages/AlbumPage'
+import HomePage from './Pages/HomePage/HomePage'
+import AlbumPage from './Pages/AlbumPage/AlbumPage'
class Routes extends Component {
render() {
+ const token = localStorage.getItem('token')
+
+ let unauthorizedRedirect = null
+ if (!token) {
+ unauthorizedRedirect =
+ }
+
return (
+ {unauthorizedRedirect}