Skip to content

Commit

Permalink
508 allow users to show most liked pictures (#512)
Browse files Browse the repository at this point in the history
* start implementing tab based overview content selection

* allow custom width for tag and picture overview

* adjust tag preview min width to fit to mobile screen

* minor changes to css

* start fixing tests

* add option to show most liked pictures instead of neuzugänge/unsere bilder

* add tooltips for tabs

* show scroll buttons on mobile

* dont use Children anymore

* remove unneccessary const

* adjust to changes made to OverviewContainer

* correct sorting order for most liked, make it work for staging

* support to set default option

* make default option optional

* show most liked as default option on start page

* add support for live updates for most liked pictures in overview

* requested changes

* fix some tests

* maybe it works now, love caching

* some requested changes

* fix fetching problem for show-more most-liked

* fix errors for tags caused by args being null, add pagination and fetchPolicy for tags

* remove unused generic picture endpoint

* fix to many tags fetched for tag overview

* fix start test

* requested changes

* fix type error
  • Loading branch information
LinoH5 authored May 26, 2023
1 parent 901e42b commit cceb5d4
Show file tree
Hide file tree
Showing 27 changed files with 417 additions and 98 deletions.
6 changes: 4 additions & 2 deletions projects/bp-gallery/cypress/e2e/archives.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ describe('Archives View', () => {
});

it('successfully sets an image as showcase picture when pressing on the star button via "Unsere Bilder"', () => {
cy.get('.overview-container:contains(Unsere Bilder)').contains('Mehr anzeigen').click();
cy.get('.overview-selection-container:contains(Unsere Bilder)')
.contains('Mehr anzeigen')
.click();
cy.get(`[data-testid="StarIcon"]:first`).click();
cy.contains('Zurück').click();
cy.get('.archive-showcase #picture-preview-for-5').should('exist');
Expand All @@ -98,7 +100,7 @@ describe('Archives View', () => {

it('shows "Unsere Bilder" picture overview', () => {
// check for basic components (title, show more button)
cy.get('.overview-container:contains(Unsere Bilder)').contains('Mehr anzeigen');
cy.get('.overview-selection-container:contains(Unsere Bilder)').contains('Mehr anzeigen');

// check if it contains rows with images
cy.get(
Expand Down
2 changes: 1 addition & 1 deletion projects/bp-gallery/cypress/e2e/bulk-edit/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ export const selectPictures = (...ids: string[]) => {

export const visitArchive1Pictures = () => {
cy.visit('/archives/1');
cy.contains('.overview-container', 'Unsere Bilder').contains('Mehr anzeigen').click();
cy.contains('.overview-selection-container', 'Unsere Bilder').contains('Mehr anzeigen').click();
};
2 changes: 1 addition & 1 deletion projects/bp-gallery/cypress/e2e/discover.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('Discover View', () => {

it('shows "Neuzugänge" picture overview', () => {
// check for basic components (title, show more button)
cy.get('.overview-container:first')
cy.get('.overview-selection-container:first')
.children()
.should('contain.text', 'Neuzugänge')
.and('contain.text', 'Mehr anzeigen');
Expand Down
6 changes: 4 additions & 2 deletions projects/bp-gallery/cypress/e2e/show-more.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe('Navigation to Show More View from Discover View', () => {
});

it('works for "Neuzugänge"', () => {
cy.get('.overview-container:contains(Neuzugänge)').contains('Mehr anzeigen').click();
cy.get('.overview-selection-container:contains(Neuzugänge)').contains('Mehr anzeigen').click();
urlIs('/show-more/latest');
});

Expand Down Expand Up @@ -76,7 +76,9 @@ describe('Navigation to Show More View from Archive View', () => {
});

it('works for "Unsere Bilder"', () => {
cy.get('.overview-container:contains(Unsere Bilder)').contains('Mehr anzeigen').click();
cy.get('.overview-selection-container:contains(Unsere Bilder)')
.contains('Mehr anzeigen')
.click();
urlIs('/archives/1/show-more/pictures');
});

Expand Down
5 changes: 5 additions & 0 deletions projects/bp-gallery/cypress/e2e/start.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ describe('Start view', () => {
cy.get('.collection-picture-display .item').should('exist');
});

it('should have selectable custom overview', () => {
cy.get('.overview-selection-container');
cy.get('[data-testid="AccessTimeIcon"]').click();
});

it('should show a picture preview', () => {
cy.get('.picture-grid').find('img').first().should('exist');
});
Expand Down
12 changes: 8 additions & 4 deletions projects/bp-gallery/src/components/common/PictureOverview.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import React, { MouseEventHandler } from 'react';
import './PictureOverview.scss';
import PictureGrid from './picture-gallery/PictureGrid';
import { useSimplifiedQueryResponseData } from '../../graphql/queryUtils';
import { PictureFiltersInput } from '../../graphql/APIConnector';
import { FlatPicture } from '../../types/additionalFlatTypes';
import { FlatPicture, PictureOverviewType } from '../../types/additionalFlatTypes';
import { useTranslation } from 'react-i18next';
import useGetPictures from '../../hooks/get-pictures.hook';
import PrimaryButton from './PrimaryButton';
import { useSimplifiedQueryResponseData } from '../../graphql/queryUtils';
import useGetPictures from '../../hooks/get-pictures.hook';

interface PictureOverviewProps {
title?: string;
queryParams: PictureFiltersInput | { searchTerms: string[]; searchTimes: string[][] };
onClick: MouseEventHandler<HTMLButtonElement>;
sortBy?: string[];
rows?: number;
type?: PictureOverviewType;
}

const ABSOLUTE_MAX_PICTURES_PER_ROW = 6;
Expand All @@ -24,6 +25,7 @@ const PictureOverview = ({
onClick,
sortBy,
rows = 2,
type = PictureOverviewType.CUSTOM,
}: PictureOverviewProps) => {
const { t } = useTranslation();

Expand All @@ -32,7 +34,9 @@ const PictureOverview = ({
false,
sortBy,
true,
ABSOLUTE_MAX_PICTURES_PER_ROW * rows
ABSOLUTE_MAX_PICTURES_PER_ROW * rows,
'cache-and-network',
type
);

const pictures: FlatPicture[] | undefined = useSimplifiedQueryResponseData(data)?.pictures;
Expand Down
11 changes: 7 additions & 4 deletions projects/bp-gallery/src/components/common/TagOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { useSimplifiedQueryResponseData } from '../../graphql/queryUtils';
import useGetTagsWithThumbnail from '../../hooks/get-tags-with-thumbnail.hook';
import PrimaryButton from './PrimaryButton';

const MAX_TAGS_PER_ROW = 3;

interface TagOverviewProps {
title?: string;
type: TagType;
Expand Down Expand Up @@ -43,9 +45,9 @@ const TagOverview = ({
const calculateMaxCategoriesPerRow = useCallback((width: number) => {
const tempRowLength = Math.max(1, Math.floor(Math.min(width, 1200) / 260));
if (Math.min(width, 1200) >= tempRowLength * 260 + (tempRowLength - 1) * 8) {
return tempRowLength;
return Math.min(tempRowLength, MAX_TAGS_PER_ROW);
}
return Math.max(1, tempRowLength - 1);
return Math.min(Math.max(1, tempRowLength - 1), MAX_TAGS_PER_ROW);
}, []);

const [rowLength, setRowLength] = useState(() => {
Expand All @@ -69,13 +71,14 @@ const TagOverview = ({
};
}, [onResize]);

// check if there is a tag
const { data } = useGetTagsWithThumbnail(
queryParams,
thumbnailQueryParams,
false,
type,
['name:asc'],
1
1,
'no-cache'
);

const flattened = useSimplifiedQueryResponseData(data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import PictureGrid from './PictureGrid';
import { PicturePreviewAdornment } from './PicturePreview';
import './PictureScrollGrid.scss';
import PictureUploadArea, { PictureUploadAreaProps } from './PictureUploadArea';
import { WatchQueryFetchPolicy } from '@apollo/client';

const PictureScrollGrid = ({
queryParams,
Expand All @@ -29,6 +30,7 @@ const PictureScrollGrid = ({
showDefaultAdornments = true,
allowClicks = true,
filterOutTextsForNonCurators = true,
fetchPolicy,
}: {
queryParams: PictureFiltersInput | { searchTerms: string[]; searchTimes: string[][] };
hashbase: string;
Expand All @@ -43,6 +45,7 @@ const PictureScrollGrid = ({
showDefaultAdornments?: boolean;
allowClicks?: boolean;
filterOutTextsForNonCurators?: boolean;
fetchPolicy?: WatchQueryFetchPolicy;
}) => {
const { t } = useTranslation();
const [lastScrollHeight, setLastScrollHeight] = useState<number>(0);
Expand All @@ -52,7 +55,9 @@ const PictureScrollGrid = ({
queryParams,
isAllSearchActive,
sortBy,
filterOutTextsForNonCurators
filterOutTextsForNonCurators,
NUMBER_OF_PICTURES_LOADED_PER_FETCH,
fetchPolicy
);

const pictures: FlatPicture[] | undefined = useSimplifiedQueryResponseData(data)?.pictures;
Expand Down
52 changes: 43 additions & 9 deletions projects/bp-gallery/src/components/views/archives/ArchiveView.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { Edit, Link } from '@mui/icons-material';
import { AccessTime, Edit, Link, ThumbUp } from '@mui/icons-material';
import { Button } from '@mui/material';
import { Redirect } from 'react-router-dom';
import { useGetArchiveQuery } from '../../../graphql/APIConnector';
import { useSimplifiedQueryResponseData } from '../../../graphql/queryUtils';
import { asUploadPath } from '../../../helpers/app-helpers';
import { FlatArchiveTag, FlatPicture, TagType } from '../../../types/additionalFlatTypes';
import {
FlatArchiveTag,
FlatPicture,
PictureOverviewType,
TagType,
} from '../../../types/additionalFlatTypes';
import PictureOverview from '../../common/PictureOverview';
import TagOverview from '../../common/TagOverview';
import PicturePreview from '../../common/picture-gallery/PicturePreview';
Expand All @@ -16,6 +21,9 @@ import ArchiveDescription from './ArchiveDescription';
import './ArchiveView.scss';
import DonateButton from '../../common/DonateButton';
import { useTranslation } from 'react-i18next';
import OverviewContainer from '../../common/OverviewContainer';
import { useMemo } from 'react';
import { OverviewContainerTab } from '../../common/OverviewContainer';

interface ArchiveViewProps {
archiveId: string;
Expand All @@ -38,6 +46,38 @@ const ArchiveView = ({ archiveId }: ArchiveViewProps) => {

const showcasePicture: FlatPicture | undefined = archive?.showcasePicture;

const tabs: OverviewContainerTab[] = useMemo(() => {
return [
{
title: t('discover.our-pictures'),
icon: <AccessTime key='0' />,
content: (
<PictureOverview
queryParams={{ archive_tag: { id: { eq: archiveId } } }}
onClick={() => {
visit('/archives/' + archiveId + '/show-more/pictures');
}}
/>
),
},
{
title: t('discover.most-liked'),
icon: <ThumbUp key='1' />,
content: (
<PictureOverview
type={PictureOverviewType.MOST_LIKED}
queryParams={{
archive_tag: { id: { eq: archiveId } },
}}
onClick={() => {
visit('/archives/' + archiveId + '/show-more/most-liked');
}}
/>
),
},
];
}, [archiveId, t, visit]);

if (!archive) {
return !loading ? <Redirect to={FALLBACK_PATH} /> : <></>;
}
Expand Down Expand Up @@ -106,13 +146,7 @@ const ArchiveView = ({ archiveId }: ArchiveViewProps) => {
)}
</div>
<ShowStats>
<PictureOverview
title='Unsere Bilder'
queryParams={{ archive_tag: { id: { eq: archiveId } } }}
onClick={() => {
visit('/archives/' + archiveId + '/show-more/pictures');
}}
/>
<OverviewContainer tabs={tabs} />
</ShowStats>

<TagOverview
Expand Down
44 changes: 36 additions & 8 deletions projects/bp-gallery/src/components/views/discover/DiscoverView.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,53 @@
import { useTranslation } from 'react-i18next';
import { useVisit } from '../../../helpers/history';
import { TagType } from '../../../types/additionalFlatTypes';
import { PictureOverviewType, TagType } from '../../../types/additionalFlatTypes';
import PictureOverview from '../../common/PictureOverview';
import TagOverview from '../../common/TagOverview';
import { ShowStats } from '../../provider/ShowStatsProvider';
import './DiscoverView.scss';
import OverviewContainer, { OverviewContainerTab } from '../../common/OverviewContainer';
import { AccessTime, ThumbUp } from '@mui/icons-material';
import { useMemo } from 'react';

const DiscoverView = () => {
const { visit } = useVisit();
const { t } = useTranslation();

const tabs: OverviewContainerTab[] = useMemo(() => {
return [
{
title: t('discover.latest-pictures'),
icon: <AccessTime key='0' />,
content: (
<PictureOverview
queryParams={{}}
onClick={() => {
visit('/show-more/latest');
}}
/>
),
},
{
title: t('discover.most-liked'),
icon: <ThumbUp key='1' />,
content: (
<PictureOverview
type={PictureOverviewType.MOST_LIKED}
queryParams={{}}
onClick={() => {
visit('/show-more/most-liked');
}}
/>
),
},
];
}, [t, visit]);

return (
<div className='discover-container'>
<ShowStats>
<PictureOverview
title={t('discover.latest-pictures')}
queryParams={{}}
onClick={() => {
visit('/show-more/latest');
}}
/>
<OverviewContainer tabs={tabs} />

<PictureOverview
title={t('discover.more-info')}
queryParams={{ collections: { name: { eq: 'Fragezeichen' } } }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const useLike = (pictureId: string, likeCount: number) => {

const [likeMutation] = useLikeMutation({
variables: { pictureId: pictureId },
refetchQueries: ['getPictureInfo'],
refetchQueries: ['getPictureInfo', 'getMostLikedPictures'],
});

const like = useCallback(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ const TagList = ({
const { data, loading, error, fetchMore } = useGetTagsWithThumbnail(
queryParams,
thumbnailQueryParams,
false,
type,
['name:asc'],
currentItemAmount ?? (scroll ? 30 : undefined)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ const ShowMoreView = ({
id: { eq: categoryId },
}
: { id: { eq: '-1' } },
limit: 1,
pagination: {
start: 0,
limit: 1,
},
},
});

Expand Down Expand Up @@ -79,12 +82,17 @@ const ShowMoreView = ({
sortBy={
categoryType !== 'pictures' && categoryId
? ['time_range_tag.start:asc']
: categoryType === 'most-liked'
? ['likes:desc']
: ['createdAt:desc']
}
hashbase={'show-more'}
extraAdornments={showcaseAdornment ? [showcaseAdornment] : []}
bulkOperations={[removeFromCollection, linkToCollection, moveToCollection, bulkEdit]}
maxNumPictures={categoryType === 'latest' ? 500 : undefined}
maxNumPictures={
categoryType === 'latest' || categoryType === 'most-liked' ? 500 : undefined
}
fetchPolicy='cache-and-network'
/>
</ShowStats>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const ShowMoreViewHeader = ({
const getShowMoreHeader = () => t(`show-more.${categoryType}-title`);
const getShowMoreText = () => t(`show-more.${categoryType}-text`);

if (categoryType === 'pictures' || categoryType === 'latest') {
if (categoryType === 'pictures' || categoryType === 'latest' || categoryType === 'most-liked') {
if (categoryId && collectionsInfo && collectionsInfo.collections.length > 0) {
return (
<CollectionDescription
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ export const getPictureQueryParams = (
? { id: { not: { eq: '-1' } } } // make sure all images get fetched
: { archive_tag: { id: { eq: archiveId } }, id: { not: { eq: '-1' } } };
}
} else if (categoryType === 'most-liked') {
return !archiveId
? { likes: { gt: 0 }, id: { not: { eq: '-1' } } }
: { archive_tag: { id: { eq: archiveId } }, likes: { gt: 0 }, id: { not: { eq: '-1' } } };
} else if (categoryId) {
return categoryQueryParams(categoryType, categoryId, archiveId);
} else {
Expand Down
Loading

0 comments on commit cceb5d4

Please sign in to comment.