I need something like light gallery in one of my sites, so i looked arround if there is something provided by plone / volto already. I saw that there is something called image-galery using the AlbumView from volto, this would provide exactly what i need but I can't find any documentation about it or how i could use this. Can anyone explain to me how i can access this.
I need a gallery too, do you success add one?
@mactrash Yes, I added one by myself since I couldn't find a good solution. I just created a new Block and used Light Gallery to display the images correctly. If you want to, I can provide the code.
I am new to volto, if you can share the code I am happy to have that
The AlbumView is a display option for the Folder content type, but usually Folders are disabled when using Volto because any page can be a folder.
Instead, for a built-in gallery option, add a Listing block and then choose the Image Gallery variation in the block settings.
Sorry for the late response. Here is the code I use (don't blame me if it's not perfect, this was one of my first tries with Plone/Volto).
As you see in the schema file, I define a URL where all images from this URL will be taken from. I recommend creating a page for each gallery and setting this URL as the start URL. This way, you will be able to create multiple Galleries. E.g. If you have a gallery on your Landing page, create a page called "landingImages". Then use the gallery block on your landing page, and your URL would be /landingimages.
LightGallerySchema.js
export const LightGallerySchema = (props) => {
return {
title: 'Image Gallery',
fieldsets: [
{
id: 'default',
title: 'Default',
fields: ['galleryurl', 'colNumb', "sortOn", "sortOrder"],
},
],
properties: {
galleryurl: {
title: 'Url',
description: 'Start Url for the image gallery',
widget: 'internal_url',
required: true,
},
colNumb: {
title: 'Column count',
description: 'Number of columns to be displayed',
widget: 'number',
required: true,
},
sortOn: {
title: 'Sort term',
description: 'Sort term to sort the images e.g. sortable_title',
widget: 'text',
},
sortOrder: {
title: 'Sort order descending',
description: 'Sort descending, otherwise its ascending',
type: 'boolean',
}
},
required: [],
};
};
export default LightGallerySchema;
LightGalleryEdit.jsx
import React from "react";
import LightGalleryData from "./LightGalleryData";
import SidebarPortal from '@plone/volto/components/manage/Sidebar/SidebarPortal';
const LightGalleryEdit = React.memo((props) => {
const { selected, onChangeBlock, block, data } = props;
return (
<>
<h3>Image gallery</h3>
<img
src='/default-image.svg'
width="400"
height="300"
/>
<SidebarPortal selected={selected}>
<LightGalleryData
{...props}
data={data}
block={block}
onChangeBlock={onChangeBlock}
/>
</SidebarPortal>
</>
)
})
export default LightGalleryEdit;
LightGalleryData.jsx
import React from 'react';
import { LightGallerySchema } from './LightGallerySchema';
import BlockDataForm from '@plone/volto/components/manage/Form/BlockDataForm';
const LightGalleryData = (props) => {
const { block, data, onChangeBlock } = props;
const schema = LightGallerySchema({ ...props });
console.log(props.metadata);
return (
<BlockDataForm
schema={schema}
title={schema.title}
onChangeField={(id, value) => {
onChangeBlock(block, {
...data,
[id]: value,
});
}}
formData={data}
block={block}
/>
);
};
export default LightGalleryData;
LightGalleryView.jsx
(Don't forget to insert the License Key into the "licensekey" attribute)
import React, { useEffect } from 'react';
import ImageList from '@mui/material/ImageList';
import ImageListItem from '@mui/material/ImageListItem';
import { useDispatch, useSelector } from 'react-redux';
import { searchContent } from '@plone/volto/actions';
import { flattenToAppURL } from '@plone/volto/helpers';
import PropTypes from 'prop-types';
import LightGallery from 'lightgallery/react';
import { Image } from 'semantic-ui-react';
import lgZoom from 'lightgallery/plugins/zoom';
import 'lightgallery/css/lightgallery.css';
import 'lightgallery/css/lg-zoom.css';
const LightGalleryView = (props) => {
const { data, id, content } = props;
const dispatch = useDispatch();
const subrequestID = content?.UID ? `${content?.UID}-${id}` : id;
const images = useSelector((state) => state?.search?.subrequests?.[subrequestID]?.items,);
const contentData = data.galleryurl;
const colNumb = data.colNumb;
//to sort by title insert sortable_title
var sortOn = "None"
var sortOrder = "ascending";
if (data.sortOn != 0) {
sortOn = data.sortOn
}
if (data.sortOrder) {
sortOrder = "descending";
}
useEffect(() => {
dispatch(
searchContent(
contentData,
{
portal_type: ['Image'],
b_size: 1000,
sort_on: sortOn,
sort_order: sortOrder,
},
subrequestID,
),
);
}, []);
return (
<>
<div className="App">
{data.title?.length > 0 && (
<h1>{data.title}</h1>
)}
{images?.length > 0 && (
<ImageList className='lightgalleryUl' variant="masonry" cols={colNumb} gap={12}>
<LightGallery plugins={[lgZoom]} mode="lg-fade" licenseKey='Insert License Key here' elementClassNames="lightgallery">
{images?.map((item, index) => (
<ImageListItem key={index} className="gallery-item"
href={flattenToAppURL(`${item['@id']}/@@images/${item?.image_field}`,)}
data-sub-html={item?.description}
data-src={flattenToAppURL(`${item['@id']}/@@images/${item?.image_field}`,)}>
<Image src={`${item['@id']}/@@images/${item?.image_field}/teaser`} className="img-responsive" alt={item?.description} loading="lazy" />
</ImageListItem>
))}
</LightGallery>
</ImageList>
)}
</div>
</>
);
};
LightGalleryView.propTypes = {
items: PropTypes.arrayOf(PropTypes.any),
};
export default LightGalleryView;
The default-image.svg used in the LightGalleryEdit.jsx file
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="300" viewBox="0 0 400 300">
<g fill="none" fill-rule="evenodd">
<rect width="399" height="299" x=".5" y=".5" fill="#D8E1E3" stroke="#878F93" rx="3"/>
<g transform="translate(130 90)">
<rect width="140" height="120" fill="#FFF" fill-opacity=".5" rx="3"/>
<g transform="translate(22 13)">
<rect width="96" height="96" fill="#93ACC8" rx="3"/>
<polygon fill="#FFF" points="14.299 72 79.949 72 60.957 44.745 49 59.702 34.836 34.246"/>
<circle cx="74" cy="29" r="8" fill="#FFF"/>
</g>
</g>
</g>
</svg>