diff --git a/docker-compose.yaml b/docker-compose.yaml
index 428d63a..9bbfbca 100644
--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -1,17 +1,17 @@
version: '3'
services:
# applications
- frontend:
- build:
- context: frontend
- args:
- REACT_APP_API_URL: http://api:5001/graphql
- restart: always
- container_name: frontend
- ports:
- - '5000:80'
- depends_on:
- - api
+ # frontend:
+ # build:
+ # context: frontend
+ # args:
+ # REACT_APP_API_URL: http://api:5001/graphql
+ # restart: always
+ # container_name: frontend
+ # ports:
+ # - '5000:80'
+ # depends_on:
+ # - api
api:
build: api
restart: always
diff --git a/frontend/public/albums.svg b/frontend/public/albums.svg
new file mode 100644
index 0000000..0f8c039
--- /dev/null
+++ b/frontend/public/albums.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/App.scss b/frontend/src/App.scss
index 19eaf86..abc40ff 100644
--- a/frontend/src/App.scss
+++ b/frontend/src/App.scss
@@ -158,7 +158,6 @@ p {
.mdc-image-list--with-text-protection .mdc-image-list__supporting {
background: rgba(0, 0, 0, 0.2) !important;
- justify-content: center !important;
}
.mdc-layout-grid {
@@ -186,6 +185,10 @@ p {
justify-content: center !important;
}
+.album-list-info {
+ justify-content: left !important;
+}
+
.mdc-image-list__label,
.mdc-text-field__input {
font-family: $font;
diff --git a/frontend/src/components/Content.js b/frontend/src/components/Content.js
index c80896d..4129164 100644
--- a/frontend/src/components/Content.js
+++ b/frontend/src/components/Content.js
@@ -2,7 +2,16 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Route, Switch } from 'react-router-dom';
import { DrawerAppContent } from '@rmwc/drawer';
-import { Photo, Photos, Search, Upcoming, Favourites, Trash } from '../pages';
+import {
+ Photo,
+ Photos,
+ Search,
+ Upcoming,
+ Favourites,
+ Trash,
+ Albums,
+ Album,
+} from '../pages';
import { Explore, People, Places, Things, Entity } from '../pages/explore';
import SideNav from './SideNav';
@@ -23,10 +32,11 @@ const Content = (props) => {
+
+
{/* static */}
-
diff --git a/frontend/src/components/DeleteAlbumDialog.js b/frontend/src/components/DeleteAlbumDialog.js
new file mode 100644
index 0000000..4a05e9d
--- /dev/null
+++ b/frontend/src/components/DeleteAlbumDialog.js
@@ -0,0 +1,70 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { useHistory } from 'react-router-dom';
+import { gql, useMutation } from '@apollo/client';
+import { CircularProgress } from '@rmwc/circular-progress';
+import { Dialog, DialogTitle, DialogActions, DialogButton } from '@rmwc/dialog';
+import '@rmwc/dialog/styles';
+
+const DELETE_ALBUM = gql`
+ mutation deleteAlbum($id: String!) {
+ deleteAlbum(id: $id)
+ }
+`;
+
+const DeleteAlbumDialog = ({ open, setOpen, albumName, albumId }) => {
+ const history = useHistory();
+ const [deleteAlbum, { data: delData, loading: delLoading, error: delError }] =
+ useMutation(DELETE_ALBUM);
+
+ const handleDeleteAlbum = (albumId) => {
+ deleteAlbum({
+ variables: { id: albumId },
+ });
+ };
+
+ if (delData && delData.deleteAlbum) {
+ setTimeout(() => {
+ history.push('/albums');
+ }, 2000);
+ }
+
+ return (
+
+ );
+};
+
+DeleteAlbumDialog.propTypes = {
+ open: PropTypes.bool,
+ setOpen: PropTypes.func,
+ albumId: PropTypes.string,
+ albumName: PropTypes.string,
+};
+
+export default DeleteAlbumDialog;
diff --git a/frontend/src/components/EditAlbum.js b/frontend/src/components/EditAlbum.js
new file mode 100644
index 0000000..c3099f6
--- /dev/null
+++ b/frontend/src/components/EditAlbum.js
@@ -0,0 +1,82 @@
+import React, { useState } from 'react';
+import { gql, useMutation } from '@apollo/client';
+import PropTypes from 'prop-types';
+import { Icon } from '@rmwc/icon';
+import { Button } from '@rmwc/button';
+import { TextField } from '@rmwc/textfield';
+import { CircularProgress } from '@rmwc/circular-progress';
+
+const UPDATE_ALBUM = gql`
+ mutation updateAlbum($id: String!, $name: String!) {
+ updateAlbum(id: $id, input: { name: $name })
+ }
+`;
+
+const EditAlbum = ({ albumId, albumName }) => {
+ const [
+ updateAlbum,
+ { loading: updateAlbumNameLoading, error: updateAlbumNameyError },
+ ] = useMutation(UPDATE_ALBUM);
+
+ const [showEdit, setShowEdit] = useState(false);
+ const [updatedAlbumName, setupdatedAlbumName] = useState(albumName);
+
+ const handleEditAlbumName = (albumId, updatedAlbumName) => {
+ updateAlbum({ variables: { id: albumId, name: updatedAlbumName } });
+ setShowEdit(false);
+ };
+
+ return (
+ <>
+ {showEdit ? (
+ <>
+
+ setupdatedAlbumName(e.target.value)}
+ style={{ height: '36px' }}
+ />
+
+
+
+
+ >
+ ) : (
+ <>
+ {updatedAlbumName}
+
+ setShowEdit(!showEdit)}
+ style={{ cursor: 'pointer', color: '#424242' }}
+ icon={{ icon: 'edit', size: 'small' }}
+ />
+ >
+ )}
+ >
+ );
+};
+
+EditAlbum.propTypes = {
+ albumId: PropTypes.string,
+ albumName: PropTypes.string,
+};
+
+export default EditAlbum;
diff --git a/frontend/src/components/index.js b/frontend/src/components/index.js
index 39305ae..8a979a0 100644
--- a/frontend/src/components/index.js
+++ b/frontend/src/components/index.js
@@ -8,6 +8,8 @@ import ExploreEntity from './explore/ExploreEntity';
import PeopleList from './PeopleList';
import FavouriteAction from './FavouriteAction';
import DeleteAction from './DeleteAction';
+import DeleteAlbumDialog from './DeleteAlbumDialog';
+import EditAlbum from './EditAlbum';
export {
Content,
@@ -20,4 +22,6 @@ export {
PeopleList,
FavouriteAction,
DeleteAction,
+ DeleteAlbumDialog,
+ EditAlbum,
};
diff --git a/frontend/src/pages/Album.js b/frontend/src/pages/Album.js
new file mode 100644
index 0000000..db03658
--- /dev/null
+++ b/frontend/src/pages/Album.js
@@ -0,0 +1,113 @@
+import React, { useState } from 'react';
+import moment from 'moment';
+import { useHistory } from 'react-router-dom';
+import { useParams } from 'react-router-dom';
+import { gql, useQuery } from '@apollo/client';
+import { Icon } from '@rmwc/icon';
+import {
+ ImageList,
+ ImageListImage,
+ ImageListItem,
+ ImageListImageAspectContainer,
+} from '@rmwc/image-list';
+import { Grid, GridCell } from '@rmwc/grid';
+import '@rmwc/grid/styles';
+import { Loading, Error, DeleteAlbumDialog, EditAlbum } from '../components';
+
+const GET_ALBUM = gql`
+ query getAlbum($id: String!) {
+ album(id: $id) {
+ id
+ name
+ description
+ createdAt
+ mediaItems {
+ totalCount
+ nodes {
+ id
+ imageUrl
+ }
+ }
+ }
+ }
+`;
+
+const Album = () => {
+ let history = useHistory();
+ let { id } = useParams();
+ const { error, loading, data } = useQuery(GET_ALBUM, {
+ variables: { id },
+ fetchPolicy: 'no-cache',
+ });
+
+ if (error) return ;
+
+ const styleFav = {
+ radius: '4px',
+ width: '180px',
+ margin: '0px 6px 8px 6px',
+ };
+
+ const [open, setOpen] = useState(false);
+
+ return (
+ <>
+ {loading ? (
+
+ ) : (
+ <>
+
+
+
+
+
+ setOpen(true)}
+ style={{ cursor: 'pointer', color: '#424242' }}
+ icon={{ icon: 'delete', size: 'small' }}
+ />
+
+
+
+ {moment(data.album.createdAt).format('MMMM D, YYYY')}
+
+
+
+
+
+
+ {data.album.mediaItems.nodes.map((img) => (
+
+
+ history.push(`/photo/${img.id}`)}
+ />
+
+
+ ))}
+
+
+
+ >
+ )}
+ >
+ );
+};
+
+export default Album;
diff --git a/frontend/src/pages/Albums.js b/frontend/src/pages/Albums.js
new file mode 100644
index 0000000..eeb468e
--- /dev/null
+++ b/frontend/src/pages/Albums.js
@@ -0,0 +1,108 @@
+import React from 'react';
+import { useHistory } from 'react-router-dom';
+import { gql, useQuery } from '@apollo/client';
+import { Grid, GridCell } from '@rmwc/grid';
+import {
+ ImageList,
+ ImageListImage,
+ ImageListItem,
+ ImageListLabel,
+ ImageListSupporting,
+ ImageListImageAspectContainer,
+} from '@rmwc/image-list';
+import { Loading, Error } from '../components';
+
+const GET_ALBUMS = gql`
+ query getAlbums {
+ albums {
+ totalCount
+ nodes {
+ id
+ name
+ mediaItems {
+ totalCount
+ nodes {
+ imageUrl
+ }
+ }
+ }
+ }
+ }
+`;
+
+const Albums = () => {
+ const { error: albumsError, data: albumsData } = useQuery(GET_ALBUMS, {
+ fetchPolicy: 'no-cache',
+ });
+ if (albumsError) return ;
+
+ let history = useHistory();
+ const styleFav = {
+ radius: '4px',
+ width: '180px',
+ margin: '0px 6px 8px 6px',
+ };
+
+ return (
+ <>
+ {albumsData && albumsData.albums && albumsData.albums.nodes ? (
+ <>
+ {albumsData.albums && albumsData.albums.totalCount === 0 ? (
+ <>
+
+
+
+
+
+
+
+ You have not created any albums yet!
+
+
+
+
+ >
+ ) : (
+ <>
+
+
+ Albums
+
+
+
+
+
+ {albumsData.albums.nodes.map((album) => (
+
+
+ history.push(`/album/${album.id}`)}
+ />
+
+
+
+ {album.name}
+
+
+ {album.mediaItems?.totalCount} items
+
+
+
+
+ ))}
+
+
+
+ >
+ )}
+ >
+ ) : (
+
+ )}
+ >
+ );
+};
+
+export default Albums;
diff --git a/frontend/src/pages/index.js b/frontend/src/pages/index.js
index a6b1098..cbaebf3 100644
--- a/frontend/src/pages/index.js
+++ b/frontend/src/pages/index.js
@@ -4,6 +4,18 @@ import Photo from './Photo';
import Photos from './Photos';
import Search from './Search';
import Sharing from './Sharing';
+import Albums from './Albums';
+import Album from './Album';
import Upcoming from './Upcoming';
-export { Trash, Favourites, Photo, Photos, Search, Sharing, Upcoming };
+export {
+ Trash,
+ Favourites,
+ Photo,
+ Photos,
+ Search,
+ Sharing,
+ Albums,
+ Album,
+ Upcoming,
+};