Compare commits

..

10 Commits

Author SHA1 Message Date
4d1d7026b0 karussel 2025-07-12 00:16:46 +02:00
6932610e86 karusell 2023-03-12 00:42:40 +01:00
8732b43c8a konf 2023-03-10 15:08:09 +01:00
409da613a8 konflikt 2023-03-10 15:07:27 +01:00
224350c12e Merge branch 'master' of https://hope-fly.de/plesk-git/gallery 2023-03-10 15:06:51 +01:00
a44f19b32d bullets index 2023-03-10 14:57:35 +01:00
bf6f3e80e8 mantine statt material ui 2023-03-10 14:46:29 +01:00
aa24ef1ee2 fullscreen 2023-03-09 23:19:44 +01:00
3603e0b881 data from settings.js 2023-03-08 00:36:39 +01:00
8409503ee6 gallery 2023-03-07 16:14:45 +01:00
20 changed files with 1512 additions and 17 deletions

1
.env.hope-fly Normal file
View File

@ -0,0 +1 @@
REACT_APP_WWW_ROOT = "https://hope-fly.de/gallery/"

1
.env.local Normal file
View File

@ -0,0 +1 @@
REACT_APP_WWW_ROOT = "http://localhost/gallery/"

2
.gitignore vendored
View File

@ -13,10 +13,10 @@
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
.metadata
npm-debug.log*
yarn-debug.log*

1124
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,12 +3,18 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@emotion/react": "^11.10.6",
"@mantine/carousel": "^6.0.1",
"@mantine/core": "^6.0.1",
"@mantine/hooks": "^6.0.1",
"@types/jest": "^27.5.2",
"@types/node": "^16.18.14",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"env-cmd": "^10.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-image-gallery": "^1.2.11",
"react-scripts": "5.0.1",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4"
@ -17,7 +23,10 @@
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
"eject": "react-scripts eject",
"build:local": "env-cmd -f .env.local npm run build",
"build:hope-fly": "env-cmd -f .env.hope-fly npm run build",
"postbuild:local": "cp -vrRT ./build/. /opt/lampp/htdocs/gallery/"
},
"eslintConfig": {
"extends": [
@ -37,7 +46,9 @@
"last 1 safari version"
]
},
"homepage": "./",
"devDependencies": {
"@types/react-image-gallery": "^1.2.0",
"tailwindcss": "^3.2.7"
}
}

4
public/.htaccess Normal file
View File

@ -0,0 +1,4 @@
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

View File

@ -27,6 +27,7 @@
<title>React App</title>
</head>
<body>
<script type="text/javascript" src="settings.js"></script>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--

View File

@ -6,16 +6,6 @@
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",

67
public/settings.js Normal file
View File

@ -0,0 +1,67 @@
window.globalThis= {
"gallery":
[
{
"original": "IMG_20230217_161150_331.jpg",
"thumbnail": "thumb-IMG_20230217_161150_331.jpg"
},
{
"original": "IMG_20230218_182608_079.jpg",
"thumbnail": "thumb-IMG_20230218_182608_079.jpg"
},
{
"original": "IMG_20230218_182625_867.jpg",
"thumbnail": "thumb-IMG_20230218_182625_867.jpg"
},
{
"original": "IMG_20230218_184359_940.jpg",
"thumbnail": "thumb-IMG_20230218_184359_940.jpg"
},
{
"original": "IMG_20230218_184429_386.jpg",
"thumbnail": "thumb-IMG_20230218_184429_386.jpg"
},
{
"original": "IMG_20230305_164907_552.jpg",
"thumbnail": "thumb-IMG_20230305_164907_552.jpg"
},
{
"original": "IMG_20230305_164913_285.jpg",
"thumbnail": "thumb-IMG_20230305_164913_285.jpg"
},
{
"original": "IMG_20230305_164919_797.jpg",
"thumbnail": "thumb-IMG_20230305_164919_797.jpg"
},
{
"original": "IMG_20230305_164921_376.jpg",
"thumbnail": "thumb-IMG_20230305_164921_376.jpg"
},
{
"original": "IMG_20230305_164923_912.jpg",
"thumbnail": "thumb-IMG_20230305_164923_912.jpg"
}
],
"gallery2":
{
"photos":
[
"IMG_20230217_161150_331.jpg",
"IMG_20230218_182608_079.jpg",
"IMG_20230218_182625_867.jpg",
"IMG_20230218_184359_940.jpg",
"IMG_20230218_184429_386.jpg",
"IMG_20230305_164907_552.jpg",
"IMG_20230305_164913_285.jpg",
"IMG_20230305_164919_797.jpg",
"IMG_20230305_164921_376.jpg",
"IMG_20230305_164923_912.jpg"
],
"videos":
[
"VID_20230226_000317.mp4",
"VID_20230303_182143.mp4",
"VID_20230305_230139.mp4"
]
}
};

View File

@ -1,10 +1,24 @@
import React from 'react';
import ImageGalleryX from './components/ImageGalleryX';
import './App.css';
import { AppShell } from '@mantine/core';
import HeaderX from './components/HeaderX';
import {photos, videos} from './state';
import GalleryCarousel from './components/GalleryCarousel';
function App()
{
const root: string = process.env.REACT_APP_WWW_ROOT!;
const uploads: string = root + 'uploads/';
function App() {
return (
<div className="App">
<h1 className=''>Gallery</h1>
<AppShell header={<HeaderX />}>
<GalleryCarousel
videos={videos.map((item: string) => uploads + item)}
photos={photos.map((item: string) => uploads + item)}
/>
</AppShell>
</div>
);
}

View File

@ -0,0 +1,30 @@
import React from "react";
import { Carousel } from '@mantine/carousel';
import VideoPlayer from "./VideoPlayer"; // assuming VideoPlayer and ImageViewer are custom components to display videos and photos
import ImageViewer from "./ImageViewer"; // assuming VideoPlayer and ImageViewer are custom components to display videos and photos
type Props = {
videos: string[];
photos: string[];
};
const GalleryCarousel: React.FC<Props> = ({ videos, photos }): JSX.Element => {
return (
<Carousel
withIndicators
height={200}
slideSize="33.333333%"
slideGap="md"
loop
align="start" >
{photos.map((photo, index) => (
<ImageViewer key={`gallery-photo-${index}`} url={photo} />
))}
{videos.map((video, index) => (
<VideoPlayer key={`gallery-video-${index}`} url={video} />
))}
</Carousel>
);
};
export default GalleryCarousel;

View File

@ -0,0 +1,22 @@
import React from 'react';
import { Burger, Header, Text } from '@mantine/core';
export default function HeaderX()
{
return (
<Header height={{ base: 50, md: 70 }} p="md">
<div style={{ display: 'flex', alignItems: 'center', height: '100%' }}>
<Burger
opened={false}
onClick={() => {}}
size="sm"
color={'blue'}
mr="xl"
/>
<Text>Gallery</Text>
</div>
</Header> );
}

View File

@ -0,0 +1,35 @@
import React, { useCallback, useMemo } from "react";
import ImageGallery, { ReactImageGalleryItem } from "react-image-gallery";
import "react-image-gallery/styles/css/image-gallery.css";
import { imageGalleryItems } from "../state";
export default function ImageGalleryX()
{
const root: string = process.env.REACT_APP_WWW_ROOT!;
const uploads: string = root + 'uploads/';
const items = useMemo(() =>
{
return imageGalleryItems.map((item: ReactImageGalleryItem) =>
{
const newItem = { ...item };
newItem.original = uploads + newItem.original;
newItem.thumbnail = uploads + newItem.thumbnail;
// newItem.thumbnailClass = {''}
return newItem;
});
}, []);
return (
<div className={''}>
<ImageGallery
items={items}
showFullscreenButton={true}
showThumbnails={true}
showBullets={true}
showIndex={true}
/>
</div>
);
}

View File

@ -0,0 +1,9 @@
import React from 'react'
function ImageViewer({key, url}:{key:string, url:string}) {
return (
<img key={key} src={url} />
)
}
export default ImageViewer

View File

@ -0,0 +1,16 @@
import React from 'react'
import { Text } from '@mantine/core';
function VideoPlayer({key, url}:{key:string, url:string})
{
return (
<video key={key} controls>
<source src={url} type="video/mp4" />
<Text >
Sorry, your browser does not support embedded videos.
</Text>
</video>
)
}
export default VideoPlayer

74
src/components/aaa.tsx Normal file
View File

@ -0,0 +1,74 @@
// import React, { useState } from "react";
// import { useMantineTheme } from "@mantine/core";
// import { createUseStyles } from "react-jss";
// import Carousel, { CarouselControls, CarouselProps } from "@mantine/carousel";
// import VideoPlayer from "../VideoPlayer";
// import Image from "../Image";
// import { useAppStore } from "../../store";
// const useStyles = createUseStyles({
// carouselWrapper: {
// marginTop: 20,
// marginBottom: 20,
// },
// });
// const MantineCarousel: React.FC = () => {
// const [index, setIndex] = useState(0);
// const appStore = useAppStore();
// const classes = useStyles();
// const items = appStore.items.map((item) => {
// if (item.mediaType === "image") {
// return <Image key={item.id} src={item.src} alt={item.alt} />;
// }
// if (item.mediaType === "video") {
// return (
// <VideoPlayer
// key={item.id}
// src={item.src}
// poster={item.poster}
// alt={item.alt}
// />
// );
// }
// return null;
// });
// const handleIndexChange = (newIndex: number) => {
// setIndex(newIndex);
// };
// const theme = useMantineTheme();
// const responsiveConfig: CarouselProps["responsive"] = {
// "@sm": {
// slidesPerView: 3,
// spacing: "md",
// },
// "@lg": {
// slidesPerView: 5,
// spacing: "xl",
// },
// };
// return (
// <div className={classes.carouselWrapper}>
// <Carousel
// height={300}
// items={items}
// current={index}
// onChange={handleIndexChange}
// responsive={responsiveConfig}
// controls={
// <CarouselControls
// color={theme.colorScheme === "dark" ? "white" : "gray"}
// variant="overlay"
// />
// }
// />
// </div>
// );
// };
// export default MantineCarousel
export{}

43
src/components/xxx.tsx Normal file
View File

@ -0,0 +1,43 @@
// import React from 'react';
// import { Carousel, TextCarousel } from '@mantine/core';
// import { useSelector } from 'react-redux';
// import { RootState } from '../../app/store';
// interface MediaCarouselProps {
// mediaType: 'video' | 'photo';
// }
// const MediaCarousel: React.FC<MediaCarouselProps> = ({ mediaType }) => {
// const media = useSelector((state: RootState) => state.media);
// const filteredMedia = media.filter((m) => m.type === mediaType);
// return (
// <Carousel
// withControls
// transition="fade"
// offset={5}
// effect="fade"
// color="gray"
// radius={5}
// height={300}
// style={{ marginTop: '2rem' }}
// >
// {filteredMedia.map((m) =>
// mediaType === 'video' ? (
// <video key={m.id} controls>
// <source src={m.url} type="video/mp4" />
// <TextCarousel delay={3000} transition="fade">
// Sorry, your browser does not support embedded videos.
// </TextCarousel>
// </video>
// ) : (
// <img key={m.id} src={m.url} alt={m.title} />
// ),
// )}
// </Carousel>
// );
// };
// export default MediaCarousel
export{}

View File

@ -0,0 +1,43 @@
[
{
"original": "IMG_20230217_161150_331.jpg",
"thumbnail": ""
},
{
"original": "IMG_20230218_182608_079.jpg",
"thumbnail": ""
},
{
"original": "IMG_20230218_182625_867.jpg",
"thumbnail": ""
},
{
"original": "IMG_20230218_184359_940.jpg",
"thumbnail": ""
},
{
"original": "IMG_20230218_184429_386.jpg",
"thumbnail": ""
},
{
"original": "IMG_20230305_164907_552.jpg",
"thumbnail": ""
},
{
"original": "IMG_20230305_164913_285.jpg",
"thumbnail": ""
},
{
"original": "IMG_20230305_164919_797.jpg",
"thumbnail": ""
},
{
"original": "IMG_20230305_164921_376.jpg",
"thumbnail": ""
},
{
"original": "IMG_20230305_164923_912.jpg",
"thumbnail": ""
}
]

10
src/state.ts Normal file
View File

@ -0,0 +1,10 @@
import { ReactImageGalleryItem } from 'react-image-gallery';
const {gallery} = window.globalThis as any;
console.log(gallery);
const {gallery2} = window.globalThis as any;
console.log(gallery2);
export const imageGalleryItems: ReactImageGalleryItem[] = gallery;
export const {photos} = gallery2;
export const {videos} = gallery2;