Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions entry_types/scrolled/config/locales/new/image_gallery_peeks.de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,30 @@ de:
displayPeeks:
label: "Anrisse benachbarter Bilder zeigen"
inline_help: "Teile der benachbarten Bilder als Hinweis auf weitere Inhalte anzeigen."
displayPaginationIndicator:
label: "Paginierung anzeigen"
inline_help: |-
Zeigt die aktuelle Bildposition und die Gesamtzahl der
Bilder an, um die Navigation durch die Galerie zu
erleichtern.
edit_item:
back: Zurück
destroy: Löschen
confirm_delete_link: Soll der Bildergalerie-Eintrag wirklich gelöscht werden?
attributes:
image:
label: Bild
portraitImage:
inline_help: |-
Wird verwendet, wenn der Browser-Viewport höher als
breit ist - zum Beispiel auf Smartphones oder
Tablets in Portrait-Ausrichtung. Kann als
Alternative zu einem querformatigen Bild
konfiguriert werden, das ansonsten zu klein
dargestellt würde.
label: Bild (Hochkant)
tabs:
item: Bildergalerie-Eintrag
public:
image_gallery_pagination: "Bildergalerie-Paginierung"
go_to_image_gallery_item: "Gehe zu Bild %{index}"
26 changes: 26 additions & 0 deletions entry_types/scrolled/config/locales/new/image_gallery_peeks.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,29 @@ en:
displayPeeks:
label: "Display peeks of neighboring images"
inline_help: "Show partial adjacent image previews as navigation cues."
displayPaginationIndicator:
label: "Display pagination"
inline_help: |-
Displays the current image position and the total
number of images to make navigating the gallery
easier.
edit_item:
back: Back
destroy: Delete
confirm_delete_link: Are you sure you want to delete this image gallery item?
attributes:
image:
label: Image
portraitImage:
inline_help: |-
Displayed when the browser viewport is taller than
wide, for example on phones or tablets in portrait
orientation. Can be used to provide an alternative
to a landscape image that would otherwise be
displayed too small.
label: Image (Portrait)
tabs:
item: Image Gallery Item
public:
image_gallery_pagination: "Image gallery pagination"
go_to_image_gallery_item: "Go to image %{index}"
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import {
Image,
InlineFileRights,
ToggleFullscreenCornerButton,
PaginationIndicator,
usePhonePlatform,
usePortraitOrientation,
contentElementWidths
} from 'pageflow-scrolled/frontend';

Expand Down Expand Up @@ -102,8 +104,12 @@ function Scroller({
}, [visibleIndex, scrollerRef, controlled]);

function scrollBy(delta) {
scrollTo(visibleIndex + delta);
}

function scrollTo(index) {
const scroller = scrollerRef.current;
const child = scroller.children[visibleIndex + delta];
const child = scroller.children[index];

if (child) {
scrollerRef.current.scrollTo(child.offsetLeft - scroller.offsetLeft, 0);
Expand Down Expand Up @@ -139,9 +145,9 @@ function Scroller({
<div className={classNames(styles.wrapper,
{[styles.wide]:
contentElementWidth === contentElementWidths.lg ||
contentElementWidth === contentElementWidths.xl},
contentElementWidth === contentElementWidths.xl},
{[styles.full]:
contentElementWidth === contentElementWidths.full},
contentElementWidth === contentElementWidths.full},
{[styles.clip]: configuration.hidePeeks},
{[styles.customMargin]: customMargin})}>
<div className={styles.leftButton}>
Expand Down Expand Up @@ -169,23 +175,70 @@ function Scroller({
</Item>
))}
</div>
{configuration.displayPaginationIndicator &&
<div className={styles.paginationIndicator}>
<PaginationIndicator
itemCount={items.length}
currentIndex={visibleIndex}
scrollerRef={scrollerRef}
navAriaLabelTranslationKey="pageflow_scrolled.public.image_gallery_pagination"
itemAriaLabelTranslationKey="pageflow_scrolled.public.go_to_image_gallery_item"
onItemClick={index => scrollTo(index)} />
</div>}
</div>
);
}

const Item = forwardRef(function({item, configuration, current, onClick, children}, ref) {
const updateConfiguration = useContentElementConfigurationUpdate();
const {shouldLoad} = useContentElementLifecycle();

const captions = configuration.captions || {};
const caption = captions[item.id];

const imageFile = useFileWithInlineRights({
configuration: item,
collectionName: 'imageFiles',
propertyName: 'image'
});

const portraitImageFile = useFileWithInlineRights({
configuration: item,
collectionName: 'imageFiles',
propertyName: 'portraitImage'
});

const ItemImageComponent = portraitImageFile ? OrientationAwareItemImage : ItemImageWithCaption;

return (
<div className={classNames(styles.item, {[styles.current]: current,
[styles.placeholder]: item.placeholder})}
ref={ref}>
<div className={styles.figure}>
<ItemImageComponent item={item}
imageFile={imageFile}
portraitImageFile={portraitImageFile}
configuration={configuration}
current={current}
onClick={onClick}
children={children} />
</div>
</div>
);
});

function OrientationAwareItemImage({imageFile, portraitImageFile, ...props}) {
const portraitOrientation = usePortraitOrientation();

imageFile = portraitOrientation && portraitImageFile ?
portraitImageFile : imageFile;
return (
<ItemImageWithCaption imageFile={imageFile} {...props} />
);
}

function ItemImageWithCaption({item, imageFile, configuration, current, onClick, children}) {
const {shouldLoad} = useContentElementLifecycle();

const updateConfiguration = useContentElementConfigurationUpdate();

const captions = configuration.captions || {};
const caption = captions[item.id];

const handleCaptionChange = function(caption) {
updateConfiguration({
captions: {
Expand All @@ -196,36 +249,30 @@ const Item = forwardRef(function({item, configuration, current, onClick, childre
}

return (
<div className={classNames(styles.item, {[styles.current]: current,
[styles.placeholder]: item.placeholder})}
ref={ref}>
<div className={styles.figure}>
<FitViewport file={imageFile}
aspectRatio={imageFile ? undefined : 0.75}
scale={0.8}
opaque={!imageFile}>
<ContentElementBox>
<Figure caption={caption}
variant={configuration.captionVariant}
onCaptionChange={handleCaptionChange}
addCaptionButtonVisible={current && !item.placeholder}
addCaptionButtonPosition="inside">
<FitViewport.Content>
<div onClick={onClick}>
<Image imageFile={imageFile} load={shouldLoad} />
</div>
{children}
<InlineFileRights configuration={configuration}
context="insideElement"
items={[{file: imageFile, label: 'image'}]} />
</FitViewport.Content>
</Figure>
</ContentElementBox>
<InlineFileRights configuration={configuration}
context="afterElement"
items={[{file: imageFile, label: 'image'}]} />
</FitViewport>
</div>
</div>
<FitViewport file={imageFile}
aspectRatio={imageFile ? undefined : 0.75}
scale={0.8}
opaque={!imageFile}>
<ContentElementBox>
<Figure caption={caption}
variant={configuration.captionVariant}
onCaptionChange={handleCaptionChange}
addCaptionButtonVisible={current && !item.placeholder}
addCaptionButtonPosition="inside">
<FitViewport.Content>
<div onClick={onClick}>
<Image imageFile={imageFile} load={shouldLoad} />
</div>
{children}
<InlineFileRights configuration={configuration}
context="insideElement"
items={[{file: imageFile, label: 'image'}]} />
</FitViewport.Content>
</Figure>
</ContentElementBox>
<InlineFileRights configuration={configuration}
context="afterElement"
items={[{file: imageFile, label: 'image'}]} />
</FitViewport>
);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@
grid-column: 3;
}

.paginationIndicator {
grid-column: 1 / -1;
align-self: end;
justify-self: center;
z-index: 3;
margin-top: var(--theme-image-gallery-pagination-margin-top, 10px);
margin-bottom: var(--theme-image-gallery-pagination-margin-bottom, 10px);
}

.items {
grid-row: 1;
grid-column: 1/-1;
Expand Down Expand Up @@ -89,7 +98,7 @@

.figure {
transition: transform .2s ease, filter .2s linear;
transform: scale(0.9);
transform: scale(var(--theme-image-gallery-item-scale, 0.9));
filter: brightness(0.5);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Marionette from 'backbone.marionette';
import {buttonStyles} from 'pageflow-scrolled/editor';
import {editor, buttonStyles} from 'pageflow-scrolled/editor';
import {ListView} from 'pageflow/editor';
import {cssModulesUtils} from 'pageflow/ui';
import I18n from 'i18n-js';
Expand Down Expand Up @@ -28,6 +28,12 @@ export const ItemsListView = Marionette.Layout.extend({
collection: this.collection,
sortable: true,

onEdit: (model) => {
editor.navigate(
`/scrolled/imageGalleries/${this.options.contentElement.id}/${model.id}`,
{trigger: true}
)
},
onRemove: (model) => this.collection.remove(model)
}));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {SidebarEditItemView} from './SidebarEditItemView';
import {ItemsCollection} from './models/ItemsCollection';
import Marionette from 'backbone.marionette';

export const SidebarController = Marionette.Controller.extend({
initialize: function(options) {
this.entry = options.entry;
this.region = options.region;
},

item: function(id, itemId) {
const contentElement = this.entry.contentElements.get(id);
const itemsCollection = ItemsCollection.forContentElement(contentElement, this.entry);

this.region.show(new SidebarEditItemView({
model: itemsCollection.get(itemId),
collection: itemsCollection,
entry: this.entry,
contentElement
}));
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {ConfigurationEditorView} from 'pageflow/ui';
import {editor, FileInputView} from 'pageflow/editor';
import Marionette from 'backbone.marionette';
import I18n from 'i18n-js';

export const SidebarEditItemView = Marionette.Layout.extend({
template: (data) => `
<a class="back">${I18n.t('pageflow_scrolled.editor.content_elements.imageGallery.edit_item.back')}</a>
<a class="destroy">${I18n.t('pageflow_scrolled.editor.content_elements.imageGallery.edit_item.destroy')}</a>

<div class='form_container'></div>
`,

regions: {
formContainer: '.form_container',
},

events: {
'click a.back': 'goBack',
'click a.destroy': 'destroyLink'
},

onRender: function () {
const options = this.options;

const configurationEditor = new ConfigurationEditorView({
model: this.model,
attributeTranslationKeyPrefixes: ['pageflow_scrolled.editor.content_elements.imageGallery.edit_item.attributes'],
tabTranslationKeyPrefix: 'pageflow_scrolled.editor.content_elements.imageGallery.edit_item.tabs',
});

configurationEditor.tab('item', function() {
this.input('image', FileInputView, {
collection: 'image_files',
fileSelectionHandler: 'imageGalleryItem',
fileSelectionHandlerOptions: {
contentElementId: options.contentElement.get('id')
},
positioning: false
});
this.input('portraitImage', FileInputView, {
collection: 'image_files',
fileSelectionHandler: 'imageGalleryItem',
fileSelectionHandlerOptions: {
contentElementId: options.contentElement.get('id')
},
positioning: false
});
});

this.formContainer.show(configurationEditor);
},

goBack: function() {
editor.navigate(`/scrolled/content_elements/${this.options.contentElement.get('id')}`, {trigger: true});
},

destroyLink: function () {
if (window.confirm(I18n.t('pageflow_scrolled.editor.content_elements.imageGallery.edit_item.confirm_delete_link'))) {
this.options.collection.remove(this.model);
this.goBack();
}
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Marionette from 'backbone.marionette';

export const SidebarRouter = Marionette.AppRouter.extend({
appRoutes: {
'scrolled/imageGalleries/:id/:item_id': 'item'
}
});
Loading
Loading